wireshark/packet-ndmp.c

3494 lines
98 KiB
C
Raw Normal View History

/* packet-ndmp.c
* Routines for NDMP dissection
* 2001 Ronnie Sahlberg (see AUTHORS for email)
*
* $Id: packet-ndmp.c,v 1.27 2004/03/11 09:54:00 sahlberg Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* see www.ndmp.org for protocol specifications.
this file implements version 3 of ndmp
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <string.h>
#include <glib.h>
#include <epan/packet.h>
#include <epan/conversation.h>
#include "packet-rpc.h"
#include "packet-scsi.h"
#include "packet-frame.h"
#include "prefs.h"
#include "reassemble.h"
#include "rpc_defrag.h"
#define TCP_PORT_NDMP 10000
static int proto_ndmp = -1;
static int hf_ndmp_version = -1;
static int hf_ndmp_header = -1;
static int hf_ndmp_sequence = -1;
static int hf_ndmp_reply_sequence = -1;
static int hf_ndmp_timestamp = -1;
static int hf_ndmp_msgtype = -1;
static int hf_ndmp_msg = -1;
static int hf_ndmp_error = -1;
static int hf_ndmp_hostname = -1;
static int hf_ndmp_os_type = -1;
static int hf_ndmp_os_vers = -1;
static int hf_ndmp_hostid = -1;
static int hf_ndmp_addr_types = -1;
static int hf_ndmp_addr_type = -1;
static int hf_ndmp_auth_type = -1;
static int hf_ndmp_auth_types = -1;
static int hf_ndmp_auth_challenge = -1;
static int hf_ndmp_auth_digest = -1;
static int hf_ndmp_auth_id = -1;
static int hf_ndmp_auth_password = -1;
static int hf_ndmp_butype_info = -1;
static int hf_ndmp_butype_name = -1;
static int hf_ndmp_butype_default_env = -1;
static int hf_ndmp_butype_attr_backup_file_history = -1;
static int hf_ndmp_butype_attr_backup_filelist = -1;
static int hf_ndmp_butype_attr_recover_filelist = -1;
static int hf_ndmp_butype_attr_backup_direct = -1;
static int hf_ndmp_butype_attr_recover_direct = -1;
static int hf_ndmp_butype_attr_backup_incremental = -1;
static int hf_ndmp_butype_attr_recover_incremental = -1;
static int hf_ndmp_butype_attr_backup_utf8 = -1;
static int hf_ndmp_butype_attr_recover_utf8 = -1;
static int hf_ndmp_butype_env_name = -1;
static int hf_ndmp_butype_env_value = -1;
static int hf_ndmp_fs_info = -1;
static int hf_ndmp_fs_invalid_total_size = -1;
static int hf_ndmp_fs_invalid_used_size = -1;
static int hf_ndmp_fs_invalid_avail_size = -1;
static int hf_ndmp_fs_invalid_total_inodes = -1;
static int hf_ndmp_fs_invalid_used_inodes = -1;
static int hf_ndmp_fs_fs_type = -1;
static int hf_ndmp_fs_logical_device = -1;
static int hf_ndmp_fs_physical_device = -1;
static int hf_ndmp_fs_total_size = -1;
static int hf_ndmp_fs_used_size = -1;
static int hf_ndmp_fs_avail_size = -1;
static int hf_ndmp_fs_total_inodes = -1;
static int hf_ndmp_fs_used_inodes = -1;
static int hf_ndmp_fs_env = -1;
static int hf_ndmp_fs_env_name = -1;
static int hf_ndmp_fs_env_value = -1;
static int hf_ndmp_fs_status = -1;
static int hf_ndmp_tape_info = -1;
static int hf_ndmp_tape_model = -1;
static int hf_ndmp_tape_dev_cap = -1;
static int hf_ndmp_tape_device = -1;
static int hf_ndmp_tape_open_mode = -1;
static int hf_ndmp_tape_attr_rewind = -1;
static int hf_ndmp_tape_attr_unload = -1;
static int hf_ndmp_tape_capability = -1;
static int hf_ndmp_tape_capability_name = -1;
static int hf_ndmp_tape_capability_value = -1;
static int hf_ndmp_scsi_info = -1;
static int hf_ndmp_scsi_model = -1;
static int hf_ndmp_server_vendor = -1;
static int hf_ndmp_server_product = -1;
static int hf_ndmp_server_revision = -1;
static int hf_ndmp_scsi_device = -1;
static int hf_ndmp_scsi_controller = -1;
static int hf_ndmp_scsi_id = -1;
static int hf_ndmp_scsi_lun = -1;
static int hf_ndmp_execute_cdb_flags_data_in = -1;
static int hf_ndmp_execute_cdb_flags_data_out = -1;
static int hf_ndmp_execute_cdb_timeout = -1;
static int hf_ndmp_execute_cdb_datain_len = -1;
static int hf_ndmp_execute_cdb_cdb_len = -1;
static int hf_ndmp_execute_cdb_dataout = -1;
static int hf_ndmp_execute_cdb_status = -1;
static int hf_ndmp_execute_cdb_dataout_len = -1;
static int hf_ndmp_execute_cdb_datain = -1;
static int hf_ndmp_execute_cdb_sns_len = -1;
static int hf_ndmp_tape_invalid_file_num = -1;
static int hf_ndmp_tape_invalid_soft_errors = -1;
static int hf_ndmp_tape_invalid_block_size = -1;
static int hf_ndmp_tape_invalid_block_no = -1;
static int hf_ndmp_tape_invalid_total_space = -1;
static int hf_ndmp_tape_invalid_space_remain = -1;
static int hf_ndmp_tape_invalid_partition = -1;
static int hf_ndmp_tape_flags_no_rewind = -1;
static int hf_ndmp_tape_flags_write_protect = -1;
static int hf_ndmp_tape_flags_error = -1;
static int hf_ndmp_tape_flags_unload = -1;
static int hf_ndmp_tape_file_num = -1;
static int hf_ndmp_tape_soft_errors = -1;
static int hf_ndmp_tape_block_size = -1;
static int hf_ndmp_tape_block_no = -1;
static int hf_ndmp_tape_total_space = -1;
static int hf_ndmp_tape_space_remain = -1;
static int hf_ndmp_tape_partition = -1;
static int hf_ndmp_tape_mtio_op = -1;
static int hf_ndmp_count = -1;
static int hf_ndmp_resid_count = -1;
static int hf_ndmp_mover_state = -1;
static int hf_ndmp_mover_pause = -1;
static int hf_ndmp_halt = -1;
static int hf_ndmp_halt_reason = -1;
static int hf_ndmp_record_size = -1;
static int hf_ndmp_record_num = -1;
static int hf_ndmp_data_written = -1;
static int hf_ndmp_seek_position = -1;
static int hf_ndmp_bytes_left_to_read = -1;
static int hf_ndmp_window_offset = -1;
static int hf_ndmp_window_length = -1;
static int hf_ndmp_addr_ip = -1;
static int hf_ndmp_addr_tcp = -1;
static int hf_ndmp_addr_fcal_loop_id = -1;
static int hf_ndmp_addr_ipc = -1;
static int hf_ndmp_mover_mode = -1;
static int hf_ndmp_file_name = -1;
static int hf_ndmp_nt_file_name = -1;
static int hf_ndmp_dos_file_name = -1;
static int hf_ndmp_log_type = -1;
static int hf_ndmp_log_message_id = -1;
static int hf_ndmp_log_message = -1;
static int hf_ndmp_connected = -1;
static int hf_ndmp_connected_reason = -1;
static int hf_ndmp_data = -1;
static int hf_ndmp_files = -1;
static int hf_ndmp_file_fs_type = -1;
static int hf_ndmp_file_names = -1;
static int hf_ndmp_file_stats = -1;
static int hf_ndmp_file_node = -1;
static int hf_ndmp_file_parent = -1;
static int hf_ndmp_file_fh_info = -1;
static int hf_ndmp_file_invalid_atime = -1;
static int hf_ndmp_file_invalid_ctime = -1;
static int hf_ndmp_file_invalid_group = -1;
static int hf_ndmp_file_type = -1;
static int hf_ndmp_file_mtime = -1;
static int hf_ndmp_file_atime = -1;
static int hf_ndmp_file_ctime = -1;
static int hf_ndmp_file_owner = -1;
static int hf_ndmp_file_group = -1;
static int hf_ndmp_file_fattr = -1;
static int hf_ndmp_file_size = -1;
static int hf_ndmp_file_links = -1;
static int hf_ndmp_dirs = -1;
static int hf_ndmp_nodes = -1;
static int hf_ndmp_nlist = -1;
static int hf_ndmp_bu_original_path = -1;
static int hf_ndmp_bu_destination_dir = -1;
static int hf_ndmp_bu_new_name = -1;
static int hf_ndmp_bu_other_name = -1;
static int hf_ndmp_state_invalid_ebr = -1;
static int hf_ndmp_state_invalid_etr = -1;
static int hf_ndmp_bu_operation = -1;
static int hf_ndmp_data_state = -1;
static int hf_ndmp_data_halted = -1;
static int hf_ndmp_data_bytes_processed = -1;
static int hf_ndmp_data_est_bytes_remain = -1;
static int hf_ndmp_data_est_time_remain = -1;
static gint ett_ndmp = -1;
static gint ett_ndmp_header = -1;
static gint ett_ndmp_butype_attrs = -1;
static gint ett_ndmp_fs_invalid = -1;
static gint ett_ndmp_tape_attr = -1;
static gint ett_ndmp_execute_cdb_flags = -1;
static gint ett_ndmp_execute_cdb_cdb = -1;
static gint ett_ndmp_execute_cdb_sns = -1;
static gint ett_ndmp_execute_cdb_payload = -1;
static gint ett_ndmp_tape_invalid = -1;
static gint ett_ndmp_tape_flags = -1;
static gint ett_ndmp_addr = -1;
static gint ett_ndmp_file = -1;
static gint ett_ndmp_file_name = -1;
static gint ett_ndmp_file_stats = -1;
static gint ett_ndmp_file_invalids = -1;
static gint ett_ndmp_state_invalids = -1;
/* XXX someone should start adding the new stuff from v3, v4 and v5*/
#define NDMP_PROTOCOL_V2 1
#define NDMP_PROTOCOL_V3 2
#define NDMP_PROTOCOL_V4 3
#define NDMP_PROTOCOL_V5 4
static enum_val_t ndmp_protocol_versions[] = {
{ "Version 2", NDMP_PROTOCOL_V2 },
{ "Version 3", NDMP_PROTOCOL_V3 },
{ "Version 4", NDMP_PROTOCOL_V4 },
{ "Version 5", NDMP_PROTOCOL_V5 },
{ NULL, 0 }
};
static gint ndmp_protocol_version = NDMP_PROTOCOL_V2;
struct ndmp_header {
guint32 seq;
guint32 time;
guint32 type;
guint32 msg;
guint32 rep_seq;
guint32 err;
};
/* desegmentation of NDMP packets */
static gboolean ndmp_desegment = TRUE;
/* defragmentation of fragmented NDMP records */
static gboolean ndmp_defragment = FALSE;
#define NDMP_MESSAGE_REQUEST 0x00
#define NDMP_MESSAGE_REPLY 0x01
static const value_string msg_type_vals[] = {
{NDMP_MESSAGE_REQUEST, "Request"},
{NDMP_MESSAGE_REPLY, "Reply"},
{0, NULL}
};
#define NDMP_NO_ERR 0x00
#define NDMP_NOT_SUPPORTED_ERR 0x01
#define NDMP_DEVICE_BUSY_ERR 0x02
#define NDMP_DEVICE_OPENED_ERR 0x03
#define NDMP_NOT_AUTHORIZED_ERR 0x04
#define NDMP_PERMISSION_ERR 0x05
#define NDMP_DEV_NOT_OPEN_ERR 0x06
#define NDMP_IO_ERR 0x07
#define NDMP_TIMEOUT_ERR 0x08
#define NDMP_ILLEGAL_ARGS_ERR 0x09
#define NDMP_NO_TAPE_LOADED_ERR 0x0a
#define NDMP_WRITE_PROTECT_ERR 0x0b
#define NDMP_EOF_ERR 0x0c
#define NDMP_EOM_ERR 0x0d
#define NDMP_FILE_NOT_FOUND_ERR 0x0e
#define NDMP_BAD_FILE_ERR 0x0f
#define NDMP_NO_DEVICE_ERR 0x10
#define NDMP_NO_BUS_ERR 0x11
#define NDMP_XDR_DECODE_ERR 0x12
#define NDMP_ILLEGAL_STATE_ERR 0x13
#define NDMP_UNDEFINED_ERR 0x14
#define NDMP_XDR_ENCODE_ERR 0x15
#define NDMP_NO_MEM_ERR 0x16
#define NDMP_CONNECT_ERR 0x17
static const value_string error_vals[] = {
{NDMP_NO_ERR, "NO_ERR"},
{NDMP_NOT_SUPPORTED_ERR, "NOT_SUPPORTED_ERR"},
{NDMP_DEVICE_BUSY_ERR, "DEVICE_BUSY_ERR"},
{NDMP_DEVICE_OPENED_ERR, "DEVICE_OPENED_ERR"},
{NDMP_NOT_AUTHORIZED_ERR, "NOT_AUTHORIZED_ERR"},
{NDMP_PERMISSION_ERR, "PERMISSION_ERR"},
{NDMP_DEV_NOT_OPEN_ERR, "DEV_NOT_OPEN_ERR"},
{NDMP_IO_ERR, "IO_ERR"},
{NDMP_TIMEOUT_ERR, "TIMEOUT_ERR"},
{NDMP_ILLEGAL_ARGS_ERR, "ILLEGAL_ARGS_ERR"},
{NDMP_NO_TAPE_LOADED_ERR, "NO_TAPE_LOADED_ERR"},
{NDMP_WRITE_PROTECT_ERR, "WRITE_PROTECT_ERR"},
{NDMP_EOF_ERR, "EOF_ERR"},
{NDMP_EOM_ERR, "EOM_ERR"},
{NDMP_FILE_NOT_FOUND_ERR, "FILE_NOT_FOUND_ERR"},
{NDMP_BAD_FILE_ERR, "BAD_FILE_ERR"},
{NDMP_NO_DEVICE_ERR, "NO_DEVICE_ERR"},
{NDMP_NO_BUS_ERR, "NO_BUS_ERR"},
{NDMP_XDR_DECODE_ERR, "XDR_DECODE_ERR"},
{NDMP_ILLEGAL_STATE_ERR, "ILLEGAL_STATE_ERR"},
{NDMP_UNDEFINED_ERR, "UNDEFINED_ERR"},
{NDMP_XDR_ENCODE_ERR, "XDR_ENCODE_ERR"},
{NDMP_NO_MEM_ERR, "NO_MEM_ERR"},
{NDMP_CONNECT_ERR, "CONNECT_ERR"},
{0, NULL}
};
#define NDMP_CONFIG_GET_HOST_INFO 0x100
#define NDMP_CONFIG_GET_CONNECTION_TYPE 0x102
#define NDMP_CONFIG_GET_AUTH_ATTR 0x103
#define NDMP_CONFIG_GET_BUTYPE_INFO 0x104
#define NDMP_CONFIG_GET_FS_INFO 0x105
#define NDMP_CONFIG_GET_TAPE_INFO 0x106
#define NDMP_CONFIG_GET_SCSI_INFO 0x107
#define NDMP_CONFIG_GET_SERVER_INFO 0x108
#define NDMP_SCSI_OPEN 0x200
#define NDMP_SCSI_CLOSE 0x201
#define NDMP_SCSI_GET_STATE 0x202
#define NDMP_SCSI_SET_TARGET 0x203
#define NDMP_SCSI_RESET_DEVICE 0x204
#define NDMP_SCSI_RESET_BUS 0x205
#define NDMP_SCSI_EXECUTE_CDB 0x206
#define NDMP_TAPE_OPEN 0x300
#define NDMP_TAPE_CLOSE 0x301
#define NDMP_TAPE_GET_STATE 0x302
#define NDMP_TAPE_MTIO 0x303
#define NDMP_TAPE_WRITE 0x304
#define NDMP_TAPE_READ 0x305
#define NDMP_TAPE_EXECUTE_CDB 0x307
#define NDMP_DATA_GET_STATE 0x400
#define NDMP_DATA_START_BACKUP 0x401
#define NDMP_DATA_START_RECOVER 0x402
#define NDMP_DATA_ABORT 0x403
#define NDMP_DATA_GET_ENV 0x404
#define NDMP_DATA_STOP 0x407
#define NDMP_DATA_LISTEN 0x409
#define NDMP_DATA_CONNECT 0x40a
#define NDMP_NOTIFY_DATA_HALTED 0x501
#define NDMP_NOTIFY_CONNECTED 0x502
#define NDMP_NOTIFY_MOVER_HALTED 0x503
#define NDMP_NOTIFY_MOVER_PAUSED 0x504
#define NDMP_NOTIFY_DATA_READ 0x505
#define NDMP_LOG_FILE 0x602
#define NDMP_LOG_MESSAGE 0x603
#define NDMP_FH_ADD_FILE 0x703
#define NDMP_FH_ADD_DIR 0x704
#define NDMP_FH_ADD_NODE 0x705
#define NDMP_CONNECT_OPEN 0x900
#define NDMP_CONNECT_CLIENT_AUTH 0x901
#define NDMP_CONNECT_CLOSE 0x902
#define NDMP_CONNECT_SERVER_AUTH 0x903
#define NDMP_MOVER_GET_STATE 0xa00
#define NDMP_MOVER_LISTEN 0xa01
#define NDMP_MOVER_CONTINUE 0xa02
#define NDMP_MOVER_ABORT 0xa03
#define NDMP_MOVER_STOP 0xa04
#define NDMP_MOVER_SET_WINDOW 0xa05
#define NDMP_MOVER_READ 0xa06
#define NDMP_MOVER_CLOSE 0xa07
#define NDMP_MOVER_SET_RECORD_SIZE 0xa08
#define NDMP_MOVER_CONNECT 0xa09
static const value_string msg_vals[] = {
{NDMP_CONFIG_GET_HOST_INFO, "CONFIG_GET_HOST_INFO"},
{NDMP_CONFIG_GET_CONNECTION_TYPE, "CONFIG_GET_CONNECTION_TYPE"},
{NDMP_CONFIG_GET_AUTH_ATTR, "CONFIG_GET_AUTH_ATTR"},
{NDMP_CONFIG_GET_BUTYPE_INFO, "CONFIG_GET_BUTYPE_INFO"},
{NDMP_CONFIG_GET_FS_INFO, "CONFIG_GET_FS_INFO"},
{NDMP_CONFIG_GET_TAPE_INFO, "CONFIG_GET_TAPE_INFO"},
{NDMP_CONFIG_GET_SCSI_INFO, "CONFIG_GET_SCSI_INFO"},
{NDMP_CONFIG_GET_SERVER_INFO, "CONFIG_GET_SERVER_INFO"},
{NDMP_SCSI_OPEN, "SCSI_OPEN"},
{NDMP_SCSI_CLOSE, "SCSI_CLOSE"},
{NDMP_SCSI_GET_STATE, "SCSI_GET_STATE"},
{NDMP_SCSI_SET_TARGET, "SCSI_SET_TARGET"},
{NDMP_SCSI_RESET_DEVICE, "SCSI_RESET_DEVICE"},
{NDMP_SCSI_RESET_BUS, "SCSI_RESET_BUS"},
{NDMP_SCSI_EXECUTE_CDB, "SCSI_EXECUTE_CDB"},
{NDMP_TAPE_OPEN, "TAPE_OPEN"},
{NDMP_TAPE_CLOSE, "TAPE_CLOSE"},
{NDMP_TAPE_GET_STATE, "TAPE_GET_STATE"},
{NDMP_TAPE_MTIO, "TAPE_MTIO"},
{NDMP_TAPE_WRITE, "TAPE_WRITE"},
{NDMP_TAPE_READ, "TAPE_READ"},
{NDMP_TAPE_EXECUTE_CDB, "TAPE_EXECUTE_CDB"},
{NDMP_DATA_GET_STATE, "DATA_GET_STATE"},
{NDMP_DATA_START_BACKUP, "DATA_START_BACKUP"},
{NDMP_DATA_START_RECOVER, "DATA_START_RECOVER"},
{NDMP_DATA_ABORT, "DATA_ABORT"},
{NDMP_DATA_GET_ENV, "DATA_GET_ENV"},
{NDMP_DATA_STOP, "DATA_STOP"},
{NDMP_DATA_LISTEN, "DATA_LISTEN"},
{NDMP_DATA_CONNECT, "DATA_CONNECT"},
{NDMP_NOTIFY_DATA_HALTED, "NOTIFY_DATA_HALTED"},
{NDMP_NOTIFY_CONNECTED, "NOTIFY_CONNECTED"},
{NDMP_NOTIFY_MOVER_HALTED, "NOTIFY_MOVER_HALTED"},
{NDMP_NOTIFY_MOVER_PAUSED, "NOTIFY_MOVER_PAUSED"},
{NDMP_NOTIFY_DATA_READ, "NOTIFY_DATA_READ"},
{NDMP_LOG_FILE, "LOG_FILE"},
{NDMP_LOG_MESSAGE, "LOG_MESSAGE"},
{NDMP_FH_ADD_FILE, "FH_ADD_FILE"},
{NDMP_FH_ADD_DIR, "FH_ADD_DIR"},
{NDMP_FH_ADD_NODE, "FH_ADD_NODE"},
{NDMP_CONNECT_OPEN, "CONNECT_OPEN"},
{NDMP_CONNECT_CLIENT_AUTH, "CONNECT_CLIENT_AUTH"},
{NDMP_CONNECT_CLOSE, "CONNECT_CLOSE"},
{NDMP_CONNECT_SERVER_AUTH, "CONNECT_SERVER_AUTH"},
{NDMP_MOVER_GET_STATE, "MOVER_GET_STATE"},
{NDMP_MOVER_LISTEN, "MOVER_LISTEN"},
{NDMP_MOVER_CONTINUE, "MOVER_CONTINUE"},
{NDMP_MOVER_ABORT, "MOVER_ABORT"},
{NDMP_MOVER_STOP, "MOVER_STOP"},
{NDMP_MOVER_SET_WINDOW, "MOVER_SET_WINDOW"},
{NDMP_MOVER_READ, "MOVER_READ"},
{NDMP_MOVER_CLOSE, "MOVER_CLOSE"},
{NDMP_MOVER_SET_RECORD_SIZE, "MOVER_SET_RECORD_SIZE"},
{NDMP_MOVER_CONNECT, "MOVER_CONNECT"},
{0, NULL}
};
static int
dissect_connect_open_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *tree, guint32 seq _U_)
{
/* version number */
proto_tree_add_item(tree, hf_ndmp_version, tvb, offset, 4, FALSE);
offset += 4;
return offset;
}
static int
dissect_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq _U_)
{
guint32 err;
/* error */
err=tvb_get_ntohl(tvb, offset);
proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
if(err && check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO,
" NDMP Error:%s",
val_to_str(err, error_vals,
"Unknown NDMP error code %#x"));
}
offset += 4;
return offset;
}
static int
dissect_ndmp_get_host_info_reply(tvbuff_t *tvb, int offset,
packet_info *pinfo, proto_tree *tree, guint32 seq)
{
/* error */
offset=dissect_error(tvb, offset, pinfo, tree, seq);
/* hostname */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_hostname, offset, NULL);
/* os type */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_os_type, offset, NULL);
/* os version */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_os_vers, offset, NULL);
/* hostid */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_hostid, offset, NULL);
return offset;
}
#define NDMP_ADDR_LOCAL 0
#define NDMP_ADDR_TCP 1
#define NDMP_ADDR_FC 2
#define NDMP_ADDR_IPC 3
static const value_string addr_type_vals[] = {
{NDMP_ADDR_LOCAL, "Local"},
{NDMP_ADDR_TCP, "TCP"},
{NDMP_ADDR_FC, "FC"},
{NDMP_ADDR_IPC, "IPC"},
{0,NULL}
};
static int
dissect_ndmp_addr_type(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *tree)
{
proto_tree_add_item(tree, hf_ndmp_addr_type, tvb, offset, 4, FALSE);
offset += 4;
return offset;
}
static int
dissect_ndmp_addr_msg(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq _U_)
{
/*address type*/
return dissect_ndmp_addr_type(tvb, offset, pinfo, tree);
}
static int
dissect_ndmp_config_get_connection_type_reply(tvbuff_t *tvb, int offset,
packet_info *pinfo, proto_tree *tree, guint32 seq)
{
/* error */
offset=dissect_error(tvb, offset, pinfo, tree, seq);
/* addr types */
offset = dissect_rpc_array(tvb, pinfo, tree, offset,
dissect_ndmp_addr_type, hf_ndmp_addr_types);
return offset;
}
#define NDMP_AUTH_NONE 0
#define NDMP_AUTH_TEXT 1
#define NDMP_AUTH_MD5 2
static const value_string auth_type_vals[] = {
{NDMP_AUTH_NONE, "None"},
{NDMP_AUTH_TEXT, "Text"},
{NDMP_AUTH_MD5, "MD5"},
{0,NULL}
};
static int
dissect_auth_type(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *tree)
{
proto_tree_add_item(tree, hf_ndmp_auth_type, tvb, offset, 4, FALSE);
offset += 4;
return offset;
}
static int
dissect_get_auth_type_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq _U_)
{
/* auth type */
return dissect_auth_type(tvb, offset, pinfo, tree);
}
static int
dissect_auth_attr_msg(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *tree, guint32 seq _U_)
{
guint type;
type=tvb_get_ntohl(tvb,offset);
/* auth type */
proto_tree_add_item(tree, hf_ndmp_auth_type, tvb, offset, 4, FALSE);
offset += 4;
switch(type){
case NDMP_AUTH_NONE:
break;
case NDMP_AUTH_TEXT:
break;
case NDMP_AUTH_MD5:
proto_tree_add_item(tree, hf_ndmp_auth_challenge,
tvb, offset, 64, FALSE);
offset+=64;
}
return offset;
}
static int
dissect_default_env(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *tree)
{
/* name */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_butype_env_name, offset, NULL);
/* value */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_butype_env_value, offset, NULL);
return offset;
}
static const true_false_string tfs_butype_attr_backup_file_history = {
"Backup FILE HISTORY",
"Do NOT backup file history"
};
static const true_false_string tfs_butype_attr_backup_filelist = {
"Backup FILELIST",
"Do NOT backup filelist"
};
static const true_false_string tfs_butype_attr_recover_filelist = {
"Recover FILELIST",
"Do NOT recover filelist"
};
static const true_false_string tfs_butype_attr_backup_direct = {
"Perform DIRECT backup",
"Do NOT perform direct backup"
};
static const true_false_string tfs_butype_attr_recover_direct = {
"Perform DIRECT recovery",
"Do NOT perform direct recovery"
};
static const true_false_string tfs_butype_attr_backup_incremental = {
"Perform INCREMENTAL backup",
"Perform FULL backup"
};
static const true_false_string tfs_butype_attr_recover_incremental = {
"Perform INCREMENTAL revocery",
"Perform FULL recovery"
};
static const true_false_string tfs_butype_attr_backup_utf8 = {
"Backup using UTF8",
"Normal backup. Do NOT use utf8"
};
static const true_false_string tfs_butype_attr_recover_utf8 = {
"Recover using UTF8",
"Normal recover. Do NOT use utf8"
};
static int
dissect_butype_attrs(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *parent_tree)
{
proto_item* item = NULL;
proto_tree* tree = NULL;
guint32 flags;
flags=tvb_get_ntohl(tvb, offset);
if (parent_tree) {
item = proto_tree_add_text(parent_tree, tvb, offset, 4,
"Attributes: 0x%08x", flags);
tree = proto_item_add_subtree(item, ett_ndmp_butype_attrs);
}
proto_tree_add_boolean(tree, hf_ndmp_butype_attr_recover_utf8,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_butype_attr_backup_utf8,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_butype_attr_recover_incremental,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_butype_attr_backup_incremental,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_butype_attr_recover_direct,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_butype_attr_backup_direct,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_butype_attr_recover_filelist,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_butype_attr_backup_filelist,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_butype_attr_backup_file_history,
tvb, offset, 4, flags);
offset += 4;
return offset;
}
static int
dissect_butype_info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
{
/*butype name*/
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_butype_name, offset, NULL);
/* default env */
offset = dissect_rpc_array(tvb, pinfo, tree, offset,
dissect_default_env, hf_ndmp_butype_default_env);
/* attrs */
offset = dissect_butype_attrs(tvb, offset, pinfo, tree);
return offset;
}
static int
dissect_get_butype_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq)
{
/* error */
offset=dissect_error(tvb, offset, pinfo, tree, seq);
/* butype */
offset = dissect_rpc_array(tvb, pinfo, tree, offset,
dissect_butype_info, hf_ndmp_butype_info);
return offset;
}
static const true_false_string tfs_fs_invalid_total_size = {
"Total size is INVALID",
"Total size is VALID"
};
static const true_false_string tfs_fs_invalid_used_size = {
"Used size is INVALID",
"Used size is VALID"
};
static const true_false_string tfs_fs_invalid_avail_size = {
"Available size is INVALID",
"Available size is VALID"
};
static const true_false_string tfs_fs_invalid_total_inodes = {
"Total inode count is INVALID",
"Total inode count is VALID"
};
static const true_false_string tfs_fs_invalid_used_inodes = {
"Used inode count is INVALID",
"Used inode count is VALID"
};
static int
dissect_fs_invalid(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *parent_tree)
{
proto_item* item = NULL;
proto_tree* tree = NULL;
guint32 flags;
flags=tvb_get_ntohl(tvb, offset);
if (parent_tree) {
item = proto_tree_add_text(parent_tree, tvb, offset, 4,
"Invalids: 0x%08x", flags);
tree = proto_item_add_subtree(item, ett_ndmp_fs_invalid);
}
proto_tree_add_boolean(tree, hf_ndmp_fs_invalid_used_inodes,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_fs_invalid_total_inodes,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_fs_invalid_avail_size,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_fs_invalid_used_size,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_fs_invalid_total_size,
tvb, offset, 4, flags);
offset+=4;
return offset;
}
static int
dissect_fs_env(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *tree)
{
/* name */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_fs_env_name, offset, NULL);
/* value */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_fs_env_value, offset, NULL);
return offset;
}
static int
dissect_fs_info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
{
/* invalid bits */
offset=dissect_fs_invalid(tvb, offset, pinfo, tree);
/* fs type */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_fs_fs_type, offset, NULL);
/* fs logical device */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_fs_logical_device, offset, NULL);
/* fs physical device */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_fs_physical_device, offset, NULL);
/*total_size*/
offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_fs_total_size,
offset);
/*used_size*/
offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_fs_used_size,
offset);
/*avail_size*/
offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_fs_avail_size,
offset);
/*total_inodes*/
offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_fs_total_inodes,
offset);
/*used_inodes*/
offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_fs_used_inodes,
offset);
/* env */
offset = dissect_rpc_array(tvb, pinfo, tree, offset,
dissect_fs_env, hf_ndmp_fs_env);
/* status */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_fs_status, offset, NULL);
return offset;
}
static int
dissect_get_fs_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq)
{
/* error */
offset=dissect_error(tvb, offset, pinfo, tree, seq);
/* fs */
offset = dissect_rpc_array(tvb, pinfo, tree, offset,
dissect_fs_info, hf_ndmp_fs_info);
return offset;
}
static const true_false_string tfs_tape_attr_rewind = {
"Device supports REWIND",
"Device does NOT support rewind"
};
static const true_false_string tfs_tape_attr_unload = {
"Device supports UNLOAD",
"Device does NOT support unload"
};
static int
dissect_tape_attr(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *parent_tree)
{
proto_item* item = NULL;
proto_tree* tree = NULL;
guint32 flags;
flags=tvb_get_ntohl(tvb, offset);
if (parent_tree) {
item = proto_tree_add_text(parent_tree, tvb, offset, 4,
"Attributes: 0x%08x", flags);
tree = proto_item_add_subtree(item, ett_ndmp_tape_attr);
}
proto_tree_add_boolean(tree, hf_ndmp_tape_attr_unload,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_tape_attr_rewind,
tvb, offset, 4, flags);
offset+=4;
return offset;
}
static int
dissect_tape_capability(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *tree)
{
/* name */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_tape_capability_name, offset, NULL);
/* value */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_tape_capability_value, offset, NULL);
return offset;
}
static int
dissect_tape_dev_cap(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
{
/* device */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_tape_device, offset, NULL);
/* tape attributes */
offset = dissect_tape_attr(tvb, offset, pinfo, tree);
/* capability */
offset = dissect_rpc_array(tvb, pinfo, tree, offset,
dissect_tape_capability, hf_ndmp_tape_capability);
return offset;
}
static int
dissect_tape_info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
{
/* model */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_tape_model, offset, NULL);
/* device capabilites */
offset = dissect_rpc_array(tvb, pinfo, tree, offset,
dissect_tape_dev_cap, hf_ndmp_tape_dev_cap);
return offset;
}
static int
dissect_get_tape_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq)
{
/* error */
offset=dissect_error(tvb, offset, pinfo, tree, seq);
/* tape */
offset = dissect_rpc_array(tvb, pinfo, tree, offset,
dissect_tape_info, hf_ndmp_tape_info);
return offset;
}
static int
dissect_scsi_info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
{
/* model */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_scsi_model, offset, NULL);
/* device capabilites */
offset = dissect_rpc_array(tvb, pinfo, tree, offset,
dissect_tape_dev_cap, hf_ndmp_tape_dev_cap);
return offset;
}
static int
dissect_get_scsi_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq)
{
/* error */
offset=dissect_error(tvb, offset, pinfo, tree, seq);
/* scsi */
offset = dissect_rpc_array(tvb, pinfo, tree, offset,
dissect_scsi_info, hf_ndmp_scsi_info);
return offset;
}
static int
dissect_get_server_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq)
{
/* error */
offset=dissect_error(tvb, offset, pinfo, tree, seq);
/* vendor */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_server_vendor, offset, NULL);
/* product */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_server_product, offset, NULL);
/* revision */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_server_revision, offset, NULL);
/* server */
offset = dissect_rpc_array(tvb, pinfo, tree, offset,
dissect_auth_type, hf_ndmp_auth_types);
return offset;
}
static int
dissect_scsi_open_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *tree, guint32 seq _U_)
{
/* device */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_scsi_device, offset, NULL);
return offset;
}
static int
dissect_scsi_get_state_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq)
{
/* error */
offset=dissect_error(tvb, offset, pinfo, tree, seq);
/* controller */
proto_tree_add_item(tree, hf_ndmp_scsi_controller, tvb, offset, 4, FALSE);
offset += 4;
/* id */
proto_tree_add_item(tree, hf_ndmp_scsi_id, tvb, offset, 4, FALSE);
offset += 4;
/* lun */
proto_tree_add_item(tree, hf_ndmp_scsi_lun, tvb, offset, 4, FALSE);
offset += 4;
return offset;
}
static int
dissect_scsi_set_state_request(tvbuff_t *tvb, int offset,
packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
{
/* device */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_scsi_device, offset, NULL);
/* controller */
proto_tree_add_item(tree, hf_ndmp_scsi_controller, tvb, offset, 4, FALSE);
offset += 4;
/* id */
proto_tree_add_item(tree, hf_ndmp_scsi_id, tvb, offset, 4, FALSE);
offset += 4;
/* lun */
proto_tree_add_item(tree, hf_ndmp_scsi_lun, tvb, offset, 4, FALSE);
offset += 4;
return offset;
}
static int
dissect_execute_cdb_flags(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *parent_tree)
{
proto_item* item = NULL;
proto_tree* tree = NULL;
guint32 flags;
flags = tvb_get_ntohl(tvb, offset);
if (parent_tree) {
item = proto_tree_add_text(parent_tree, tvb, offset, 4,
"Flags: 0x%08x", flags);
tree = proto_item_add_subtree(item, ett_ndmp_execute_cdb_flags);
}
proto_tree_add_boolean(tree, hf_ndmp_execute_cdb_flags_data_in,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_execute_cdb_flags_data_out,
tvb, offset, 4, flags);
offset += 4;
return offset;
}
static int
dissect_execute_cdb_cdb(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *parent_tree, gint devtype)
{
proto_item* item = NULL;
proto_tree* tree = NULL;
guint32 cdb_len;
guint32 cdb_len_full;
cdb_len = tvb_get_ntohl(tvb, offset);
cdb_len_full = rpc_roundup(cdb_len);
if (parent_tree) {
item = proto_tree_add_text(parent_tree, tvb, offset,
4+cdb_len_full, "CDB");
tree = proto_item_add_subtree(item, ett_ndmp_execute_cdb_cdb);
}
proto_tree_add_uint(tree, hf_ndmp_execute_cdb_cdb_len, tvb, offset, 4,
cdb_len);
offset += 4;
if (cdb_len != 0) {
dissect_scsi_cdb(tvb, pinfo, tree, offset, cdb_len, devtype);
offset += cdb_len_full;
}
return offset;
}
static int
dissect_execute_cdb_payload(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree,
char *name, int hf_len, gboolean isreq)
{
proto_item* item = NULL;
proto_tree* tree = NULL;
guint32 payload_len;
guint32 payload_len_full;
payload_len = tvb_get_ntohl(tvb, offset);
payload_len_full = rpc_roundup(payload_len);
if (parent_tree) {
item = proto_tree_add_text(parent_tree, tvb, offset,
4+payload_len_full, "%s", name);
tree = proto_item_add_subtree(item,
ett_ndmp_execute_cdb_payload);
}
proto_tree_add_uint(tree, hf_len, tvb, offset, 4, payload_len);
offset += 4;
if (payload_len != 0) {
dissect_scsi_payload(tvb, pinfo, tree, offset, isreq,
payload_len);
offset += payload_len_full;
}
return offset;
}
/*
* XXX - we assume that NDMP_SCSI_EXECUTE_CDB requests only go to SCSI Media
* Changer devices and NDMP_TAPE_EXECUTE_CDB only go to SCSI Sequential
* Access devices.
*
* If that's not the case, we'll have to use the SCSI dissector's mechanisms
* for saving inquiry data for devices, and use inquiry data when available.
* Unfortunately, that means we need to save the name of the device, and
* use it as a device identifier; as the name isn't available in the
* NDMP_SCSI_EXECUTE_CDB or NDMP_TAPE_EXECUTE_CDB messages, that means
* we need to remember the currently-opened "SCSI" and "TAPE" devices
* from NDMP_SCSI_OPEN and NDMP_TAPE_OPEN, and attach to all frames
* that are the ones that trigger the dissection of NDMP_SCSI_EXECUTE_CDB
* or NDMP_TAPE_EXECUTE_CDB requests pointers to those names.
*/
static int
dissect_execute_cdb_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq, gint devtype)
{
conversation_t *conversation;
scsi_task_id_t task_key;
/*
* We need to provide SCSI task information to the SCSI
* dissection routines. We use a conversation plus the
* sequence number in requests and the reply sequence
* number in replies to identify SCSI tasks.
*/
conversation = find_conversation(&pinfo->src, &pinfo->dst,
pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
if (conversation == NULL) {
conversation = conversation_new(&pinfo->src, &pinfo->dst,
pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
}
task_key.conv_id = conversation->index;
task_key.task_id = seq;
pinfo->private_data = &task_key;
/* flags */
offset = dissect_execute_cdb_flags(tvb, offset, pinfo, tree);
/* timeout */
proto_tree_add_item(tree, hf_ndmp_execute_cdb_timeout, tvb, offset, 4, FALSE);
offset += 4;
/* datain_len */
proto_tree_add_item(tree, hf_ndmp_execute_cdb_datain_len, tvb, offset, 4, FALSE);
offset += 4;
/* CDB */
offset = dissect_execute_cdb_cdb(tvb, offset, pinfo, tree, devtype);
/* dataout */
offset = dissect_execute_cdb_payload(tvb, offset, pinfo, tree,
"Data out", hf_ndmp_execute_cdb_dataout_len, TRUE);
return offset;
}
static int
dissect_execute_cdb_request_mc(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq)
{
return dissect_execute_cdb_request(tvb, offset, pinfo, tree, seq,
SCSI_DEV_SMC);
}
static int
dissect_execute_cdb_request_tape(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq)
{
return dissect_execute_cdb_request(tvb, offset, pinfo, tree, seq,
SCSI_DEV_SSC);
}
static int
dissect_execute_cdb_sns(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
{
proto_item* item = NULL;
proto_tree* tree = NULL;
guint32 sns_len;
guint32 sns_len_full;
sns_len = tvb_get_ntohl(tvb, offset);
sns_len_full = rpc_roundup(sns_len);
if (parent_tree) {
item = proto_tree_add_text(parent_tree, tvb, offset,
4+sns_len_full, "Sense data");
tree = proto_item_add_subtree(item, ett_ndmp_execute_cdb_sns);
}
proto_tree_add_uint(tree, hf_ndmp_execute_cdb_sns_len, tvb, offset, 4,
sns_len);
offset += 4;
if (sns_len != 0) {
dissect_scsi_snsinfo(tvb, pinfo, tree, offset, sns_len);
offset += sns_len_full;
}
return offset;
}
static int
dissect_execute_cdb_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq)
{
conversation_t *conversation;
scsi_task_id_t task_key;
/*
* We need to provide SCSI task information to the SCSI
* dissection routines. We use a conversation plus the
* sequence number in requests and the reply sequence
* number in replies to identify SCSI tasks.
*/
conversation = find_conversation(&pinfo->src, &pinfo->dst,
pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
if (conversation != NULL) {
task_key.conv_id = conversation->index;
task_key.task_id = seq;
pinfo->private_data = &task_key;
} else {
/* no conversation, meaning we didn't see the request */
pinfo->private_data = NULL;
}
/* error */
offset=dissect_error(tvb, offset, pinfo, tree, seq);
/* status */
proto_tree_add_item(tree, hf_ndmp_execute_cdb_status, tvb, offset, 4, FALSE);
offset += 4;
/* dataout_len */
proto_tree_add_item(tree, hf_ndmp_execute_cdb_dataout_len, tvb, offset, 4, FALSE);
offset += 4;
/* datain */
offset = dissect_execute_cdb_payload(tvb, offset, pinfo, tree,
"Data in", hf_ndmp_execute_cdb_datain_len, FALSE);
/* ext_sense */
offset = dissect_execute_cdb_sns(tvb, offset, pinfo, tree);
return offset;
}
#define NDMP_TAPE_OPEN_MODE_READ 0
#define NDMP_TAPE_OPEN_MODE_RDWR 1
static const value_string tape_open_mode_vals[] = {
{NDMP_TAPE_OPEN_MODE_READ, "Read"},
{NDMP_TAPE_OPEN_MODE_RDWR, "Read/Write"},
{0, NULL}
};
static int
dissect_tape_open_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *tree, guint32 seq _U_)
{
/* device */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_tape_device, offset, NULL);
/* open mode */
proto_tree_add_item(tree, hf_ndmp_tape_open_mode, tvb, offset, 4, FALSE);
offset += 4;
return offset;
}
static const true_false_string tfs_ndmp_tape_invalid_file_num = {
"File num is valid",
"File num is INVALID"
};
static const true_false_string tfs_ndmp_tape_invalid_soft_errors = {
"Soft errors is valid",
"Soft errors is INVALID"
};
static const true_false_string tfs_ndmp_tape_invalid_block_size = {
"Block size is valid",
"Block size is INVALID"
};
static const true_false_string tfs_ndmp_tape_invalid_block_no = {
"Block no is valid",
"Block no is INVALID"
};
static const true_false_string tfs_ndmp_tape_invalid_total_space = {
"Total space is valid",
"Total space is INVALID"
};
static const true_false_string tfs_ndmp_tape_invalid_space_remain = {
"Space remaining is INVALID",
"Space remaining is valid"
};
static const true_false_string tfs_ndmp_tape_invalid_partition = {
"Partition is INVALID",
"Partition is valid"
};
static int
dissect_tape_invalid(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *parent_tree)
{
proto_item* item = NULL;
proto_tree* tree = NULL;
guint32 flags;
flags=tvb_get_ntohl(tvb, offset);
if (parent_tree) {
item = proto_tree_add_text(parent_tree, tvb, offset, 4,
"Invalids: 0x%08x", flags);
tree = proto_item_add_subtree(item, ett_ndmp_tape_invalid);
}
proto_tree_add_boolean(tree, hf_ndmp_tape_invalid_partition,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_tape_invalid_space_remain,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_tape_invalid_total_space,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_tape_invalid_block_no,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_tape_invalid_block_size,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_tape_invalid_soft_errors,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_tape_invalid_file_num,
tvb, offset, 4, flags);
offset+=4;
return offset;
}
static const true_false_string tfs_ndmp_tape_flags_no_rewind = {
"This is a NON-REWINDING device",
"This device supports rewind"
};
static const true_false_string tfs_ndmp_tape_flags_write_protect = {
"This device is WRITE-PROTECTED",
"This device is NOT write-protected"
};
static const true_false_string tfs_ndmp_tape_flags_error = {
"This device shows ERROR",
"This device shows NO errors"
};
static const true_false_string tfs_ndmp_tape_flags_unload = {
"This device supports UNLOAD",
"This device does NOT support unload"
};
static int
dissect_tape_flags(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *parent_tree)
{
proto_item* item = NULL;
proto_tree* tree = NULL;
guint32 flags;
flags=tvb_get_ntohl(tvb, offset);
if (parent_tree) {
item = proto_tree_add_text(parent_tree, tvb, offset, 4,
"Flags: 0x%08x", flags);
tree = proto_item_add_subtree(item, ett_ndmp_tape_flags);
}
proto_tree_add_boolean(tree, hf_ndmp_tape_flags_unload,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_tape_flags_error,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_tape_flags_write_protect,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_tape_flags_no_rewind,
tvb, offset, 4, flags);
offset+=4;
return offset;
}
static int
dissect_tape_get_state_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq)
{
/* invalid bits */
offset=dissect_tape_invalid(tvb, offset, pinfo, tree);
/* error */
offset=dissect_error(tvb, offset, pinfo, tree, seq);
/* flags */
offset=dissect_tape_flags(tvb, offset, pinfo, tree);
/* file_num */
proto_tree_add_item(tree, hf_ndmp_tape_file_num, tvb, offset, 4, FALSE);
offset += 4;
/* soft_errors */
proto_tree_add_item(tree, hf_ndmp_tape_soft_errors, tvb, offset, 4, FALSE);
offset += 4;
/* block_size */
proto_tree_add_item(tree, hf_ndmp_tape_block_size, tvb, offset, 4, FALSE);
offset += 4;
/* block_no */
proto_tree_add_item(tree, hf_ndmp_tape_block_no, tvb, offset, 4, FALSE);
offset += 4;
/* total_space */
offset = dissect_rpc_uint64(tvb, tree,hf_ndmp_tape_total_space,
offset);
/* space_remain */
offset = dissect_rpc_uint64(tvb, tree,hf_ndmp_tape_space_remain,
offset);
/* partition */
proto_tree_add_item(tree, hf_ndmp_tape_partition, tvb, offset, 4, FALSE);
offset += 4;
return offset;
}
#define NDMP_TAPE_MTIO_FSF 0
#define NDMP_TAPE_MTIO_BSF 1
#define NDMP_TAPE_MTIO_FSR 2
#define NDMP_TAPE_MTIO_BSR 3
#define NDMP_TAPE_MTIO_REW 4
#define NDMP_TAPE_MTIO_EOF 5
#define NDMP_TAPE_MTIO_OFF 6
static const value_string tape_mtio_vals[] = {
{NDMP_TAPE_MTIO_FSF, "FSF"},
{NDMP_TAPE_MTIO_BSF, "BSF"},
{NDMP_TAPE_MTIO_FSR, "FSR"},
{NDMP_TAPE_MTIO_BSR, "BSR"},
{NDMP_TAPE_MTIO_REW, "REW"},
{NDMP_TAPE_MTIO_EOF, "EOF"},
{NDMP_TAPE_MTIO_OFF, "OFF"},
{0, NULL}
};
static int
dissect_tape_mtio_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *tree, guint32 seq _U_)
{
/* op */
proto_tree_add_item(tree, hf_ndmp_tape_mtio_op, tvb, offset, 4, FALSE);
offset += 4;
/* count */
proto_tree_add_item(tree, hf_ndmp_count, tvb, offset, 4, FALSE);
offset += 4;
return offset;
}
static int
dissect_tape_mtio_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq)
{
/* error */
offset=dissect_error(tvb, offset, pinfo, tree, seq);
/* resid count */
proto_tree_add_item(tree, hf_ndmp_resid_count, tvb, offset, 4, FALSE);
offset += 4;
return offset;
}
#define NDMP_MOVER_STATE_IDLE 0
#define NDMP_MOVER_STATE_LISTEN 1
#define NDMP_MOVER_STATE_ACTIVE 2
#define NDMP_MOVER_STATE_PAUSED 3
#define NDMP_MOVER_STATE_HALTED 4
static const value_string mover_state_vals[] = {
{NDMP_MOVER_STATE_IDLE, "MOVER_STATE_IDLE"},
{NDMP_MOVER_STATE_LISTEN, "MOVER_STATE_LISTEN"},
{NDMP_MOVER_STATE_ACTIVE, "MOVER_STATE_ACTIVE"},
{NDMP_MOVER_STATE_PAUSED, "MOVER_STATE_PAUSED"},
{NDMP_MOVER_STATE_HALTED, "MOVER_STATE_HALTED"},
{0, NULL}
};
#define NDMP_MOVER_PAUSE_NA 0
#define NDMP_MOVER_PAUSE_EOM 1
#define NDMP_MOVER_PAUSE_EOF 2
#define NDMP_MOVER_PAUSE_SEEK 3
#define NDMP_MOVER_PAUSE_MEDIA_ERROR 4
#define NDMP_MOVER_PAUSE_EOW 5
static const value_string mover_pause_vals[] = {
{NDMP_MOVER_PAUSE_NA, "MOVER_PAUSE_NA"},
{NDMP_MOVER_PAUSE_EOM, "MOVER_PAUSE_EOM"},
{NDMP_MOVER_PAUSE_EOF, "MOVER_PAUSE_EOF"},
{NDMP_MOVER_PAUSE_SEEK, "MOVER_PAUSE_SEEK"},
{NDMP_MOVER_PAUSE_MEDIA_ERROR, "MOVER_PAUSE_MEDIA_ERROR"},
{NDMP_MOVER_PAUSE_EOW, "MOVER_PAUSE_EOW"},
{0, NULL}
};
#define NDMP_HALT_NA 0
#define NDMP_HALT_CONNECT_CLOSE 1
#define NDMP_HALT_ABORTED 2
#define NDMP_HALT_INTERNAL_ERROR 3
#define NDMP_HALT_CONNECT_ERROR 4
static const value_string halt_vals[] = {
{NDMP_HALT_NA, "HALT_NA"},
{NDMP_HALT_CONNECT_CLOSE, "HALT_CONNECT_CLOSE"},
{NDMP_HALT_ABORTED, "HALT_ABORTED"},
{NDMP_HALT_INTERNAL_ERROR, "HALT_INTERNAL_ERROR"},
{NDMP_HALT_CONNECT_ERROR, "HALT_CONNECT_ERROR"},
{0, NULL}
};
static int
dissect_ndmp_addr(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *parent_tree)
{
proto_item* item = NULL;
proto_tree* tree = NULL;
guint32 type;
type=tvb_get_ntohl(tvb, offset);
if (parent_tree) {
item = proto_tree_add_text(parent_tree, tvb, offset, 4,
"Type: %s ", val_to_str(type, addr_type_vals,"Unknown addr type (0x%02x)") );
tree = proto_item_add_subtree(item, ett_ndmp_addr);
}
/*address type*/
proto_tree_add_item(tree, hf_ndmp_addr_type, tvb, offset, 4, FALSE);
offset += 4;
switch(type){
case NDMP_ADDR_LOCAL:
break;
case NDMP_ADDR_TCP:
/* IP addr */
proto_tree_add_item(tree, hf_ndmp_addr_ip, tvb, offset, 4, FALSE);
offset+=4;
/* TCP port */
proto_tree_add_item(tree, hf_ndmp_addr_tcp, tvb, offset, 4, FALSE);
offset+=4;
break;
case NDMP_ADDR_FC:
/* FCAL loop id */
proto_tree_add_item(tree, hf_ndmp_addr_fcal_loop_id, tvb, offset, 4, FALSE);
offset+=4;
break;
case NDMP_ADDR_IPC:
/* IPC address */
offset = dissect_rpc_data(tvb, tree, hf_ndmp_addr_ipc, offset);
break;
}
return offset;
}
static int
dissect_mover_get_state_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq)
{
/* error */
offset=dissect_error(tvb, offset, pinfo, tree, seq);
/* mover state */
proto_tree_add_item(tree, hf_ndmp_mover_state, tvb, offset, 4, FALSE);
offset += 4;
/* mover pause */
proto_tree_add_item(tree, hf_ndmp_mover_pause, tvb, offset, 4, FALSE);
offset += 4;
/* halt */
proto_tree_add_item(tree, hf_ndmp_halt, tvb, offset, 4, FALSE);
offset += 4;
/* record size */
proto_tree_add_item(tree, hf_ndmp_record_size, tvb, offset, 4, FALSE);
offset += 4;
/* record num */
proto_tree_add_item(tree, hf_ndmp_record_num, tvb, offset, 4, FALSE);
offset += 4;
/* data written */
proto_tree_add_item(tree, hf_ndmp_data_written, tvb, offset, 8, FALSE);
offset += 8;
/* seek position */
proto_tree_add_item(tree, hf_ndmp_seek_position, tvb, offset, 8, FALSE);
offset += 8;
/* bytes left to read */
proto_tree_add_item(tree, hf_ndmp_bytes_left_to_read, tvb, offset, 8, FALSE);
offset += 8;
/* window offset */
proto_tree_add_item(tree, hf_ndmp_window_offset, tvb, offset, 8, FALSE);
offset += 8;
/* window length */
proto_tree_add_item(tree, hf_ndmp_window_length, tvb, offset, 8, FALSE);
offset += 8;
/* this is where v2 ends */
if(ndmp_protocol_version==NDMP_PROTOCOL_V2){
return offset;
}
/* ndmp addr */
offset=dissect_ndmp_addr(tvb, offset, pinfo, tree);
return offset;
}
#define NDMP_MOVER_MODE_READ 0
#define NDMP_MOVER_MODE_WRITE 1
static const value_string mover_mode_vals[] = {
{NDMP_MOVER_MODE_READ, "MODE_READ"},
{NDMP_MOVER_MODE_WRITE, "MOVER_MODE_WRITE"},
{0, NULL}
};
static int
dissect_mover_listen_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *tree, guint32 seq _U_)
{
/* mode */
proto_tree_add_item(tree, hf_ndmp_mover_mode, tvb, offset, 4, FALSE);
offset += 4;
/*address type*/
proto_tree_add_item(tree, hf_ndmp_addr_type, tvb, offset, 4, FALSE);
offset += 4;
return offset;
}
static int
dissect_mover_listen_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq)
{
/* error */
offset=dissect_error(tvb, offset, pinfo, tree, seq);
/* ndmp addr */
offset=dissect_ndmp_addr(tvb, offset, pinfo, tree);
return offset;
}
static int
dissect_mover_set_window_request(tvbuff_t *tvb, int offset,
packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
{
/* window offset */
proto_tree_add_item(tree, hf_ndmp_window_offset, tvb, offset, 8, FALSE);
offset += 8;
/* window length */
proto_tree_add_item(tree, hf_ndmp_window_length, tvb, offset, 8, FALSE);
offset += 8;
return offset;
}
static int
dissect_mover_set_record_size_request(tvbuff_t *tvb, int offset,
packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
{
/* record size */
proto_tree_add_item(tree, hf_ndmp_record_size, tvb, offset, 4, FALSE);
offset += 4;
return offset;
}
static int
dissect_mover_connect_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq _U_)
{
/* mode */
proto_tree_add_item(tree, hf_ndmp_mover_mode, tvb, offset, 4, FALSE);
offset += 4;
/* ndmp addr */
offset=dissect_ndmp_addr(tvb, offset, pinfo, tree);
return offset;
}
static int
dissect_log_file_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq)
{
/* file */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_file_name, offset, NULL);
/* error */
offset=dissect_error(tvb, offset, pinfo, tree, seq);
return offset;
}
#define NDMP_LOG_TYPE_NORMAL 0
#define NDMP_LOG_TYPE_DEBUG 1
#define NDMP_LOG_TYPE_ERROR 2
#define NDMP_LOG_TYPE_WARNING 3
static const value_string log_type_vals[] = {
{NDMP_LOG_TYPE_NORMAL, "NORMAL"},
{NDMP_LOG_TYPE_DEBUG, "DEBUG"},
{NDMP_LOG_TYPE_ERROR, "ERROR"},
{NDMP_LOG_TYPE_WARNING, "WARNING"},
{0, NULL}
};
static int
dissect_log_message_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *tree, guint32 seq _U_)
{
/* type */
proto_tree_add_item(tree, hf_ndmp_log_type, tvb, offset, 4, FALSE);
offset += 4;
/* message id */
proto_tree_add_item(tree, hf_ndmp_log_message_id, tvb, offset, 4, FALSE);
offset += 4;
/* message */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_log_message, offset, NULL);
return offset;
}
static int
dissect_notify_data_halted_request(tvbuff_t *tvb, int offset,
packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
{
/* halt */
proto_tree_add_item(tree, hf_ndmp_halt, tvb, offset, 4, FALSE);
offset += 4;
/* reason */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_halt_reason, offset, NULL);
return offset;
}
#define NDMP_CONNECTED_CONNECTED 0
#define NDMP_CONNECTED_SHUTDOWN 1
#define NDMP_CONNECTED_REFUSED 2
static const value_string connected_vals[] = {
{NDMP_CONNECTED_CONNECTED, "CONNECTED"},
{NDMP_CONNECTED_SHUTDOWN, "SHUTDOWN"},
{NDMP_CONNECTED_REFUSED, "REFUSED"},
{0, NULL}
};
static int
dissect_notify_connected_request(tvbuff_t *tvb, int offset,
packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
{
/* connected */
proto_tree_add_item(tree, hf_ndmp_connected, tvb, offset, 4, FALSE);
offset += 4;
/* version number */
proto_tree_add_item(tree, hf_ndmp_version, tvb, offset, 4, FALSE);
offset += 4;
/* reason */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_connected_reason, offset, NULL);
return offset;
}
static int
dissect_notify_mover_paused_request(tvbuff_t *tvb, int offset,
packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
{
/* mover pause */
proto_tree_add_item(tree, hf_ndmp_mover_pause, tvb, offset, 4, FALSE);
offset += 4;
/* seek position */
proto_tree_add_item(tree, hf_ndmp_seek_position, tvb, offset, 8, FALSE);
offset += 8;
return offset;
}
static int
dissect_auth_data(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *tree)
{
guint type;
type=tvb_get_ntohl(tvb,offset);
/* auth type */
proto_tree_add_item(tree, hf_ndmp_auth_type, tvb, offset, 4, FALSE);
offset += 4;
switch(type){
case NDMP_AUTH_NONE:
break;
case NDMP_AUTH_TEXT:
/* auth id */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_auth_id, offset, NULL);
/* auth password */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_auth_password, offset, NULL);
break;
case NDMP_AUTH_MD5:
/* auth id */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_auth_id, offset, NULL);
/* digest */
proto_tree_add_item(tree, hf_ndmp_auth_digest,
tvb, offset, 16, FALSE);
offset+=16;
}
return offset;
}
static int
dissect_connect_client_auth_request(tvbuff_t *tvb, int offset,
packet_info *pinfo, proto_tree *tree, guint32 seq _U_)
{
return dissect_auth_data(tvb, offset, pinfo, tree);
}
static int
dissect_connect_server_auth_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq)
{
/* error */
offset=dissect_error(tvb, offset, pinfo, tree, seq);
/* auth data */
offset = dissect_auth_data(tvb, offset, pinfo, tree);
return offset;
}
static int
dissect_tape_write_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *tree, guint32 seq _U_)
{
/* data */
offset = dissect_rpc_data(tvb, tree, hf_ndmp_data, offset);
return offset;
}
static int
dissect_tape_write_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq)
{
/* error */
offset=dissect_error(tvb, offset, pinfo, tree, seq);
/* count */
proto_tree_add_item(tree, hf_ndmp_count, tvb, offset, 4, FALSE);
offset += 4;
return offset;
}
static int
dissect_tape_read_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *tree, guint32 seq _U_)
{
/* count */
proto_tree_add_item(tree, hf_ndmp_count, tvb, offset, 4, FALSE);
offset += 4;
return offset;
}
static int
dissect_tape_read_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq)
{
/* error */
offset=dissect_error(tvb, offset, pinfo, tree, seq);
/* data */
offset = dissect_rpc_data(tvb, tree, hf_ndmp_data, offset);
return offset;
}
#define NDMP_FS_UNIX 0
#define NDMP_FS_NT 1
#define NDMP_FS_OTHER 2
static const value_string file_fs_type_vals[] = {
{NDMP_FS_UNIX, "UNIX"},
{NDMP_FS_NT, "NT"},
{NDMP_FS_OTHER, "OTHER"},
{0, NULL}
};
static int
dissect_file_name(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
{
proto_item* item = NULL;
proto_tree* tree = NULL;
int old_offset=offset;
guint32 type;
char *name;
if (parent_tree) {
Allow a length of -1 to be specified when adding FT_NONE and FT_PROTOCOL items to the protocol tree; it's interpreted as "the rest of the data in the tvbuff". This can be used if 1) the item covers the entire packet or the remaining payload in the packet or 2) the item's length won't be known until it's dissected, and will be then set with "proto_item_set_len()" - if an exception is thrown in the dissection, it means the item ran *past* the end of the tvbuff, so saying it runs to the end of the tvbuff is reasonable. Convert a number of "proto_tree_add_XXX()" calls using "tvb_length_remaining()", values derived from the result of "tvb_length()", or 0 (in the case of items whose length is unknown) to use -1 instead (using 0 means that if an exception is thrown, selecting the item highlights nothing; using -1 means it highlights all the data for that item that's available). In some places where "tvb_length()" or "tvb_length_remaining()" was used to determine how large a packet is, use "tvb_reported_length()" or "tvb_reported_length_remaining()", instead - the first two calls indicate how much captured data was in the packet, the latter two calls indicate how large the packet actually was (and the fact that using the latter could cause BoundsError exceptions to be thrown is a feature - if such an exception is thrown, the frame really *was* short, and it should be tagged as such). Replace some "proto_tree_add_XXX()" calls with equivalent "proto_tree_add_item()" calls. Fix some indentation. svn path=/trunk/; revision=4578
2002-01-20 22:12:39 +00:00
item = proto_tree_add_text(parent_tree, tvb, offset, -1,
"File");
tree = proto_item_add_subtree(item, ett_ndmp_file_name);
}
/* file type */
type=tvb_get_ntohl(tvb, offset);
proto_tree_add_item(tree, hf_ndmp_file_fs_type, tvb, offset, 4, FALSE);
offset += 4;
switch(type){
case NDMP_FS_UNIX:
/* file */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_file_name, offset, &name);
if (check_col(pinfo->cinfo, COL_INFO)){
col_append_fstr(pinfo->cinfo, COL_INFO, " %s", name);
}
break;
case NDMP_FS_NT:
/* nt file */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_nt_file_name, offset, &name);
if (check_col(pinfo->cinfo, COL_INFO)){
col_append_fstr(pinfo->cinfo, COL_INFO, " %s", name);
}
/* dos file */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_dos_file_name, offset, NULL);
break;
default:
/* file */
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_file_name, offset, &name);
if (check_col(pinfo->cinfo, COL_INFO)){
col_append_fstr(pinfo->cinfo, COL_INFO, " %s", name);
}
}
if (check_col(pinfo->cinfo, COL_INFO)){
col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
val_to_str(type, file_fs_type_vals, "Unknown type") );
}
proto_item_set_len(item, offset-old_offset);
return offset;
}
static const true_false_string tfs_ndmp_file_invalid_atime = {
"Atime is INVALID",
"Atime is valid"
};
static const true_false_string tfs_ndmp_file_invalid_ctime = {
"Ctime is INVALID",
"Ctime is valid"
};
static const true_false_string tfs_ndmp_file_invalid_group = {
"Group is INVALID",
"Group is valid"
};
static int
dissect_file_invalids(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *parent_tree)
{
proto_item* item = NULL;
proto_tree* tree = NULL;
guint32 flags;
flags=tvb_get_ntohl(tvb, offset);
if (parent_tree) {
item = proto_tree_add_text(parent_tree, tvb, offset, 4,
"Invalids: 0x%08x", flags);
tree = proto_item_add_subtree(item, ett_ndmp_file_invalids);
}
proto_tree_add_boolean(tree, hf_ndmp_file_invalid_group,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_file_invalid_ctime,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_file_invalid_atime,
tvb, offset, 4, flags);
offset+=4;
return offset;
}
#define NDMP_FILE_TYPE_DIR 0
#define NDMP_FILE_TYPE_FIFO 1
#define NDMP_FILE_TYPE_CSPEC 2
#define NDMP_FILE_TYPE_BSPEC 3
#define NDMP_FILE_TYPE_REG 4
#define NDMP_FILE_TYPE_SLINK 5
#define NDMP_FILE_TYPE_SOCK 6
#define NDMP_FILE_TYPE_REGISTRY 7
#define NDMP_FILE_TYPE_OTHER 8
static const value_string file_type_vals[] = {
{NDMP_FILE_TYPE_DIR, "DIR"},
{NDMP_FILE_TYPE_FIFO, "FIFO"},
{NDMP_FILE_TYPE_CSPEC, "CSPEC"},
{NDMP_FILE_TYPE_BSPEC, "BSPEC"},
{NDMP_FILE_TYPE_REG, "REG"},
{NDMP_FILE_TYPE_SLINK, "SLINK"},
{NDMP_FILE_TYPE_SOCK, "SOCK"},
{NDMP_FILE_TYPE_REGISTRY, "REGISTRY"},
{NDMP_FILE_TYPE_OTHER, "OTHER"},
{0, NULL}
};
static int
dissect_file_stats(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
{
proto_item* item = NULL;
proto_tree* tree = NULL;
int old_offset=offset;
nstime_t ns;
if (parent_tree) {
Allow a length of -1 to be specified when adding FT_NONE and FT_PROTOCOL items to the protocol tree; it's interpreted as "the rest of the data in the tvbuff". This can be used if 1) the item covers the entire packet or the remaining payload in the packet or 2) the item's length won't be known until it's dissected, and will be then set with "proto_item_set_len()" - if an exception is thrown in the dissection, it means the item ran *past* the end of the tvbuff, so saying it runs to the end of the tvbuff is reasonable. Convert a number of "proto_tree_add_XXX()" calls using "tvb_length_remaining()", values derived from the result of "tvb_length()", or 0 (in the case of items whose length is unknown) to use -1 instead (using 0 means that if an exception is thrown, selecting the item highlights nothing; using -1 means it highlights all the data for that item that's available). In some places where "tvb_length()" or "tvb_length_remaining()" was used to determine how large a packet is, use "tvb_reported_length()" or "tvb_reported_length_remaining()", instead - the first two calls indicate how much captured data was in the packet, the latter two calls indicate how large the packet actually was (and the fact that using the latter could cause BoundsError exceptions to be thrown is a feature - if such an exception is thrown, the frame really *was* short, and it should be tagged as such). Replace some "proto_tree_add_XXX()" calls with equivalent "proto_tree_add_item()" calls. Fix some indentation. svn path=/trunk/; revision=4578
2002-01-20 22:12:39 +00:00
item = proto_tree_add_text(parent_tree, tvb, offset, -1,
"Stats:");
tree = proto_item_add_subtree(item, ett_ndmp_file_stats);
}
/* invalids */
offset = dissect_file_invalids(tvb, offset, pinfo, tree);
/* file fs type */
proto_tree_add_item(tree, hf_ndmp_file_fs_type, tvb, offset, 4, FALSE);
offset += 4;
/* file type */
proto_tree_add_item(tree, hf_ndmp_file_type, tvb, offset, 4, FALSE);
offset += 4;
/* mtime */
ns.secs=tvb_get_ntohl(tvb, offset);
ns.nsecs=0;
proto_tree_add_time(tree, hf_ndmp_file_mtime, tvb, offset, 4, &ns);
offset += 4;
/* atime */
ns.secs=tvb_get_ntohl(tvb, offset);
ns.nsecs=0;
proto_tree_add_time(tree, hf_ndmp_file_atime, tvb, offset, 4, &ns);
offset += 4;
/* ctime */
ns.secs=tvb_get_ntohl(tvb, offset);
ns.nsecs=0;
proto_tree_add_time(tree, hf_ndmp_file_ctime, tvb, offset, 4, &ns);
offset += 4;
/* owner */
proto_tree_add_item(tree, hf_ndmp_file_owner, tvb, offset, 4, FALSE);
offset += 4;
/* group */
proto_tree_add_item(tree, hf_ndmp_file_group, tvb, offset, 4, FALSE);
offset += 4;
/*XXX here we should do proper dissection of mode for unix or
fattr for nt, call appropriate functions in nfs/smb*/
/* fattr */
proto_tree_add_item(tree, hf_ndmp_file_fattr, tvb, offset, 4, FALSE);
offset += 4;
/*file size*/
offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_file_size,
offset);
/* links */
proto_tree_add_item(tree, hf_ndmp_file_links, tvb, offset, 4, FALSE);
offset += 4;
proto_item_set_len(item, offset-old_offset);
return offset;
}
static int
dissect_file(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
{
proto_item* item = NULL;
proto_tree* tree = NULL;
int old_offset=offset;
if (parent_tree) {
Allow a length of -1 to be specified when adding FT_NONE and FT_PROTOCOL items to the protocol tree; it's interpreted as "the rest of the data in the tvbuff". This can be used if 1) the item covers the entire packet or the remaining payload in the packet or 2) the item's length won't be known until it's dissected, and will be then set with "proto_item_set_len()" - if an exception is thrown in the dissection, it means the item ran *past* the end of the tvbuff, so saying it runs to the end of the tvbuff is reasonable. Convert a number of "proto_tree_add_XXX()" calls using "tvb_length_remaining()", values derived from the result of "tvb_length()", or 0 (in the case of items whose length is unknown) to use -1 instead (using 0 means that if an exception is thrown, selecting the item highlights nothing; using -1 means it highlights all the data for that item that's available). In some places where "tvb_length()" or "tvb_length_remaining()" was used to determine how large a packet is, use "tvb_reported_length()" or "tvb_reported_length_remaining()", instead - the first two calls indicate how much captured data was in the packet, the latter two calls indicate how large the packet actually was (and the fact that using the latter could cause BoundsError exceptions to be thrown is a feature - if such an exception is thrown, the frame really *was* short, and it should be tagged as such). Replace some "proto_tree_add_XXX()" calls with equivalent "proto_tree_add_item()" calls. Fix some indentation. svn path=/trunk/; revision=4578
2002-01-20 22:12:39 +00:00
item = proto_tree_add_text(parent_tree, tvb, offset, -1,
"File:");
tree = proto_item_add_subtree(item, ett_ndmp_file);
}
/* file names */
offset = dissect_rpc_array(tvb, pinfo, tree, offset,
dissect_file_name, hf_ndmp_file_names);
/* file stats */
offset = dissect_rpc_array(tvb, pinfo, tree, offset,
dissect_file_stats, hf_ndmp_file_stats);
/* node */
proto_tree_add_item(tree, hf_ndmp_file_node, tvb, offset, 8, FALSE);
offset += 8;
/* fh_info */
proto_tree_add_item(tree, hf_ndmp_file_fh_info, tvb, offset, 8, FALSE);
offset += 8;
proto_item_set_len(item, offset-old_offset);
return offset;
}
static int
dissect_fh_add_file_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq _U_)
{
/* files */
offset = dissect_rpc_array(tvb, pinfo, tree, offset,
dissect_file, hf_ndmp_files);
return offset;
}
static int
dissect_dir(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
{
/* file names */
offset = dissect_rpc_array(tvb, pinfo, tree, offset,
dissect_file_name, hf_ndmp_file_names);
/* node */
proto_tree_add_item(tree, hf_ndmp_file_node, tvb, offset, 8, FALSE);
offset += 8;
/* parent */
proto_tree_add_item(tree, hf_ndmp_file_parent, tvb, offset, 8, FALSE);
offset += 8;
return offset;
}
static int
dissect_fh_add_dir_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq _U_)
{
/* dirs */
offset = dissect_rpc_array(tvb, pinfo, tree, offset,
dissect_dir, hf_ndmp_dirs);
return offset;
}
static int
dissect_node(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
{
/* file stats */
offset = dissect_rpc_array(tvb, pinfo, tree, offset,
dissect_file_stats, hf_ndmp_file_stats);
/* node */
proto_tree_add_item(tree, hf_ndmp_file_node, tvb, offset, 8, FALSE);
offset += 8;
/* fh_info */
proto_tree_add_item(tree, hf_ndmp_file_fh_info, tvb, offset, 8, FALSE);
offset += 8;
return offset;
}
static int
dissect_fh_add_node_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq _U_)
{
/* node */
offset = dissect_rpc_array(tvb, pinfo, tree, offset,
dissect_node, hf_ndmp_nodes);
return offset;
}
static int
dissect_data_start_backup_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq _U_)
{
/*butype name*/
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_butype_name, offset, NULL);
/* default env */
offset = dissect_rpc_array(tvb, pinfo, tree, offset,
dissect_default_env, hf_ndmp_butype_default_env);
return offset;
}
static int
dissect_nlist(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *tree)
{
/*original path*/
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_bu_original_path, offset, NULL);
/*destination dir*/
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_bu_destination_dir, offset, NULL);
if(ndmp_protocol_version==NDMP_PROTOCOL_V2){
/* just 2 reserved bytes (4 with padding) */
offset += 4;
} else {
/*new name*/
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_bu_new_name, offset, NULL);
/*other name*/
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_bu_other_name, offset, NULL);
/* node */
proto_tree_add_item(tree, hf_ndmp_file_node, tvb, offset, 8, FALSE);
offset += 8;
}
/* fh_info */
proto_tree_add_item(tree, hf_ndmp_file_fh_info, tvb, offset, 8, FALSE);
offset += 8;
return offset;
}
static int
dissect_data_start_recover_request(tvbuff_t *tvb, int offset,
packet_info *pinfo, proto_tree *tree, guint32 seq _U_)
{
if(ndmp_protocol_version==NDMP_PROTOCOL_V2){
/* ndmp addr */
offset=dissect_ndmp_addr(tvb, offset, pinfo, tree);
}
/* default env */
offset = dissect_rpc_array(tvb, pinfo, tree, offset,
dissect_default_env, hf_ndmp_butype_default_env);
/* nlist */
offset = dissect_rpc_array(tvb, pinfo, tree, offset,
dissect_nlist, hf_ndmp_nlist);
/*butype name*/
offset = dissect_rpc_string(tvb, tree,
hf_ndmp_butype_name, offset, NULL);
return offset;
}
static int
dissect_data_get_env_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq)
{
/* error */
offset=dissect_error(tvb, offset, pinfo, tree, seq);
/* default env */
offset = dissect_rpc_array(tvb, pinfo, tree, offset,
dissect_default_env, hf_ndmp_butype_default_env);
return offset;
}
static const true_false_string tfs_ndmp_state_invalid_ebr = {
"Estimated Bytes Remaining is INVALID",
"Estimated Bytes Remaining is valid"
};
static const true_false_string tfs_ndmp_state_invalid_etr = {
"Estimated Time Remaining is INVALID",
"Estimated Time Remaining is valid"
};
static int
dissect_state_invalids(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *parent_tree)
{
proto_item* item = NULL;
proto_tree* tree = NULL;
guint32 flags;
flags=tvb_get_ntohl(tvb, offset);
if (parent_tree) {
item = proto_tree_add_text(parent_tree, tvb, offset, 4,
"Invalids: 0x%08x", flags);
tree = proto_item_add_subtree(item, ett_ndmp_state_invalids);
}
proto_tree_add_boolean(tree, hf_ndmp_state_invalid_etr,
tvb, offset, 4, flags);
proto_tree_add_boolean(tree, hf_ndmp_state_invalid_ebr,
tvb, offset, 4, flags);
offset+=4;
return offset;
}
#define NDMP_DATA_OP_NOACTION 0
#define NDMP_DATA_OP_BACKUP 1
#define NDMP_DATA_OP_RESTORE 2
static const value_string bu_operation_vals[] = {
{NDMP_DATA_OP_NOACTION, "NOACTION"},
{NDMP_DATA_OP_BACKUP, "BACKUP"},
{NDMP_DATA_OP_RESTORE, "RESTORE"},
{0, NULL}
};
#define NDMP_DATA_STATE_IDLE 0
#define NDMP_DATA_STATE_ACTIVE 1
#define NDMP_DATA_STATE_HALTED 2
#define NDMP_DATA_STATE_LISTEN 3
#define NDMP_DATA_STATE_CONNECTED 4
static const value_string data_state_vals[] = {
{NDMP_DATA_STATE_IDLE, "IDLE"},
{NDMP_DATA_STATE_ACTIVE, "ACTIVE"},
{NDMP_DATA_STATE_HALTED, "HALTED"},
{NDMP_DATA_STATE_LISTEN, "LISTEN"},
{NDMP_DATA_STATE_CONNECTED, "CONNECTED"},
{0, NULL}
};
#define NDMP_DATA_HALTED_NA 0
#define NDMP_DATA_HALTED_SUCCESSFUL 1
#define NDMP_DATA_HALTED_ABORTED 2
#define NDMP_DATA_HALTED_INTERNAL_ERROR 3
#define NDMP_DATA_HALTED_CONNECT_ERROR 4
static const value_string data_halted_vals[] = {
{NDMP_DATA_HALTED_NA, "HALTED_NA"},
{NDMP_DATA_HALTED_SUCCESSFUL, "HALTED_SUCCESSFUL"},
{NDMP_DATA_HALTED_ABORTED, "HALTED_ABORTED"},
{NDMP_DATA_HALTED_INTERNAL_ERROR, "HALTED_INTERNAL_ERROR"},
{NDMP_DATA_HALTED_CONNECT_ERROR, "HALTED_CONNECT_ERROR"},
{0, NULL}
};
static int
dissect_data_get_state_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq)
{
nstime_t ns;
/* invalids */
offset = dissect_state_invalids(tvb, offset, pinfo, tree);
/* error */
offset=dissect_error(tvb, offset, pinfo, tree, seq);
/* operation */
proto_tree_add_item(tree, hf_ndmp_bu_operation, tvb, offset, 4, FALSE);
offset += 4;
/* state */
proto_tree_add_item(tree, hf_ndmp_data_state, tvb, offset, 4, FALSE);
offset += 4;
/* halted reason */
proto_tree_add_item(tree, hf_ndmp_data_halted, tvb, offset, 4, FALSE);
offset += 4;
/*bytes processed*/
offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_data_bytes_processed,
offset);
/*est bytes remain*/
offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_data_est_bytes_remain,
offset);
/* est time remain */
ns.secs=tvb_get_ntohl(tvb, offset);
ns.nsecs=0;
proto_tree_add_time(tree, hf_ndmp_data_est_time_remain, tvb, offset, 4, &ns);
offset += 4;
/* ndmp addr */
offset=dissect_ndmp_addr(tvb, offset, pinfo, tree);
/* window offset */
proto_tree_add_item(tree, hf_ndmp_window_offset, tvb, offset, 8, FALSE);
offset += 8;
/* window length */
proto_tree_add_item(tree, hf_ndmp_window_length, tvb, offset, 8, FALSE);
offset += 8;
return offset;
}
typedef struct _ndmp_command {
guint32 cmd;
int (*request) (tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq);
int (*response)(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint32 seq);
} ndmp_command;
static const ndmp_command ndmp_commands[] = {
{NDMP_CONFIG_GET_HOST_INFO,
NULL, dissect_ndmp_get_host_info_reply},
{NDMP_CONFIG_GET_CONNECTION_TYPE,
NULL, dissect_ndmp_config_get_connection_type_reply},
{NDMP_CONFIG_GET_AUTH_ATTR,
dissect_get_auth_type_request, dissect_auth_attr_msg},
{NDMP_CONFIG_GET_BUTYPE_INFO,
NULL, dissect_get_butype_info_reply},
{NDMP_CONFIG_GET_FS_INFO,
NULL, dissect_get_fs_info_reply},
{NDMP_CONFIG_GET_TAPE_INFO,
NULL, dissect_get_tape_info_reply},
{NDMP_CONFIG_GET_SCSI_INFO,
NULL, dissect_get_scsi_info_reply},
{NDMP_CONFIG_GET_SERVER_INFO,
NULL, dissect_get_server_info_reply},
{NDMP_SCSI_OPEN,
dissect_scsi_open_request, dissect_error},
{NDMP_SCSI_CLOSE,
NULL, dissect_error},
{NDMP_SCSI_GET_STATE,
NULL, dissect_scsi_get_state_reply},
{NDMP_SCSI_SET_TARGET,
dissect_scsi_set_state_request, dissect_error},
{NDMP_SCSI_RESET_DEVICE,
NULL, dissect_error},
{NDMP_SCSI_RESET_BUS,
NULL, dissect_error},
{NDMP_SCSI_EXECUTE_CDB,
dissect_execute_cdb_request_mc, dissect_execute_cdb_reply},
{NDMP_TAPE_OPEN,
dissect_tape_open_request, dissect_error},
{NDMP_TAPE_CLOSE,
NULL, dissect_error},
{NDMP_TAPE_GET_STATE,
NULL, dissect_tape_get_state_reply},
{NDMP_TAPE_MTIO,
dissect_tape_mtio_request, dissect_tape_mtio_reply},
{NDMP_TAPE_WRITE,
dissect_tape_write_request, dissect_tape_write_reply},
{NDMP_TAPE_READ,
dissect_tape_read_request, dissect_tape_read_reply},
{NDMP_TAPE_EXECUTE_CDB,
dissect_execute_cdb_request_tape, dissect_execute_cdb_reply},
{NDMP_DATA_GET_STATE,
NULL, dissect_data_get_state_reply},
{NDMP_DATA_START_BACKUP,
dissect_data_start_backup_request, dissect_error },
{NDMP_DATA_START_RECOVER,
dissect_data_start_recover_request, dissect_error },
{NDMP_DATA_ABORT,
NULL, dissect_error},
{NDMP_DATA_GET_ENV,
NULL, dissect_data_get_env_reply},
{NDMP_DATA_STOP,
NULL, dissect_error},
{NDMP_DATA_LISTEN,
dissect_ndmp_addr_msg, dissect_mover_listen_reply},
{NDMP_DATA_CONNECT,
dissect_ndmp_addr_msg, dissect_error},
{NDMP_NOTIFY_DATA_HALTED,
dissect_notify_data_halted_request, NULL},
{NDMP_NOTIFY_CONNECTED,
dissect_notify_connected_request, NULL},
{NDMP_NOTIFY_MOVER_HALTED,
dissect_notify_data_halted_request, NULL},
{NDMP_NOTIFY_MOVER_PAUSED,
dissect_notify_mover_paused_request, NULL},
{NDMP_NOTIFY_DATA_READ,
dissect_mover_set_window_request, NULL},
{NDMP_LOG_FILE,
dissect_log_file_request, NULL},
{NDMP_LOG_MESSAGE,
dissect_log_message_request, NULL},
{NDMP_FH_ADD_FILE,
dissect_fh_add_file_request, NULL},
{NDMP_FH_ADD_DIR,
dissect_fh_add_dir_request, NULL},
{NDMP_FH_ADD_NODE,
dissect_fh_add_node_request, NULL},
{NDMP_CONNECT_OPEN,
dissect_connect_open_request, dissect_error},
{NDMP_CONNECT_CLIENT_AUTH,
dissect_connect_client_auth_request, dissect_error},
{NDMP_CONNECT_CLOSE,
NULL,NULL},
{NDMP_CONNECT_SERVER_AUTH,
dissect_auth_attr_msg, dissect_connect_server_auth_reply},
{NDMP_MOVER_GET_STATE,
NULL, dissect_mover_get_state_reply},
{NDMP_MOVER_LISTEN,
dissect_mover_listen_request, dissect_mover_listen_reply},
{NDMP_MOVER_CONTINUE,
NULL, dissect_error},
{NDMP_MOVER_ABORT,
NULL, dissect_error},
{NDMP_MOVER_STOP,
NULL, dissect_error},
{NDMP_MOVER_SET_WINDOW,
dissect_mover_set_window_request, dissect_error},
{NDMP_MOVER_READ,
dissect_mover_set_window_request, dissect_error},
{NDMP_MOVER_CLOSE,
NULL, dissect_error},
{NDMP_MOVER_SET_RECORD_SIZE,
dissect_mover_set_record_size_request, dissect_error},
{NDMP_MOVER_CONNECT,
dissect_mover_connect_request, dissect_error},
{0, NULL,NULL}
};
static int
dissect_ndmp_header(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, struct ndmp_header *nh)
{
proto_item* item = NULL;
proto_tree* tree = NULL;
nstime_t ns;
if (parent_tree) {
item = proto_tree_add_item(parent_tree, hf_ndmp_header, tvb,
offset, 24, FALSE);
tree = proto_item_add_subtree(item, ett_ndmp_header);
}
/* sequence number */
proto_tree_add_uint(tree, hf_ndmp_sequence, tvb, offset, 4, nh->seq);
offset += 4;
/* timestamp */
ns.secs=nh->time;
ns.nsecs=0;
proto_tree_add_time(tree, hf_ndmp_timestamp, tvb, offset, 4, &ns);
offset += 4;
/* Message Type */
proto_tree_add_uint(tree, hf_ndmp_msgtype, tvb, offset, 4, nh->type);
offset += 4;
/* Message */
proto_tree_add_uint(tree, hf_ndmp_msg, tvb, offset, 4, nh->msg);
offset += 4;
/* Reply sequence number */
proto_tree_add_uint(tree, hf_ndmp_reply_sequence, tvb, offset, 4, nh->rep_seq);
offset += 4;
/* error */
offset=dissect_error(tvb, offset, pinfo, tree, nh->seq);
if (check_col(pinfo->cinfo, COL_INFO)){
col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
val_to_str(nh->msg, msg_vals, "Unknown Message (0x%02x)"),
val_to_str(nh->type, msg_type_vals, "Unknown Type (0x%02x)")
);
}
return offset;
}
static int
dissect_ndmp_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, struct ndmp_header *nh)
{
int i;
proto_item *cmd_item=NULL;
proto_tree *cmd_tree=NULL;
offset=dissect_ndmp_header(tvb, offset, pinfo, tree, nh);
for(i=0;ndmp_commands[i].cmd!=0;i++){
if(ndmp_commands[i].cmd==nh->msg){
break;
}
}
if(ndmp_commands[i].cmd==0){
/* we do not know this message */
proto_tree_add_text(tree, tvb, offset, -1, "Unknown type of NDMP message: 0x%02x", nh->msg);
offset+=tvb_length_remaining(tvb, offset);
return offset;
}
if (tvb_reported_length_remaining(tvb, offset) > 0) {
if(tree){
cmd_item = proto_tree_add_text(tree, tvb, offset, -1,
msg_vals[i].strptr);
cmd_tree = proto_item_add_subtree(cmd_item, ett_ndmp);
}
}
if(nh->type==NDMP_MESSAGE_REQUEST){
if(ndmp_commands[i].request){
offset=ndmp_commands[i].request(tvb, offset, pinfo, cmd_tree,
nh->seq);
}
} else {
if(ndmp_commands[i].response){
offset=ndmp_commands[i].response(tvb, offset, pinfo, cmd_tree,
nh->rep_seq);
}
}
return offset;
}
static gboolean
dissect_ndmp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
tvbuff_t *frag_tvb, fragment_data *ipfd_head, gboolean is_tcp,
guint32 rpc_rm, gboolean first_pdu)
{
int offset = (is_tcp && tvb == frag_tvb) ? 4 : 0;
guint32 size;
struct ndmp_header nh;
proto_item *ndmp_item = NULL;
proto_tree *ndmp_tree = NULL;
/* size of this NDMP PDU */
size = tvb_length_remaining(tvb, offset);
if (size < 24) {
/* too short to be NDMP */
return FALSE;
}
/*
* Check the NDMP header, if we have it.
*/
nh.seq = tvb_get_ntohl(tvb, offset);
nh.time = tvb_get_ntohl(tvb, offset+4);
nh.type = tvb_get_ntohl(tvb, offset+8);
nh.msg = tvb_get_ntohl(tvb, offset+12);
nh.rep_seq = tvb_get_ntohl(tvb, offset+16);
nh.err = tvb_get_ntohl(tvb, offset+20);
if (nh.type > 1)
return FALSE;
if (nh.msg > 0xa09 || nh.msg == 0)
return FALSE;
if (nh.err > 0x17)
return FALSE;
/*
* Check if this is the last fragment.
*/
if (!(rpc_rm & RPC_RM_LASTFRAG)) {
/*
* This isn't the last fragment.
* If we're doing reassembly, just return
* TRUE to indicate that this looks like
* the beginning of an NDMP message,
* and let them do reassembly.
*/
if (ndmp_defragment)
return TRUE;
}
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "NDMP");
if (check_col(pinfo->cinfo, COL_INFO)) {
if (first_pdu)
col_clear(pinfo->cinfo, COL_INFO);
else
col_append_fstr(pinfo->cinfo, COL_INFO, "; ");
}
if (tree) {
ndmp_item = proto_tree_add_item(tree, proto_ndmp,
tvb, 0, -1, FALSE);
ndmp_tree = proto_item_add_subtree(ndmp_item, ett_ndmp);
if (is_tcp) {
show_rpc_fraginfo(tvb, frag_tvb, ndmp_tree, rpc_rm,
ipfd_head, pinfo);
}
}
/*
* We cannot trust what dissect_ndmp_cmd() tells us, as there
* are implementations which pad some additional data after
* the PDU. We MUST use size.
*/
dissect_ndmp_cmd(tvb, offset, pinfo, ndmp_tree, &nh);
return TRUE;
}
static void
dissect_ndmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
int offset = 0;
int len;
gboolean first_pdu = TRUE;
while (tvb_reported_length_remaining(tvb, offset) != 0) {
/*
* Process this fragment.
*/
len = dissect_rpc_fragment(tvb, offset, pinfo, tree,
dissect_ndmp_message, FALSE, proto_ndmp, ett_ndmp,
ndmp_defragment, first_pdu);
first_pdu = FALSE;
if (len < 0) {
/*
* We need more data from the TCP stream for
* this fragment.
*/
return;
}
if (len == 0) {
/*
* It's not NDMP. Stop processing.
*/
break;
}
offset += len;
}
}
void
proto_register_ndmp(void)
{
static hf_register_info hf_ndmp[] = {
{ &hf_ndmp_header, {
"NDMP Header", "ndmp.header", FT_NONE, 0,
NULL, 0, "NDMP Header", HFILL }},
{ &hf_ndmp_sequence, {
"Sequence", "ndmp.sequence", FT_UINT32, BASE_DEC,
NULL, 0, "Sequence number for NDMP PDU", HFILL }},
{ &hf_ndmp_reply_sequence, {
"Reply Sequence", "ndmp.reply_sequence", FT_UINT32, BASE_DEC,
NULL, 0, "Reply Sequence number for NDMP PDU", HFILL }},
{ &hf_ndmp_timestamp, {
"Time", "ndmp.timestamp", FT_ABSOLUTE_TIME, BASE_NONE,
NULL, 0, "Timestamp for this NDMP PDU", HFILL }},
{ &hf_ndmp_msgtype, {
"Type", "ndmp.msg_type", FT_UINT32, BASE_DEC,
VALS(msg_type_vals), 0, "Is this a Request or Response?", HFILL }},
{ &hf_ndmp_msg, {
"Message", "ndmp.msg", FT_UINT32, BASE_HEX,
VALS(msg_vals), 0, "Type of NDMP PDU", HFILL }},
{ &hf_ndmp_error, {
"Error", "ndmp.error", FT_UINT32, BASE_DEC,
VALS(error_vals), 0, "Error code for this NDMP PDU", HFILL }},
{ &hf_ndmp_version, {
"Version", "ndmp.version", FT_UINT32, BASE_DEC,
NULL, 0, "Version of NDMP protocol", HFILL }},
{ &hf_ndmp_hostname, {
"Hostname", "ndmp.hostname", FT_STRING, BASE_NONE,
NULL, 0, "Hostname", HFILL }},
{ &hf_ndmp_hostid, {
"HostID", "ndmp.hostid", FT_STRING, BASE_NONE,
NULL, 0, "HostID", HFILL }},
{ &hf_ndmp_os_type, {
"OS Type", "ndmp.os.type", FT_STRING, BASE_NONE,
NULL, 0, "OS Type", HFILL }},
{ &hf_ndmp_os_vers, {
"OS Version", "ndmp.os.version", FT_STRING, BASE_NONE,
NULL, 0, "OS Version", HFILL }},
{ &hf_ndmp_addr_types, {
"Addr Types", "ndmp.addr_types", FT_NONE, BASE_NONE,
NULL, 0, "List Of Address Types", HFILL }},
{ &hf_ndmp_addr_type, {
"Addr Type", "ndmp.addr_type", FT_UINT32, BASE_DEC,
VALS(addr_type_vals), 0, "Address Type", HFILL }},
{ &hf_ndmp_auth_type, {
"Auth Type", "ndmp.auth_type", FT_UINT32, BASE_DEC,
VALS(auth_type_vals), 0, "Authentication Type", HFILL }},
{ &hf_ndmp_auth_challenge, {
"Challenge", "ndmp.auth.challenge", FT_BYTES, BASE_HEX,
NULL, 0, "Authentication Challenge", HFILL }},
{ &hf_ndmp_auth_digest, {
"Digest", "ndmp.auth.digest", FT_BYTES, BASE_HEX,
NULL, 0, "Authentication Digest", HFILL }},
{ &hf_ndmp_butype_info, {
"Butype Info", "ndmp.butype.info", FT_NONE, BASE_NONE,
NULL, 0, "Butype Info", HFILL }},
{ &hf_ndmp_butype_name, {
"Butype Name", "ndmp.butype.name", FT_STRING, BASE_NONE,
NULL, 0, "Name of Butype", HFILL }},
{ &hf_ndmp_butype_default_env, {
"Default Env", "ndmp.butype.default_env", FT_NONE, BASE_NONE,
NULL, 0, "Default Env's for this Butype Info", HFILL }},
{ &hf_ndmp_butype_attr_backup_file_history, {
"", "ndmp.butype.attr.backup_file_history", FT_BOOLEAN, 32,
TFS(&tfs_butype_attr_backup_file_history), 0x00000001, "backup_file_history", HFILL }},
{ &hf_ndmp_butype_attr_backup_filelist, {
"", "ndmp.butype.attr.backup_filelist", FT_BOOLEAN, 32,
TFS(&tfs_butype_attr_backup_filelist), 0x00000002, "backup_filelist", HFILL }},
{ &hf_ndmp_butype_attr_recover_filelist, {
"", "ndmp.butype.attr.recover_filelist", FT_BOOLEAN, 32,
TFS(&tfs_butype_attr_recover_filelist), 0x00000004, "recover_filelist", HFILL }},
{ &hf_ndmp_butype_attr_backup_direct, {
"", "ndmp.butype.attr.backup_direct", FT_BOOLEAN, 32,
TFS(&tfs_butype_attr_backup_direct), 0x00000008, "backup_direct", HFILL }},
{ &hf_ndmp_butype_attr_recover_direct, {
"", "ndmp.butype.attr.recover_direct", FT_BOOLEAN, 32,
TFS(&tfs_butype_attr_recover_direct), 0x00000010, "recover_direct", HFILL }},
{ &hf_ndmp_butype_attr_backup_incremental, {
"", "ndmp.butype.attr.backup_incremental", FT_BOOLEAN, 32,
TFS(&tfs_butype_attr_backup_incremental), 0x00000020, "backup_incremental", HFILL }},
{ &hf_ndmp_butype_attr_recover_incremental, {
"", "ndmp.butype.attr.recover_incremental", FT_BOOLEAN, 32,
TFS(&tfs_butype_attr_recover_incremental), 0x00000040, "recover_incremental", HFILL }},
{ &hf_ndmp_butype_attr_backup_utf8, {
"", "ndmp.butype.attr.backup_utf8", FT_BOOLEAN, 32,
TFS(&tfs_butype_attr_backup_utf8), 0x00000080, "backup_utf8", HFILL }},
{ &hf_ndmp_butype_attr_recover_utf8, {
"", "ndmp.butype.attr.recover_utf8", FT_BOOLEAN, 32,
TFS(&tfs_butype_attr_recover_utf8), 0x00000100, "recover_utf8", HFILL }},
{ &hf_ndmp_butype_env_name, {
"Name", "ndmp.butype.env.name", FT_STRING, BASE_NONE,
NULL, 0, "Name for this env-variable", HFILL }},
{ &hf_ndmp_butype_env_value, {
"Value", "ndmp.butype.env.value", FT_STRING, BASE_NONE,
NULL, 0, "Value for this env-variable", HFILL }},
{ &hf_ndmp_fs_info, {
"FS Info", "ndmp.fs.info", FT_NONE, BASE_NONE,
NULL, 0, "FS Info", HFILL }},
{ &hf_ndmp_fs_invalid_total_size, {
"", "ndmp.fs.invalid.total_size", FT_BOOLEAN, 32,
TFS(&tfs_fs_invalid_total_size), 0x00000001, "If total size is invalid", HFILL }},
{ &hf_ndmp_fs_invalid_used_size, {
"", "ndmp.fs.invalid.used_size", FT_BOOLEAN, 32,
TFS(&tfs_fs_invalid_used_size), 0x00000002, "If used size is invalid", HFILL }},
{ &hf_ndmp_fs_invalid_avail_size, {
"", "ndmp.fs.invalid.avail_size", FT_BOOLEAN, 32,
TFS(&tfs_fs_invalid_avail_size), 0x00000004, "If available size is invalid", HFILL }},
{ &hf_ndmp_fs_invalid_total_inodes, {
"", "ndmp.fs.invalid.total_inodes", FT_BOOLEAN, 32,
TFS(&tfs_fs_invalid_total_inodes), 0x00000008, "If total number of inodes is invalid", HFILL }},
{ &hf_ndmp_fs_invalid_used_inodes, {
"", "ndmp.fs.invalid.used_inodes", FT_BOOLEAN, 32,
TFS(&tfs_fs_invalid_used_inodes), 0x00000010, "If used number of inodes is invalid", HFILL }},
{ &hf_ndmp_fs_fs_type, {
"Type", "ndmp.fs.type", FT_STRING, BASE_NONE,
NULL, 0, "Type of FS", HFILL }},
{ &hf_ndmp_fs_logical_device, {
"Logical Device", "ndmp.fs.logical_device", FT_STRING, BASE_NONE,
NULL, 0, "Name of logical device", HFILL }},
{ &hf_ndmp_fs_physical_device, {
"Physical Device", "ndmp.fs.physical_device", FT_STRING, BASE_NONE,
NULL, 0, "Name of physical device", HFILL }},
{ &hf_ndmp_fs_total_size, {
"Total Size", "ndmp.fs.total_size", FT_UINT64, BASE_DEC,
NULL, 0, "Total size of FS", HFILL }},
{ &hf_ndmp_fs_used_size, {
"Used Size", "ndmp.fs.used_size", FT_UINT64, BASE_DEC,
NULL, 0, "Total used size of FS", HFILL }},
{ &hf_ndmp_fs_avail_size, {
"Avail Size", "ndmp.fs.avail_size", FT_UINT64, BASE_DEC,
NULL, 0, "Total available size on FS", HFILL }},
{ &hf_ndmp_fs_total_inodes, {
"Total Inodes", "ndmp.fs.total_inodes", FT_UINT64, BASE_DEC,
NULL, 0, "Total number of inodes on FS", HFILL }},
{ &hf_ndmp_fs_used_inodes, {
"Used Inodes", "ndmp.fs.used_inodes", FT_UINT64, BASE_DEC,
NULL, 0, "Number of used inodes on FS", HFILL }},
{ &hf_ndmp_fs_env, {
"Env variables", "ndmp.fs.env", FT_NONE, BASE_NONE,
NULL, 0, "Environment variables for FS", HFILL }},
{ &hf_ndmp_fs_env_name, {
"Name", "ndmp.fs.env.name", FT_STRING, BASE_NONE,
NULL, 0, "Name for this env-variable", HFILL }},
{ &hf_ndmp_fs_env_value, {
"Value", "ndmp.fs.env.value", FT_STRING, BASE_NONE,
NULL, 0, "Value for this env-variable", HFILL }},
{ &hf_ndmp_fs_status, {
"Status", "ndmp.fs.status", FT_STRING, BASE_NONE,
NULL, 0, "Status for this FS", HFILL }},
{ &hf_ndmp_tape_info, {
"Tape Info", "ndmp.tape.info", FT_NONE, BASE_NONE,
NULL, 0, "Tape Info", HFILL }},
{ &hf_ndmp_tape_model, {
"Model", "ndmp.tape.model", FT_STRING, BASE_NONE,
NULL, 0, "Model of the TAPE drive", HFILL }},
{ &hf_ndmp_tape_dev_cap, {
"Device Capability", "ndmp.tape.dev_cap", FT_NONE, BASE_NONE,
NULL, 0, "Tape Device Capability", HFILL }},
{ &hf_ndmp_tape_device, {
"Device", "ndmp.tape.device", FT_STRING, BASE_NONE,
NULL, 0, "Name of TAPE Device", HFILL }},
{ &hf_ndmp_tape_attr_rewind, {
"", "ndmp.tape.attr.rewind", FT_BOOLEAN, 32,
TFS(&tfs_tape_attr_rewind), 0x00000001, "If this device supports rewind", HFILL }},
{ &hf_ndmp_tape_attr_unload, {
"", "ndmp.tape.attr.unload", FT_BOOLEAN, 32,
TFS(&tfs_tape_attr_unload), 0x00000002, "If this device supports unload", HFILL }},
{ &hf_ndmp_tape_capability, {
"Tape Capabilities", "ndmp.tape.capability", FT_NONE, BASE_NONE,
NULL, 0, "Tape Capabilities", HFILL }},
{ &hf_ndmp_tape_capability_name, {
"Name", "ndmp.tape.cap.name", FT_STRING, BASE_NONE,
NULL, 0, "Name for this env-variable", HFILL }},
{ &hf_ndmp_tape_capability_value, {
"Value", "ndmp.tape.cap.value", FT_STRING, BASE_NONE,
NULL, 0, "Value for this env-variable", HFILL }},
{ &hf_ndmp_scsi_info, {
"SCSI Info", "ndmp.scsi.info", FT_NONE, BASE_NONE,
NULL, 0, "SCSI Info", HFILL }},
{ &hf_ndmp_scsi_model, {
"Model", "ndmp.scsi.model", FT_STRING, BASE_NONE,
NULL, 0, "Model of the SCSI device", HFILL }},
{ &hf_ndmp_server_vendor, {
"Vendor", "ndmp.server.vendor", FT_STRING, BASE_NONE,
NULL, 0, "Name of vendor", HFILL }},
{ &hf_ndmp_server_product, {
"Product", "ndmp.server.product", FT_STRING, BASE_NONE,
NULL, 0, "Name of product", HFILL }},
{ &hf_ndmp_server_revision, {
"Revision", "ndmp.server.revision", FT_STRING, BASE_NONE,
NULL, 0, "Revision of this product", HFILL }},
{ &hf_ndmp_auth_types, {
"Auth types", "ndmp.auth.types", FT_NONE, BASE_NONE,
NULL, 0, "Auth types", HFILL }},
{ &hf_ndmp_scsi_device, {
"Device", "ndmp.scsi.device", FT_STRING, BASE_NONE,
NULL, 0, "Name of SCSI Device", HFILL }},
{ &hf_ndmp_scsi_controller, {
"Controller", "ndmp.scsi.controller", FT_UINT32, BASE_DEC,
NULL, 0, "Target Controller", HFILL }},
{ &hf_ndmp_scsi_id, {
"ID", "ndmp.scsi.id", FT_UINT32, BASE_DEC,
NULL, 0, "Target ID", HFILL }},
{ &hf_ndmp_scsi_lun, {
"LUN", "ndmp.scsi.lun", FT_UINT32, BASE_DEC,
NULL, 0, "Target LUN", HFILL }},
{ &hf_ndmp_execute_cdb_flags_data_in, {
"DATA_IN", "ndmp.execute_cdb.flags.data_in", FT_BOOLEAN, 32,
NULL, 0x00000001, "DATA_IN", HFILL }},
{ &hf_ndmp_execute_cdb_flags_data_out, {
"DATA_OUT", "ndmp.execute_cdb.flags.data_out", FT_BOOLEAN, 32,
NULL, 0x00000002, "DATA_OUT", HFILL }},
{ &hf_ndmp_execute_cdb_timeout, {
"Timeout", "ndmp.execute_cdb.timeout", FT_UINT32, BASE_DEC,
NULL, 0, "Reselect timeout, in milliseconds", HFILL }},
{ &hf_ndmp_execute_cdb_datain_len, {
"Data in length", "ndmp.execute_cdb.datain_len", FT_UINT32, BASE_DEC,
NULL, 0, "Expected length of data bytes to read", HFILL }},
{ &hf_ndmp_execute_cdb_cdb_len, {
"CDB length", "ndmp.execute_cdb.cdb_len", FT_UINT32, BASE_DEC,
NULL, 0, "Length of CDB", HFILL }},
{ &hf_ndmp_execute_cdb_dataout, {
"Data out", "ndmp.execute_cdb.dataout", FT_BYTES, BASE_NONE,
NULL, 0, "Data to be transferred to the SCSI device", HFILL }},
{ &hf_ndmp_execute_cdb_status, {
"Status", "ndmp.execute_cdb.status", FT_UINT8, BASE_DEC,
VALS(scsi_status_val), 0, "SCSI status", HFILL }},
{ &hf_ndmp_execute_cdb_dataout_len, {
"Data out length", "ndmp.execute_cdb.dataout_len", FT_UINT32, BASE_DEC,
NULL, 0, "Number of bytes transferred to the device", HFILL }},
{ &hf_ndmp_execute_cdb_datain, {
"Data in", "ndmp.execute_cdb.datain", FT_BYTES, BASE_NONE,
NULL, 0, "Data transferred from the SCSI device", HFILL }},
{ &hf_ndmp_execute_cdb_sns_len, {
"Sense data length", "ndmp.execute_cdb.sns_len", FT_UINT32, BASE_DEC,
NULL, 0, "Length of sense data", HFILL }},
{ &hf_ndmp_tape_open_mode, {
"Mode", "ndmp.tape.open_mode", FT_UINT32, BASE_DEC,
VALS(tape_open_mode_vals), 0, "Mode to open tape in", HFILL }},
{ &hf_ndmp_tape_invalid_file_num, {
"", "ndmp.tape.invalid.file_num", FT_BOOLEAN, 32,
TFS(&tfs_ndmp_tape_invalid_file_num), 0x00000001, "invalid_file_num", HFILL }},
{ &hf_ndmp_tape_invalid_soft_errors, {
"", "ndmp.tape.invalid.soft_errors", FT_BOOLEAN, 32,
TFS(&tfs_ndmp_tape_invalid_soft_errors), 0x00000002, "soft_errors", HFILL }},
{ &hf_ndmp_tape_invalid_block_size, {
"", "ndmp.tape.invalid.block_size", FT_BOOLEAN, 32,
TFS(&tfs_ndmp_tape_invalid_block_size), 0x00000004, "block_size", HFILL }},
{ &hf_ndmp_tape_invalid_block_no, {
"", "ndmp.tape.invalid.block_no", FT_BOOLEAN, 32,
TFS(&tfs_ndmp_tape_invalid_block_no), 0x00000008, "block_no", HFILL }},
{ &hf_ndmp_tape_invalid_total_space, {
"", "ndmp.tape.invalid.total_space", FT_BOOLEAN, 32,
TFS(&tfs_ndmp_tape_invalid_total_space), 0x00000010, "total_space", HFILL }},
{ &hf_ndmp_tape_invalid_space_remain, {
"", "ndmp.tape.invalid.space_remain", FT_BOOLEAN, 32,
TFS(&tfs_ndmp_tape_invalid_space_remain), 0x00000020, "space_remain", HFILL }},
{ &hf_ndmp_tape_invalid_partition, {
"", "ndmp.tape.invalid.partition", FT_BOOLEAN, 32,
TFS(&tfs_ndmp_tape_invalid_partition), 0x00000040, "partition", HFILL }},
{ &hf_ndmp_tape_flags_no_rewind, {
"", "ndmp.tape.flags.no_rewind", FT_BOOLEAN, 32,
TFS(&tfs_ndmp_tape_flags_no_rewind), 0x00000008, "no_rewind", HFILL, }},
{ &hf_ndmp_tape_flags_write_protect, {
"", "ndmp.tape.flags.write_protect", FT_BOOLEAN, 32,
TFS(&tfs_ndmp_tape_flags_write_protect), 0x00000010, "write_protect", HFILL, }},
{ &hf_ndmp_tape_flags_error, {
"", "ndmp.tape.flags.error", FT_BOOLEAN, 32,
TFS(&tfs_ndmp_tape_flags_error), 0x00000020, "error", HFILL, }},
{ &hf_ndmp_tape_flags_unload, {
"", "ndmp.tape.flags.unload", FT_BOOLEAN, 32,
TFS(&tfs_ndmp_tape_flags_unload), 0x00000040, "unload", HFILL, }},
{ &hf_ndmp_tape_file_num, {
"file_num", "ndmp.tape.status.file_num", FT_UINT32, BASE_DEC,
NULL, 0, "file_num", HFILL }},
{ &hf_ndmp_tape_soft_errors, {
"soft_errors", "ndmp.tape.status.soft_errors", FT_UINT32, BASE_DEC,
NULL, 0, "soft_errors", HFILL }},
{ &hf_ndmp_tape_block_size, {
"block_size", "ndmp.tape.status.block_size", FT_UINT32, BASE_DEC,
NULL, 0, "block_size", HFILL }},
{ &hf_ndmp_tape_block_no, {
"block_no", "ndmp.tape.status.block_no", FT_UINT32, BASE_DEC,
NULL, 0, "block_no", HFILL }},
{ &hf_ndmp_tape_total_space, {
"total_space", "ndmp.tape.status.total_space", FT_UINT64, BASE_DEC,
NULL, 0, "total_space", HFILL }},
{ &hf_ndmp_tape_space_remain, {
"space_remain", "ndmp.tape.status.space_remain", FT_UINT64, BASE_DEC,
NULL, 0, "space_remain", HFILL }},
{ &hf_ndmp_tape_partition, {
"partition", "ndmp.tape.status.partition", FT_UINT32, BASE_DEC,
NULL, 0, "partition", HFILL }},
{ &hf_ndmp_tape_mtio_op, {
"Operation", "ndmp.tape.mtio.op", FT_UINT32, BASE_DEC,
VALS(tape_mtio_vals), 0, "MTIO Operation", HFILL }},
{ &hf_ndmp_count, {
"Count", "ndmp.count", FT_UINT32, BASE_DEC,
NULL, 0, "Number of bytes/objects/operations", HFILL }},
{ &hf_ndmp_resid_count, {
"Resid Count", "ndmp.resid_count", FT_UINT32, BASE_DEC,
NULL, 0, "Number of remaining bytes/objects/operations", HFILL }},
{ &hf_ndmp_mover_state, {
"State", "ndmp.mover.state", FT_UINT32, BASE_DEC,
VALS(mover_state_vals), 0, "State of the selected mover", HFILL }},
{ &hf_ndmp_mover_pause, {
"Pause", "ndmp.mover.pause", FT_UINT32, BASE_DEC,
VALS(mover_pause_vals), 0, "Reason why the mover paused", HFILL }},
{ &hf_ndmp_halt, {
"Halt", "ndmp.halt", FT_UINT32, BASE_DEC,
VALS(halt_vals), 0, "Reason why it halted", HFILL }},
{ &hf_ndmp_record_size, {
"Record Size", "ndmp.record.size", FT_UINT32, BASE_DEC,
NULL, 0, "Record size in bytes", HFILL }},
{ &hf_ndmp_record_num, {
"Record Num", "ndmp.record.num", FT_UINT32, BASE_DEC,
NULL, 0, "Number of records", HFILL }},
{ &hf_ndmp_data_written, {
"Data Written", "ndmp.data.written", FT_UINT64, BASE_DEC,
NULL, 0, "Number of data bytes written", HFILL }},
{ &hf_ndmp_seek_position, {
"Seek Position", "ndmp.seek.position", FT_UINT64, BASE_DEC,
NULL, 0, "Current seek position on device", HFILL }},
{ &hf_ndmp_bytes_left_to_read, {
"Bytes left to read", "ndmp.bytes_left_to_read", FT_UINT64, BASE_DEC,
NULL, 0, "Number of bytes left to be read from the device", HFILL }},
{ &hf_ndmp_window_offset, {
"Window Offset", "ndmp.window.offset", FT_UINT64, BASE_DEC,
NULL, 0, "Offset to window in bytes", HFILL }},
{ &hf_ndmp_window_length, {
"Window Length", "ndmp.window.length", FT_UINT64, BASE_DEC,
NULL, 0, "Size of window in bytes", HFILL }},
{ &hf_ndmp_addr_ip, {
"IP Address", "ndmp.addr.ip", FT_IPv4, BASE_DEC,
NULL, 0, "IP Address", HFILL }},
{ &hf_ndmp_addr_tcp, {
"TCP Port", "ndmp.addr.tcp_port", FT_UINT32, BASE_DEC,
NULL, 0, "TCP Port", HFILL }},
{ &hf_ndmp_addr_fcal_loop_id, {
"Loop ID", "ndmp.addr.loop_id", FT_UINT32, BASE_HEX,
NULL, 0, "FCAL Loop ID", HFILL }},
{ &hf_ndmp_addr_ipc, {
"IPC", "ndmp.addr.ipc", FT_BYTES, BASE_HEX,
NULL, 0, "IPC identifier", HFILL }},
{ &hf_ndmp_mover_mode, {
"Mode", "ndmp.mover.mode", FT_UINT32, BASE_HEX,
VALS(mover_mode_vals), 0, "Mover Mode", HFILL }},
{ &hf_ndmp_file_name, {
"File", "ndmp.file", FT_STRING, BASE_NONE,
NULL, 0, "Name of File", HFILL }},
{ &hf_ndmp_nt_file_name, {
"NT File", "ndmp.file", FT_STRING, BASE_NONE,
NULL, 0, "NT Name of File", HFILL }},
{ &hf_ndmp_dos_file_name, {
"DOS File", "ndmp.file", FT_STRING, BASE_NONE,
NULL, 0, "DOS Name of File", HFILL }},
{ &hf_ndmp_log_type, {
"Type", "ndmp.log.type", FT_UINT32, BASE_HEX,
VALS(log_type_vals), 0, "Type of log entry", HFILL }},
{ &hf_ndmp_log_message_id, {
"Message ID", "ndmp.log.message.id", FT_UINT32, BASE_DEC,
NULL, 0, "ID of this log entry", HFILL }},
{ &hf_ndmp_log_message, {
"Message", "ndmp.log.message", FT_STRING, BASE_NONE,
NULL, 0, "Log entry", HFILL }},
{ &hf_ndmp_halt_reason, {
"Reason", "ndmp.halt.reason", FT_STRING, BASE_NONE,
NULL, 0, "Textual reason for why it halted", HFILL }},
{ &hf_ndmp_connected, {
"Connected", "ndmp.connected", FT_UINT32, BASE_DEC,
VALS(connected_vals), 0, "Status of connection", HFILL }},
{ &hf_ndmp_connected_reason, {
"Reason", "ndmp.connected.reason", FT_STRING, BASE_NONE,
NULL, 0, "Textual description of the connection status", HFILL }},
{ &hf_ndmp_auth_id, {
"ID", "ndmp.auth.id", FT_STRING, BASE_NONE,
NULL, 0, "ID of client authenticating", HFILL }},
{ &hf_ndmp_auth_password, {
"Password", "ndmp.auth.password", FT_STRING, BASE_NONE,
NULL, 0, "Password of client authenticating", HFILL }},
{ &hf_ndmp_data, {
"Data", "ndmp.data", FT_BYTES, BASE_HEX,
NULL, 0, "Data written/read", HFILL }},
{ &hf_ndmp_files, {
"Files", "ndmp.files", FT_NONE, 0,
NULL, 0, "List of files", HFILL }},
{ &hf_ndmp_file_names, {
"File Names", "ndmp.file.names", FT_NONE, 0,
NULL, 0, "List of file names", HFILL }},
{ &hf_ndmp_file_fs_type, {
"File FS Type", "ndmp.file.fs_type", FT_UINT32, BASE_DEC,
VALS(file_fs_type_vals), 0, "Type of file permissions (UNIX or NT)", HFILL }},
{ &hf_ndmp_file_type, {
"File Type", "ndmp.file.type", FT_UINT32, BASE_DEC,
VALS(file_type_vals), 0, "Type of file", HFILL }},
{ &hf_ndmp_file_stats, {
"File Stats", "ndmp.file.stats", FT_NONE, 0,
NULL, 0, "List of file stats", HFILL }},
{ &hf_ndmp_file_node, {
"Node", "ndmp.file.node", FT_UINT64, BASE_DEC,
NULL, 0, "Node used for direct access", HFILL }},
{ &hf_ndmp_file_parent, {
"Parent", "ndmp.file.parent", FT_UINT64, BASE_DEC,
NULL, 0, "Parent node(directory) for this node", HFILL }},
{ &hf_ndmp_file_fh_info, {
"FH Info", "ndmp.file.fh_info", FT_UINT64, BASE_DEC,
NULL, 0, "FH Info used for direct access", HFILL }},
{ &hf_ndmp_file_invalid_atime, {
"", "ndmp.file.invalid_atime", FT_BOOLEAN, 32,
TFS(&tfs_ndmp_file_invalid_atime), 0x00000001, "invalid_atime", HFILL, }},
{ &hf_ndmp_file_invalid_ctime, {
"", "ndmp.file.invalid_ctime", FT_BOOLEAN, 32,
TFS(&tfs_ndmp_file_invalid_ctime), 0x00000002, "invalid_ctime", HFILL, }},
{ &hf_ndmp_file_invalid_group, {
"", "ndmp.file.invalid_group", FT_BOOLEAN, 32,
TFS(&tfs_ndmp_file_invalid_group), 0x00000004, "invalid_group", HFILL, }},
{ &hf_ndmp_file_mtime, {
"mtime", "ndmp.file.mtime", FT_ABSOLUTE_TIME, BASE_NONE,
NULL, 0, "Timestamp for mtime for this file", HFILL }},
{ &hf_ndmp_file_atime, {
"atime", "ndmp.file.atime", FT_ABSOLUTE_TIME, BASE_NONE,
NULL, 0, "Timestamp for atime for this file", HFILL }},
{ &hf_ndmp_file_ctime, {
"ctime", "ndmp.file.ctime", FT_ABSOLUTE_TIME, BASE_NONE,
NULL, 0, "Timestamp for ctime for this file", HFILL }},
{ &hf_ndmp_file_owner, {
"Owner", "ndmp.file.owner", FT_UINT32, BASE_DEC,
NULL, 0, "UID for UNIX, owner for NT", HFILL }},
{ &hf_ndmp_file_group, {
"Group", "ndmp.file.group", FT_UINT32, BASE_DEC,
NULL, 0, "GID for UNIX, NA for NT", HFILL }},
{ &hf_ndmp_file_fattr, {
"Fattr", "ndmp.file.fattr", FT_UINT32, BASE_HEX,
NULL, 0, "Mode for UNIX, fattr for NT", HFILL }},
{ &hf_ndmp_file_size, {
"Size", "ndmp.file.size", FT_UINT64, BASE_DEC,
NULL, 0, "File Size", HFILL }},
{ &hf_ndmp_file_links, {
"Links", "ndmp.file.links", FT_UINT32, BASE_DEC,
NULL, 0, "Number of links to this file", HFILL }},
{ &hf_ndmp_dirs, {
"Dirs", "ndmp.dirs", FT_NONE, 0,
NULL, 0, "List of directories", HFILL }},
{ &hf_ndmp_nodes, {
"Nodes", "ndmp.nodes", FT_NONE, 0,
NULL, 0, "List of nodes", HFILL }},
{ &hf_ndmp_nlist, {
"Nlist", "ndmp.nlist", FT_NONE, 0,
NULL, 0, "List of names", HFILL }},
{ &hf_ndmp_bu_original_path, {
"Original Path", "ndmp.bu.original_path", FT_STRING, BASE_NONE,
NULL, 0, "Original path where backup was created", HFILL }},
{ &hf_ndmp_bu_destination_dir, {
"Destination Dir", "ndmp.bu.destination_dir", FT_STRING, BASE_NONE,
NULL, 0, "Destination directory to restore backup to", HFILL }},
{ &hf_ndmp_bu_new_name, {
"New Name", "ndmp.bu.new_name", FT_STRING, BASE_NONE,
NULL, 0, "New Name", HFILL }},
{ &hf_ndmp_bu_other_name, {
"Other Name", "ndmp.bu.other_name", FT_STRING, BASE_NONE,
NULL, 0, "Other Name", HFILL }},
{ &hf_ndmp_state_invalid_ebr, {
"", "ndmp.bu.state.invalid_ebr", FT_BOOLEAN, 32,
TFS(&tfs_ndmp_state_invalid_ebr), 0x00000001, "Whether EstimatedBytesLeft is valid or not", HFILL, }},
{ &hf_ndmp_state_invalid_etr, {
"", "ndmp.bu.state.invalid_etr", FT_BOOLEAN, 32,
TFS(&tfs_ndmp_state_invalid_etr), 0x00000002, "Whether EstimatedTimeLeft is valid or not", HFILL, }},
{ &hf_ndmp_bu_operation, {
"Operation", "ndmp.bu.operation", FT_UINT32, BASE_DEC,
VALS(bu_operation_vals), 0, "BU Operation", HFILL, }},
{ &hf_ndmp_data_state, {
"State", "ndmp.data.state", FT_UINT32, BASE_DEC,
VALS(data_state_vals), 0, "Data state", HFILL, }},
{ &hf_ndmp_data_halted, {
"Halted Reason", "ndmp.data.halted", FT_UINT32, BASE_DEC,
VALS(data_halted_vals), 0, "Data halted reason", HFILL, }},
{ &hf_ndmp_data_bytes_processed, {
"Bytes Processed", "ndmp.data.bytes_processed", FT_UINT64, BASE_DEC,
NULL, 0, "Number of bytes processed", HFILL }},
{ &hf_ndmp_data_est_bytes_remain, {
"Est Bytes Remain", "ndmp.data.est_bytes_remain", FT_UINT64, BASE_DEC,
NULL, 0, "Estimated number of bytes remaining", HFILL }},
{ &hf_ndmp_data_est_time_remain, {
"Est Time Remain", "ndmp.data.est_time_remain", FT_RELATIVE_TIME, BASE_DEC,
NULL, 0, "Estimated time remaining", HFILL }},
};
static gint *ett[] = {
&ett_ndmp,
&ett_ndmp_header,
&ett_ndmp_butype_attrs,
&ett_ndmp_fs_invalid,
&ett_ndmp_tape_attr,
&ett_ndmp_execute_cdb_flags,
&ett_ndmp_execute_cdb_cdb,
&ett_ndmp_execute_cdb_sns,
&ett_ndmp_execute_cdb_payload,
&ett_ndmp_tape_invalid,
&ett_ndmp_tape_flags,
&ett_ndmp_addr,
&ett_ndmp_file,
&ett_ndmp_file_name,
&ett_ndmp_file_stats,
&ett_ndmp_file_invalids,
&ett_ndmp_state_invalids,
};
module_t *ndmp_module;
proto_ndmp = proto_register_protocol("Network Data Management Protocol", "NDMP", "ndmp");
proto_register_field_array(proto_ndmp, hf_ndmp, array_length(hf_ndmp));
proto_register_subtree_array(ett, array_length(ett));
/* desegmentation */
ndmp_module = prefs_register_protocol(proto_ndmp, NULL);
prefs_register_enum_preference(ndmp_module,
"protocol_version",
"Protocol version",
"Version of the NDMP protocol",
&ndmp_protocol_version,
ndmp_protocol_versions,
FALSE);
prefs_register_bool_preference(ndmp_module, "desegment",
"Desegment all NDMP messages spanning multiple TCP segments",
"Whether the dissector should desegment NDMP messages",
&ndmp_desegment);
prefs_register_bool_preference(ndmp_module, "defragment",
"Defragment all multi-fragment NDMP messages",
"Whether the dissector should defragment multi-fragment NDMP messages",
&ndmp_defragment);
}
void
proto_reg_handoff_ndmp(void)
{
dissector_handle_t ndmp_handle;
ndmp_handle = create_dissector_handle(dissect_ndmp, proto_ndmp);
dissector_add("tcp.port",TCP_PORT_NDMP, ndmp_handle);
}