Put "WTP" into the Info column for segmented invoke/result PDUs on which
[obnox/wireshark/wip.git] / packet-ndmp.c
1 /* packet-ndmp.c
2  * Routines for NDMP dissection
3  * 2001 Ronnie Sahlberg (see AUTHORS for email)
4  *
5  * $Id: packet-ndmp.c,v 1.24 2003/04/21 08:13:18 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 /* see www.ndmp.org for protocol specifications.
27    this file implements version 3 of ndmp
28 */
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <stdio.h>
35 #include <string.h>
36 #include <glib.h>
37
38 #include <epan/packet.h>
39 #include <epan/conversation.h>
40 #include "packet-rpc.h"
41 #include "packet-scsi.h"
42 #include "packet-frame.h"
43 #include "prefs.h"
44 #include "reassemble.h"
45 #include "rpc_defrag.h"
46
47 #define TCP_PORT_NDMP 10000
48
49 static int proto_ndmp = -1;
50 static int hf_ndmp_version = -1;
51 static int hf_ndmp_header = -1;
52 static int hf_ndmp_sequence = -1;
53 static int hf_ndmp_reply_sequence = -1;
54 static int hf_ndmp_timestamp = -1;
55 static int hf_ndmp_msgtype = -1;
56 static int hf_ndmp_msg = -1;
57 static int hf_ndmp_error = -1;
58 static int hf_ndmp_hostname = -1;
59 static int hf_ndmp_os_type = -1;
60 static int hf_ndmp_os_vers = -1;
61 static int hf_ndmp_hostid = -1;
62 static int hf_ndmp_addr_types = -1;
63 static int hf_ndmp_addr_type = -1;
64 static int hf_ndmp_auth_type = -1;
65 static int hf_ndmp_auth_types = -1;
66 static int hf_ndmp_auth_challenge = -1;
67 static int hf_ndmp_auth_digest = -1;
68 static int hf_ndmp_auth_id = -1;
69 static int hf_ndmp_auth_password = -1;
70 static int hf_ndmp_butype_info = -1;
71 static int hf_ndmp_butype_name = -1;
72 static int hf_ndmp_butype_default_env = -1;
73 static int hf_ndmp_butype_attr_backup_file_history = -1;
74 static int hf_ndmp_butype_attr_backup_filelist = -1;
75 static int hf_ndmp_butype_attr_recover_filelist = -1;
76 static int hf_ndmp_butype_attr_backup_direct = -1;
77 static int hf_ndmp_butype_attr_recover_direct = -1;
78 static int hf_ndmp_butype_attr_backup_incremental = -1;
79 static int hf_ndmp_butype_attr_recover_incremental = -1;
80 static int hf_ndmp_butype_attr_backup_utf8 = -1;
81 static int hf_ndmp_butype_attr_recover_utf8 = -1;
82 static int hf_ndmp_butype_env_name = -1;
83 static int hf_ndmp_butype_env_value = -1;
84 static int hf_ndmp_fs_info = -1;
85 static int hf_ndmp_fs_invalid_total_size = -1;
86 static int hf_ndmp_fs_invalid_used_size = -1;
87 static int hf_ndmp_fs_invalid_avail_size = -1;
88 static int hf_ndmp_fs_invalid_total_inodes = -1;
89 static int hf_ndmp_fs_invalid_used_inodes = -1;
90 static int hf_ndmp_fs_fs_type = -1;
91 static int hf_ndmp_fs_logical_device = -1;
92 static int hf_ndmp_fs_physical_device = -1;
93 static int hf_ndmp_fs_total_size = -1;
94 static int hf_ndmp_fs_used_size = -1;
95 static int hf_ndmp_fs_avail_size = -1;
96 static int hf_ndmp_fs_total_inodes = -1;
97 static int hf_ndmp_fs_used_inodes = -1;
98 static int hf_ndmp_fs_env = -1;
99 static int hf_ndmp_fs_env_name = -1;
100 static int hf_ndmp_fs_env_value = -1;
101 static int hf_ndmp_fs_status = -1;
102 static int hf_ndmp_tape_info = -1;
103 static int hf_ndmp_tape_model = -1;
104 static int hf_ndmp_tape_dev_cap = -1;
105 static int hf_ndmp_tape_device = -1;
106 static int hf_ndmp_tape_open_mode = -1;
107 static int hf_ndmp_tape_attr_rewind = -1;
108 static int hf_ndmp_tape_attr_unload = -1;
109 static int hf_ndmp_tape_capability = -1;
110 static int hf_ndmp_tape_capability_name = -1;
111 static int hf_ndmp_tape_capability_value = -1;
112 static int hf_ndmp_scsi_info = -1;
113 static int hf_ndmp_scsi_model = -1;
114 static int hf_ndmp_server_vendor = -1;
115 static int hf_ndmp_server_product = -1;
116 static int hf_ndmp_server_revision = -1;
117 static int hf_ndmp_scsi_device = -1;
118 static int hf_ndmp_scsi_controller = -1;
119 static int hf_ndmp_scsi_id = -1;
120 static int hf_ndmp_scsi_lun = -1;
121 static int hf_ndmp_execute_cdb_flags_data_in = -1;
122 static int hf_ndmp_execute_cdb_flags_data_out = -1;
123 static int hf_ndmp_execute_cdb_timeout = -1;
124 static int hf_ndmp_execute_cdb_datain_len = -1;
125 static int hf_ndmp_execute_cdb_cdb_len = -1;
126 static int hf_ndmp_execute_cdb_dataout = -1;
127 static int hf_ndmp_execute_cdb_status = -1;
128 static int hf_ndmp_execute_cdb_dataout_len = -1;
129 static int hf_ndmp_execute_cdb_datain = -1;
130 static int hf_ndmp_execute_cdb_sns_len = -1;
131 static int hf_ndmp_tape_invalid_file_num = -1;
132 static int hf_ndmp_tape_invalid_soft_errors = -1;
133 static int hf_ndmp_tape_invalid_block_size = -1;
134 static int hf_ndmp_tape_invalid_block_no = -1;
135 static int hf_ndmp_tape_invalid_total_space = -1;
136 static int hf_ndmp_tape_invalid_space_remain = -1;
137 static int hf_ndmp_tape_invalid_partition = -1;
138 static int hf_ndmp_tape_flags_no_rewind = -1;
139 static int hf_ndmp_tape_flags_write_protect = -1;
140 static int hf_ndmp_tape_flags_error = -1;
141 static int hf_ndmp_tape_flags_unload = -1;
142 static int hf_ndmp_tape_file_num = -1;
143 static int hf_ndmp_tape_soft_errors = -1;
144 static int hf_ndmp_tape_block_size = -1;
145 static int hf_ndmp_tape_block_no = -1;
146 static int hf_ndmp_tape_total_space = -1;
147 static int hf_ndmp_tape_space_remain = -1;
148 static int hf_ndmp_tape_partition = -1;
149 static int hf_ndmp_tape_mtio_op = -1;
150 static int hf_ndmp_count = -1;
151 static int hf_ndmp_resid_count = -1;
152 static int hf_ndmp_mover_state = -1;
153 static int hf_ndmp_mover_pause = -1;
154 static int hf_ndmp_halt = -1;
155 static int hf_ndmp_halt_reason = -1;
156 static int hf_ndmp_record_size = -1;
157 static int hf_ndmp_record_num = -1;
158 static int hf_ndmp_data_written = -1;
159 static int hf_ndmp_seek_position = -1;
160 static int hf_ndmp_bytes_left_to_read = -1;
161 static int hf_ndmp_window_offset = -1;
162 static int hf_ndmp_window_length = -1;
163 static int hf_ndmp_addr_ip = -1;
164 static int hf_ndmp_addr_tcp = -1;
165 static int hf_ndmp_addr_fcal_loop_id = -1;
166 static int hf_ndmp_addr_ipc = -1;
167 static int hf_ndmp_mover_mode = -1;
168 static int hf_ndmp_file_name = -1;
169 static int hf_ndmp_nt_file_name = -1;
170 static int hf_ndmp_dos_file_name = -1;
171 static int hf_ndmp_log_type = -1;
172 static int hf_ndmp_log_message_id = -1;
173 static int hf_ndmp_log_message = -1;
174 static int hf_ndmp_connected = -1;
175 static int hf_ndmp_connected_reason = -1;
176 static int hf_ndmp_data = -1;
177 static int hf_ndmp_files = -1;
178 static int hf_ndmp_file_fs_type = -1;
179 static int hf_ndmp_file_names = -1;
180 static int hf_ndmp_file_stats = -1;
181 static int hf_ndmp_file_node = -1;
182 static int hf_ndmp_file_parent = -1;
183 static int hf_ndmp_file_fh_info = -1;
184 static int hf_ndmp_file_invalid_atime = -1;
185 static int hf_ndmp_file_invalid_ctime = -1;
186 static int hf_ndmp_file_invalid_group = -1;
187 static int hf_ndmp_file_type = -1;
188 static int hf_ndmp_file_mtime = -1;
189 static int hf_ndmp_file_atime = -1;
190 static int hf_ndmp_file_ctime = -1;
191 static int hf_ndmp_file_owner = -1;
192 static int hf_ndmp_file_group = -1;
193 static int hf_ndmp_file_fattr = -1;
194 static int hf_ndmp_file_size = -1;
195 static int hf_ndmp_file_links = -1;
196 static int hf_ndmp_dirs = -1;
197 static int hf_ndmp_nodes = -1;
198 static int hf_ndmp_nlist = -1;
199 static int hf_ndmp_bu_original_path = -1;
200 static int hf_ndmp_bu_destination_dir = -1;
201 static int hf_ndmp_bu_new_name = -1;
202 static int hf_ndmp_bu_other_name = -1;
203 static int hf_ndmp_state_invalid_ebr = -1;
204 static int hf_ndmp_state_invalid_etr = -1;
205 static int hf_ndmp_bu_operation = -1;
206 static int hf_ndmp_data_state = -1;
207 static int hf_ndmp_data_halted = -1;
208 static int hf_ndmp_data_bytes_processed = -1;
209 static int hf_ndmp_data_est_bytes_remain = -1;
210 static int hf_ndmp_data_est_time_remain = -1;
211
212 static gint ett_ndmp = -1;
213 static gint ett_ndmp_header = -1;
214 static gint ett_ndmp_butype_attrs = -1;
215 static gint ett_ndmp_fs_invalid = -1;
216 static gint ett_ndmp_tape_attr = -1;
217 static gint ett_ndmp_execute_cdb_flags = -1;
218 static gint ett_ndmp_execute_cdb_cdb = -1;
219 static gint ett_ndmp_execute_cdb_sns = -1;
220 static gint ett_ndmp_execute_cdb_payload = -1;
221 static gint ett_ndmp_tape_invalid = -1;
222 static gint ett_ndmp_tape_flags = -1;
223 static gint ett_ndmp_addr = -1;
224 static gint ett_ndmp_file = -1;
225 static gint ett_ndmp_file_name = -1;
226 static gint ett_ndmp_file_stats = -1;
227 static gint ett_ndmp_file_invalids = -1;
228 static gint ett_ndmp_state_invalids = -1;
229
230 struct ndmp_header {
231         guint32 seq;
232         guint32 time;
233         guint32 type;
234         guint32 msg;
235         guint32 rep_seq;
236         guint32 err;
237 };
238
239 /* desegmentation of NDMP packets */
240 static gboolean ndmp_desegment = TRUE;
241
242 /* defragmentation of fragmented NDMP records */
243 static gboolean ndmp_defragment = FALSE;
244
245 #define NDMP_MESSAGE_REQUEST    0x00
246 #define NDMP_MESSAGE_REPLY      0x01
247 static const value_string msg_type_vals[] = {
248         {NDMP_MESSAGE_REQUEST,          "Request"},
249         {NDMP_MESSAGE_REPLY,            "Reply"},
250         {0, NULL}
251 };
252
253 #define NDMP_NO_ERR                     0x00
254 #define NDMP_NOT_SUPPORTED_ERR          0x01
255 #define NDMP_DEVICE_BUSY_ERR            0x02
256 #define NDMP_DEVICE_OPENED_ERR          0x03
257 #define NDMP_NOT_AUTHORIZED_ERR         0x04
258 #define NDMP_PERMISSION_ERR             0x05
259 #define NDMP_DEV_NOT_OPEN_ERR           0x06
260 #define NDMP_IO_ERR                     0x07
261 #define NDMP_TIMEOUT_ERR                0x08
262 #define NDMP_ILLEGAL_ARGS_ERR           0x09
263 #define NDMP_NO_TAPE_LOADED_ERR         0x0a
264 #define NDMP_WRITE_PROTECT_ERR          0x0b
265 #define NDMP_EOF_ERR                    0x0c
266 #define NDMP_EOM_ERR                    0x0d
267 #define NDMP_FILE_NOT_FOUND_ERR         0x0e
268 #define NDMP_BAD_FILE_ERR               0x0f
269 #define NDMP_NO_DEVICE_ERR              0x10
270 #define NDMP_NO_BUS_ERR                 0x11
271 #define NDMP_XDR_DECODE_ERR             0x12
272 #define NDMP_ILLEGAL_STATE_ERR          0x13
273 #define NDMP_UNDEFINED_ERR              0x14
274 #define NDMP_XDR_ENCODE_ERR             0x15
275 #define NDMP_NO_MEM_ERR                 0x16
276 #define NDMP_CONNECT_ERR                0x17
277
278 static const value_string error_vals[] = {
279         {NDMP_NO_ERR,                   "NO_ERR"},
280         {NDMP_NOT_SUPPORTED_ERR,        "NOT_SUPPORTED_ERR"},
281         {NDMP_DEVICE_BUSY_ERR,          "DEVICE_BUSY_ERR"},
282         {NDMP_DEVICE_OPENED_ERR,        "DEVICE_OPENED_ERR"},
283         {NDMP_NOT_AUTHORIZED_ERR,       "NOT_AUTHORIZED_ERR"},
284         {NDMP_PERMISSION_ERR,           "PERMISSION_ERR"},
285         {NDMP_DEV_NOT_OPEN_ERR,         "DEV_NOT_OPEN_ERR"},
286         {NDMP_IO_ERR,                   "IO_ERR"},
287         {NDMP_TIMEOUT_ERR,              "TIMEOUT_ERR"},
288         {NDMP_ILLEGAL_ARGS_ERR,         "ILLEGAL_ARGS_ERR"},
289         {NDMP_NO_TAPE_LOADED_ERR,       "NO_TAPE_LOADED_ERR"},
290         {NDMP_WRITE_PROTECT_ERR,        "WRITE_PROTECT_ERR"},
291         {NDMP_EOF_ERR,                  "EOF_ERR"},
292         {NDMP_EOM_ERR,                  "EOM_ERR"},
293         {NDMP_FILE_NOT_FOUND_ERR,       "FILE_NOT_FOUND_ERR"},
294         {NDMP_BAD_FILE_ERR,             "BAD_FILE_ERR"},
295         {NDMP_NO_DEVICE_ERR,            "NO_DEVICE_ERR"},
296         {NDMP_NO_BUS_ERR,               "NO_BUS_ERR"},
297         {NDMP_XDR_DECODE_ERR,           "XDR_DECODE_ERR"},
298         {NDMP_ILLEGAL_STATE_ERR,        "ILLEGAL_STATE_ERR"},
299         {NDMP_UNDEFINED_ERR,            "UNDEFINED_ERR"},
300         {NDMP_XDR_ENCODE_ERR,           "XDR_ENCODE_ERR"},
301         {NDMP_NO_MEM_ERR,               "NO_MEM_ERR"},
302         {NDMP_CONNECT_ERR,              "CONNECT_ERR"},
303         {0, NULL}
304 };
305
306
307
308 #define NDMP_CONFIG_GET_HOST_INFO       0x100
309 #define NDMP_CONFIG_GET_CONNECTION_TYPE 0x102
310 #define NDMP_CONFIG_GET_AUTH_ATTR       0x103
311 #define NDMP_CONFIG_GET_BUTYPE_INFO     0x104
312 #define NDMP_CONFIG_GET_FS_INFO         0x105
313 #define NDMP_CONFIG_GET_TAPE_INFO       0x106
314 #define NDMP_CONFIG_GET_SCSI_INFO       0x107
315 #define NDMP_CONFIG_GET_SERVER_INFO     0x108
316 #define NDMP_SCSI_OPEN                  0x200
317 #define NDMP_SCSI_CLOSE                 0x201
318 #define NDMP_SCSI_GET_STATE             0x202
319 #define NDMP_SCSI_SET_TARGET            0x203
320 #define NDMP_SCSI_RESET_DEVICE          0x204
321 #define NDMP_SCSI_RESET_BUS             0x205
322 #define NDMP_SCSI_EXECUTE_CDB           0x206
323 #define NDMP_TAPE_OPEN                  0x300
324 #define NDMP_TAPE_CLOSE                 0x301
325 #define NDMP_TAPE_GET_STATE             0x302
326 #define NDMP_TAPE_MTIO                  0x303
327 #define NDMP_TAPE_WRITE                 0x304
328 #define NDMP_TAPE_READ                  0x305
329 #define NDMP_TAPE_EXECUTE_CDB           0x307
330 #define NDMP_DATA_GET_STATE             0x400
331 #define NDMP_DATA_START_BACKUP          0x401
332 #define NDMP_DATA_START_RECOVER         0x402
333 #define NDMP_DATA_ABORT                 0x403
334 #define NDMP_DATA_GET_ENV               0x404
335 #define NDMP_DATA_STOP                  0x407
336 #define NDMP_DATA_LISTEN                0x409
337 #define NDMP_DATA_CONNECT               0x40a
338 #define NDMP_NOTIFY_DATA_HALTED         0x501
339 #define NDMP_NOTIFY_CONNECTED           0x502
340 #define NDMP_NOTIFY_MOVER_HALTED        0x503
341 #define NDMP_NOTIFY_MOVER_PAUSED        0x504
342 #define NDMP_NOTIFY_DATA_READ           0x505
343 #define NDMP_LOG_FILE                   0x602
344 #define NDMP_LOG_MESSAGE                0x603
345 #define NDMP_FH_ADD_FILE                0x703
346 #define NDMP_FH_ADD_DIR                 0x704
347 #define NDMP_FH_ADD_NODE                0x705
348 #define NDMP_CONNECT_OPEN               0x900
349 #define NDMP_CONNECT_CLIENT_AUTH        0x901
350 #define NDMP_CONNECT_CLOSE              0x902
351 #define NDMP_CONNECT_SERVER_AUTH        0x903
352 #define NDMP_MOVER_GET_STATE            0xa00
353 #define NDMP_MOVER_LISTEN               0xa01
354 #define NDMP_MOVER_CONTINUE             0xa02
355 #define NDMP_MOVER_ABORT                0xa03
356 #define NDMP_MOVER_STOP                 0xa04
357 #define NDMP_MOVER_SET_WINDOW           0xa05
358 #define NDMP_MOVER_READ                 0xa06
359 #define NDMP_MOVER_CLOSE                0xa07
360 #define NDMP_MOVER_SET_RECORD_SIZE      0xa08
361 #define NDMP_MOVER_CONNECT              0xa09
362
363
364
365
366 static const value_string msg_vals[] = {
367         {NDMP_CONFIG_GET_HOST_INFO,     "CONFIG_GET_HOST_INFO"},
368         {NDMP_CONFIG_GET_CONNECTION_TYPE, "CONFIG_GET_CONNECTION_TYPE"},
369         {NDMP_CONFIG_GET_AUTH_ATTR,     "CONFIG_GET_AUTH_ATTR"},
370         {NDMP_CONFIG_GET_BUTYPE_INFO,   "CONFIG_GET_BUTYPE_INFO"},
371         {NDMP_CONFIG_GET_FS_INFO,       "CONFIG_GET_FS_INFO"},
372         {NDMP_CONFIG_GET_TAPE_INFO,     "CONFIG_GET_TAPE_INFO"},
373         {NDMP_CONFIG_GET_SCSI_INFO,     "CONFIG_GET_SCSI_INFO"},
374         {NDMP_CONFIG_GET_SERVER_INFO,   "CONFIG_GET_SERVER_INFO"},
375         {NDMP_SCSI_OPEN,                "SCSI_OPEN"},
376         {NDMP_SCSI_CLOSE,               "SCSI_CLOSE"},
377         {NDMP_SCSI_GET_STATE,           "SCSI_GET_STATE"},
378         {NDMP_SCSI_SET_TARGET,          "SCSI_SET_TARGET"},
379         {NDMP_SCSI_RESET_DEVICE,        "SCSI_RESET_DEVICE"},
380         {NDMP_SCSI_RESET_BUS,           "SCSI_RESET_BUS"},
381         {NDMP_SCSI_EXECUTE_CDB,         "SCSI_EXECUTE_CDB"},
382         {NDMP_TAPE_OPEN,                "TAPE_OPEN"},
383         {NDMP_TAPE_CLOSE,               "TAPE_CLOSE"},
384         {NDMP_TAPE_GET_STATE,           "TAPE_GET_STATE"},
385         {NDMP_TAPE_MTIO,                "TAPE_MTIO"},
386         {NDMP_TAPE_WRITE,               "TAPE_WRITE"},
387         {NDMP_TAPE_READ,                "TAPE_READ"},
388         {NDMP_TAPE_EXECUTE_CDB,         "TAPE_EXECUTE_CDB"},
389         {NDMP_DATA_GET_STATE,           "DATA_GET_STATE"},
390         {NDMP_DATA_START_BACKUP,        "DATA_START_BACKUP"},
391         {NDMP_DATA_START_RECOVER,       "DATA_START_RECOVER"},
392         {NDMP_DATA_ABORT,               "DATA_ABORT"},
393         {NDMP_DATA_GET_ENV,             "DATA_GET_ENV"},
394         {NDMP_DATA_STOP,                "DATA_STOP"},
395         {NDMP_DATA_LISTEN,              "DATA_LISTEN"},
396         {NDMP_DATA_CONNECT,             "DATA_CONNECT"},
397         {NDMP_NOTIFY_DATA_HALTED,       "NOTIFY_DATA_HALTED"},
398         {NDMP_NOTIFY_CONNECTED,         "NOTIFY_CONNECTED"},
399         {NDMP_NOTIFY_MOVER_HALTED,      "NOTIFY_MOVER_HALTED"},
400         {NDMP_NOTIFY_MOVER_PAUSED,      "NOTIFY_MOVER_PAUSED"},
401         {NDMP_NOTIFY_DATA_READ,         "NOTIFY_DATA_READ"},
402         {NDMP_LOG_FILE,                 "LOG_FILE"},
403         {NDMP_LOG_MESSAGE,              "LOG_MESSAGE"},
404         {NDMP_FH_ADD_FILE,              "FH_ADD_FILE"},
405         {NDMP_FH_ADD_DIR,               "FH_ADD_DIR"},
406         {NDMP_FH_ADD_NODE,              "FH_ADD_NODE"},
407         {NDMP_CONNECT_OPEN,             "CONNECT_OPEN"},
408         {NDMP_CONNECT_CLIENT_AUTH,      "CONNECT_CLIENT_AUTH"},
409         {NDMP_CONNECT_CLOSE,            "CONNECT_CLOSE"},
410         {NDMP_CONNECT_SERVER_AUTH,      "CONNECT_SERVER_AUTH"},
411         {NDMP_MOVER_GET_STATE,          "MOVER_GET_STATE"},
412         {NDMP_MOVER_LISTEN,             "MOVER_LISTEN"},
413         {NDMP_MOVER_CONTINUE,           "MOVER_CONTINUE"},
414         {NDMP_MOVER_ABORT,              "MOVER_ABORT"},
415         {NDMP_MOVER_STOP,               "MOVER_STOP"},
416         {NDMP_MOVER_SET_WINDOW,         "MOVER_SET_WINDOW"},
417         {NDMP_MOVER_READ,               "MOVER_READ"},
418         {NDMP_MOVER_CLOSE,              "MOVER_CLOSE"},
419         {NDMP_MOVER_SET_RECORD_SIZE,    "MOVER_SET_RECORD_SIZE"},
420         {NDMP_MOVER_CONNECT,            "MOVER_CONNECT"},
421         {0, NULL}
422 };
423
424 static int
425 dissect_connect_open_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
426     proto_tree *tree, guint32 seq _U_)
427 {
428         /* version number */
429         proto_tree_add_item(tree, hf_ndmp_version, tvb, offset, 4, FALSE);
430         offset += 4;
431
432         return offset;
433 }
434
435 static int
436 dissect_error(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
437     proto_tree *tree, guint32 seq _U_)
438 {
439         /* error */
440         proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
441         offset += 4;
442
443         return offset;
444 }
445
446 static int
447 dissect_ndmp_get_host_info_reply(tvbuff_t *tvb, int offset,
448     packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
449 {
450         /* error */
451         proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
452         offset += 4;
453
454         /* hostname */
455         offset = dissect_rpc_string(tvb, tree,
456                         hf_ndmp_hostname, offset, NULL);
457
458         /* os type */
459         offset = dissect_rpc_string(tvb, tree,
460                         hf_ndmp_os_type, offset, NULL);
461
462         /* os version */
463         offset = dissect_rpc_string(tvb, tree,
464                         hf_ndmp_os_vers, offset, NULL);
465
466         /* hostid */
467         offset = dissect_rpc_string(tvb, tree,
468                         hf_ndmp_hostid, offset, NULL);
469
470         return offset;
471 }
472
473 #define NDMP_ADDR_LOCAL         0
474 #define NDMP_ADDR_TCP           1
475 #define NDMP_ADDR_FC            2
476 #define NDMP_ADDR_IPC           3
477 static const value_string addr_type_vals[] = {
478         {NDMP_ADDR_LOCAL,       "Local"},
479         {NDMP_ADDR_TCP,         "TCP"},
480         {NDMP_ADDR_FC,          "FC"},
481         {NDMP_ADDR_IPC,         "IPC"},
482         {0,NULL}
483 };
484
485 static int
486 dissect_ndmp_addr_type(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
487     proto_tree *tree)
488 {
489         proto_tree_add_item(tree, hf_ndmp_addr_type, tvb, offset, 4, FALSE);
490         offset += 4;
491
492         return offset;
493 }
494
495 static int
496 dissect_ndmp_addr_msg(tvbuff_t *tvb, int offset, packet_info *pinfo,
497     proto_tree *tree, guint32 seq _U_)
498 {
499         /*address type*/
500         return dissect_ndmp_addr_type(tvb, offset, pinfo, tree);
501 }
502
503 static int
504 dissect_ndmp_config_get_connection_type_reply(tvbuff_t *tvb, int offset,
505     packet_info *pinfo, proto_tree *tree, guint32 seq _U_)
506 {
507         /* error */
508         proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
509         offset += 4;
510
511         /* addr types */
512         offset = dissect_rpc_array(tvb, pinfo, tree, offset,
513                         dissect_ndmp_addr_type, hf_ndmp_addr_types);
514
515         return offset;
516 }
517
518 #define NDMP_AUTH_NONE          0
519 #define NDMP_AUTH_TEXT          1
520 #define NDMP_AUTH_MD5           2
521 static const value_string auth_type_vals[] = {
522         {NDMP_AUTH_NONE,        "None"},
523         {NDMP_AUTH_TEXT,        "Text"},
524         {NDMP_AUTH_MD5,         "MD5"},
525         {0,NULL}
526 };
527 static int
528 dissect_auth_type(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
529     proto_tree *tree)
530 {
531         proto_tree_add_item(tree, hf_ndmp_auth_type, tvb, offset, 4, FALSE);
532         offset += 4;
533
534         return offset;
535 }
536
537 static int
538 dissect_get_auth_type_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
539     proto_tree *tree, guint32 seq _U_)
540 {
541         /* auth type */
542         return dissect_auth_type(tvb, offset, pinfo, tree);
543 }
544
545 static int
546 dissect_auth_attr_msg(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
547     proto_tree *tree, guint32 seq _U_)
548 {
549         guint type;
550
551         type=tvb_get_ntohl(tvb,offset);
552
553         /* auth type */
554         proto_tree_add_item(tree, hf_ndmp_auth_type, tvb, offset, 4, FALSE);
555         offset += 4;
556
557         switch(type){
558         case NDMP_AUTH_NONE:
559                 break;
560         case NDMP_AUTH_TEXT:
561                 break;
562         case NDMP_AUTH_MD5:
563                 proto_tree_add_item(tree, hf_ndmp_auth_challenge,
564                         tvb, offset, 64, FALSE);
565                 offset+=64;
566         }
567
568         return offset;
569 }
570
571 static int
572 dissect_default_env(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
573     proto_tree *tree)
574 {
575         /* name */
576         offset = dissect_rpc_string(tvb, tree,
577                         hf_ndmp_butype_env_name, offset, NULL);
578
579         /* value */
580         offset = dissect_rpc_string(tvb, tree,
581                         hf_ndmp_butype_env_value, offset, NULL);
582
583         return offset;
584 }
585
586
587 static const true_false_string tfs_butype_attr_backup_file_history = {
588         "Backup FILE HISTORY",
589         "Do NOT backup file history"
590 };
591 static const true_false_string tfs_butype_attr_backup_filelist = {
592         "Backup FILELIST",
593         "Do NOT backup filelist"
594 };
595 static const true_false_string tfs_butype_attr_recover_filelist = {
596         "Recover FILELIST",
597         "Do NOT recover filelist"
598 };
599 static const true_false_string tfs_butype_attr_backup_direct = {
600         "Perform DIRECT backup",
601         "Do NOT perform direct backup"
602 };
603 static const true_false_string tfs_butype_attr_recover_direct = {
604         "Perform DIRECT recovery",
605         "Do NOT perform direct recovery"
606 };
607 static const true_false_string tfs_butype_attr_backup_incremental = {
608         "Perform INCREMENTAL backup",
609         "Perform FULL backup"
610 };
611 static const true_false_string tfs_butype_attr_recover_incremental = {
612         "Perform INCREMENTAL revocery",
613         "Perform FULL recovery"
614 };
615 static const true_false_string tfs_butype_attr_backup_utf8 = {
616         "Backup using UTF8",
617         "Normal backup. Do NOT use utf8"
618 };
619 static const true_false_string tfs_butype_attr_recover_utf8 = {
620         "Recover using UTF8",
621         "Normal recover. Do NOT use utf8"
622 };
623 static int
624 dissect_butype_attrs(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
625     proto_tree *parent_tree)
626 {
627         proto_item* item = NULL;
628         proto_tree* tree = NULL;
629         guint32 flags;
630
631         flags=tvb_get_ntohl(tvb, offset);
632         if (parent_tree) {
633                 item = proto_tree_add_text(parent_tree, tvb, offset, 4,
634                                 "Attributes: 0x%08x", flags);
635                 tree = proto_item_add_subtree(item, ett_ndmp_butype_attrs);
636         }
637
638         proto_tree_add_boolean(tree, hf_ndmp_butype_attr_recover_utf8,
639                                 tvb, offset, 4, flags);
640         proto_tree_add_boolean(tree, hf_ndmp_butype_attr_backup_utf8,
641                                 tvb, offset, 4, flags);
642         proto_tree_add_boolean(tree, hf_ndmp_butype_attr_recover_incremental,
643                                 tvb, offset, 4, flags);
644         proto_tree_add_boolean(tree, hf_ndmp_butype_attr_backup_incremental,
645                                 tvb, offset, 4, flags);
646         proto_tree_add_boolean(tree, hf_ndmp_butype_attr_recover_direct,
647                                 tvb, offset, 4, flags);
648         proto_tree_add_boolean(tree, hf_ndmp_butype_attr_backup_direct,
649                                 tvb, offset, 4, flags);
650         proto_tree_add_boolean(tree, hf_ndmp_butype_attr_recover_filelist,
651                                 tvb, offset, 4, flags);
652         proto_tree_add_boolean(tree, hf_ndmp_butype_attr_backup_filelist,
653                                 tvb, offset, 4, flags);
654         proto_tree_add_boolean(tree, hf_ndmp_butype_attr_backup_file_history,
655                                 tvb, offset, 4, flags);
656
657         offset += 4;
658         return offset;
659 }
660
661 static int
662 dissect_butype_info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
663 {
664         /*butype name*/
665         offset = dissect_rpc_string(tvb, tree,
666                         hf_ndmp_butype_name, offset, NULL);
667
668         /* default env */
669         offset = dissect_rpc_array(tvb, pinfo, tree, offset,
670                         dissect_default_env, hf_ndmp_butype_default_env);
671
672         /* attrs */
673         offset = dissect_butype_attrs(tvb, offset, pinfo, tree);
674
675         return offset;
676 }
677
678 static int
679 dissect_get_butype_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
680     proto_tree *tree, guint32 seq _U_)
681 {
682         /* error */
683         proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
684         offset += 4;
685
686         /* butype */
687         offset = dissect_rpc_array(tvb, pinfo, tree, offset,
688                         dissect_butype_info, hf_ndmp_butype_info);
689
690         return offset;
691 }
692
693 static const true_false_string tfs_fs_invalid_total_size = {
694         "Total size is INVALID",
695         "Total size is VALID"
696 };
697 static const true_false_string tfs_fs_invalid_used_size = {
698         "Used size is INVALID",
699         "Used size is VALID"
700 };
701 static const true_false_string tfs_fs_invalid_avail_size = {
702         "Available size is INVALID",
703         "Available size is VALID"
704 };
705 static const true_false_string tfs_fs_invalid_total_inodes = {
706         "Total inode count is INVALID",
707         "Total inode count is VALID"
708 };
709 static const true_false_string tfs_fs_invalid_used_inodes = {
710         "Used inode count is INVALID",
711         "Used inode count is VALID"
712 };
713 static int
714 dissect_fs_invalid(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
715     proto_tree *parent_tree)
716 {
717         proto_item* item = NULL;
718         proto_tree* tree = NULL;
719         guint32 flags;
720
721         flags=tvb_get_ntohl(tvb, offset);
722         if (parent_tree) {
723                 item = proto_tree_add_text(parent_tree, tvb, offset, 4,
724                                 "Invalids: 0x%08x", flags);
725                 tree = proto_item_add_subtree(item, ett_ndmp_fs_invalid);
726         }
727
728         proto_tree_add_boolean(tree, hf_ndmp_fs_invalid_used_inodes,
729                                 tvb, offset, 4, flags);
730         proto_tree_add_boolean(tree, hf_ndmp_fs_invalid_total_inodes,
731                                 tvb, offset, 4, flags);
732         proto_tree_add_boolean(tree, hf_ndmp_fs_invalid_avail_size,
733                                 tvb, offset, 4, flags);
734         proto_tree_add_boolean(tree, hf_ndmp_fs_invalid_used_size,
735                                 tvb, offset, 4, flags);
736         proto_tree_add_boolean(tree, hf_ndmp_fs_invalid_total_size,
737                                 tvb, offset, 4, flags);
738
739         offset+=4;
740         return offset;
741 }
742
743 static int
744 dissect_fs_env(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
745     proto_tree *tree)
746 {
747         /* name */
748         offset = dissect_rpc_string(tvb, tree,
749                         hf_ndmp_fs_env_name, offset, NULL);
750
751         /* value */
752         offset = dissect_rpc_string(tvb, tree,
753                         hf_ndmp_fs_env_value, offset, NULL);
754
755         return offset;
756 }
757
758 static int
759 dissect_fs_info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
760 {
761         /* invalid bits */
762         offset=dissect_fs_invalid(tvb, offset, pinfo, tree);
763
764         /* fs type */
765         offset = dissect_rpc_string(tvb, tree,
766                         hf_ndmp_fs_fs_type, offset, NULL);
767
768         /* fs logical device */
769         offset = dissect_rpc_string(tvb, tree,
770                         hf_ndmp_fs_logical_device, offset, NULL);
771
772         /* fs physical device */
773         offset = dissect_rpc_string(tvb, tree,
774                         hf_ndmp_fs_physical_device, offset, NULL);
775
776         /*total_size*/
777         offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_fs_total_size,
778                         offset);
779
780         /*used_size*/
781         offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_fs_used_size,
782                         offset);
783
784         /*avail_size*/
785         offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_fs_avail_size,
786                         offset);
787
788         /*total_inodes*/
789         offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_fs_total_inodes,
790                         offset);
791
792         /*used_inodes*/
793         offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_fs_used_inodes,
794                         offset);
795
796         /* env */
797         offset = dissect_rpc_array(tvb, pinfo, tree, offset,
798                         dissect_fs_env, hf_ndmp_fs_env);
799
800         /* status */
801         offset = dissect_rpc_string(tvb, tree,
802                         hf_ndmp_fs_status, offset, NULL);
803
804         return offset;
805 }
806
807 static int
808 dissect_get_fs_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
809     proto_tree *tree, guint32 seq _U_)
810 {
811         /* error */
812         proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
813         offset += 4;
814
815         /* fs */
816         offset = dissect_rpc_array(tvb, pinfo, tree, offset,
817                         dissect_fs_info, hf_ndmp_fs_info);
818
819         return offset;
820 }
821
822 static const true_false_string tfs_tape_attr_rewind = {
823         "Device supports REWIND",
824         "Device does NOT support rewind"
825 };
826 static const true_false_string tfs_tape_attr_unload = {
827         "Device supports UNLOAD",
828         "Device does NOT support unload"
829 };
830 static int
831 dissect_tape_attr(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
832     proto_tree *parent_tree)
833 {
834         proto_item* item = NULL;
835         proto_tree* tree = NULL;
836         guint32 flags;
837
838         flags=tvb_get_ntohl(tvb, offset);
839         if (parent_tree) {
840                 item = proto_tree_add_text(parent_tree, tvb, offset, 4,
841                                 "Attributes: 0x%08x", flags);
842                 tree = proto_item_add_subtree(item, ett_ndmp_tape_attr);
843         }
844
845         proto_tree_add_boolean(tree, hf_ndmp_tape_attr_unload,
846                                 tvb, offset, 4, flags);
847         proto_tree_add_boolean(tree, hf_ndmp_tape_attr_rewind,
848                                 tvb, offset, 4, flags);
849
850         offset+=4;
851         return offset;
852 }
853
854 static int
855 dissect_tape_capability(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
856     proto_tree *tree)
857 {
858         /* name */
859         offset = dissect_rpc_string(tvb, tree,
860                         hf_ndmp_tape_capability_name, offset, NULL);
861
862         /* value */
863         offset = dissect_rpc_string(tvb, tree,
864                         hf_ndmp_tape_capability_value, offset, NULL);
865
866         return offset;
867 }
868
869 static int
870 dissect_tape_dev_cap(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
871 {
872         /* device */
873         offset = dissect_rpc_string(tvb, tree,
874                         hf_ndmp_tape_device, offset, NULL);
875
876         /* tape attributes */
877         offset = dissect_tape_attr(tvb, offset, pinfo, tree);
878
879         /* capability */
880         offset = dissect_rpc_array(tvb, pinfo, tree, offset,
881                         dissect_tape_capability, hf_ndmp_tape_capability);
882
883         return offset;
884 }
885
886 static int
887 dissect_tape_info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
888 {
889         /* model */
890         offset = dissect_rpc_string(tvb, tree,
891                         hf_ndmp_tape_model, offset, NULL);
892
893         /* device capabilites */
894         offset = dissect_rpc_array(tvb, pinfo, tree, offset,
895                         dissect_tape_dev_cap, hf_ndmp_tape_dev_cap);
896
897         return offset;
898 }
899
900 static int
901 dissect_get_tape_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
902     proto_tree *tree, guint32 seq _U_)
903 {
904         /* error */
905         proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
906         offset += 4;
907
908         /* tape */
909         offset = dissect_rpc_array(tvb, pinfo, tree, offset,
910                         dissect_tape_info, hf_ndmp_tape_info);
911
912         return offset;
913 }
914
915 static int
916 dissect_scsi_info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
917 {
918         /* model */
919         offset = dissect_rpc_string(tvb, tree,
920                         hf_ndmp_scsi_model, offset, NULL);
921
922         /* device capabilites */
923         offset = dissect_rpc_array(tvb, pinfo, tree, offset,
924                         dissect_tape_dev_cap, hf_ndmp_tape_dev_cap);
925
926         return offset;
927 }
928
929 static int
930 dissect_get_scsi_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
931     proto_tree *tree, guint32 seq _U_)
932 {
933         /* error */
934         proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
935         offset += 4;
936
937         /* scsi */
938         offset = dissect_rpc_array(tvb, pinfo, tree, offset,
939                         dissect_scsi_info, hf_ndmp_scsi_info);
940
941         return offset;
942 }
943
944 static int
945 dissect_get_server_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
946     proto_tree *tree, guint32 seq _U_)
947 {
948         /* error */
949         proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
950         offset += 4;
951
952         /* vendor */
953         offset = dissect_rpc_string(tvb, tree,
954                         hf_ndmp_server_vendor, offset, NULL);
955
956         /* product */
957         offset = dissect_rpc_string(tvb, tree,
958                         hf_ndmp_server_product, offset, NULL);
959
960         /* revision */
961         offset = dissect_rpc_string(tvb, tree,
962                         hf_ndmp_server_revision, offset, NULL);
963
964
965         /* server */
966         offset = dissect_rpc_array(tvb, pinfo, tree, offset,
967                         dissect_auth_type, hf_ndmp_auth_types);
968
969         return offset;
970 }
971
972 static int
973 dissect_scsi_open_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
974     proto_tree *tree, guint32 seq _U_)
975 {
976         /* device */
977         offset = dissect_rpc_string(tvb, tree,
978                         hf_ndmp_scsi_device, offset, NULL);
979
980         return offset;
981 }
982
983 static int
984 dissect_scsi_get_state_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
985     proto_tree *tree, guint32 seq _U_)
986 {
987         /* error */
988         proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
989         offset += 4;
990
991         /* controller */
992         proto_tree_add_item(tree, hf_ndmp_scsi_controller, tvb, offset, 4, FALSE);
993         offset += 4;
994
995         /* id */
996         proto_tree_add_item(tree, hf_ndmp_scsi_id, tvb, offset, 4, FALSE);
997         offset += 4;
998
999         /* lun */
1000         proto_tree_add_item(tree, hf_ndmp_scsi_lun, tvb, offset, 4, FALSE);
1001         offset += 4;
1002
1003         return offset;
1004 }
1005
1006 static int
1007 dissect_scsi_set_state_request(tvbuff_t *tvb, int offset,
1008     packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
1009 {
1010         /* device */
1011         offset = dissect_rpc_string(tvb, tree,
1012                         hf_ndmp_scsi_device, offset, NULL);
1013
1014         /* controller */
1015         proto_tree_add_item(tree, hf_ndmp_scsi_controller, tvb, offset, 4, FALSE);
1016         offset += 4;
1017
1018         /* id */
1019         proto_tree_add_item(tree, hf_ndmp_scsi_id, tvb, offset, 4, FALSE);
1020         offset += 4;
1021
1022         /* lun */
1023         proto_tree_add_item(tree, hf_ndmp_scsi_lun, tvb, offset, 4, FALSE);
1024         offset += 4;
1025
1026         return offset;
1027 }
1028
1029 static int
1030 dissect_execute_cdb_flags(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
1031     proto_tree *parent_tree)
1032 {
1033         proto_item* item = NULL;
1034         proto_tree* tree = NULL;
1035         guint32 flags;
1036
1037         flags = tvb_get_ntohl(tvb, offset);
1038         if (parent_tree) {
1039                 item = proto_tree_add_text(parent_tree, tvb, offset, 4,
1040                                 "Flags: 0x%08x", flags);
1041                 tree = proto_item_add_subtree(item, ett_ndmp_execute_cdb_flags);
1042         }
1043
1044         proto_tree_add_boolean(tree, hf_ndmp_execute_cdb_flags_data_in,
1045                                 tvb, offset, 4, flags);
1046         proto_tree_add_boolean(tree, hf_ndmp_execute_cdb_flags_data_out,
1047                                 tvb, offset, 4, flags);
1048         offset += 4;
1049         return offset;
1050 }
1051
1052 static int
1053 dissect_execute_cdb_cdb(tvbuff_t *tvb, int offset, packet_info *pinfo,
1054     proto_tree *parent_tree, gint devtype)
1055 {
1056         proto_item* item = NULL;
1057         proto_tree* tree = NULL;
1058         guint32 cdb_len;
1059         guint32 cdb_len_full;
1060
1061         cdb_len = tvb_get_ntohl(tvb, offset);
1062         cdb_len_full = rpc_roundup(cdb_len);
1063
1064         if (parent_tree) {
1065                 item = proto_tree_add_text(parent_tree, tvb, offset,
1066                                 4+cdb_len_full, "CDB");
1067                 tree = proto_item_add_subtree(item, ett_ndmp_execute_cdb_cdb);
1068         }
1069
1070         proto_tree_add_uint(tree, hf_ndmp_execute_cdb_cdb_len, tvb, offset, 4,
1071                         cdb_len);
1072         offset += 4;
1073
1074         if (cdb_len != 0) {
1075                 dissect_scsi_cdb(tvb, pinfo, tree, offset, cdb_len, devtype);
1076                 offset += cdb_len_full;
1077         }
1078
1079         return offset;
1080 }
1081
1082
1083 static int
1084 dissect_execute_cdb_payload(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree,
1085     char *name, int hf_len, gboolean isreq)
1086 {
1087         proto_item* item = NULL;
1088         proto_tree* tree = NULL;
1089         guint32 payload_len;
1090         guint32 payload_len_full;
1091
1092         payload_len = tvb_get_ntohl(tvb, offset);
1093         payload_len_full = rpc_roundup(payload_len);
1094
1095         if (parent_tree) {
1096                 item = proto_tree_add_text(parent_tree, tvb, offset,
1097                                 4+payload_len_full, "%s", name);
1098                 tree = proto_item_add_subtree(item,
1099                     ett_ndmp_execute_cdb_payload);
1100         }
1101
1102         proto_tree_add_uint(tree, hf_len, tvb, offset, 4, payload_len);
1103         offset += 4;
1104
1105         if (payload_len != 0) {
1106                 dissect_scsi_payload(tvb, pinfo, tree, offset, isreq,
1107                     payload_len);
1108                 offset += payload_len_full;
1109         }
1110
1111         return offset;
1112 }
1113
1114 /*
1115  * XXX - we assume that NDMP_SCSI_EXECUTE_CDB requests only go to SCSI Media
1116  * Changer devices and NDMP_TAPE_EXECUTE_CDB only go to SCSI Sequential
1117  * Access devices.
1118  *
1119  * If that's not the case, we'll have to use the SCSI dissector's mechanisms
1120  * for saving inquiry data for devices, and use inquiry data when available.
1121  * Unfortunately, that means we need to save the name of the device, and
1122  * use it as a device identifier; as the name isn't available in the
1123  * NDMP_SCSI_EXECUTE_CDB or NDMP_TAPE_EXECUTE_CDB messages, that means
1124  * we need to remember the currently-opened "SCSI" and "TAPE" devices
1125  * from NDMP_SCSI_OPEN and NDMP_TAPE_OPEN, and attach to all frames
1126  * that are the ones that trigger the dissection of NDMP_SCSI_EXECUTE_CDB
1127  * or NDMP_TAPE_EXECUTE_CDB requests pointers to those names.
1128  */
1129 static int
1130 dissect_execute_cdb_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
1131     proto_tree *tree, guint32 seq, gint devtype)
1132 {
1133         conversation_t *conversation;
1134         scsi_task_id_t task_key;
1135
1136         /*
1137          * We need to provide SCSI task information to the SCSI
1138          * dissection routines.  We use a conversation plus the
1139          * sequence number in requests and the reply sequence
1140          * number in replies to identify SCSI tasks.
1141          */
1142         conversation = find_conversation(&pinfo->src, &pinfo->dst,
1143             pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
1144         if (conversation == NULL) {
1145                 conversation = conversation_new(&pinfo->src, &pinfo->dst,
1146                     pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
1147         }
1148         task_key.conv_id = conversation->index;
1149         task_key.task_id = seq;
1150         pinfo->private_data = &task_key;
1151
1152         /* flags */
1153         offset = dissect_execute_cdb_flags(tvb, offset, pinfo, tree);
1154
1155         /* timeout */
1156         proto_tree_add_item(tree, hf_ndmp_execute_cdb_timeout, tvb, offset, 4, FALSE);
1157         offset += 4;
1158
1159         /* datain_len */
1160         proto_tree_add_item(tree, hf_ndmp_execute_cdb_datain_len, tvb, offset, 4, FALSE);
1161         offset += 4;
1162
1163         /* CDB */
1164         offset = dissect_execute_cdb_cdb(tvb, offset, pinfo, tree, devtype);
1165
1166         /* dataout */
1167         offset = dissect_execute_cdb_payload(tvb, offset, pinfo, tree,
1168             "Data out", hf_ndmp_execute_cdb_dataout_len, TRUE);
1169
1170         return offset;
1171 }
1172
1173 static int
1174 dissect_execute_cdb_request_mc(tvbuff_t *tvb, int offset, packet_info *pinfo,
1175     proto_tree *tree, guint32 seq)
1176 {
1177         return dissect_execute_cdb_request(tvb, offset, pinfo, tree, seq,
1178             SCSI_DEV_SMC);
1179 }
1180
1181 static int
1182 dissect_execute_cdb_request_tape(tvbuff_t *tvb, int offset, packet_info *pinfo,
1183     proto_tree *tree, guint32 seq)
1184 {
1185         return dissect_execute_cdb_request(tvb, offset, pinfo, tree, seq,
1186             SCSI_DEV_SSC);
1187 }
1188
1189 static int
1190 dissect_execute_cdb_sns(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
1191 {
1192         proto_item* item = NULL;
1193         proto_tree* tree = NULL;
1194         guint32 sns_len;
1195         guint32 sns_len_full;
1196
1197         sns_len = tvb_get_ntohl(tvb, offset);
1198         sns_len_full = rpc_roundup(sns_len);
1199
1200         if (parent_tree) {
1201                 item = proto_tree_add_text(parent_tree, tvb, offset,
1202                                 4+sns_len_full, "Sense data");
1203                 tree = proto_item_add_subtree(item, ett_ndmp_execute_cdb_sns);
1204         }
1205
1206         proto_tree_add_uint(tree, hf_ndmp_execute_cdb_sns_len, tvb, offset, 4,
1207                         sns_len);
1208         offset += 4;
1209
1210         if (sns_len != 0) {
1211                 dissect_scsi_snsinfo(tvb, pinfo, tree, offset, sns_len);
1212                 offset += sns_len_full;
1213         }
1214
1215         return offset;
1216 }
1217
1218 static int
1219 dissect_execute_cdb_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
1220     proto_tree *tree, guint32 seq)
1221 {
1222         conversation_t *conversation;
1223         scsi_task_id_t task_key;
1224
1225         /*
1226          * We need to provide SCSI task information to the SCSI
1227          * dissection routines.  We use a conversation plus the
1228          * sequence number in requests and the reply sequence
1229          * number in replies to identify SCSI tasks.
1230          */
1231         conversation = find_conversation(&pinfo->src, &pinfo->dst,
1232             pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
1233         if (conversation != NULL) {
1234                 task_key.conv_id = conversation->index;
1235                 task_key.task_id = seq;
1236                 pinfo->private_data = &task_key;
1237         } else {
1238                 /* no conversation, meaning we didn't see the request */
1239                 pinfo->private_data = NULL;
1240         }
1241
1242         /* error */
1243         proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
1244         offset += 4;
1245
1246         /* status */
1247         proto_tree_add_item(tree, hf_ndmp_execute_cdb_status, tvb, offset, 4, FALSE);
1248         offset += 4;
1249
1250         /* dataout_len */
1251         proto_tree_add_item(tree, hf_ndmp_execute_cdb_dataout_len, tvb, offset, 4, FALSE);
1252         offset += 4;
1253
1254         /* datain */
1255         offset = dissect_execute_cdb_payload(tvb, offset, pinfo, tree,
1256             "Data in", hf_ndmp_execute_cdb_datain_len, FALSE);
1257
1258         /* ext_sense */
1259         offset = dissect_execute_cdb_sns(tvb, offset, pinfo, tree);
1260
1261         return offset;
1262 }
1263
1264 #define NDMP_TAPE_OPEN_MODE_READ        0
1265 #define NDMP_TAPE_OPEN_MODE_RDWR        1
1266 static const value_string tape_open_mode_vals[] = {
1267         {NDMP_TAPE_OPEN_MODE_READ,      "Read"},
1268         {NDMP_TAPE_OPEN_MODE_RDWR,      "Read/Write"},
1269         {0, NULL}
1270 };
1271
1272 static int
1273 dissect_tape_open_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
1274     proto_tree *tree, guint32 seq _U_)
1275 {
1276         /* device */
1277         offset = dissect_rpc_string(tvb, tree,
1278                         hf_ndmp_tape_device, offset, NULL);
1279
1280         /* open mode */
1281         proto_tree_add_item(tree, hf_ndmp_tape_open_mode, tvb, offset, 4, FALSE);
1282         offset += 4;
1283
1284         return offset;
1285 }
1286
1287
1288 static const true_false_string tfs_ndmp_tape_invalid_file_num = {
1289         "File num is valid",
1290         "File num is INVALID"
1291 };
1292 static const true_false_string tfs_ndmp_tape_invalid_soft_errors = {
1293         "Soft errors is valid",
1294         "Soft errors is INVALID"
1295 };
1296 static const true_false_string tfs_ndmp_tape_invalid_block_size = {
1297         "Block size is valid",
1298         "Block size is INVALID"
1299 };
1300 static const true_false_string tfs_ndmp_tape_invalid_block_no = {
1301         "Block no is valid",
1302         "Block no is INVALID"
1303 };
1304 static const true_false_string tfs_ndmp_tape_invalid_total_space = {
1305         "Total space is valid",
1306         "Total space is INVALID"
1307 };
1308 static const true_false_string tfs_ndmp_tape_invalid_space_remain = {
1309         "Space remaining is INVALID",
1310         "Space remaining is valid"
1311 };
1312 static const true_false_string tfs_ndmp_tape_invalid_partition = {
1313         "Partition is INVALID",
1314         "Partition is valid"
1315 };
1316 static int
1317 dissect_tape_invalid(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
1318     proto_tree *parent_tree)
1319 {
1320         proto_item* item = NULL;
1321         proto_tree* tree = NULL;
1322         guint32 flags;
1323
1324         flags=tvb_get_ntohl(tvb, offset);
1325         if (parent_tree) {
1326                 item = proto_tree_add_text(parent_tree, tvb, offset, 4,
1327                                 "Invalids: 0x%08x", flags);
1328                 tree = proto_item_add_subtree(item, ett_ndmp_tape_invalid);
1329         }
1330
1331         proto_tree_add_boolean(tree, hf_ndmp_tape_invalid_partition,
1332                                 tvb, offset, 4, flags);
1333         proto_tree_add_boolean(tree, hf_ndmp_tape_invalid_space_remain,
1334                                 tvb, offset, 4, flags);
1335         proto_tree_add_boolean(tree, hf_ndmp_tape_invalid_total_space,
1336                                 tvb, offset, 4, flags);
1337         proto_tree_add_boolean(tree, hf_ndmp_tape_invalid_block_no,
1338                                 tvb, offset, 4, flags);
1339         proto_tree_add_boolean(tree, hf_ndmp_tape_invalid_block_size,
1340                                 tvb, offset, 4, flags);
1341         proto_tree_add_boolean(tree, hf_ndmp_tape_invalid_soft_errors,
1342                                 tvb, offset, 4, flags);
1343         proto_tree_add_boolean(tree, hf_ndmp_tape_invalid_file_num,
1344                                 tvb, offset, 4, flags);
1345
1346         offset+=4;
1347         return offset;
1348 }
1349
1350 static const true_false_string tfs_ndmp_tape_flags_no_rewind = {
1351         "This is a NON-REWINDING device",
1352         "This device supports rewind"
1353 };
1354 static const true_false_string tfs_ndmp_tape_flags_write_protect = {
1355         "This device is WRITE-PROTECTED",
1356         "This device is NOT write-protected"
1357 };
1358 static const true_false_string tfs_ndmp_tape_flags_error = {
1359         "This device shows ERROR",
1360         "This device shows NO errors"
1361 };
1362 static const true_false_string tfs_ndmp_tape_flags_unload = {
1363         "This device supports UNLOAD",
1364         "This device does NOT support unload"
1365 };
1366 static int
1367 dissect_tape_flags(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
1368     proto_tree *parent_tree)
1369 {
1370         proto_item* item = NULL;
1371         proto_tree* tree = NULL;
1372         guint32 flags;
1373
1374         flags=tvb_get_ntohl(tvb, offset);
1375         if (parent_tree) {
1376                 item = proto_tree_add_text(parent_tree, tvb, offset, 4,
1377                                 "Flags: 0x%08x", flags);
1378                 tree = proto_item_add_subtree(item, ett_ndmp_tape_flags);
1379         }
1380
1381
1382         proto_tree_add_boolean(tree, hf_ndmp_tape_flags_unload,
1383                                 tvb, offset, 4, flags);
1384         proto_tree_add_boolean(tree, hf_ndmp_tape_flags_error,
1385                                 tvb, offset, 4, flags);
1386         proto_tree_add_boolean(tree, hf_ndmp_tape_flags_write_protect,
1387                                 tvb, offset, 4, flags);
1388         proto_tree_add_boolean(tree, hf_ndmp_tape_flags_no_rewind,
1389                                 tvb, offset, 4, flags);
1390
1391         offset+=4;
1392         return offset;
1393 }
1394
1395 static int
1396 dissect_tape_get_state_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
1397     proto_tree *tree, guint32 seq _U_)
1398 {
1399         /* invalid bits */
1400         offset=dissect_tape_invalid(tvb, offset, pinfo, tree);
1401
1402         /* error */
1403         proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
1404         offset += 4;
1405
1406         /* flags */
1407         offset=dissect_tape_flags(tvb, offset, pinfo, tree);
1408
1409         /* file_num */
1410         proto_tree_add_item(tree, hf_ndmp_tape_file_num, tvb, offset, 4, FALSE);
1411         offset += 4;
1412
1413         /* soft_errors */
1414         proto_tree_add_item(tree, hf_ndmp_tape_soft_errors, tvb, offset, 4, FALSE);
1415         offset += 4;
1416
1417         /* block_size */
1418         proto_tree_add_item(tree, hf_ndmp_tape_block_size, tvb, offset, 4, FALSE);
1419         offset += 4;
1420
1421         /* block_no */
1422         proto_tree_add_item(tree, hf_ndmp_tape_block_no, tvb, offset, 4, FALSE);
1423         offset += 4;
1424
1425         /* total_space */
1426         offset = dissect_rpc_uint64(tvb, tree,hf_ndmp_tape_total_space,
1427                         offset);
1428
1429         /* space_remain */
1430         offset = dissect_rpc_uint64(tvb, tree,hf_ndmp_tape_space_remain,
1431                         offset);
1432
1433         /* partition */
1434         proto_tree_add_item(tree, hf_ndmp_tape_partition, tvb, offset, 4, FALSE);
1435         offset += 4;
1436
1437         return offset;
1438 }
1439
1440 #define NDMP_TAPE_MTIO_FSF      0
1441 #define NDMP_TAPE_MTIO_BSF      1
1442 #define NDMP_TAPE_MTIO_FSR      2
1443 #define NDMP_TAPE_MTIO_BSR      3
1444 #define NDMP_TAPE_MTIO_REW      4
1445 #define NDMP_TAPE_MTIO_EOF      5
1446 #define NDMP_TAPE_MTIO_OFF      6
1447 static const value_string tape_mtio_vals[] = {
1448         {NDMP_TAPE_MTIO_FSF,    "FSF"},
1449         {NDMP_TAPE_MTIO_BSF,    "BSF"},
1450         {NDMP_TAPE_MTIO_FSR,    "FSR"},
1451         {NDMP_TAPE_MTIO_BSR,    "BSR"},
1452         {NDMP_TAPE_MTIO_REW,    "REW"},
1453         {NDMP_TAPE_MTIO_EOF,    "EOF"},
1454         {NDMP_TAPE_MTIO_OFF,    "OFF"},
1455         {0, NULL}
1456 };
1457
1458 static int
1459 dissect_tape_mtio_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
1460     proto_tree *tree, guint32 seq _U_)
1461 {
1462         /* op */
1463         proto_tree_add_item(tree, hf_ndmp_tape_mtio_op, tvb, offset, 4, FALSE);
1464         offset += 4;
1465
1466         /* count */
1467         proto_tree_add_item(tree, hf_ndmp_count, tvb, offset, 4, FALSE);
1468         offset += 4;
1469
1470         return offset;
1471 }
1472
1473 static int
1474 dissect_tape_mtio_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
1475     proto_tree *tree, guint32 seq _U_)
1476 {
1477         /* error */
1478         proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
1479         offset += 4;
1480
1481         /* resid count */
1482         proto_tree_add_item(tree, hf_ndmp_resid_count, tvb, offset, 4, FALSE);
1483         offset += 4;
1484
1485         return offset;
1486 }
1487
1488 #define NDMP_MOVER_STATE_IDLE           0
1489 #define NDMP_MOVER_STATE_LISTEN         1
1490 #define NDMP_MOVER_STATE_ACTIVE         2
1491 #define NDMP_MOVER_STATE_PAUSED         3
1492 #define NDMP_MOVER_STATE_HALTED         4
1493 static const value_string mover_state_vals[] = {
1494         {NDMP_MOVER_STATE_IDLE, "MOVER_STATE_IDLE"},
1495         {NDMP_MOVER_STATE_LISTEN,       "MOVER_STATE_LISTEN"},
1496         {NDMP_MOVER_STATE_ACTIVE,       "MOVER_STATE_ACTIVE"},
1497         {NDMP_MOVER_STATE_PAUSED,       "MOVER_STATE_PAUSED"},
1498         {NDMP_MOVER_STATE_HALTED,       "MOVER_STATE_HALTED"},
1499         {0, NULL}
1500 };
1501
1502 #define NDMP_MOVER_PAUSE_NA             0
1503 #define NDMP_MOVER_PAUSE_EOM            1
1504 #define NDMP_MOVER_PAUSE_EOF            2
1505 #define NDMP_MOVER_PAUSE_SEEK           3
1506 #define NDMP_MOVER_PAUSE_MEDIA_ERROR    4
1507 #define NDMP_MOVER_PAUSE_EOW            5
1508 static const value_string mover_pause_vals[] = {
1509         {NDMP_MOVER_PAUSE_NA,           "MOVER_PAUSE_NA"},
1510         {NDMP_MOVER_PAUSE_EOM,          "MOVER_PAUSE_EOM"},
1511         {NDMP_MOVER_PAUSE_EOF,          "MOVER_PAUSE_EOF"},
1512         {NDMP_MOVER_PAUSE_SEEK,         "MOVER_PAUSE_SEEK"},
1513         {NDMP_MOVER_PAUSE_MEDIA_ERROR,  "MOVER_PAUSE_MEDIA_ERROR"},
1514         {NDMP_MOVER_PAUSE_EOW,          "MOVER_PAUSE_EOW"},
1515         {0, NULL}
1516 };
1517
1518 #define NDMP_HALT_NA            0
1519 #define NDMP_HALT_CONNECT_CLOSE 1
1520 #define NDMP_HALT_ABORTED               2
1521 #define NDMP_HALT_INTERNAL_ERROR        3
1522 #define NDMP_HALT_CONNECT_ERROR 4
1523 static const value_string halt_vals[] = {
1524         {NDMP_HALT_NA,                  "HALT_NA"},
1525         {NDMP_HALT_CONNECT_CLOSE,       "HALT_CONNECT_CLOSE"},
1526         {NDMP_HALT_ABORTED,             "HALT_ABORTED"},
1527         {NDMP_HALT_INTERNAL_ERROR,      "HALT_INTERNAL_ERROR"},
1528         {NDMP_HALT_CONNECT_ERROR,       "HALT_CONNECT_ERROR"},
1529         {0, NULL}
1530 };
1531
1532 static int
1533 dissect_ndmp_addr(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
1534     proto_tree *parent_tree)
1535 {
1536         proto_item* item = NULL;
1537         proto_tree* tree = NULL;
1538         guint32 type;
1539
1540         type=tvb_get_ntohl(tvb, offset);
1541         if (parent_tree) {
1542                 item = proto_tree_add_text(parent_tree, tvb, offset, 4,
1543                                 "Type: %s ", val_to_str(type, addr_type_vals,"Unknown addr type (0x%02x)") );
1544                 tree = proto_item_add_subtree(item, ett_ndmp_addr);
1545         }
1546
1547         /*address type*/
1548         proto_tree_add_item(tree, hf_ndmp_addr_type, tvb, offset, 4, FALSE);
1549         offset += 4;
1550
1551
1552         switch(type){
1553         case NDMP_ADDR_LOCAL:
1554                 break;
1555         case NDMP_ADDR_TCP:
1556                 /* IP addr */
1557                 proto_tree_add_item(tree, hf_ndmp_addr_ip, tvb, offset, 4, FALSE);
1558                 offset+=4;
1559
1560                 /* TCP port */
1561                 proto_tree_add_item(tree, hf_ndmp_addr_tcp, tvb, offset, 4, FALSE);
1562                 offset+=4;
1563
1564                 break;
1565         case NDMP_ADDR_FC:
1566                 /* FCAL loop id */
1567                 proto_tree_add_item(tree, hf_ndmp_addr_fcal_loop_id, tvb, offset, 4, FALSE);
1568                 offset+=4;
1569
1570                 break;
1571         case NDMP_ADDR_IPC:
1572                 /* IPC address */
1573                 offset = dissect_rpc_data(tvb, tree, hf_ndmp_addr_ipc, offset);
1574                 break;
1575         }
1576
1577         return offset;
1578 }
1579
1580 static int
1581 dissect_mover_get_state_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
1582     proto_tree *tree, guint32 seq _U_)
1583 {
1584         /* error */
1585         proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
1586         offset += 4;
1587
1588         /* mover state */
1589         proto_tree_add_item(tree, hf_ndmp_mover_state, tvb, offset, 4, FALSE);
1590         offset += 4;
1591
1592         /* mover pause */
1593         proto_tree_add_item(tree, hf_ndmp_mover_pause, tvb, offset, 4, FALSE);
1594         offset += 4;
1595
1596         /* halt */
1597         proto_tree_add_item(tree, hf_ndmp_halt, tvb, offset, 4, FALSE);
1598         offset += 4;
1599
1600         /* record size */
1601         proto_tree_add_item(tree, hf_ndmp_record_size, tvb, offset, 4, FALSE);
1602         offset += 4;
1603
1604         /* record num */
1605         proto_tree_add_item(tree, hf_ndmp_record_num, tvb, offset, 4, FALSE);
1606         offset += 4;
1607
1608         /* data written */
1609         proto_tree_add_item(tree, hf_ndmp_data_written, tvb, offset, 8, FALSE);
1610         offset += 8;
1611
1612         /* seek position */
1613         proto_tree_add_item(tree, hf_ndmp_seek_position, tvb, offset, 8, FALSE);
1614         offset += 8;
1615
1616         /* bytes left to read */
1617         proto_tree_add_item(tree, hf_ndmp_bytes_left_to_read, tvb, offset, 8, FALSE);
1618         offset += 8;
1619
1620         /* window offset */
1621         proto_tree_add_item(tree, hf_ndmp_window_offset, tvb, offset, 8, FALSE);
1622         offset += 8;
1623
1624         /* window length */
1625         proto_tree_add_item(tree, hf_ndmp_window_length, tvb, offset, 8, FALSE);
1626         offset += 8;
1627
1628         /* ndmp addr */
1629         offset=dissect_ndmp_addr(tvb, offset, pinfo, tree);
1630
1631         return offset;
1632 }
1633
1634 #define NDMP_MOVER_MODE_READ    0
1635 #define NDMP_MOVER_MODE_WRITE   1
1636 static const value_string mover_mode_vals[] = {
1637         {NDMP_MOVER_MODE_READ,  "MODE_READ"},
1638         {NDMP_MOVER_MODE_WRITE, "MOVER_MODE_WRITE"},
1639         {0, NULL}
1640 };
1641
1642 static int
1643 dissect_mover_listen_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
1644     proto_tree *tree, guint32 seq _U_)
1645 {
1646         /* mode */
1647         proto_tree_add_item(tree, hf_ndmp_mover_mode, tvb, offset, 4, FALSE);
1648         offset += 4;
1649
1650         /*address type*/
1651         proto_tree_add_item(tree, hf_ndmp_addr_type, tvb, offset, 4, FALSE);
1652         offset += 4;
1653
1654         return offset;
1655 }
1656
1657 static int
1658 dissect_mover_listen_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
1659     proto_tree *tree, guint32 seq _U_)
1660 {
1661         /* error */
1662         proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
1663         offset += 4;
1664
1665         /* ndmp addr */
1666         offset=dissect_ndmp_addr(tvb, offset, pinfo, tree);
1667
1668         return offset;
1669 }
1670
1671 static int
1672 dissect_mover_set_window_request(tvbuff_t *tvb, int offset,
1673     packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
1674 {
1675         /* window offset */
1676         proto_tree_add_item(tree, hf_ndmp_window_offset, tvb, offset, 8, FALSE);
1677         offset += 8;
1678
1679         /* window length */
1680         proto_tree_add_item(tree, hf_ndmp_window_length, tvb, offset, 8, FALSE);
1681         offset += 8;
1682
1683         return offset;
1684 }
1685
1686 static int
1687 dissect_mover_set_record_size_request(tvbuff_t *tvb, int offset,
1688     packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
1689 {
1690         /* record size */
1691         proto_tree_add_item(tree, hf_ndmp_record_size, tvb, offset, 4, FALSE);
1692         offset += 4;
1693
1694         return offset;
1695 }
1696
1697 static int
1698 dissect_mover_connect_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
1699     proto_tree *tree, guint32 seq _U_)
1700 {
1701         /* mode */
1702         proto_tree_add_item(tree, hf_ndmp_mover_mode, tvb, offset, 4, FALSE);
1703         offset += 4;
1704
1705         /* ndmp addr */
1706         offset=dissect_ndmp_addr(tvb, offset, pinfo, tree);
1707
1708         return offset;
1709 }
1710
1711 static int
1712 dissect_log_file_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
1713     proto_tree *tree, guint32 seq _U_)
1714 {
1715         /* file */
1716         offset = dissect_rpc_string(tvb, tree,
1717                         hf_ndmp_file_name, offset, NULL);
1718
1719         /* error */
1720         proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
1721         offset += 4;
1722
1723         return offset;
1724 }
1725
1726 #define NDMP_LOG_TYPE_NORMAL    0
1727 #define NDMP_LOG_TYPE_DEBUG     1
1728 #define NDMP_LOG_TYPE_ERROR     2
1729 #define NDMP_LOG_TYPE_WARNING   3
1730 static const value_string log_type_vals[] = {
1731         {NDMP_LOG_TYPE_NORMAL,  "NORMAL"},
1732         {NDMP_LOG_TYPE_DEBUG,   "DEBUG"},
1733         {NDMP_LOG_TYPE_ERROR,   "ERROR"},
1734         {NDMP_LOG_TYPE_WARNING, "WARNING"},
1735         {0, NULL}
1736 };
1737
1738 static int
1739 dissect_log_message_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
1740     proto_tree *tree, guint32 seq _U_)
1741 {
1742         /* type */
1743         proto_tree_add_item(tree, hf_ndmp_log_type, tvb, offset, 4, FALSE);
1744         offset += 4;
1745
1746         /* message id */
1747         proto_tree_add_item(tree, hf_ndmp_log_message_id, tvb, offset, 4, FALSE);
1748         offset += 4;
1749
1750         /* message */
1751         offset = dissect_rpc_string(tvb, tree,
1752                         hf_ndmp_log_message, offset, NULL);
1753
1754         return offset;
1755 }
1756
1757 static int
1758 dissect_notify_data_halted_request(tvbuff_t *tvb, int offset,
1759     packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
1760 {
1761         /* halt */
1762         proto_tree_add_item(tree, hf_ndmp_halt, tvb, offset, 4, FALSE);
1763         offset += 4;
1764
1765         /* reason */
1766         offset = dissect_rpc_string(tvb, tree,
1767                         hf_ndmp_halt_reason, offset, NULL);
1768
1769         return offset;
1770 }
1771
1772 #define NDMP_CONNECTED_CONNECTED        0
1773 #define NDMP_CONNECTED_SHUTDOWN         1
1774 #define NDMP_CONNECTED_REFUSED          2
1775 static const value_string connected_vals[] = {
1776         {NDMP_CONNECTED_CONNECTED,      "CONNECTED"},
1777         {NDMP_CONNECTED_SHUTDOWN,       "SHUTDOWN"},
1778         {NDMP_CONNECTED_REFUSED,        "REFUSED"},
1779         {0, NULL}
1780 };
1781
1782 static int
1783 dissect_notify_connected_request(tvbuff_t *tvb, int offset,
1784     packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
1785 {
1786         /* connected */
1787         proto_tree_add_item(tree, hf_ndmp_connected, tvb, offset, 4, FALSE);
1788         offset += 4;
1789
1790         /* version number */
1791         proto_tree_add_item(tree, hf_ndmp_version, tvb, offset, 4, FALSE);
1792         offset += 4;
1793
1794         /* reason */
1795         offset = dissect_rpc_string(tvb, tree,
1796                         hf_ndmp_connected_reason, offset, NULL);
1797
1798         return offset;
1799 }
1800
1801
1802 static int
1803 dissect_notify_mover_paused_request(tvbuff_t *tvb, int offset,
1804     packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
1805 {
1806         /* mover pause */
1807         proto_tree_add_item(tree, hf_ndmp_mover_pause, tvb, offset, 4, FALSE);
1808         offset += 4;
1809
1810         /* seek position */
1811         proto_tree_add_item(tree, hf_ndmp_seek_position, tvb, offset, 8, FALSE);
1812         offset += 8;
1813
1814         return offset;
1815 }
1816
1817 static int
1818 dissect_auth_data(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
1819     proto_tree *tree)
1820 {
1821         guint type;
1822
1823         type=tvb_get_ntohl(tvb,offset);
1824
1825         /* auth type */
1826         proto_tree_add_item(tree, hf_ndmp_auth_type, tvb, offset, 4, FALSE);
1827         offset += 4;
1828
1829         switch(type){
1830         case NDMP_AUTH_NONE:
1831                 break;
1832         case NDMP_AUTH_TEXT:
1833                 /* auth id */
1834                 offset = dissect_rpc_string(tvb, tree,
1835                                 hf_ndmp_auth_id, offset, NULL);
1836
1837                 /* auth password */
1838                 offset = dissect_rpc_string(tvb, tree,
1839                                 hf_ndmp_auth_password, offset, NULL);
1840
1841
1842                 break;
1843         case NDMP_AUTH_MD5:
1844                 /* auth id */
1845                 offset = dissect_rpc_string(tvb, tree,
1846                                 hf_ndmp_auth_id, offset, NULL);
1847
1848                 /* digest */
1849                 proto_tree_add_item(tree, hf_ndmp_auth_digest,
1850                         tvb, offset, 16, FALSE);
1851                 offset+=16;
1852         }
1853
1854         return offset;
1855 }
1856
1857 static int
1858 dissect_connect_client_auth_request(tvbuff_t *tvb, int offset,
1859     packet_info *pinfo, proto_tree *tree, guint32 seq _U_)
1860 {
1861         return dissect_auth_data(tvb, offset, pinfo, tree);
1862 }
1863
1864 static int
1865 dissect_connect_server_auth_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
1866     proto_tree *tree, guint32 seq _U_)
1867 {
1868         /* error */
1869         proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
1870         offset += 4;
1871
1872         /* auth data */
1873         offset = dissect_auth_data(tvb, offset, pinfo, tree);
1874
1875         return offset;
1876 }
1877
1878 static int
1879 dissect_tape_write_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
1880     proto_tree *tree, guint32 seq _U_)
1881 {
1882         /* data */
1883         offset = dissect_rpc_data(tvb, tree, hf_ndmp_data, offset);
1884
1885         return offset;
1886 }
1887
1888 static int
1889 dissect_tape_write_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
1890     proto_tree *tree, guint32 seq _U_)
1891 {
1892         /* error */
1893         proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
1894         offset += 4;
1895
1896         /* count */
1897         proto_tree_add_item(tree, hf_ndmp_count, tvb, offset, 4, FALSE);
1898         offset += 4;
1899
1900         return offset;
1901 }
1902
1903 static int
1904 dissect_tape_read_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
1905     proto_tree *tree, guint32 seq _U_)
1906 {
1907         /* count */
1908         proto_tree_add_item(tree, hf_ndmp_count, tvb, offset, 4, FALSE);
1909         offset += 4;
1910
1911         return offset;
1912 }
1913
1914 static int
1915 dissect_tape_read_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
1916     proto_tree *tree, guint32 seq _U_)
1917 {
1918         /* error */
1919         proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
1920         offset += 4;
1921
1922         /* data */
1923         offset = dissect_rpc_data(tvb, tree, hf_ndmp_data, offset);
1924
1925         return offset;
1926 }
1927
1928 #define NDMP_FS_UNIX    0
1929 #define NDMP_FS_NT      1
1930 #define NDMP_FS_OTHER   2
1931 static const value_string file_fs_type_vals[] = {
1932         {NDMP_FS_UNIX,  "UNIX"},
1933         {NDMP_FS_NT,    "NT"},
1934         {NDMP_FS_OTHER, "OTHER"},
1935         {0, NULL}
1936 };
1937
1938 static int
1939 dissect_file_name(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
1940 {
1941         proto_item* item = NULL;
1942         proto_tree* tree = NULL;
1943         int old_offset=offset;
1944         guint32 type;
1945         char *name;
1946
1947         if (parent_tree) {
1948                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
1949                                 "File");
1950                 tree = proto_item_add_subtree(item, ett_ndmp_file_name);
1951         }
1952
1953         /* file type */
1954         type=tvb_get_ntohl(tvb, offset);
1955         proto_tree_add_item(tree, hf_ndmp_file_fs_type, tvb, offset, 4, FALSE);
1956         offset += 4;
1957
1958         switch(type){
1959         case NDMP_FS_UNIX:
1960                 /* file */
1961                 offset = dissect_rpc_string(tvb, tree,
1962                                 hf_ndmp_file_name, offset, &name);
1963                 if (check_col(pinfo->cinfo, COL_INFO)){
1964                         col_append_fstr(pinfo->cinfo, COL_INFO, " %s", name);
1965                 }
1966                 break;
1967         case NDMP_FS_NT:
1968                 /* nt file */
1969                 offset = dissect_rpc_string(tvb, tree,
1970                                 hf_ndmp_nt_file_name, offset, &name);
1971                 if (check_col(pinfo->cinfo, COL_INFO)){
1972                         col_append_fstr(pinfo->cinfo, COL_INFO, " %s", name);
1973                 }
1974
1975                 /* dos file */
1976                 offset = dissect_rpc_string(tvb, tree,
1977                                 hf_ndmp_dos_file_name, offset, NULL);
1978                 break;
1979         default:
1980                 /* file */
1981                 offset = dissect_rpc_string(tvb, tree,
1982                                 hf_ndmp_file_name, offset, &name);
1983                 if (check_col(pinfo->cinfo, COL_INFO)){
1984                         col_append_fstr(pinfo->cinfo, COL_INFO, " %s", name);
1985                 }
1986         }
1987
1988         if (check_col(pinfo->cinfo, COL_INFO)){
1989                 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
1990                         val_to_str(type, file_fs_type_vals, "Unknown type") );
1991         }
1992
1993         proto_item_set_len(item, offset-old_offset);
1994         return offset;
1995 }
1996
1997
1998 static const true_false_string tfs_ndmp_file_invalid_atime = {
1999         "Atime is INVALID",
2000         "Atime is valid"
2001 };
2002 static const true_false_string tfs_ndmp_file_invalid_ctime = {
2003         "Ctime is INVALID",
2004         "Ctime is valid"
2005 };
2006 static const true_false_string tfs_ndmp_file_invalid_group = {
2007         "Group is INVALID",
2008         "Group is valid"
2009 };
2010 static int
2011 dissect_file_invalids(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
2012     proto_tree *parent_tree)
2013 {
2014         proto_item* item = NULL;
2015         proto_tree* tree = NULL;
2016         guint32 flags;
2017
2018         flags=tvb_get_ntohl(tvb, offset);
2019         if (parent_tree) {
2020                 item = proto_tree_add_text(parent_tree, tvb, offset, 4,
2021                                 "Invalids: 0x%08x", flags);
2022                 tree = proto_item_add_subtree(item, ett_ndmp_file_invalids);
2023         }
2024
2025         proto_tree_add_boolean(tree, hf_ndmp_file_invalid_group,
2026                         tvb, offset, 4, flags);
2027         proto_tree_add_boolean(tree, hf_ndmp_file_invalid_ctime,
2028                         tvb, offset, 4, flags);
2029         proto_tree_add_boolean(tree, hf_ndmp_file_invalid_atime,
2030                         tvb, offset, 4, flags);
2031
2032         offset+=4;
2033         return offset;
2034 }
2035
2036 #define NDMP_FILE_TYPE_DIR      0
2037 #define NDMP_FILE_TYPE_FIFO     1
2038 #define NDMP_FILE_TYPE_CSPEC    2
2039 #define NDMP_FILE_TYPE_BSPEC    3
2040 #define NDMP_FILE_TYPE_REG      4
2041 #define NDMP_FILE_TYPE_SLINK    5
2042 #define NDMP_FILE_TYPE_SOCK     6
2043 #define NDMP_FILE_TYPE_REGISTRY 7
2044 #define NDMP_FILE_TYPE_OTHER    8
2045 static const value_string file_type_vals[] = {
2046         {NDMP_FILE_TYPE_DIR,    "DIR"},
2047         {NDMP_FILE_TYPE_FIFO,   "FIFO"},
2048         {NDMP_FILE_TYPE_CSPEC,  "CSPEC"},
2049         {NDMP_FILE_TYPE_BSPEC,  "BSPEC"},
2050         {NDMP_FILE_TYPE_REG,    "REG"},
2051         {NDMP_FILE_TYPE_SLINK,  "SLINK"},
2052         {NDMP_FILE_TYPE_SOCK,   "SOCK"},
2053         {NDMP_FILE_TYPE_REGISTRY,       "REGISTRY"},
2054         {NDMP_FILE_TYPE_OTHER,  "OTHER"},
2055         {0, NULL}
2056 };
2057
2058 static int
2059 dissect_file_stats(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
2060 {
2061         proto_item* item = NULL;
2062         proto_tree* tree = NULL;
2063         int old_offset=offset;
2064         nstime_t ns;
2065
2066         if (parent_tree) {
2067                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
2068                                 "Stats:");
2069                 tree = proto_item_add_subtree(item, ett_ndmp_file_stats);
2070         }
2071
2072         /* invalids */
2073         offset = dissect_file_invalids(tvb, offset, pinfo, tree);
2074
2075         /* file fs type */
2076         proto_tree_add_item(tree, hf_ndmp_file_fs_type, tvb, offset, 4, FALSE);
2077         offset += 4;
2078
2079         /* file type */
2080         proto_tree_add_item(tree, hf_ndmp_file_type, tvb, offset, 4, FALSE);
2081         offset += 4;
2082
2083         /* mtime */
2084         ns.secs=tvb_get_ntohl(tvb, offset);
2085         ns.nsecs=0;
2086         proto_tree_add_time(tree, hf_ndmp_file_mtime, tvb, offset, 4, &ns);
2087         offset += 4;
2088
2089         /* atime */
2090         ns.secs=tvb_get_ntohl(tvb, offset);
2091         ns.nsecs=0;
2092         proto_tree_add_time(tree, hf_ndmp_file_atime, tvb, offset, 4, &ns);
2093         offset += 4;
2094
2095         /* ctime */
2096         ns.secs=tvb_get_ntohl(tvb, offset);
2097         ns.nsecs=0;
2098         proto_tree_add_time(tree, hf_ndmp_file_ctime, tvb, offset, 4, &ns);
2099         offset += 4;
2100
2101         /* owner */
2102         proto_tree_add_item(tree, hf_ndmp_file_owner, tvb, offset, 4, FALSE);
2103         offset += 4;
2104
2105         /* group */
2106         proto_tree_add_item(tree, hf_ndmp_file_group, tvb, offset, 4, FALSE);
2107         offset += 4;
2108
2109         /*XXX here we should do proper dissection of mode for unix or
2110               fattr for nt, call appropriate functions in nfs/smb*/
2111         /* fattr */
2112         proto_tree_add_item(tree, hf_ndmp_file_fattr, tvb, offset, 4, FALSE);
2113         offset += 4;
2114
2115         /*file size*/
2116         offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_file_size,
2117                         offset);
2118
2119         /* links */
2120         proto_tree_add_item(tree, hf_ndmp_file_links, tvb, offset, 4, FALSE);
2121         offset += 4;
2122
2123         proto_item_set_len(item, offset-old_offset);
2124         return offset;
2125 }
2126
2127
2128 static int
2129 dissect_file(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
2130 {
2131         proto_item* item = NULL;
2132         proto_tree* tree = NULL;
2133         int old_offset=offset;
2134
2135         if (parent_tree) {
2136                 item = proto_tree_add_text(parent_tree, tvb, offset, -1,
2137                                 "File:");
2138                 tree = proto_item_add_subtree(item, ett_ndmp_file);
2139         }
2140
2141         /* file names */
2142         offset = dissect_rpc_array(tvb, pinfo, tree, offset,
2143                         dissect_file_name, hf_ndmp_file_names);
2144
2145         /* file stats */
2146         offset = dissect_rpc_array(tvb, pinfo, tree, offset,
2147                         dissect_file_stats, hf_ndmp_file_stats);
2148
2149         /* node */
2150         proto_tree_add_item(tree, hf_ndmp_file_node, tvb, offset, 8, FALSE);
2151         offset += 8;
2152
2153         /* fh_info */
2154         proto_tree_add_item(tree, hf_ndmp_file_fh_info, tvb, offset, 8, FALSE);
2155         offset += 8;
2156
2157         proto_item_set_len(item, offset-old_offset);
2158         return offset;
2159 }
2160
2161 static int
2162 dissect_fh_add_file_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
2163     proto_tree *tree, guint32 seq _U_)
2164 {
2165         /* files */
2166         offset = dissect_rpc_array(tvb, pinfo, tree, offset,
2167                         dissect_file, hf_ndmp_files);
2168
2169         return offset;
2170 }
2171
2172 static int
2173 dissect_dir(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
2174 {
2175         /* file names */
2176         offset = dissect_rpc_array(tvb, pinfo, tree, offset,
2177                         dissect_file_name, hf_ndmp_file_names);
2178
2179         /* node */
2180         proto_tree_add_item(tree, hf_ndmp_file_node, tvb, offset, 8, FALSE);
2181         offset += 8;
2182
2183         /* parent */
2184         proto_tree_add_item(tree, hf_ndmp_file_parent, tvb, offset, 8, FALSE);
2185         offset += 8;
2186
2187         return offset;
2188 }
2189
2190 static int
2191 dissect_fh_add_dir_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
2192     proto_tree *tree, guint32 seq _U_)
2193 {
2194         /* dirs */
2195         offset = dissect_rpc_array(tvb, pinfo, tree, offset,
2196                         dissect_dir, hf_ndmp_dirs);
2197
2198         return offset;
2199 }
2200
2201 static int
2202 dissect_node(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
2203 {
2204         /* file stats */
2205         offset = dissect_rpc_array(tvb, pinfo, tree, offset,
2206                         dissect_file_stats, hf_ndmp_file_stats);
2207
2208         /* node */
2209         proto_tree_add_item(tree, hf_ndmp_file_node, tvb, offset, 8, FALSE);
2210         offset += 8;
2211
2212         /* fh_info */
2213         proto_tree_add_item(tree, hf_ndmp_file_fh_info, tvb, offset, 8, FALSE);
2214         offset += 8;
2215
2216         return offset;
2217 }
2218
2219
2220 static int
2221 dissect_fh_add_node_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
2222     proto_tree *tree, guint32 seq _U_)
2223 {
2224         /* node */
2225         offset = dissect_rpc_array(tvb, pinfo, tree, offset,
2226                         dissect_node, hf_ndmp_nodes);
2227
2228         return offset;
2229 }
2230
2231 static int
2232 dissect_data_start_backup_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
2233     proto_tree *tree, guint32 seq _U_)
2234 {
2235         /*butype name*/
2236         offset = dissect_rpc_string(tvb, tree,
2237                         hf_ndmp_butype_name, offset, NULL);
2238
2239         /* default env */
2240         offset = dissect_rpc_array(tvb, pinfo, tree, offset,
2241                         dissect_default_env, hf_ndmp_butype_default_env);
2242
2243         return offset;
2244 }
2245
2246 static int
2247 dissect_nlist(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
2248     proto_tree *tree)
2249 {
2250         /*original path*/
2251         offset = dissect_rpc_string(tvb, tree,
2252                         hf_ndmp_bu_original_path, offset, NULL);
2253
2254         /*destination dir*/
2255         offset = dissect_rpc_string(tvb, tree,
2256                         hf_ndmp_bu_destination_dir, offset, NULL);
2257
2258         /*new name*/
2259         offset = dissect_rpc_string(tvb, tree,
2260                         hf_ndmp_bu_new_name, offset, NULL);
2261
2262         /*other name*/
2263         offset = dissect_rpc_string(tvb, tree,
2264                         hf_ndmp_bu_other_name, offset, NULL);
2265
2266         /* node */
2267         proto_tree_add_item(tree, hf_ndmp_file_node, tvb, offset, 8, FALSE);
2268         offset += 8;
2269
2270         /* fh_info */
2271         proto_tree_add_item(tree, hf_ndmp_file_fh_info, tvb, offset, 8, FALSE);
2272         offset += 8;
2273
2274         return offset;
2275 }
2276
2277
2278 static int
2279 dissect_data_start_recover_request(tvbuff_t *tvb, int offset,
2280     packet_info *pinfo, proto_tree *tree, guint32 seq _U_)
2281 {
2282         /* default env */
2283         offset = dissect_rpc_array(tvb, pinfo, tree, offset,
2284                         dissect_default_env, hf_ndmp_butype_default_env);
2285
2286         /* nlist */
2287         offset = dissect_rpc_array(tvb, pinfo, tree, offset,
2288                         dissect_nlist, hf_ndmp_nlist);
2289
2290         /*butype name*/
2291         offset = dissect_rpc_string(tvb, tree,
2292                         hf_ndmp_butype_name, offset, NULL);
2293
2294         return offset;
2295 }
2296
2297 static int
2298 dissect_data_get_env_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
2299     proto_tree *tree, guint32 seq _U_)
2300 {
2301         /* error */
2302         proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
2303         offset += 4;
2304
2305         /* default env */
2306         offset = dissect_rpc_array(tvb, pinfo, tree, offset,
2307                         dissect_default_env, hf_ndmp_butype_default_env);
2308
2309         return offset;
2310 }
2311
2312
2313 static const true_false_string tfs_ndmp_state_invalid_ebr = {
2314         "Estimated Bytes Remaining is INVALID",
2315         "Estimated Bytes Remaining is valid"
2316 };
2317 static const true_false_string tfs_ndmp_state_invalid_etr = {
2318         "Estimated Time Remaining is INVALID",
2319         "Estimated Time Remaining is valid"
2320 };
2321 static int
2322 dissect_state_invalids(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
2323     proto_tree *parent_tree)
2324 {
2325         proto_item* item = NULL;
2326         proto_tree* tree = NULL;
2327         guint32 flags;
2328
2329         flags=tvb_get_ntohl(tvb, offset);
2330         if (parent_tree) {
2331                 item = proto_tree_add_text(parent_tree, tvb, offset, 4,
2332                                 "Invalids: 0x%08x", flags);
2333                 tree = proto_item_add_subtree(item, ett_ndmp_state_invalids);
2334         }
2335
2336         proto_tree_add_boolean(tree, hf_ndmp_state_invalid_etr,
2337                                 tvb, offset, 4, flags);
2338         proto_tree_add_boolean(tree, hf_ndmp_state_invalid_ebr,
2339                                 tvb, offset, 4, flags);
2340
2341         offset+=4;
2342         return offset;
2343 }
2344
2345 #define NDMP_DATA_OP_NOACTION   0
2346 #define NDMP_DATA_OP_BACKUP     1
2347 #define NDMP_DATA_OP_RESTORE    2
2348 static const value_string bu_operation_vals[] = {
2349         {NDMP_DATA_OP_NOACTION, "NOACTION"},
2350         {NDMP_DATA_OP_BACKUP,   "BACKUP"},
2351         {NDMP_DATA_OP_RESTORE,  "RESTORE"},
2352         {0, NULL}
2353 };
2354
2355 #define NDMP_DATA_STATE_IDLE            0
2356 #define NDMP_DATA_STATE_ACTIVE          1
2357 #define NDMP_DATA_STATE_HALTED          2
2358 #define NDMP_DATA_STATE_LISTEN          3
2359 #define NDMP_DATA_STATE_CONNECTED       4
2360 static const value_string data_state_vals[] = {
2361         {NDMP_DATA_STATE_IDLE,          "IDLE"},
2362         {NDMP_DATA_STATE_ACTIVE,        "ACTIVE"},
2363         {NDMP_DATA_STATE_HALTED,        "HALTED"},
2364         {NDMP_DATA_STATE_LISTEN,        "LISTEN"},
2365         {NDMP_DATA_STATE_CONNECTED,     "CONNECTED"},
2366         {0, NULL}
2367 };
2368
2369 #define NDMP_DATA_HALTED_NA             0
2370 #define NDMP_DATA_HALTED_SUCCESSFUL     1
2371 #define NDMP_DATA_HALTED_ABORTED        2
2372 #define NDMP_DATA_HALTED_INTERNAL_ERROR 3
2373 #define NDMP_DATA_HALTED_CONNECT_ERROR  4
2374 static const value_string data_halted_vals[] = {
2375         {NDMP_DATA_HALTED_NA,                   "HALTED_NA"},
2376         {NDMP_DATA_HALTED_SUCCESSFUL,           "HALTED_SUCCESSFUL"},
2377         {NDMP_DATA_HALTED_ABORTED,              "HALTED_ABORTED"},
2378         {NDMP_DATA_HALTED_INTERNAL_ERROR,       "HALTED_INTERNAL_ERROR"},
2379         {NDMP_DATA_HALTED_CONNECT_ERROR,        "HALTED_CONNECT_ERROR"},
2380         {0, NULL}
2381 };
2382
2383 static int
2384 dissect_data_get_state_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
2385     proto_tree *tree, guint32 seq _U_)
2386 {
2387         nstime_t ns;
2388
2389         /* invalids */
2390         offset = dissect_state_invalids(tvb, offset, pinfo, tree);
2391
2392         /* error */
2393         proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
2394         offset += 4;
2395
2396         /* operation */
2397         proto_tree_add_item(tree, hf_ndmp_bu_operation, tvb, offset, 4, FALSE);
2398         offset += 4;
2399
2400         /* state */
2401         proto_tree_add_item(tree, hf_ndmp_data_state, tvb, offset, 4, FALSE);
2402         offset += 4;
2403
2404         /* halted reason */
2405         proto_tree_add_item(tree, hf_ndmp_data_halted, tvb, offset, 4, FALSE);
2406         offset += 4;
2407
2408         /*bytes processed*/
2409         offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_data_bytes_processed,
2410                         offset);
2411
2412         /*est bytes remain*/
2413         offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_data_est_bytes_remain,
2414                         offset);
2415
2416         /* est time remain */
2417         ns.secs=tvb_get_ntohl(tvb, offset);
2418         ns.nsecs=0;
2419         proto_tree_add_time(tree, hf_ndmp_data_est_time_remain, tvb, offset, 4, &ns);
2420         offset += 4;
2421
2422         /* ndmp addr */
2423         offset=dissect_ndmp_addr(tvb, offset, pinfo, tree);
2424
2425         /* window offset */
2426         proto_tree_add_item(tree, hf_ndmp_window_offset, tvb, offset, 8, FALSE);
2427         offset += 8;
2428
2429         /* window length */
2430         proto_tree_add_item(tree, hf_ndmp_window_length, tvb, offset, 8, FALSE);
2431         offset += 8;
2432
2433         return offset;
2434 }
2435
2436
2437 typedef struct _ndmp_command {
2438         guint32 cmd;
2439         int (*request) (tvbuff_t *tvb, int offset, packet_info *pinfo,
2440             proto_tree *tree, guint32 seq);
2441         int (*response)(tvbuff_t *tvb, int offset, packet_info *pinfo,
2442             proto_tree *tree, guint32 seq);
2443 } ndmp_command;
2444
2445 static const ndmp_command ndmp_commands[] = {
2446         {NDMP_CONFIG_GET_HOST_INFO,
2447                 NULL, dissect_ndmp_get_host_info_reply},
2448         {NDMP_CONFIG_GET_CONNECTION_TYPE,
2449                 NULL, dissect_ndmp_config_get_connection_type_reply},
2450         {NDMP_CONFIG_GET_AUTH_ATTR,
2451                 dissect_get_auth_type_request, dissect_auth_attr_msg},
2452         {NDMP_CONFIG_GET_BUTYPE_INFO,
2453                 NULL, dissect_get_butype_info_reply},
2454         {NDMP_CONFIG_GET_FS_INFO,
2455                 NULL, dissect_get_fs_info_reply},
2456         {NDMP_CONFIG_GET_TAPE_INFO,
2457                 NULL, dissect_get_tape_info_reply},
2458         {NDMP_CONFIG_GET_SCSI_INFO,
2459                 NULL, dissect_get_scsi_info_reply},
2460         {NDMP_CONFIG_GET_SERVER_INFO,
2461                 NULL, dissect_get_server_info_reply},
2462         {NDMP_SCSI_OPEN,
2463                 dissect_scsi_open_request, dissect_error},
2464         {NDMP_SCSI_CLOSE,
2465                 NULL, dissect_error},
2466         {NDMP_SCSI_GET_STATE,
2467                 NULL, dissect_scsi_get_state_reply},
2468         {NDMP_SCSI_SET_TARGET,
2469                 dissect_scsi_set_state_request, dissect_error},
2470         {NDMP_SCSI_RESET_DEVICE,
2471                 NULL, dissect_error},
2472         {NDMP_SCSI_RESET_BUS,
2473                 NULL, dissect_error},
2474         {NDMP_SCSI_EXECUTE_CDB,
2475                 dissect_execute_cdb_request_mc, dissect_execute_cdb_reply},
2476         {NDMP_TAPE_OPEN,
2477                 dissect_tape_open_request, dissect_error},
2478         {NDMP_TAPE_CLOSE,
2479                 NULL, dissect_error},
2480         {NDMP_TAPE_GET_STATE,
2481                 NULL, dissect_tape_get_state_reply},
2482         {NDMP_TAPE_MTIO,
2483                 dissect_tape_mtio_request, dissect_tape_mtio_reply},
2484         {NDMP_TAPE_WRITE,
2485                 dissect_tape_write_request, dissect_tape_write_reply},
2486         {NDMP_TAPE_READ,
2487                 dissect_tape_read_request, dissect_tape_read_reply},
2488         {NDMP_TAPE_EXECUTE_CDB,
2489                 dissect_execute_cdb_request_tape, dissect_execute_cdb_reply},
2490         {NDMP_DATA_GET_STATE,
2491                 NULL, dissect_data_get_state_reply},
2492         {NDMP_DATA_START_BACKUP,
2493                 dissect_data_start_backup_request, dissect_error },
2494         {NDMP_DATA_START_RECOVER,
2495                 dissect_data_start_recover_request, dissect_error },
2496         {NDMP_DATA_ABORT,
2497                 NULL, dissect_error},
2498         {NDMP_DATA_GET_ENV,
2499                 NULL, dissect_data_get_env_reply},
2500         {NDMP_DATA_STOP,
2501                 NULL, dissect_error},
2502         {NDMP_DATA_LISTEN,
2503                 dissect_ndmp_addr_msg, dissect_mover_listen_reply},
2504         {NDMP_DATA_CONNECT,
2505                 dissect_ndmp_addr_msg, dissect_error},
2506         {NDMP_NOTIFY_DATA_HALTED,
2507                 dissect_notify_data_halted_request, NULL},
2508         {NDMP_NOTIFY_CONNECTED,
2509                 dissect_notify_connected_request, NULL},
2510         {NDMP_NOTIFY_MOVER_HALTED,
2511                 dissect_notify_data_halted_request, NULL},
2512         {NDMP_NOTIFY_MOVER_PAUSED,
2513                 dissect_notify_mover_paused_request, NULL},
2514         {NDMP_NOTIFY_DATA_READ,
2515                 dissect_mover_set_window_request, NULL},
2516         {NDMP_LOG_FILE,
2517                 dissect_log_file_request, NULL},
2518         {NDMP_LOG_MESSAGE,
2519                 dissect_log_message_request, NULL},
2520         {NDMP_FH_ADD_FILE,
2521                 dissect_fh_add_file_request, NULL},
2522         {NDMP_FH_ADD_DIR,
2523                 dissect_fh_add_dir_request, NULL},
2524         {NDMP_FH_ADD_NODE,
2525                 dissect_fh_add_node_request, NULL},
2526         {NDMP_CONNECT_OPEN,
2527                 dissect_connect_open_request, dissect_error},
2528         {NDMP_CONNECT_CLIENT_AUTH,
2529                 dissect_connect_client_auth_request, dissect_error},
2530         {NDMP_CONNECT_CLOSE,
2531                 NULL,NULL},
2532         {NDMP_CONNECT_SERVER_AUTH,
2533                 dissect_auth_attr_msg, dissect_connect_server_auth_reply},
2534         {NDMP_MOVER_GET_STATE,
2535                 NULL, dissect_mover_get_state_reply},
2536         {NDMP_MOVER_LISTEN,
2537                 dissect_mover_listen_request, dissect_mover_listen_reply},
2538         {NDMP_MOVER_CONTINUE,
2539                 NULL, dissect_error},
2540         {NDMP_MOVER_ABORT,
2541                 NULL, dissect_error},
2542         {NDMP_MOVER_STOP,
2543                 NULL, dissect_error},
2544         {NDMP_MOVER_SET_WINDOW,
2545                 dissect_mover_set_window_request, dissect_error},
2546         {NDMP_MOVER_READ,
2547                 dissect_mover_set_window_request, dissect_error},
2548         {NDMP_MOVER_CLOSE,
2549                 NULL, dissect_error},
2550         {NDMP_MOVER_SET_RECORD_SIZE,
2551                 dissect_mover_set_record_size_request, dissect_error},
2552         {NDMP_MOVER_CONNECT,
2553                 dissect_mover_connect_request, dissect_error},
2554         {0, NULL,NULL}
2555 };
2556
2557
2558 static int
2559 dissect_ndmp_header(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, struct ndmp_header *nh)
2560 {
2561         proto_item* item = NULL;
2562         proto_tree* tree = NULL;
2563         nstime_t ns;
2564
2565         if (parent_tree) {
2566                 item = proto_tree_add_item(parent_tree, hf_ndmp_header, tvb,
2567                                 offset, 24, FALSE);
2568                 tree = proto_item_add_subtree(item, ett_ndmp_header);
2569         }
2570
2571         /* sequence number */
2572         proto_tree_add_uint(tree, hf_ndmp_sequence, tvb, offset, 4, nh->seq);
2573         offset += 4;
2574
2575         /* timestamp */
2576         ns.secs=nh->time;
2577         ns.nsecs=0;
2578         proto_tree_add_time(tree, hf_ndmp_timestamp, tvb, offset, 4, &ns);
2579         offset += 4;
2580
2581         /* Message Type */
2582         proto_tree_add_uint(tree, hf_ndmp_msgtype, tvb, offset, 4, nh->type);
2583         offset += 4;
2584
2585         /* Message */
2586         proto_tree_add_uint(tree, hf_ndmp_msg, tvb, offset, 4, nh->msg);
2587         offset += 4;
2588
2589         /* Reply sequence number */
2590         proto_tree_add_uint(tree, hf_ndmp_reply_sequence, tvb, offset, 4, nh->rep_seq);
2591         offset += 4;
2592
2593         /* error */
2594         proto_tree_add_uint(tree, hf_ndmp_error, tvb, offset, 4, nh->err);
2595         offset += 4;
2596
2597         if (check_col(pinfo->cinfo, COL_INFO)){
2598                 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
2599                         val_to_str(nh->msg, msg_vals, "Unknown Message (0x%02x)"),
2600                         val_to_str(nh->type, msg_type_vals, "Unknown Type (0x%02x)")
2601                         );
2602         }
2603
2604         return offset;
2605 }
2606
2607
2608 static int
2609 dissect_ndmp_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, struct ndmp_header *nh)
2610 {
2611         int i;
2612         proto_item *cmd_item=NULL;
2613         proto_tree *cmd_tree=NULL;
2614
2615         offset=dissect_ndmp_header(tvb, offset, pinfo, tree, nh);
2616
2617         for(i=0;ndmp_commands[i].cmd!=0;i++){
2618                 if(ndmp_commands[i].cmd==nh->msg){
2619                         break;
2620                 }
2621         }
2622
2623
2624         if(ndmp_commands[i].cmd==0){
2625                 /* we do not know this message */
2626                 proto_tree_add_text(tree, tvb, offset, -1, "Unknown type of NDMP message: 0x%02x", nh->msg);
2627                 offset+=tvb_length_remaining(tvb, offset);
2628                 return offset;
2629         }
2630
2631         if(tree){
2632                 cmd_item = proto_tree_add_text(tree, tvb, offset, -1,
2633                         msg_vals[i].strptr);
2634                 cmd_tree = proto_item_add_subtree(cmd_item, ett_ndmp);
2635         }
2636
2637         if(nh->type==NDMP_MESSAGE_REQUEST){
2638                 if(ndmp_commands[i].request){
2639                         offset=ndmp_commands[i].request(tvb, offset, pinfo, cmd_tree,
2640                             nh->seq);
2641                 }
2642         } else {
2643                 if(ndmp_commands[i].response){
2644                         offset=ndmp_commands[i].response(tvb, offset, pinfo, cmd_tree,
2645                             nh->rep_seq);
2646                 }
2647         }
2648
2649         return offset;
2650 }
2651
2652 static gboolean
2653 dissect_ndmp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2654     tvbuff_t *frag_tvb, fragment_data *ipfd_head, gboolean is_tcp,
2655     guint32 rpc_rm, gboolean first_pdu)
2656 {
2657         int offset = (is_tcp && tvb == frag_tvb) ? 4 : 0;
2658         guint32 size;
2659         struct ndmp_header nh;
2660         proto_item *ndmp_item = NULL;
2661         proto_tree *ndmp_tree = NULL;
2662
2663         /* size of this NDMP PDU */
2664         size = tvb_length_remaining(tvb, offset);
2665         if (size < 24) {
2666                 /* too short to be NDMP */
2667                 return FALSE;
2668         }
2669
2670         /*
2671          * Check the NDMP header, if we have it.
2672          */
2673         nh.seq = tvb_get_ntohl(tvb, offset);
2674         nh.time = tvb_get_ntohl(tvb, offset+4);
2675         nh.type = tvb_get_ntohl(tvb, offset+8);
2676         nh.msg = tvb_get_ntohl(tvb, offset+12);
2677         nh.rep_seq = tvb_get_ntohl(tvb, offset+16);
2678         nh.err = tvb_get_ntohl(tvb, offset+20);
2679
2680         if (nh.type > 1)
2681                 return FALSE;
2682         if (nh.msg > 0xa09 || nh.msg == 0)
2683                 return FALSE;
2684         if (nh.err > 0x17)
2685                 return FALSE;
2686
2687         /*
2688          * Check if this is the last fragment.
2689          */
2690         if (!(rpc_rm & RPC_RM_LASTFRAG)) {
2691                 /*
2692                  * This isn't the last fragment.
2693                  * If we're doing reassembly, just return
2694                  * TRUE to indicate that this looks like
2695                  * the beginning of an NDMP message,
2696                  * and let them do reassembly.
2697                  */
2698                 if (ndmp_defragment)
2699                         return TRUE;
2700         }
2701
2702         if (check_col(pinfo->cinfo, COL_PROTOCOL))
2703                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NDMP");
2704         if (check_col(pinfo->cinfo, COL_INFO)) {
2705                 if (first_pdu)
2706                         col_clear(pinfo->cinfo, COL_INFO);
2707                 else
2708                         col_append_fstr(pinfo->cinfo, COL_INFO, "; ");
2709         }
2710
2711         if (tree) {
2712                 ndmp_item = proto_tree_add_item(tree, proto_ndmp,
2713                     tvb, 0, -1, FALSE);
2714                 ndmp_tree = proto_item_add_subtree(ndmp_item, ett_ndmp);
2715
2716                 if (is_tcp) {
2717                         show_rpc_fraginfo(tvb, frag_tvb, ndmp_tree, rpc_rm,
2718                             ipfd_head, pinfo);
2719                 }
2720         }
2721
2722         /*
2723          * We cannot trust what dissect_ndmp_cmd() tells us, as there
2724          * are implementations which pad some additional data after
2725          * the PDU.  We MUST use size.
2726          */
2727         dissect_ndmp_cmd(tvb, offset, pinfo, ndmp_tree, &nh);
2728         return TRUE;
2729 }
2730
2731 static void
2732 dissect_ndmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2733 {
2734         int offset = 0;
2735         int len;
2736         gboolean first_pdu = TRUE;
2737
2738         while (tvb_reported_length_remaining(tvb, offset) != 0) {
2739                 /*
2740                  * Process this fragment.
2741                  */
2742                 len = dissect_rpc_fragment(tvb, offset, pinfo, tree,
2743                     dissect_ndmp_message, FALSE, proto_ndmp, ett_ndmp,
2744                     ndmp_defragment, first_pdu);
2745                 first_pdu = FALSE;
2746                 if (len < 0) {
2747                         /*
2748                          * We need more data from the TCP stream for
2749                          * this fragment.
2750                          */
2751                         return;
2752                 }
2753                 if (len == 0) {
2754                         /*
2755                          * It's not NDMP.  Stop processing.
2756                          */
2757                         break;
2758                 }
2759
2760                 offset += len;
2761         }
2762 }
2763
2764 void
2765 proto_register_ndmp(void)
2766 {
2767
2768   static hf_register_info hf_ndmp[] = {
2769         { &hf_ndmp_header, {
2770                 "NDMP Header", "ndmp.header", FT_NONE, 0,
2771                 NULL, 0, "NDMP Header", HFILL }},
2772
2773         { &hf_ndmp_sequence, {
2774                 "Sequence", "ndmp.sequence", FT_UINT32, BASE_DEC,
2775                 NULL, 0, "Sequence number for NDMP PDU", HFILL }},
2776
2777         { &hf_ndmp_reply_sequence, {
2778                 "Reply Sequence", "ndmp.reply_sequence", FT_UINT32, BASE_DEC,
2779                 NULL, 0, "Reply Sequence number for NDMP PDU", HFILL }},
2780
2781         { &hf_ndmp_timestamp, {
2782                 "Time", "ndmp.timestamp", FT_ABSOLUTE_TIME, BASE_NONE,
2783                 NULL, 0, "Timestamp for this NDMP PDU", HFILL }},
2784
2785         { &hf_ndmp_msgtype, {
2786                 "Type", "ndmp.msg_type", FT_UINT32, BASE_DEC,
2787                 VALS(msg_type_vals), 0, "Is this a Request or Response?", HFILL }},
2788
2789         { &hf_ndmp_msg, {
2790                 "Message", "ndmp.msg", FT_UINT32, BASE_HEX,
2791                 VALS(msg_vals), 0, "Type of NDMP PDU", HFILL }},
2792
2793         { &hf_ndmp_error, {
2794                 "Error", "ndmp.error", FT_UINT32, BASE_DEC,
2795                 VALS(error_vals), 0, "Error code for this NDMP PDU", HFILL }},
2796
2797         { &hf_ndmp_version, {
2798                 "Version", "ndmp.version", FT_UINT32, BASE_DEC,
2799                 NULL, 0, "Version of NDMP protocol", HFILL }},
2800
2801         { &hf_ndmp_hostname, {
2802                 "Hostname", "ndmp.hostname", FT_STRING, BASE_NONE,
2803                 NULL, 0, "Hostname", HFILL }},
2804
2805         { &hf_ndmp_hostid, {
2806                 "HostID", "ndmp.hostid", FT_STRING, BASE_NONE,
2807                 NULL, 0, "HostID", HFILL }},
2808
2809         { &hf_ndmp_os_type, {
2810                 "OS Type", "ndmp.os.type", FT_STRING, BASE_NONE,
2811                 NULL, 0, "OS Type", HFILL }},
2812
2813         { &hf_ndmp_os_vers, {
2814                 "OS Version", "ndmp.os.version", FT_STRING, BASE_NONE,
2815                 NULL, 0, "OS Version", HFILL }},
2816
2817         { &hf_ndmp_addr_types, {
2818                 "Addr Types", "ndmp.addr_types", FT_NONE, BASE_NONE,
2819                 NULL, 0, "List Of Address Types", HFILL }},
2820
2821         { &hf_ndmp_addr_type, {
2822                 "Addr Type", "ndmp.addr_type", FT_UINT32, BASE_DEC,
2823                 VALS(addr_type_vals), 0, "Address Type", HFILL }},
2824
2825         { &hf_ndmp_auth_type, {
2826                 "Auth Type", "ndmp.auth_type", FT_UINT32, BASE_DEC,
2827                 VALS(auth_type_vals), 0, "Authentication Type", HFILL }},
2828
2829         { &hf_ndmp_auth_challenge, {
2830                 "Challenge", "ndmp.auth.challenge", FT_BYTES, BASE_HEX,
2831                 NULL, 0, "Authentication Challenge", HFILL }},
2832
2833         { &hf_ndmp_auth_digest, {
2834                 "Digest", "ndmp.auth.digest", FT_BYTES, BASE_HEX,
2835                 NULL, 0, "Authentication Digest", HFILL }},
2836
2837         { &hf_ndmp_butype_info, {
2838                 "Butype Info", "ndmp.butype.info", FT_NONE, BASE_NONE,
2839                 NULL, 0, "Butype Info", HFILL }},
2840
2841         { &hf_ndmp_butype_name, {
2842                 "Butype Name", "ndmp.butype.name", FT_STRING, BASE_NONE,
2843                 NULL, 0, "Name of Butype", HFILL }},
2844
2845         { &hf_ndmp_butype_default_env, {
2846                 "Default Env", "ndmp.butype.default_env", FT_NONE, BASE_NONE,
2847                 NULL, 0, "Default Env's for this Butype Info", HFILL }},
2848
2849         { &hf_ndmp_butype_attr_backup_file_history, {
2850                 "", "ndmp.butype.attr.backup_file_history", FT_BOOLEAN, 32,
2851                 TFS(&tfs_butype_attr_backup_file_history), 0x00000001, "backup_file_history", HFILL }},
2852
2853         { &hf_ndmp_butype_attr_backup_filelist, {
2854                 "", "ndmp.butype.attr.backup_filelist", FT_BOOLEAN, 32,
2855                 TFS(&tfs_butype_attr_backup_filelist), 0x00000002, "backup_filelist", HFILL }},
2856
2857         { &hf_ndmp_butype_attr_recover_filelist, {
2858                 "", "ndmp.butype.attr.recover_filelist", FT_BOOLEAN, 32,
2859                 TFS(&tfs_butype_attr_recover_filelist), 0x00000004, "recover_filelist", HFILL }},
2860
2861         { &hf_ndmp_butype_attr_backup_direct, {
2862                 "", "ndmp.butype.attr.backup_direct", FT_BOOLEAN, 32,
2863                 TFS(&tfs_butype_attr_backup_direct), 0x00000008, "backup_direct", HFILL }},
2864
2865         { &hf_ndmp_butype_attr_recover_direct, {
2866                 "", "ndmp.butype.attr.recover_direct", FT_BOOLEAN, 32,
2867                 TFS(&tfs_butype_attr_recover_direct), 0x00000010, "recover_direct", HFILL }},
2868
2869         { &hf_ndmp_butype_attr_backup_incremental, {
2870                 "", "ndmp.butype.attr.backup_incremental", FT_BOOLEAN, 32,
2871                 TFS(&tfs_butype_attr_backup_incremental), 0x00000020, "backup_incremental", HFILL }},
2872
2873         { &hf_ndmp_butype_attr_recover_incremental, {
2874                 "", "ndmp.butype.attr.recover_incremental", FT_BOOLEAN, 32,
2875                 TFS(&tfs_butype_attr_recover_incremental), 0x00000040, "recover_incremental", HFILL }},
2876
2877         { &hf_ndmp_butype_attr_backup_utf8, {
2878                 "", "ndmp.butype.attr.backup_utf8", FT_BOOLEAN, 32,
2879                 TFS(&tfs_butype_attr_backup_utf8), 0x00000080, "backup_utf8", HFILL }},
2880
2881         { &hf_ndmp_butype_attr_recover_utf8, {
2882                 "", "ndmp.butype.attr.recover_utf8", FT_BOOLEAN, 32,
2883                 TFS(&tfs_butype_attr_recover_utf8), 0x00000100, "recover_utf8", HFILL }},
2884
2885         { &hf_ndmp_butype_env_name, {
2886                 "Name", "ndmp.butype.env.name", FT_STRING, BASE_NONE,
2887                 NULL, 0, "Name for this env-variable", HFILL }},
2888
2889         { &hf_ndmp_butype_env_value, {
2890                 "Value", "ndmp.butype.env.value", FT_STRING, BASE_NONE,
2891                 NULL, 0, "Value for this env-variable", HFILL }},
2892
2893         { &hf_ndmp_fs_info, {
2894                 "FS Info", "ndmp.fs.info", FT_NONE, BASE_NONE,
2895                 NULL, 0, "FS Info", HFILL }},
2896
2897         { &hf_ndmp_fs_invalid_total_size, {
2898                 "", "ndmp.fs.invalid.total_size", FT_BOOLEAN, 32,
2899                 TFS(&tfs_fs_invalid_total_size), 0x00000001, "If total size is invalid", HFILL }},
2900
2901         { &hf_ndmp_fs_invalid_used_size, {
2902                 "", "ndmp.fs.invalid.used_size", FT_BOOLEAN, 32,
2903                 TFS(&tfs_fs_invalid_used_size), 0x00000002, "If used size is invalid", HFILL }},
2904
2905         { &hf_ndmp_fs_invalid_avail_size, {
2906                 "", "ndmp.fs.invalid.avail_size", FT_BOOLEAN, 32,
2907                 TFS(&tfs_fs_invalid_avail_size), 0x00000004, "If available size is invalid", HFILL }},
2908
2909         { &hf_ndmp_fs_invalid_total_inodes, {
2910                 "", "ndmp.fs.invalid.total_inodes", FT_BOOLEAN, 32,
2911                 TFS(&tfs_fs_invalid_total_inodes), 0x00000008, "If total number of inodes is invalid", HFILL }},
2912
2913         { &hf_ndmp_fs_invalid_used_inodes, {
2914                 "", "ndmp.fs.invalid.used_inodes", FT_BOOLEAN, 32,
2915                 TFS(&tfs_fs_invalid_used_inodes), 0x00000010, "If used number of inodes is invalid", HFILL }},
2916
2917         { &hf_ndmp_fs_fs_type, {
2918                 "Type", "ndmp.fs.type", FT_STRING, BASE_NONE,
2919                 NULL, 0, "Type of FS", HFILL }},
2920
2921         { &hf_ndmp_fs_logical_device, {
2922                 "Logical Device", "ndmp.fs.logical_device", FT_STRING, BASE_NONE,
2923                 NULL, 0, "Name of logical device", HFILL }},
2924
2925         { &hf_ndmp_fs_physical_device, {
2926                 "Physical Device", "ndmp.fs.physical_device", FT_STRING, BASE_NONE,
2927                 NULL, 0, "Name of physical device", HFILL }},
2928
2929         { &hf_ndmp_fs_total_size, {
2930                 "Total Size", "ndmp.fs.total_size", FT_UINT64, BASE_DEC,
2931                 NULL, 0, "Total size of FS", HFILL }},
2932
2933         { &hf_ndmp_fs_used_size, {
2934                 "Used Size", "ndmp.fs.used_size", FT_UINT64, BASE_DEC,
2935                 NULL, 0, "Total used size of FS", HFILL }},
2936
2937         { &hf_ndmp_fs_avail_size, {
2938                 "Avail Size", "ndmp.fs.avail_size", FT_UINT64, BASE_DEC,
2939                 NULL, 0, "Total available size on FS", HFILL }},
2940
2941         { &hf_ndmp_fs_total_inodes, {
2942                 "Total Inodes", "ndmp.fs.total_inodes", FT_UINT64, BASE_DEC,
2943                 NULL, 0, "Total number of inodes on FS", HFILL }},
2944
2945         { &hf_ndmp_fs_used_inodes, {
2946                 "Used Inodes", "ndmp.fs.used_inodes", FT_UINT64, BASE_DEC,
2947                 NULL, 0, "Number of used inodes on FS", HFILL }},
2948
2949         { &hf_ndmp_fs_env, {
2950                 "Env variables", "ndmp.fs.env", FT_NONE, BASE_NONE,
2951                 NULL, 0, "Environment variables for FS", HFILL }},
2952
2953         { &hf_ndmp_fs_env_name, {
2954                 "Name", "ndmp.fs.env.name", FT_STRING, BASE_NONE,
2955                 NULL, 0, "Name for this env-variable", HFILL }},
2956
2957         { &hf_ndmp_fs_env_value, {
2958                 "Value", "ndmp.fs.env.value", FT_STRING, BASE_NONE,
2959                 NULL, 0, "Value for this env-variable", HFILL }},
2960
2961         { &hf_ndmp_fs_status, {
2962                 "Status", "ndmp.fs.status", FT_STRING, BASE_NONE,
2963                 NULL, 0, "Status for this FS", HFILL }},
2964
2965         { &hf_ndmp_tape_info, {
2966                 "Tape Info", "ndmp.tape.info", FT_NONE, BASE_NONE,
2967                 NULL, 0, "Tape Info", HFILL }},
2968
2969         { &hf_ndmp_tape_model, {
2970                 "Model", "ndmp.tape.model", FT_STRING, BASE_NONE,
2971                 NULL, 0, "Model of the TAPE drive", HFILL }},
2972
2973         { &hf_ndmp_tape_dev_cap, {
2974                 "Device Capability", "ndmp.tape.dev_cap", FT_NONE, BASE_NONE,
2975                 NULL, 0, "Tape Device Capability", HFILL }},
2976
2977         { &hf_ndmp_tape_device, {
2978                 "Device", "ndmp.tape.device", FT_STRING, BASE_NONE,
2979                 NULL, 0, "Name of TAPE Device", HFILL }},
2980
2981         { &hf_ndmp_tape_attr_rewind, {
2982                 "", "ndmp.tape.attr.rewind", FT_BOOLEAN, 32,
2983                 TFS(&tfs_tape_attr_rewind), 0x00000001, "If this device supports rewind", HFILL }},
2984
2985         { &hf_ndmp_tape_attr_unload, {
2986                 "", "ndmp.tape.attr.unload", FT_BOOLEAN, 32,
2987                 TFS(&tfs_tape_attr_unload), 0x00000002, "If this device supports unload", HFILL }},
2988
2989         { &hf_ndmp_tape_capability, {
2990                 "Tape Capabilities", "ndmp.tape.capability", FT_NONE, BASE_NONE,
2991                 NULL, 0, "Tape Capabilities", HFILL }},
2992
2993         { &hf_ndmp_tape_capability_name, {
2994                 "Name", "ndmp.tape.cap.name", FT_STRING, BASE_NONE,
2995                 NULL, 0, "Name for this env-variable", HFILL }},
2996
2997         { &hf_ndmp_tape_capability_value, {
2998                 "Value", "ndmp.tape.cap.value", FT_STRING, BASE_NONE,
2999                 NULL, 0, "Value for this env-variable", HFILL }},
3000
3001         { &hf_ndmp_scsi_info, {
3002                 "SCSI Info", "ndmp.scsi.info", FT_NONE, BASE_NONE,
3003                 NULL, 0, "SCSI Info", HFILL }},
3004
3005         { &hf_ndmp_scsi_model, {
3006                 "Model", "ndmp.scsi.model", FT_STRING, BASE_NONE,
3007                 NULL, 0, "Model of the SCSI device", HFILL }},
3008
3009         { &hf_ndmp_server_vendor, {
3010                 "Vendor", "ndmp.server.vendor", FT_STRING, BASE_NONE,
3011                 NULL, 0, "Name of vendor", HFILL }},
3012
3013         { &hf_ndmp_server_product, {
3014                 "Product", "ndmp.server.product", FT_STRING, BASE_NONE,
3015                 NULL, 0, "Name of product", HFILL }},
3016
3017         { &hf_ndmp_server_revision, {
3018                 "Revision", "ndmp.server.revision", FT_STRING, BASE_NONE,
3019                 NULL, 0, "Revision of this product", HFILL }},
3020
3021         { &hf_ndmp_auth_types, {
3022                 "Auth types", "ndmp.auth.types", FT_NONE, BASE_NONE,
3023                 NULL, 0, "Auth types", HFILL }},
3024
3025         { &hf_ndmp_scsi_device, {
3026                 "Device", "ndmp.scsi.device", FT_STRING, BASE_NONE,
3027                 NULL, 0, "Name of SCSI Device", HFILL }},
3028
3029         { &hf_ndmp_scsi_controller, {
3030                 "Controller", "ndmp.scsi.controller", FT_UINT32, BASE_DEC,
3031                 NULL, 0, "Target Controller", HFILL }},
3032
3033         { &hf_ndmp_scsi_id, {
3034                 "ID", "ndmp.scsi.id", FT_UINT32, BASE_DEC,
3035                 NULL, 0, "Target ID", HFILL }},
3036
3037         { &hf_ndmp_scsi_lun, {
3038                 "LUN", "ndmp.scsi.lun", FT_UINT32, BASE_DEC,
3039                 NULL, 0, "Target LUN", HFILL }},
3040
3041         { &hf_ndmp_execute_cdb_flags_data_in, {
3042                 "DATA_IN", "ndmp.execute_cdb.flags.data_in", FT_BOOLEAN, 32,
3043                 NULL, 0x00000001, "DATA_IN", HFILL }},
3044
3045         { &hf_ndmp_execute_cdb_flags_data_out, {
3046                 "DATA_OUT", "ndmp.execute_cdb.flags.data_out", FT_BOOLEAN, 32,
3047                 NULL, 0x00000002, "DATA_OUT", HFILL }},
3048
3049         { &hf_ndmp_execute_cdb_timeout, {
3050                 "Timeout", "ndmp.execute_cdb.timeout", FT_UINT32, BASE_DEC,
3051                 NULL, 0, "Reselect timeout, in milliseconds", HFILL }},
3052
3053         { &hf_ndmp_execute_cdb_datain_len, {
3054                 "Data in length", "ndmp.execute_cdb.datain_len", FT_UINT32, BASE_DEC,
3055                 NULL, 0, "Expected length of data bytes to read", HFILL }},
3056
3057         { &hf_ndmp_execute_cdb_cdb_len, {
3058                 "CDB length", "ndmp.execute_cdb.cdb_len", FT_UINT32, BASE_DEC,
3059                 NULL, 0, "Length of CDB", HFILL }},
3060
3061         { &hf_ndmp_execute_cdb_dataout, {
3062                 "Data out", "ndmp.execute_cdb.dataout", FT_BYTES, BASE_NONE,
3063                 NULL, 0, "Data to be transferred to the SCSI device", HFILL }},
3064
3065         { &hf_ndmp_execute_cdb_status, {
3066                 "Status", "ndmp.execute_cdb.status", FT_UINT8, BASE_DEC,
3067                 VALS(scsi_status_val), 0, "SCSI status", HFILL }},
3068
3069         { &hf_ndmp_execute_cdb_dataout_len, {
3070                 "Data out length", "ndmp.execute_cdb.dataout_len", FT_UINT32, BASE_DEC,
3071                 NULL, 0, "Number of bytes transferred to the device", HFILL }},
3072
3073         { &hf_ndmp_execute_cdb_datain, {
3074                 "Data in", "ndmp.execute_cdb.datain", FT_BYTES, BASE_NONE,
3075                 NULL, 0, "Data transferred from the SCSI device", HFILL }},
3076
3077         { &hf_ndmp_execute_cdb_sns_len, {
3078                 "Sense data length", "ndmp.execute_cdb.sns_len", FT_UINT32, BASE_DEC,
3079                 NULL, 0, "Length of sense data", HFILL }},
3080
3081         { &hf_ndmp_tape_open_mode, {
3082                 "Mode", "ndmp.tape.open_mode", FT_UINT32, BASE_DEC,
3083                 VALS(tape_open_mode_vals), 0, "Mode to open tape in", HFILL }},
3084
3085         { &hf_ndmp_tape_invalid_file_num, {
3086                 "", "ndmp.tape.invalid.file_num", FT_BOOLEAN, 32,
3087                 TFS(&tfs_ndmp_tape_invalid_file_num), 0x00000001, "invalid_file_num", HFILL }},
3088
3089         { &hf_ndmp_tape_invalid_soft_errors, {
3090                 "", "ndmp.tape.invalid.soft_errors", FT_BOOLEAN, 32,
3091                 TFS(&tfs_ndmp_tape_invalid_soft_errors), 0x00000002, "soft_errors", HFILL }},
3092
3093         { &hf_ndmp_tape_invalid_block_size, {
3094                 "", "ndmp.tape.invalid.block_size", FT_BOOLEAN, 32,
3095                 TFS(&tfs_ndmp_tape_invalid_block_size), 0x00000004, "block_size", HFILL }},
3096
3097         { &hf_ndmp_tape_invalid_block_no, {
3098                 "", "ndmp.tape.invalid.block_no", FT_BOOLEAN, 32,
3099                 TFS(&tfs_ndmp_tape_invalid_block_no), 0x00000008, "block_no", HFILL }},
3100
3101         { &hf_ndmp_tape_invalid_total_space, {
3102                 "", "ndmp.tape.invalid.total_space", FT_BOOLEAN, 32,
3103                 TFS(&tfs_ndmp_tape_invalid_total_space), 0x00000010, "total_space", HFILL }},
3104
3105         { &hf_ndmp_tape_invalid_space_remain, {
3106                 "", "ndmp.tape.invalid.space_remain", FT_BOOLEAN, 32,
3107                 TFS(&tfs_ndmp_tape_invalid_space_remain), 0x00000020, "space_remain", HFILL }},
3108
3109         { &hf_ndmp_tape_invalid_partition, {
3110                 "", "ndmp.tape.invalid.partition", FT_BOOLEAN, 32,
3111                 TFS(&tfs_ndmp_tape_invalid_partition), 0x00000040, "partition", HFILL }},
3112
3113         { &hf_ndmp_tape_flags_no_rewind, {
3114                 "", "ndmp.tape.flags.no_rewind", FT_BOOLEAN, 32,
3115                 TFS(&tfs_ndmp_tape_flags_no_rewind), 0x00000008, "no_rewind", HFILL, }},
3116
3117         { &hf_ndmp_tape_flags_write_protect, {
3118                 "", "ndmp.tape.flags.write_protect", FT_BOOLEAN, 32,
3119                 TFS(&tfs_ndmp_tape_flags_write_protect), 0x00000010, "write_protect", HFILL, }},
3120
3121         { &hf_ndmp_tape_flags_error, {
3122                 "", "ndmp.tape.flags.error", FT_BOOLEAN, 32,
3123                 TFS(&tfs_ndmp_tape_flags_error), 0x00000020, "error", HFILL, }},
3124
3125         { &hf_ndmp_tape_flags_unload, {
3126                 "", "ndmp.tape.flags.unload", FT_BOOLEAN, 32,
3127                 TFS(&tfs_ndmp_tape_flags_unload), 0x00000040, "unload", HFILL, }},
3128
3129         { &hf_ndmp_tape_file_num, {
3130                 "file_num", "ndmp.tape.status.file_num", FT_UINT32, BASE_DEC,
3131                 NULL, 0, "file_num", HFILL }},
3132
3133         { &hf_ndmp_tape_soft_errors, {
3134                 "soft_errors", "ndmp.tape.status.soft_errors", FT_UINT32, BASE_DEC,
3135                 NULL, 0, "soft_errors", HFILL }},
3136
3137         { &hf_ndmp_tape_block_size, {
3138                 "block_size", "ndmp.tape.status.block_size", FT_UINT32, BASE_DEC,
3139                 NULL, 0, "block_size", HFILL }},
3140
3141         { &hf_ndmp_tape_block_no, {
3142                 "block_no", "ndmp.tape.status.block_no", FT_UINT32, BASE_DEC,
3143                 NULL, 0, "block_no", HFILL }},
3144
3145         { &hf_ndmp_tape_total_space, {
3146                 "total_space", "ndmp.tape.status.total_space", FT_UINT64, BASE_DEC,
3147                 NULL, 0, "total_space", HFILL }},
3148
3149         { &hf_ndmp_tape_space_remain, {
3150                 "space_remain", "ndmp.tape.status.space_remain", FT_UINT64, BASE_DEC,
3151                 NULL, 0, "space_remain", HFILL }},
3152
3153         { &hf_ndmp_tape_partition, {
3154                 "partition", "ndmp.tape.status.partition", FT_UINT32, BASE_DEC,
3155                 NULL, 0, "partition", HFILL }},
3156
3157         { &hf_ndmp_tape_mtio_op, {
3158                 "Operation", "ndmp.tape.mtio.op", FT_UINT32, BASE_DEC,
3159                 VALS(tape_mtio_vals), 0, "MTIO Operation", HFILL }},
3160
3161         { &hf_ndmp_count, {
3162                 "Count", "ndmp.count", FT_UINT32, BASE_DEC,
3163                 NULL, 0, "Number of bytes/objects/operations", HFILL }},
3164
3165         { &hf_ndmp_resid_count, {
3166                 "Resid Count", "ndmp.resid_count", FT_UINT32, BASE_DEC,
3167                 NULL, 0, "Number of remaining bytes/objects/operations", HFILL }},
3168
3169         { &hf_ndmp_mover_state, {
3170                 "State", "ndmp.mover.state", FT_UINT32, BASE_DEC,
3171                 VALS(mover_state_vals), 0, "State of the selected mover", HFILL }},
3172
3173         { &hf_ndmp_mover_pause, {
3174                 "Pause", "ndmp.mover.pause", FT_UINT32, BASE_DEC,
3175                 VALS(mover_pause_vals), 0, "Reason why the mover paused", HFILL }},
3176
3177         { &hf_ndmp_halt, {
3178                 "Halt", "ndmp.halt", FT_UINT32, BASE_DEC,
3179                 VALS(halt_vals), 0, "Reason why it halted", HFILL }},
3180
3181         { &hf_ndmp_record_size, {
3182                 "Record Size", "ndmp.record.size", FT_UINT32, BASE_DEC,
3183                 NULL, 0, "Record size in bytes", HFILL }},
3184
3185         { &hf_ndmp_record_num, {
3186                 "Record Num", "ndmp.record.num", FT_UINT32, BASE_DEC,
3187                 NULL, 0, "Number of records", HFILL }},
3188
3189         { &hf_ndmp_data_written, {
3190                 "Data Written", "ndmp.data.written", FT_UINT64, BASE_DEC,
3191                 NULL, 0, "Number of data bytes written", HFILL }},
3192
3193         { &hf_ndmp_seek_position, {
3194                 "Seek Position", "ndmp.seek.position", FT_UINT64, BASE_DEC,
3195                 NULL, 0, "Current seek position on device", HFILL }},
3196
3197         { &hf_ndmp_bytes_left_to_read, {
3198                 "Bytes left to read", "ndmp.bytes_left_to_read", FT_UINT64, BASE_DEC,
3199                 NULL, 0, "Number of bytes left to be read from the device", HFILL }},
3200
3201         { &hf_ndmp_window_offset, {
3202                 "Window Offset", "ndmp.window.offset", FT_UINT64, BASE_DEC,
3203                 NULL, 0, "Offset to window in bytes", HFILL }},
3204
3205         { &hf_ndmp_window_length, {
3206                 "Window Length", "ndmp.window.length", FT_UINT64, BASE_DEC,
3207                 NULL, 0, "Size of window in bytes", HFILL }},
3208
3209         { &hf_ndmp_addr_ip, {
3210                 "IP Address", "ndmp.addr.ip", FT_IPv4, BASE_DEC,
3211                 NULL, 0, "IP Address", HFILL }},
3212
3213         { &hf_ndmp_addr_tcp, {
3214                 "TCP Port", "ndmp.addr.tcp_port", FT_UINT32, BASE_DEC,
3215                 NULL, 0, "TCP Port", HFILL }},
3216
3217         { &hf_ndmp_addr_fcal_loop_id, {
3218                 "Loop ID", "ndmp.addr.loop_id", FT_UINT32, BASE_HEX,
3219                 NULL, 0, "FCAL Loop ID", HFILL }},
3220
3221         { &hf_ndmp_addr_ipc, {
3222                 "IPC", "ndmp.addr.ipc", FT_BYTES, BASE_HEX,
3223                 NULL, 0, "IPC identifier", HFILL }},
3224
3225         { &hf_ndmp_mover_mode, {
3226                 "Mode", "ndmp.mover.mode", FT_UINT32, BASE_HEX,
3227                 VALS(mover_mode_vals), 0, "Mover Mode", HFILL }},
3228
3229         { &hf_ndmp_file_name, {
3230                 "File", "ndmp.file", FT_STRING, BASE_NONE,
3231                 NULL, 0, "Name of File", HFILL }},
3232
3233         { &hf_ndmp_nt_file_name, {
3234                 "NT File", "ndmp.file", FT_STRING, BASE_NONE,
3235                 NULL, 0, "NT Name of File", HFILL }},
3236
3237         { &hf_ndmp_dos_file_name, {
3238                 "DOS File", "ndmp.file", FT_STRING, BASE_NONE,
3239                 NULL, 0, "DOS Name of File", HFILL }},
3240
3241         { &hf_ndmp_log_type, {
3242                 "Type", "ndmp.log.type", FT_UINT32, BASE_HEX,
3243                 VALS(log_type_vals), 0, "Type of log entry", HFILL }},
3244
3245         { &hf_ndmp_log_message_id, {
3246                 "Message ID", "ndmp.log.message.id", FT_UINT32, BASE_DEC,
3247                 NULL, 0, "ID of this log entry", HFILL }},
3248
3249         { &hf_ndmp_log_message, {
3250                 "Message", "ndmp.log.message", FT_STRING, BASE_NONE,
3251                 NULL, 0, "Log entry", HFILL }},
3252
3253         { &hf_ndmp_halt_reason, {
3254                 "Reason", "ndmp.halt.reason", FT_STRING, BASE_NONE,
3255                 NULL, 0, "Textual reason for why it halted", HFILL }},
3256
3257         { &hf_ndmp_connected, {
3258                 "Connected", "ndmp.connected", FT_UINT32, BASE_DEC,
3259                 VALS(connected_vals), 0, "Status of connection", HFILL }},
3260
3261         { &hf_ndmp_connected_reason, {
3262                 "Reason", "ndmp.connected.reason", FT_STRING, BASE_NONE,
3263                 NULL, 0, "Textual description of the connection status", HFILL }},
3264
3265         { &hf_ndmp_auth_id, {
3266                 "ID", "ndmp.auth.id", FT_STRING, BASE_NONE,
3267                 NULL, 0, "ID of client authenticating", HFILL }},
3268
3269         { &hf_ndmp_auth_password, {
3270                 "Password", "ndmp.auth.password", FT_STRING, BASE_NONE,
3271                 NULL, 0, "Password of client authenticating", HFILL }},
3272
3273         { &hf_ndmp_data, {
3274                 "Data", "ndmp.data", FT_BYTES, BASE_HEX,
3275                 NULL, 0, "Data written/read", HFILL }},
3276
3277         { &hf_ndmp_files, {
3278                 "Files", "ndmp.files", FT_NONE, 0,
3279                 NULL, 0, "List of files", HFILL }},
3280
3281         { &hf_ndmp_file_names, {
3282                 "File Names", "ndmp.file.names", FT_NONE, 0,
3283                 NULL, 0, "List of file names", HFILL }},
3284
3285         { &hf_ndmp_file_fs_type, {
3286                 "File FS Type", "ndmp.file.fs_type", FT_UINT32, BASE_DEC,
3287                 VALS(file_fs_type_vals), 0, "Type of file permissions (UNIX or NT)", HFILL }},
3288
3289         { &hf_ndmp_file_type, {
3290                 "File Type", "ndmp.file.type", FT_UINT32, BASE_DEC,
3291                 VALS(file_type_vals), 0, "Type of file", HFILL }},
3292
3293         { &hf_ndmp_file_stats, {
3294                 "File Stats", "ndmp.file.stats", FT_NONE, 0,
3295                 NULL, 0, "List of file stats", HFILL }},
3296
3297         { &hf_ndmp_file_node, {
3298                 "Node", "ndmp.file.node", FT_UINT64, BASE_DEC,
3299                 NULL, 0, "Node used for direct access", HFILL }},
3300
3301         { &hf_ndmp_file_parent, {
3302                 "Parent", "ndmp.file.parent", FT_UINT64, BASE_DEC,
3303                 NULL, 0, "Parent node(directory) for this node", HFILL }},
3304
3305         { &hf_ndmp_file_fh_info, {
3306                 "FH Info", "ndmp.file.fh_info", FT_UINT64, BASE_DEC,
3307                 NULL, 0, "FH Info used for direct access", HFILL }},
3308
3309         { &hf_ndmp_file_invalid_atime, {
3310                 "", "ndmp.file.invalid_atime", FT_BOOLEAN, 32,
3311                 TFS(&tfs_ndmp_file_invalid_atime), 0x00000001, "invalid_atime", HFILL, }},
3312
3313         { &hf_ndmp_file_invalid_ctime, {
3314                 "", "ndmp.file.invalid_ctime", FT_BOOLEAN, 32,
3315                 TFS(&tfs_ndmp_file_invalid_ctime), 0x00000002, "invalid_ctime", HFILL, }},
3316
3317         { &hf_ndmp_file_invalid_group, {
3318                 "", "ndmp.file.invalid_group", FT_BOOLEAN, 32,
3319                 TFS(&tfs_ndmp_file_invalid_group), 0x00000004, "invalid_group", HFILL, }},
3320
3321         { &hf_ndmp_file_mtime, {
3322                 "mtime", "ndmp.file.mtime", FT_ABSOLUTE_TIME, BASE_NONE,
3323                 NULL, 0, "Timestamp for mtime for this file", HFILL }},
3324
3325         { &hf_ndmp_file_atime, {
3326                 "atime", "ndmp.file.atime", FT_ABSOLUTE_TIME, BASE_NONE,
3327                 NULL, 0, "Timestamp for atime for this file", HFILL }},
3328
3329         { &hf_ndmp_file_ctime, {
3330                 "ctime", "ndmp.file.ctime", FT_ABSOLUTE_TIME, BASE_NONE,
3331                 NULL, 0, "Timestamp for ctime for this file", HFILL }},
3332
3333         { &hf_ndmp_file_owner, {
3334                 "Owner", "ndmp.file.owner", FT_UINT32, BASE_DEC,
3335                 NULL, 0, "UID for UNIX, owner for NT", HFILL }},
3336
3337         { &hf_ndmp_file_group, {
3338                 "Group", "ndmp.file.group", FT_UINT32, BASE_DEC,
3339                 NULL, 0, "GID for UNIX, NA for NT", HFILL }},
3340
3341         { &hf_ndmp_file_fattr, {
3342                 "Fattr", "ndmp.file.fattr", FT_UINT32, BASE_HEX,
3343                 NULL, 0, "Mode for UNIX, fattr for NT", HFILL }},
3344
3345         { &hf_ndmp_file_size, {
3346                 "Size", "ndmp.file.size", FT_UINT64, BASE_DEC,
3347                 NULL, 0, "File Size", HFILL }},
3348
3349         { &hf_ndmp_file_links, {
3350                 "Links", "ndmp.file.links", FT_UINT32, BASE_DEC,
3351                 NULL, 0, "Number of links to this file", HFILL }},
3352
3353         { &hf_ndmp_dirs, {
3354                 "Dirs", "ndmp.dirs", FT_NONE, 0,
3355                 NULL, 0, "List of directories", HFILL }},
3356
3357         { &hf_ndmp_nodes, {
3358                 "Nodes", "ndmp.nodes", FT_NONE, 0,
3359                 NULL, 0, "List of nodes", HFILL }},
3360
3361         { &hf_ndmp_nlist, {
3362                 "Nlist", "ndmp.nlist", FT_NONE, 0,
3363                 NULL, 0, "List of names", HFILL }},
3364
3365         { &hf_ndmp_bu_original_path, {
3366                 "Original Path", "ndmp.bu.original_path", FT_STRING, BASE_NONE,
3367                 NULL, 0, "Original path where backup was created", HFILL }},
3368
3369         { &hf_ndmp_bu_destination_dir, {
3370                 "Destination Dir", "ndmp.bu.destination_dir", FT_STRING, BASE_NONE,
3371                 NULL, 0, "Destination directory to restore backup to", HFILL }},
3372
3373         { &hf_ndmp_bu_new_name, {
3374                 "New Name", "ndmp.bu.new_name", FT_STRING, BASE_NONE,
3375                 NULL, 0, "New Name", HFILL }},
3376
3377         { &hf_ndmp_bu_other_name, {
3378                 "Other Name", "ndmp.bu.other_name", FT_STRING, BASE_NONE,
3379                 NULL, 0, "Other Name", HFILL }},
3380
3381         { &hf_ndmp_state_invalid_ebr, {
3382                 "", "ndmp.bu.state.invalid_ebr", FT_BOOLEAN, 32,
3383                 TFS(&tfs_ndmp_state_invalid_ebr), 0x00000001, "Whether EstimatedBytesLeft is valid or not", HFILL, }},
3384
3385         { &hf_ndmp_state_invalid_etr, {
3386                 "", "ndmp.bu.state.invalid_etr", FT_BOOLEAN, 32,
3387                 TFS(&tfs_ndmp_state_invalid_etr), 0x00000002, "Whether EstimatedTimeLeft is valid or not", HFILL, }},
3388
3389         { &hf_ndmp_bu_operation, {
3390                 "Operation", "ndmp.bu.operation", FT_UINT32, BASE_DEC,
3391                 VALS(bu_operation_vals), 0, "BU Operation", HFILL, }},
3392
3393         { &hf_ndmp_data_state, {
3394                 "State", "ndmp.data.state", FT_UINT32, BASE_DEC,
3395                 VALS(data_state_vals), 0, "Data state", HFILL, }},
3396
3397         { &hf_ndmp_data_halted, {
3398                 "Halted Reason", "ndmp.data.halted", FT_UINT32, BASE_DEC,
3399                 VALS(data_halted_vals), 0, "Data halted reason", HFILL, }},
3400
3401         { &hf_ndmp_data_bytes_processed, {
3402                 "Bytes Processed", "ndmp.data.bytes_processed", FT_UINT64, BASE_DEC,
3403                 NULL, 0, "Number of bytes processed", HFILL }},
3404
3405         { &hf_ndmp_data_est_bytes_remain, {
3406                 "Est Bytes Remain", "ndmp.data.est_bytes_remain", FT_UINT64, BASE_DEC,
3407                 NULL, 0, "Estimated number of bytes remaining", HFILL }},
3408
3409         { &hf_ndmp_data_est_time_remain, {
3410                 "Est Time Remain", "ndmp.data.est_time_remain", FT_RELATIVE_TIME, BASE_DEC,
3411                 NULL, 0, "Estimated time remaining", HFILL }},
3412   };
3413
3414   static gint *ett[] = {
3415     &ett_ndmp,
3416     &ett_ndmp_header,
3417     &ett_ndmp_butype_attrs,
3418     &ett_ndmp_fs_invalid,
3419     &ett_ndmp_tape_attr,
3420     &ett_ndmp_execute_cdb_flags,
3421     &ett_ndmp_execute_cdb_cdb,
3422     &ett_ndmp_execute_cdb_sns,
3423     &ett_ndmp_execute_cdb_payload,
3424     &ett_ndmp_tape_invalid,
3425     &ett_ndmp_tape_flags,
3426     &ett_ndmp_addr,
3427     &ett_ndmp_file,
3428     &ett_ndmp_file_name,
3429     &ett_ndmp_file_stats,
3430     &ett_ndmp_file_invalids,
3431     &ett_ndmp_state_invalids,
3432   };
3433
3434   module_t *ndmp_module;
3435
3436   proto_ndmp = proto_register_protocol("Network Data Management Protocol", "NDMP", "ndmp");
3437   proto_register_field_array(proto_ndmp, hf_ndmp, array_length(hf_ndmp));
3438
3439   proto_register_subtree_array(ett, array_length(ett));
3440
3441   /* desegmentation */
3442   ndmp_module = prefs_register_protocol(proto_ndmp, NULL);
3443   prefs_register_bool_preference(ndmp_module, "desegment",
3444         "Desegment all NDMP messages spanning multiple TCP segments",
3445         "Whether the dissector should desegment NDMP messages",
3446         &ndmp_desegment);
3447   prefs_register_bool_preference(ndmp_module, "defragment",
3448         "Defragment all multi-fragment NDMP messages",
3449         "Whether the dissector should defragment multi-fragment NDMP messages",
3450         &ndmp_defragment);
3451 }
3452
3453 void
3454 proto_reg_handoff_ndmp(void)
3455 {
3456   dissector_handle_t ndmp_handle;
3457
3458   ndmp_handle = create_dissector_handle(dissect_ndmp, proto_ndmp);
3459   dissector_add("tcp.port",TCP_PORT_NDMP, ndmp_handle);
3460 }