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