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