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