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