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