1 /* packet-rsvd.c
2  * Routines for RSVD dissection
3  * Copyright 2015, Richard Sharpe <realrichardsharpe@gmail.com>
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * SPDX-License-Identifier: GPL-2.0-or-later
10  */
11 
12 /*
13  * RSVD, documented in [MS-RSVD].pdf, by Microsoft, the Remote Shared Virtual
14  * Disk protocol.
15  */
16 
17 #include "config.h"
18 
19 #include <epan/conversation.h>
20 #include <epan/packet.h>
21 #if 0
22 #include "packet-smb-common.h"
23 #endif
24 #include "packet-windows-common.h"
25 #include "packet-scsi.h"
26 
27 void proto_register_rsvd(void);
28 
29 static int proto_rsvd = -1;
30 static int hf_svhdx_protocol_id = -1;
31 static int hf_svhdx_protocol_version = -1;
32 static int hf_svhdx_operation_code = -1;
33 static int hf_svhdx_status = -1;
34 static int hf_svhdx_request_id = -1;
35 static int hf_svhdx_tunnel_scsi_length = -1;
36 static int hf_svhdx_tunnel_scsi_reserved1 = -1;
37 static int hf_svhdx_tunnel_scsi_cdb_length = -1;
38 static int hf_svhdx_tunnel_scsi_sense_info_ex_length = -1;
39 static int hf_svhdx_tunnel_scsi_data_in = -1;
40 static int hf_svhdx_tunnel_scsi_reserved2 =  -1;
41 static int hf_svhdx_tunnel_scsi_srb_flags = -1;
42 static int hf_svhdx_tunnel_scsi_data_transfer_length = -1;
43 static int hf_svhdx_tunnel_scsi_reserved3 = -1;
44 static int hf_svhdx_tunnel_scsi_cdb = -1;
45 static int hf_svhdx_tunnel_scsi_cdb_padding = -1;
46 static int hf_svhdx_tunnel_scsi_data = -1;
47 static int hf_svhdx_tunnel_scsi_auto_generated_sense = -1;
48 static int hf_svhdx_tunnel_scsi_srb_status = -1;
49 static int hf_svhdx_tunnel_scsi_sense_data_ex = -1;
50 static int hf_svhdx_tunnel_scsi_status = -1;
51 static int hf_svhdx_tunnel_file_info_server_version = -1;
52 static int hf_svhdx_tunnel_file_info_sector_size = -1;
53 static int hf_svhdx_tunnel_file_info_physical_sector_size = -1;
54 static int hf_svhdx_tunnel_file_info_reserved = -1;
55 static int hf_svhdx_tunnel_file_info_virtual_size = -1;
56 static int hf_svhdx_tunnel_disk_info_reserved1 = -1;
57 static int hf_svhdx_tunnel_disk_info_blocksize = -1;
58 static int hf_svhdx_tunnel_disk_info_linkage_id = -1;
59 static int hf_svhdx_tunnel_disk_info_disk_type = -1;
60 static int hf_svhdx_tunnel_disk_info_disk_format = -1;
61 static int hf_svhdx_tunnel_disk_info_is_mounted = -1;
62 static int hf_svhdx_tunnel_disk_info_is_4k_aligned = -1;
63 static int hf_svhdx_tunnel_disk_info_reserved = -1;
64 static int hf_svhdx_tunnel_disk_info_file_size = -1;
65 static int hf_svhdx_tunnel_disk_info_virtual_disk_id = -1;
66 static int hf_svhdx_tunnel_validate_disk_reserved = -1;
67 static int hf_svhdx_tunnel_validate_disk_is_valid_disk = -1;
68 static int hf_svhdx_tunnel_srb_status_status_key = -1;
69 static int hf_svhdx_tunnel_srb_status_reserved = -1;
70 static int hf_svhdx_tunnel_srb_status_sense_info_auto_generated = -1;
71 static int hf_svhdx_tunnel_srb_status_srb_status = -1;
72 static int hf_svhdx_tunnel_srb_status_scsi_status = -1;
73 static int hf_svhdx_tunnel_srb_status_sense_info_ex_length = -1;
74 static int hf_svhdx_tunnel_srb_status_sense_data_ex = -1;
75 static int hf_svhdx_tunnel_safe_virtual_size = -1;
76 static int hf_svhdx_tunnel_transaction_id = -1;
77 static int hf_svhdx_tunnel_meta_operation_type = -1;
78 static int hf_svhdx_tunnel_padding = -1;
79 static int hf_svhdx_tunnel_resize_new_size = -1;
80 static int hf_svhdx_tunnel_resize_expand_only_flag = -1;
81 static int hf_svhdx_tunnel_resize_allow_unsafe_virt_size_flag = -1;
82 static int hf_svhdx_tunnel_resize_shrink_to_minimum_safe_size_flag = -1;
83 static int hf_svhdx_tunnel_meta_operation_start_reserved = -1;
84 static int hf_svhdx_tunnel_snapshot_type = -1;
85 static int hf_svhdx_tunnel_snapshot_id = -1;
86 static int hf_svhdx_tunnel_create_snapshot_flags = -1;
87 static int hf_svhdx_tunnel_create_snapshot_flag_enable_change_tracking = -1;
88 static int hf_svhdx_tunnel_create_snapshot_stage1 = -1;
89 static int hf_svhdx_tunnel_create_snapshot_stage2 = -1;
90 static int hf_svhdx_tunnel_create_snapshot_stage3 = -1;
91 static int hf_svhdx_tunnel_create_snapshot_stage4 = -1;
92 static int hf_svhdx_tunnel_create_snapshot_stage5 = -1;
93 static int hf_svhdx_tunnel_create_snapshot_stage6 = -1;
94 static int hf_svhdx_tunnel_create_snapshot_parameters_payload_size = -1;
95 static int hf_svhdx_tunnel_convert_dst_vhdset_name_len = -1;
96 static int hf_svhdx_tunnel_convert_dst_vhdset_name = -1;
97 static int hf_svhdx_tunnel_delete_snapshot_persist_reference = -1;
98 static int hf_svhdx_tunnel_meta_op_query_progress_current_progress = -1;
99 static int hf_svhdx_tunnel_meta_op_query_progress_complete_value = -1;
100 static int hf_svhdx_tunnel_vhdset_information_type = -1;
101 static int hf_svhdx_tunnel_vhdset_snapshot_creation_time = -1;
102 static int hf_svhdx_tunnel_vhdset_is_valid_snapshot = -1;
103 static int hf_svhdx_tunnel_vhdset_parent_snapshot_id = -1;
104 static int hf_svhdx_tunnel_vhdset_log_file_id = -1;
105 
106 static gint ett_rsvd = -1;
107 static gint ett_svhdx_tunnel_op_header = -1;
108 static gint ett_svhdx_tunnel_scsi_request = -1;
109 static gint ett_rsvd_create_snapshot_flags = -1;
110 
111 static const value_string rsvd_operation_code_vals[] = {
112         { 0x02001001, "RSVD_TUNNEL_GET_INITIAL_INFO" },
113         { 0x02001002, "RSVD_TUNNEL_SCSI" },
114         { 0x02001003, "RSVD_TUNNEL_CHECK_CONNECTION_STATUS" },
115         { 0x02001004, "RSVD_TUNNEL_SRB_STATUS" },
116         { 0x02001005, "RSVD_TUNNEL_GET_DISK_INFO" },
117         { 0x02001006, "RSVD_TUNNEL_VALIDATE_DISK" },
118         { 0x02002101, "RSVD_TUNNEL_META_OPERATION_START" },
119         { 0x02002002, "RSVD_TUNNEL_META_OPERATION_QUERY_PROGRESS" },
120         { 0x02002005, "RSVD_TUNNEL_VHDSET_QUERY_INFORMATION" },
121         { 0x02002006, "RSVD_TUNNEL_DELETE_SNAPSHOT" },
122         { 0x02002008, "RSVD_TUNNEL_CHANGE_TRACKING_GET_PARAMETERS" },
123         { 0x02002009, "RSVD_TUNNEL_CHANGE_TRACKING_START" },
124         { 0x0200200A, "RSVD_TUNNEL_CHANGE_TRACKING_STOP" },
125         { 0x0200200C, "RSVD_TUNNEL_QUERY_VIRTUAL_DISK_CHANGES" },
126         { 0x0200200D, "RSVD_TUNNEL_QUERY_SAFE_SIZE" },
127         { 0, NULL }
128 };
129 
130 static const value_string rsvd_sense_info_vals[] = {
131         { 0x0, "Sense Info Not Auto Generated" },
132         { 0x1, "Sense Info Auto Generated" },
133         { 0, NULL }
134 };
135 
136 static const value_string rsvd_disk_type_vals[] = {
137         { 0x02, "VHD_TYPE_FIXED" },
138         { 0x03, "VHD_TYPE_DYNAMIC" },
139         { 0, NULL }
140 };
141 
142 static const value_string rsvd_disk_format_vals[] = {
143         { 0x03, "VIRTUAL_STORAGE_TYPE_DEVICE_VHDX" },
144         { 0x04, "VIRTUAL_STORAGE_TYPE_DEVICE_VHDSET" },
145         { 0, NULL }
146 };
147 
148 /*
149  * We need this data to handle SCSI requests and responses, I think
150  */
151 typedef struct _rsvd_task_data_t {
152         guint32 request_frame;
153         guint32 response_frame;
154         itlq_nexus_t *itlq;
155 } rsvd_task_data_t;
156 
157 typedef struct _rsvd_conv_data_t {
158         wmem_map_t *tasks;
159         wmem_tree_t *itl;
160         rsvd_task_data_t *task;
161         conversation_t *conversation;
162 } rsvd_conv_data_t;
163 
164 static rsvd_conv_data_t *rsvd_conv_data = NULL;
165 
166 static proto_tree *top_tree = NULL;
167 
168 static itl_nexus_t *
get_itl_nexus(packet_info * pinfo)169 get_itl_nexus(packet_info *pinfo)
170 {
171     itl_nexus_t *itl = NULL;
172 
173     if (!(itl = (itl_nexus_t *)wmem_tree_lookup32_le(rsvd_conv_data->itl, pinfo->num))) {
174         itl = wmem_new(wmem_file_scope(), itl_nexus_t);
175         itl->cmdset = 0xff;
176         itl->conversation = rsvd_conv_data->conversation;
177         wmem_tree_insert32(rsvd_conv_data->itl, pinfo->num, itl);
178     }
179 
180     return itl;
181 }
182 
183 static int
dissect_RSVD_GET_INITIAL_INFO(tvbuff_t * tvb,proto_tree * parent_tree,int offset,gint16 len,gboolean request)184 dissect_RSVD_GET_INITIAL_INFO(tvbuff_t *tvb, proto_tree *parent_tree, int offset, gint16 len, gboolean request)
185 {
186     proto_tree *gfi_sub_tree;
187     proto_item *gfi_sub_item;
188 
189     if (!request) {
190         gfi_sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, len, ett_svhdx_tunnel_op_header, &gfi_sub_item, "RSVD_TUNNEL_GET_INITIAL_INFO_RESPONSE");
191 
192         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_file_info_server_version, tvb, offset, 4, ENC_LITTLE_ENDIAN);
193         offset += 4;
194 
195         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_file_info_sector_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
196         offset += 4;
197 
198         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_file_info_physical_sector_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
199         offset += 4;
200 
201         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_file_info_reserved, tvb, offset, 4, ENC_LITTLE_ENDIAN);
202         offset += 4;
203 
204         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_file_info_virtual_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
205         offset += 8;
206     }
207 
208     return offset;
209 }
210 
211 static const value_string rsvd_data_in_vals[] = {
212         { 0x00, "Client is requesting data from the server" },
213         { 0x01, "Client is sending data to the server" },
214         { 0x02, "Client is neither sending nor requesting an additional data buffer" },
215         { 0, NULL }
216 };
217 
218 static void
dissect_scsi_payload_databuffer(tvbuff_t * tvb,packet_info * pinfo,int offset,guint32 data_transfer_length,gboolean request)219 dissect_scsi_payload_databuffer(tvbuff_t *tvb, packet_info *pinfo, int offset, guint32 data_transfer_length, gboolean request)
220 {
221     tvbuff_t *data_tvb = NULL;
222     int tvb_len, tvb_rlen;
223 
224     tvb_len = tvb_captured_length_remaining(tvb, offset);
225     if (tvb_len > (int)data_transfer_length)
226         tvb_len = data_transfer_length;
227 
228     tvb_rlen = tvb_reported_length_remaining(tvb, offset);
229     if (tvb_rlen > (int)data_transfer_length)
230         tvb_rlen = data_transfer_length;
231 
232     data_tvb = tvb_new_subset_length_caplen(tvb, offset, tvb_len, tvb_rlen);
233 
234     if (rsvd_conv_data->task && rsvd_conv_data->task->itlq) {
235         rsvd_conv_data->task->itlq->task_flags = SCSI_DATA_READ |
236                                                  SCSI_DATA_WRITE;
237         rsvd_conv_data->task->itlq->data_length = data_transfer_length;
238         rsvd_conv_data->task->itlq->bidir_data_length = data_transfer_length;
239         dissect_scsi_payload(data_tvb, pinfo, top_tree, request,
240                              rsvd_conv_data->task->itlq,
241                              get_itl_nexus(pinfo), 0);
242     }
243 }
244 
245 /*
246  * Dissect a tunnelled SCSI request and call the SCSI dissector where
247  * needed.
248  */
249 static int
dissect_RSVD_TUNNEL_SCSI(tvbuff_t * tvb,packet_info * pinfo,proto_tree * parent_tree,int offset,gint16 len,gboolean request,guint64 request_id)250 dissect_RSVD_TUNNEL_SCSI(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, gint16 len, gboolean request, guint64 request_id)
251 {
252     proto_tree *sub_tree;
253     proto_item *sub_item;
254     guint32 cdb_length;
255     guint8 data_in;
256     guint32 data_transfer_length;
257     guint32 sense_info_ex_length;
258     conversation_t *conversation;
259 
260     conversation = find_or_create_conversation(pinfo);
261     rsvd_conv_data = (rsvd_conv_data_t *)conversation_get_proto_data(conversation, proto_rsvd);
262 
263     if (!rsvd_conv_data) {
264         rsvd_conv_data = wmem_new(wmem_file_scope(), rsvd_conv_data_t);
265         rsvd_conv_data->tasks = wmem_map_new(wmem_file_scope(),
266                                              wmem_int64_hash,
267                                              g_int64_equal);
268         rsvd_conv_data->itl   = wmem_tree_new(wmem_file_scope());
269         rsvd_conv_data->conversation = conversation;
270         conversation_add_proto_data(conversation, proto_rsvd, rsvd_conv_data);
271     }
272 
273     rsvd_conv_data->task = NULL;
274     if (!pinfo->fd->visited) {
275         guint64 *key_copy = wmem_new(wmem_file_scope(), guint64);
276 
277         *key_copy = request_id;
278         rsvd_conv_data->task = wmem_new(wmem_file_scope(), rsvd_task_data_t);
279         rsvd_conv_data->task->request_frame=pinfo->num;
280         rsvd_conv_data->task->response_frame=0;
281         rsvd_conv_data->task->itlq = NULL;
282         wmem_map_insert(rsvd_conv_data->tasks, (const void *)key_copy,
283                         rsvd_conv_data->task);
284     } else {
285         rsvd_conv_data->task = (rsvd_task_data_t *)wmem_map_lookup(rsvd_conv_data->tasks, (const void *)&request_id);
286     }
287 
288     sub_tree = proto_tree_add_subtree_format(parent_tree, tvb, offset, len, ett_svhdx_tunnel_scsi_request, &sub_item, "SVHDX_TUNNEL_SCSI_%s", (request ? "REQUEST" : "RESPONSE"));
289 
290     if (request) {
291         tvbuff_t *scsi_cdb = NULL;
292 
293         /* Length */
294         proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
295         offset += 2;
296 
297         /* Reserved1 */
298         proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_reserved1, tvb, offset, 2, ENC_LITTLE_ENDIAN);
299         offset += 2;
300 
301         /* CDBLength */
302         cdb_length = tvb_get_guint8(tvb, offset);
303         proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_cdb_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
304         offset++;
305 
306         /* SensInfoExLength */
307         proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_sense_info_ex_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
308         offset++;
309 
310         /* DataIn */
311         data_in = tvb_get_guint8(tvb, offset);
312         proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_data_in, tvb, offset, 1, ENC_LITTLE_ENDIAN);
313         offset++;
314 
315         /* Reserved2 */
316         proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_reserved2, tvb, offset, 1, ENC_LITTLE_ENDIAN);
317         offset++;
318 
319         /* SrbFlags */
320         proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_srb_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
321         offset += 4;
322 
323         /* DataTransferLength */
324         data_transfer_length = tvb_get_letohl(tvb, offset);
325         proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_data_transfer_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
326         offset += 4;
327 
328         /* CDBBuffer */
329         scsi_cdb = tvb_new_subset_length_caplen(tvb,
330                                   offset,
331                                   cdb_length,
332                                   tvb_reported_length_remaining(tvb, offset));
333         proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_cdb, tvb, offset, cdb_length, ENC_NA);
334         offset += cdb_length;
335         if (cdb_length < 16) {
336             /*
337              * CDBBuffer is always 16 bytes - see MS-RSVD section 2.2.4.7
338              * "SVHDX_TUNNEL_SCSI_REQUEST Structure":
339              *
340              *     https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rsvd/e8bcb003-97b3-41ef-9689-cd2d1668a9cc
341              *
342              * If CDB is actually smaller, we need to define padding bytes
343              */
344             guint32 cdb_padding_length = 16 - cdb_length;
345             proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_cdb_padding, tvb, offset, cdb_padding_length, ENC_NA);
346             offset += cdb_padding_length;
347         }
348 
349         /* Reserved3 */
350         proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_reserved3, tvb, offset, 4, ENC_LITTLE_ENDIAN);
351         offset += 4;
352 
353         /* DataBuffer */
354         if (data_transfer_length) {
355             proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_data, tvb, offset, data_transfer_length, ENC_NA);
356         }
357 
358         /*
359          * Now the SCSI Request
360          */
361         if (rsvd_conv_data->task && !rsvd_conv_data->task->itlq) {
362             rsvd_conv_data->task->itlq = wmem_new(wmem_file_scope(),
363                                                   itlq_nexus_t);
364             rsvd_conv_data->task->itlq->first_exchange_frame = pinfo->num;
365             rsvd_conv_data->task->itlq->last_exchange_frame = 0;
366             rsvd_conv_data->task->itlq->lun = 0xffff;
367             rsvd_conv_data->task->itlq->scsi_opcode = 0xffff;
368             rsvd_conv_data->task->itlq->task_flags = 0;
369             rsvd_conv_data->task->itlq->data_length = 0;
370             rsvd_conv_data->task->itlq->bidir_data_length = 0;
371             rsvd_conv_data->task->itlq->flags = 0;
372             rsvd_conv_data->task->itlq->alloc_len = 0;
373             rsvd_conv_data->task->itlq->fc_time = pinfo->abs_ts;
374             rsvd_conv_data->task->itlq->extra_data = NULL;
375         }
376 
377         if (rsvd_conv_data->task && rsvd_conv_data->task->itlq) {
378             dissect_scsi_cdb(scsi_cdb, pinfo, top_tree, SCSI_DEV_SMC, rsvd_conv_data->task->itlq, get_itl_nexus(pinfo));
379             if (data_in == 0) { /* Only OUT operations have meaningful SCSI payload in request packet */
380                 dissect_scsi_payload_databuffer(tvb, pinfo, offset, data_transfer_length, request);
381             }
382         }
383 
384         /* increment after DataBuffer */
385         offset += data_transfer_length;
386     } else {
387         guint8 scsi_status = 0;
388 
389         /* Length */
390         proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
391         offset += 2;
392 
393         /* A */
394         proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_auto_generated_sense, tvb, offset, 1, ENC_BIG_ENDIAN);
395 
396         /* SrbStatus */
397         proto_tree_add_bits_item(sub_tree, hf_svhdx_tunnel_scsi_srb_status, tvb, offset * 8 + 1, 7, ENC_BIG_ENDIAN);
398         offset++;
399 
400         /* ScsiStatus */
401         scsi_status = tvb_get_guint8(tvb, offset);
402         proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_status, tvb, offset, 1, ENC_LITTLE_ENDIAN);
403         offset++;
404 
405         /* CdbLength */
406         proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_cdb_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
407         offset++;
408 
409         /* SensInfoExLength */
410         sense_info_ex_length = tvb_get_guint8(tvb, offset);
411         proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_sense_info_ex_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
412         offset++;
413 
414         /* DataIn */
415         data_in = tvb_get_guint8(tvb, offset);
416         proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_data_in, tvb, offset, 1, ENC_LITTLE_ENDIAN);
417         offset++;
418 
419         /* Reserved */
420         proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_reserved2, tvb, offset, 1, ENC_LITTLE_ENDIAN);
421         offset++;
422 
423         /* SrbFlags */
424         proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_srb_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
425         offset += 4;
426 
427         /* DataTransferLength */
428         data_transfer_length = tvb_get_letohl(tvb, offset);
429         proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_data_transfer_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
430         offset += 4;
431 
432         /* SenseDataEx */
433         proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_sense_data_ex, tvb, offset, sense_info_ex_length, ENC_NA);
434         offset += sense_info_ex_length;
435 
436         /* DataBuffer */
437         if (data_transfer_length) {
438             proto_tree_add_item(sub_tree, hf_svhdx_tunnel_scsi_data, tvb, offset, data_transfer_length, ENC_NA);
439 
440             if (data_in == 1) { /* Only IN operations have meaningful SCSI payload in reply packet */
441                 dissect_scsi_payload_databuffer(tvb, pinfo, offset, data_transfer_length, request);
442             }
443 
444             offset += data_transfer_length;
445         }
446 
447         /*
448          * Now, the SCSI response
449          */
450         if (rsvd_conv_data->task && rsvd_conv_data->task->itlq) {
451             dissect_scsi_rsp(tvb, pinfo, top_tree, rsvd_conv_data->task->itlq, get_itl_nexus(pinfo), scsi_status);
452         }
453     }
454 
455     return offset;
456 }
457 
458 static int
dissect_RSVD_SRB_STATUS(tvbuff_t * tvb,proto_tree * parent_tree,int offset,gint16 len,gboolean request)459 dissect_RSVD_SRB_STATUS(tvbuff_t *tvb, proto_tree *parent_tree, int offset, gint16 len, gboolean request)
460 {
461     proto_tree *gfi_sub_tree;
462     proto_item *gfi_sub_item;
463 
464     if (request) {
465         gfi_sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, len, ett_svhdx_tunnel_op_header, &gfi_sub_item, "RSVD_TUNNEL_SRB_STATUS_REQUEST");
466 
467         /* StatusKey */
468         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_srb_status_status_key, tvb, offset, 1, ENC_LITTLE_ENDIAN);
469         offset += 1;
470 
471         /* Reserved */
472         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_srb_status_reserved, tvb, offset, 1, ENC_NA);
473         offset += 27;
474     } else {
475         guint8 sense_info_length;
476 
477         gfi_sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, len, ett_svhdx_tunnel_op_header, &gfi_sub_item, "RSVD_TUNNEL_SRB_STATUS_RESPONSE");
478 
479         /* StatusKey */
480         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_srb_status_status_key, tvb, offset, 1, ENC_LITTLE_ENDIAN);
481         offset += 1;
482 
483         /* SenseInfoAutoGenerated and SrbStatus */
484         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_srb_status_sense_info_auto_generated, tvb, offset, 1, ENC_BIG_ENDIAN);
485         proto_tree_add_bits_item(gfi_sub_tree, hf_svhdx_tunnel_srb_status_srb_status, tvb, offset * 8 + 1, 7, ENC_BIG_ENDIAN);
486         offset += 1;
487 
488         /* ScsiStatus */
489         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_srb_status_scsi_status, tvb, offset, 1, ENC_LITTLE_ENDIAN);
490         offset += 1;
491 
492         /* SenseInfoExLength */
493         sense_info_length = tvb_get_guint8(tvb, offset);
494         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_srb_status_sense_info_ex_length, tvb, offset, 1, ENC_NA);
495         offset += 1;
496 
497         /* SenseDataEx */
498         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_srb_status_sense_data_ex, tvb, offset, sense_info_length, ENC_NA);
499         offset += sense_info_length;
500     }
501 
502     return offset;
503 }
504 
505 static int
dissect_RSVD_GET_DISK_INFO(tvbuff_t * tvb,proto_tree * parent_tree,int offset,gint16 len,gboolean request)506 dissect_RSVD_GET_DISK_INFO(tvbuff_t *tvb, proto_tree *parent_tree, int offset, gint16 len, gboolean request)
507 {
508     proto_tree *gfi_sub_tree;
509     proto_item *gfi_sub_item;
510 
511     if (request) {
512         gfi_sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, len, ett_svhdx_tunnel_op_header, &gfi_sub_item, "RSVD_TUNNEL_GET_DISK_INFO_REQUEST");
513 
514         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_disk_info_reserved1, tvb, offset, 8, ENC_LITTLE_ENDIAN);
515         offset += 8;
516 
517         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_disk_info_blocksize, tvb, offset, 4, ENC_LITTLE_ENDIAN);
518         offset += 4;
519 
520         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_disk_info_linkage_id, tvb, offset, 16, ENC_LITTLE_ENDIAN);
521         offset += 16;
522 
523         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_disk_info_is_mounted, tvb, offset, 1, ENC_LITTLE_ENDIAN);
524         offset += 1;
525 
526         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_disk_info_is_4k_aligned, tvb, offset, 1, ENC_LITTLE_ENDIAN);
527         offset += 1;
528 
529         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_disk_info_reserved, tvb, offset, 2, ENC_LITTLE_ENDIAN);
530         offset += 2;
531 
532         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_disk_info_file_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
533         offset += 8;
534 
535         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_disk_info_virtual_disk_id, tvb, offset, 16, ENC_LITTLE_ENDIAN);
536         offset += 16;
537     } else {
538         gfi_sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, len, ett_svhdx_tunnel_op_header, &gfi_sub_item, "RSVD_TUNNEL_GET_DISK_INFO_RESPONSE");
539 
540         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_disk_info_disk_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
541         offset += 4;
542 
543         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_disk_info_disk_format, tvb, offset, 4, ENC_LITTLE_ENDIAN);
544         offset += 4;
545 
546         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_disk_info_blocksize, tvb, offset, 4, ENC_LITTLE_ENDIAN);
547         offset += 4;
548 
549         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_disk_info_linkage_id, tvb, offset, 16, ENC_LITTLE_ENDIAN);
550         offset += 16;
551 
552         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_disk_info_is_mounted, tvb, offset, 1, ENC_LITTLE_ENDIAN);
553         offset += 1;
554 
555         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_disk_info_is_4k_aligned, tvb, offset, 1, ENC_LITTLE_ENDIAN);
556         offset += 1;
557 
558         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_disk_info_reserved, tvb, offset, 2, ENC_LITTLE_ENDIAN);
559         offset += 2;
560 
561         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_disk_info_file_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
562         offset += 8;
563 
564         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_disk_info_virtual_disk_id, tvb, offset, 16, ENC_LITTLE_ENDIAN);
565         offset += 16;
566     }
567 
568     return offset;
569 }
570 
571 static int
dissect_RSVD_VALIDATE_DISK(tvbuff_t * tvb,proto_tree * parent_tree,int offset,gint16 len,gboolean request)572 dissect_RSVD_VALIDATE_DISK(tvbuff_t *tvb, proto_tree *parent_tree, int offset, gint16 len, gboolean request)
573 {
574     proto_tree *gfi_sub_tree;
575     proto_item *gfi_sub_item;
576 
577     if (request) {
578         gfi_sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, len, ett_svhdx_tunnel_op_header, &gfi_sub_item, "RSVD_TUNNEL_VALIDATE_DISK_REQUEST");
579 
580         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_validate_disk_reserved, tvb, offset, 56, ENC_NA);
581         offset += 56;
582     } else {
583         gfi_sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, len, ett_svhdx_tunnel_op_header, &gfi_sub_item, "RSVD_TUNNEL_VALIDATE_DISK_RESPONSE");
584 
585         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_validate_disk_is_valid_disk, tvb, offset, 1, ENC_NA);
586         offset += 1;
587     }
588 
589     return offset;
590 }
591 
592 static const value_string rsvd_meta_operation_type_vals[] = {
593         { 0x00, "SvhdxMetaOperationTypeResize" },
594         { 0x01, "SvhdxMetaOperationTypeCreateSnapshot" },
595         { 0x02, "SvhdxMetaOperationTypeOptimize" },
596         { 0x03, "SvhdxMetaOperationTypeExtractVHD" },
597         { 0x04, "SvhdxMetaOperationTypeConvertToVHDSet" },
598         { 0x05, "SvhdxMetaOperationTypeApplySnapshot" },
599         { 0, NULL }
600 };
601 
602 static const value_string svhdx_snapshot_type_vals[] = {
603         { 0x01, "SvhdxSnapshotTypeVM" },
604         { 0x03, "SvhdxSnapshotTypeCDP" },
605         { 0x04, "SvhdxSnapshotTypeWriteable" },
606         { 0, NULL }
607 };
608 
609 static const value_string svhdx_snapshot_stage_vals[] = {
610         { 0x00, "SvhdxSnapshotStageInvalid" },
611         { 0x01, "SvhdxSnapshotStageInitialize" },
612         { 0x02, "SvhdxSnapshotStageBlockIO" },
613         { 0x03, "SvhdxSnapshotStageSwitchObjectStore" },
614         { 0x04, "SvhdxSnapshotStageUnblockIO" },
615         { 0x05, "SvhdxSnapshotStageFinalize" },
616         { 0, NULL }
617 };
618 
619 #define SVHDX_SNAPSHOT_DISK_FLAG_ENABLE_CHANGE_TRACKING 0x00000001
620 
621 static int
dissect_RSVD2_META_OPERATION_START(tvbuff_t * tvb,proto_tree * parent_tree,int offset,gint16 len,gboolean request)622 dissect_RSVD2_META_OPERATION_START(tvbuff_t *tvb, proto_tree *parent_tree, int offset, gint16 len, gboolean request)
623 {
624     static int * const meta_operation_create_snapshot_flags[] = {
625         &hf_svhdx_tunnel_create_snapshot_flag_enable_change_tracking,
626         NULL
627     };
628 
629     guint32 operation_type = 0;
630     guint32 length = 0;
631     proto_tree *gfi_sub_tree;
632     proto_item *gfi_sub_item;
633 
634     if (request) {
635 
636         gfi_sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, len, ett_svhdx_tunnel_op_header, &gfi_sub_item, "RSVD_TUNNEL_META_OPERATION_START_REQUEST");
637 
638         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_transaction_id, tvb, offset, 16, ENC_LITTLE_ENDIAN);
639         offset += 16;
640 
641         operation_type = tvb_get_letohl(tvb, offset);
642         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_meta_operation_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
643         offset += 4;
644 
645         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_padding, tvb, offset, 4, ENC_LITTLE_ENDIAN);
646         offset += 4;
647 
648         switch (operation_type) {
649         case 0x00: /* SvhdxMetaOperationTypeResize */
650             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_resize_new_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
651             offset += 8;
652 
653             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_resize_expand_only_flag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
654             offset += 1;
655 
656             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_resize_allow_unsafe_virt_size_flag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
657             offset += 1;
658 
659             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_resize_shrink_to_minimum_safe_size_flag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
660             offset += 1;
661 
662             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_meta_operation_start_reserved, tvb, offset, 1, ENC_LITTLE_ENDIAN);
663             offset += 1;
664             break;
665         case 0x01: /* SvhdxMetaOperationTypeCreateSnapshot */
666             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_snapshot_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
667             offset += 4;
668 
669             proto_tree_add_bitmask(gfi_sub_tree, tvb, offset, hf_svhdx_tunnel_create_snapshot_flags,
670                                    ett_rsvd_create_snapshot_flags, meta_operation_create_snapshot_flags, ENC_LITTLE_ENDIAN);
671             offset += 4;
672 
673             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_create_snapshot_stage1, tvb, offset, 4, ENC_LITTLE_ENDIAN);
674             offset += 4;
675 
676             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_create_snapshot_stage2, tvb, offset, 4, ENC_LITTLE_ENDIAN);
677             offset += 4;
678 
679             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_create_snapshot_stage3, tvb, offset, 4, ENC_LITTLE_ENDIAN);
680             offset += 4;
681 
682             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_create_snapshot_stage4, tvb, offset, 4, ENC_LITTLE_ENDIAN);
683             offset += 4;
684 
685             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_create_snapshot_stage5, tvb, offset, 4, ENC_LITTLE_ENDIAN);
686             offset += 4;
687 
688             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_create_snapshot_stage6, tvb, offset, 4, ENC_LITTLE_ENDIAN);
689             offset += 4;
690 
691             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_snapshot_id, tvb, offset, 16, ENC_LITTLE_ENDIAN);
692             offset += 16;
693 
694             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_create_snapshot_parameters_payload_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
695             offset += 4;
696 
697             break;
698         case 0x02: /* SvhdxMetaOperationTypeOptimize */
699             /* No Data, field MUST be empty */
700             break;
701         case 0x03: /* SvhdxMetaOperationTypeExtractVHD */
702             /* TODO */
703             break;
704         case 0x04: /* SvhdxMetaOperationTypeConvertToVHDSet */
705             length = tvb_get_letohl(tvb, offset);
706             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_convert_dst_vhdset_name_len, tvb, offset, 4, ENC_LITTLE_ENDIAN);
707             offset += 4;
708 
709             if (length) {
710                 proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_convert_dst_vhdset_name, tvb, offset, length, ENC_UTF_16|ENC_LITTLE_ENDIAN);
711             }
712             break;
713 
714         case 0x05: /* SvhdxMetaOperationTypeApplySnapshot */
715             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_snapshot_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
716             offset += 4;
717 
718             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_snapshot_id, tvb, offset, 16, ENC_LITTLE_ENDIAN);
719             offset += 16;
720 
721             break;
722         }
723     }
724     return offset;
725 }
726 
727 static int
dissect_RSVD2_META_OPERATION_QUERY_PROGRESS(tvbuff_t * tvb,proto_tree * parent_tree,int offset,gint16 len,gboolean request,guint32 status)728 dissect_RSVD2_META_OPERATION_QUERY_PROGRESS(tvbuff_t *tvb,
729             proto_tree *parent_tree, int offset, gint16 len, gboolean request, guint32 status)
730 {
731     proto_tree *gfi_sub_tree;
732     proto_item *gfi_sub_item;
733 
734     if (request) {
735         gfi_sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, len, ett_svhdx_tunnel_op_header, &gfi_sub_item, "RSVD_TUNNEL_META_OPERATION_QUERY_PROGRESS_REQUEST");
736 
737         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_transaction_id, tvb, offset, 16, ENC_LITTLE_ENDIAN);
738         offset += 16;
739     } else {
740         if (status == 0) { /* If status is not successful, RSVD response buffer is filled by data from request buffer and we should not parse output structure */
741             gfi_sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, len, ett_svhdx_tunnel_op_header, &gfi_sub_item, "RSVD_TUNNEL_META_OPERATION_QUERY_PROGRESS_RESPONSE");
742 
743             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_meta_op_query_progress_current_progress, tvb, offset, 8, ENC_LITTLE_ENDIAN);
744             offset += 8;
745 
746             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_meta_op_query_progress_complete_value, tvb, offset, 8, ENC_LITTLE_ENDIAN);
747             offset += 8;
748         }
749     }
750     return offset;
751 }
752 
753 static const value_string svhdx_vhdset_information_type_vals[] = {
754         { 0x02, "SvhdxVHDSetInformationTypeSnapshotList" },
755         { 0x05, "SvhdxVHDSetInformationTypeSnapshotEntry" },
756         { 0x08, "SvhdxVHDSetInformationTypeOptimizeNeeded" },
757         { 0x09, "SvhdxVHDSetInformationTypeCdpSnapshotRoot" },
758         { 0x0A, "SvhdxVHDSetInformationTypeCdpSnapshotActiveList" },
759         { 0x0C, "SvhdxVHDSetInformationTypeCdpSnapshotInactiveList" },
760         { 0, NULL }
761 };
762 static int
dissect_RSVD2_VHDSET_QUERY_INFORMATION(tvbuff_t * tvb,proto_tree * parent_tree,int offset,gint16 len,gboolean request)763 dissect_RSVD2_VHDSET_QUERY_INFORMATION(tvbuff_t *tvb, proto_tree *parent_tree, int offset, gint16 len, gboolean request)
764 {
765     proto_tree *gfi_sub_tree;
766     proto_item *gfi_sub_item;
767 
768     if (request) {
769         gfi_sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, len, ett_svhdx_tunnel_op_header, &gfi_sub_item, "RSVD_TUNNEL_VHDSET_QUERY_INFORMATION_REQUEST");
770 
771         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_vhdset_information_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
772         offset += 4;
773 
774         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_snapshot_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
775         offset += 4;
776 
777         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_snapshot_id, tvb, offset, 16, ENC_LITTLE_ENDIAN);
778         offset += 16;
779     } else {
780         guint32 vhdset_info_type = tvb_get_letohl(tvb, offset);
781         switch (vhdset_info_type) {
782         case 0x02: /* SvhdxVHDSetInformationTypeSnapshotList */
783             gfi_sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, len, ett_svhdx_tunnel_op_header, &gfi_sub_item, "RSVD_TUNNEL_VHDSET_QUERY_INFORMATION_SNAPSHOT_LIST_RESPONSE");
784 
785             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_vhdset_information_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
786             offset += 4;
787             /* TODO: make full dissection */
788 
789             break;
790         case 0x05: /* SvhdxVHDSetInformationTypeSnapshotEntry */
791             gfi_sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, len, ett_svhdx_tunnel_op_header, &gfi_sub_item, "RSVD_TUNNEL_VHDSET_QUERY_INFORMATION_SNAPSHOT_ENTRY_RESPONSE");
792 
793             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_vhdset_information_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
794             offset += 4;
795 
796             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_padding, tvb, offset, 4, ENC_LITTLE_ENDIAN);
797             offset += 4;
798 
799             offset = dissect_nt_64bit_time(tvb, gfi_sub_tree, offset, hf_svhdx_tunnel_vhdset_snapshot_creation_time);
800 
801             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_snapshot_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
802             offset += 4;
803 
804             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_vhdset_is_valid_snapshot, tvb, offset, 4, ENC_LITTLE_ENDIAN);
805             offset += 4;
806 
807             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_snapshot_id, tvb, offset, 16, ENC_LITTLE_ENDIAN);
808             offset += 16;
809 
810             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_vhdset_parent_snapshot_id, tvb, offset, 16, ENC_LITTLE_ENDIAN);
811             offset += 16;
812 
813             proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_vhdset_log_file_id, tvb, offset, 16, ENC_LITTLE_ENDIAN);
814             offset += 16;
815 
816             break;
817         }
818     }
819     return offset;
820 }
821 
822 static int
dissect_RSVD2_DELETE_SNAPSHOT(tvbuff_t * tvb,proto_tree * parent_tree,int offset,gint16 len,gboolean request)823 dissect_RSVD2_DELETE_SNAPSHOT(tvbuff_t *tvb, proto_tree *parent_tree, int offset, gint16 len, gboolean request)
824 {
825     proto_tree *gfi_sub_tree;
826     proto_item *gfi_sub_item;
827 
828     if (request) {
829         gfi_sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, len, ett_svhdx_tunnel_op_header, &gfi_sub_item, "RSVD_TUNNEL_DELETE_SNAPSHOT_REQUEST");
830 
831         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_snapshot_id, tvb, offset, 16, ENC_LITTLE_ENDIAN);
832         offset += 16;
833 
834         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_delete_snapshot_persist_reference, tvb, offset, 4, ENC_LITTLE_ENDIAN);
835         offset += 4;
836 
837         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_snapshot_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
838         offset += 4;
839     }
840     return offset;
841 }
842 
843 static int
dissect_RSVD2_QUERY_SAFE_SIZE(tvbuff_t * tvb,proto_tree * parent_tree,int offset,gint16 len,gboolean request)844 dissect_RSVD2_QUERY_SAFE_SIZE(tvbuff_t *tvb, proto_tree *parent_tree, int offset, gint16 len, gboolean request)
845 {
846     proto_tree *gfi_sub_tree;
847     proto_item *gfi_sub_item;
848 
849     if (!request) {
850         gfi_sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, len, ett_svhdx_tunnel_op_header, &gfi_sub_item, "RSVD_TUNNEL_QUERY_SAFE_SIZE_RESPONSE");
851 
852         proto_tree_add_item(gfi_sub_tree, hf_svhdx_tunnel_safe_virtual_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
853         offset += 8;
854     }
855     return offset;
856 }
857 
858 static int
dissect_rsvd(tvbuff_t * tvb,packet_info * pinfo,proto_tree * parent_tree,void * data)859 dissect_rsvd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void *data)
860 {
861     guint32 header_bytes = 0;
862     guint proto_id = 0;
863     guint proto_version = 0;
864     guint32 operation_code = 0;
865     guint32 status;
866     proto_item *ti;
867     proto_tree *rsvd_tree;
868     proto_item *sub_item;
869     proto_tree *sub_tree;
870     guint       offset = 0;
871     guint16 len;
872     guint64 request_id = 0;
873     gboolean request = *(gboolean *)data;
874 
875     top_tree = parent_tree;
876 
877     len = tvb_reported_length(tvb);
878 
879     col_set_str(pinfo->cinfo, COL_PROTOCOL, "RSVD");
880 
881     col_clear(pinfo->cinfo, COL_INFO);
882 
883     /*
884      * The header bytes need to be pulled in as a 32bit LE value. And the
885      * header is the same in a request or a response ...
886      */
887     header_bytes = tvb_get_letohl(tvb, 0); /* Get the header bytes */
888     proto_id = header_bytes >> 24;
889     proto_version = (header_bytes >> 12) & 0x0FFF;
890     operation_code = header_bytes;
891 
892     ti = proto_tree_add_item(parent_tree, proto_rsvd, tvb, offset, -1, ENC_NA);
893 
894     rsvd_tree = proto_item_add_subtree(ti, ett_rsvd);
895 
896     sub_tree = proto_tree_add_subtree(rsvd_tree, tvb, offset, (len>16) ? 16 : len, ett_svhdx_tunnel_op_header, &sub_item, "SVHDX_TUNNEL_OPERATION_HEADER");
897 
898     /* ProtocolID */
899     proto_tree_add_uint(sub_tree, hf_svhdx_protocol_id, tvb, offset, 4, proto_id);
900 
901     /* ProtocolVersion */
902     proto_tree_add_uint(sub_tree, hf_svhdx_protocol_version, tvb, offset, 4, proto_version);
903 
904     /* Operation Code */
905     proto_tree_add_uint(sub_tree, hf_svhdx_operation_code, tvb, offset, 4, operation_code);
906     offset += 4;
907 
908     /* Status */
909     status = tvb_get_letohl(tvb, offset);
910     proto_tree_add_item(sub_tree, hf_svhdx_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
911     offset += 4;
912 
913     /* RequestId */
914     request_id = tvb_get_ntoh64(tvb, offset);
915     proto_tree_add_item(sub_tree, hf_svhdx_request_id, tvb, offset, 8, ENC_LITTLE_ENDIAN);
916     offset += 8;
917 
918     col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
919                     val_to_str(operation_code,
920                                rsvd_operation_code_vals,
921                                "Unknown Operation Code (0x%08X)"),
922                     request ? "Request" : "Response");
923 
924     proto_item_append_text(ti, ", %s %s",
925                           val_to_str(operation_code,
926                                      rsvd_operation_code_vals,
927                                      "Unknown Operation Code (0x%08X)"),
928                           request ? "Request" : "Response");
929     /*
930      * Now process the individual requests ...
931      */
932     switch (operation_code) {
933     case 0x02001001:
934         offset += dissect_RSVD_GET_INITIAL_INFO(tvb, rsvd_tree, offset, len - offset, request);
935         break;
936 
937     case 0x02001002:
938         offset += dissect_RSVD_TUNNEL_SCSI(tvb, pinfo, rsvd_tree, offset, len - offset, request, request_id);
939         break;
940 
941     case 0x02001003:
942 
943         /*
944          * There is nothing more here.
945          */
946 
947         break;
948 
949     case 0x02001004:
950         offset += dissect_RSVD_SRB_STATUS(tvb, rsvd_tree, offset, len - offset, request);
951         break;
952 
953     case 0x02001005:
954         offset += dissect_RSVD_GET_DISK_INFO(tvb, rsvd_tree, offset, len - offset, request);
955         break;
956 
957     case 0x02001006:
958         offset += dissect_RSVD_VALIDATE_DISK(tvb, rsvd_tree, offset, len - offset, request);
959         break;
960     /* RSVD v2 operations */
961     case 0x02002101:
962         offset += dissect_RSVD2_META_OPERATION_START(tvb, rsvd_tree, offset, len - offset, request);
963         break;
964 
965     case 0x02002002:
966         offset += dissect_RSVD2_META_OPERATION_QUERY_PROGRESS(tvb, rsvd_tree, offset, len - offset, request, status);
967         break;
968 
969     case 0x02002005:
970         offset += dissect_RSVD2_VHDSET_QUERY_INFORMATION(tvb, rsvd_tree, offset, len - offset, request);
971         break;
972 
973     case 0x02002006:
974         offset += dissect_RSVD2_DELETE_SNAPSHOT(tvb, rsvd_tree, offset, len - offset, request);
975         break;
976 
977     case 0x0200200D:
978         offset += dissect_RSVD2_QUERY_SAFE_SIZE(tvb, rsvd_tree, offset, len - offset, request);
979         break;
980 
981     /* TODO: implement more dissectors for RSVD v2 */
982 
983     default:
984         break;
985     }
986 
987     return offset;
988 }
989 
990 void
proto_register_rsvd(void)991 proto_register_rsvd(void)
992 {
993 
994     static hf_register_info hf[] = {
995                 { &hf_svhdx_protocol_id,
996                   { "ProtocolId", "rsvd.svhdx_protocol_id", FT_UINT8, BASE_DEC,
997                     NULL, 0, NULL, HFILL }},
998 
999                 { &hf_svhdx_protocol_version,
1000                   { "ProtocolVersion", "rsvd.svhdx_protocol_version", FT_UINT16, BASE_DEC,
1001                      NULL, 0, NULL, HFILL }},
1002 
1003                 { &hf_svhdx_operation_code,
1004                   { "OperationCode", "rsvd.svhdx_operation_code", FT_UINT32, BASE_HEX,
1005                      VALS(rsvd_operation_code_vals), 0, "Operation Code", HFILL }},
1006 
1007                 { &hf_svhdx_status,
1008                   { "Status", "rsvd.svhdx_status", FT_UINT32, BASE_HEX | BASE_EXT_STRING,
1009                     &NT_errors_ext, 0, NULL, HFILL }},
1010 
1011 
1012                 { &hf_svhdx_request_id,
1013                   { "RequestId", "rsvd.svhdx_request_id", FT_UINT64, BASE_HEX,
1014                     NULL, 0, NULL, HFILL }},
1015 
1016                 { &hf_svhdx_tunnel_scsi_length,
1017                   { "Length", "rsvd.svhdx_length", FT_UINT16, BASE_DEC,
1018                     NULL, 0, NULL, HFILL }},
1019 
1020                 { &hf_svhdx_tunnel_scsi_reserved1,
1021                   { "Reserved1", "rsvd.svhdx_scsi_reserved1", FT_UINT16, BASE_HEX,
1022                     NULL, 0, NULL, HFILL }},
1023 
1024                 { &hf_svhdx_tunnel_scsi_cdb_length,
1025                   { "CDBLength", "rsvd.svhdx_scsi_cdb_length", FT_UINT8, BASE_DEC,
1026                     NULL, 0, NULL, HFILL }},
1027 
1028                 { &hf_svhdx_tunnel_scsi_sense_info_ex_length,
1029                   { "SenseInfoExLength", "rsvd.svhdx_scsi_sense_info_ex_length", FT_UINT8, BASE_DEC,
1030                     NULL, 0, NULL, HFILL }},
1031 
1032                 { &hf_svhdx_tunnel_scsi_data_in,
1033                   { "DataIn", "rsvd.svhdx_scsi_data_in", FT_UINT8, BASE_HEX,
1034                     VALS(rsvd_data_in_vals), 0, "SCSI CDB transfer type", HFILL }},
1035 
1036                 { &hf_svhdx_tunnel_scsi_reserved2,
1037                   { "Reserved2", "rsvd.svhdx_scsi_reserved2", FT_UINT8, BASE_HEX,
1038                     NULL, 0, NULL, HFILL }},
1039 
1040                 { &hf_svhdx_tunnel_scsi_srb_flags,
1041                   { "SRBFlags", "rsvd.svhdx_scsi_srbflags", FT_UINT32, BASE_HEX,
1042                     NULL, 0, NULL, HFILL }},
1043 
1044                 { &hf_svhdx_tunnel_scsi_data_transfer_length,
1045                   { "DataTransferLength", "rsvd.svhdx_scsi_data_transfer_length", FT_UINT32, BASE_DEC,
1046                     NULL, 0, NULL, HFILL }},
1047 
1048                 { &hf_svhdx_tunnel_scsi_reserved3,
1049                   { "Reserved3", "rsvd.svhdx_scsi_reserved3", FT_UINT32, BASE_HEX,
1050                     NULL, 0, NULL, HFILL }},
1051 
1052                 { &hf_svhdx_tunnel_scsi_cdb,
1053                   { "CDB", "rsvd.svhdx_scsi_cdb", FT_BYTES, BASE_NONE,
1054                     NULL, 0, NULL, HFILL }},
1055 
1056                 { &hf_svhdx_tunnel_scsi_cdb_padding,
1057                   { "CDBPadding", "rsvd.svhdx_scsi_cdb_padding", FT_BYTES, BASE_NONE,
1058                     NULL, 0, NULL, HFILL }},
1059 
1060                 { &hf_svhdx_tunnel_scsi_data,
1061                   {"Data", "rsvd.svhdx_scsi_data", FT_BYTES, BASE_NONE,
1062                     NULL, 0, NULL, HFILL }},
1063 
1064                 { &hf_svhdx_tunnel_scsi_auto_generated_sense,
1065                   {"AutoGeneratedSenseInfo", "rsvd.svhdx_auto_generated_sense_info", FT_UINT8, BASE_HEX,
1066                     VALS(rsvd_sense_info_vals), 0x80, NULL, HFILL }},
1067 
1068                 { &hf_svhdx_tunnel_scsi_srb_status,
1069                   { "SrbStatus", "rsvd.svhdx_srb_status", FT_UINT8, BASE_HEX,
1070                     NULL, 0, NULL, HFILL }},
1071 
1072                 { &hf_svhdx_tunnel_scsi_status,
1073                   { "ScsiStatus", "rsvd.svhdx_scsi_status", FT_UINT8, BASE_HEX,
1074                     NULL, 0, NULL, HFILL }},
1075 
1076                 { &hf_svhdx_tunnel_scsi_sense_data_ex,
1077                   { "SenseDataEx", "rsvd.svhdx_scsi_sense_data_ex", FT_BYTES, BASE_NONE,
1078                     NULL, 0, NULL, HFILL }},
1079 
1080                 { &hf_svhdx_tunnel_file_info_server_version,
1081                   { "ServerVersion", "rsvd.svhdx_file_info_server_version", FT_UINT32, BASE_DEC,
1082                     NULL, 0, NULL, HFILL }},
1083 
1084                 { &hf_svhdx_tunnel_file_info_sector_size,
1085                   { "SectorSize", "rsvd.svhdx_file_info_sector_size", FT_UINT32, BASE_DEC,
1086                     NULL, 0, NULL, HFILL }},
1087 
1088                 { &hf_svhdx_tunnel_file_info_physical_sector_size,
1089                   { "PhysicalSectorSize", "rsvd.svhdx_file_info_physical_sector_size", FT_UINT32, BASE_DEC,
1090                     NULL, 0, NULL, HFILL }},
1091 
1092                 { &hf_svhdx_tunnel_file_info_reserved,
1093                   { "Reserved", "rsvd.svhdx_file_info_reserved", FT_UINT32, BASE_DEC,
1094                     NULL, 0, NULL, HFILL }},
1095 
1096                 { &hf_svhdx_tunnel_file_info_virtual_size,
1097                   { "VirtualSize", "rsvd.svhdx_file_info_virtual_size", FT_UINT64, BASE_DEC,
1098                     NULL, 0, NULL, HFILL }},
1099 
1100 
1101                 { &hf_svhdx_tunnel_disk_info_reserved1,
1102                   { "Reserved1", "rsvd.svhdx_disk_info_reserved1", FT_UINT64, BASE_DEC,
1103                     NULL, 0, NULL, HFILL }},
1104 
1105                 { &hf_svhdx_tunnel_disk_info_blocksize,
1106                   { "BlockSize", "rsvd.svhdx_disk_info_blocksize", FT_UINT32, BASE_DEC,
1107                     NULL, 0, NULL, HFILL }},
1108 
1109                 { &hf_svhdx_tunnel_disk_info_linkage_id,
1110                   { "LinkageID", "rsvd.svhdx_disk_info_linkage_id", FT_GUID, BASE_NONE,
1111                     NULL, 0, NULL, HFILL }},
1112 
1113                 { &hf_svhdx_tunnel_disk_info_disk_type,
1114                   { "DiskType", "rsvd.svhdx_disk_info_disk_type", FT_UINT16, BASE_HEX,
1115                      VALS(rsvd_disk_type_vals), 0, "Disk Type", HFILL }},
1116 
1117                 { &hf_svhdx_tunnel_disk_info_disk_format,
1118                   { "DiskFormat", "rsvd.svhdx_disk_info_disk_format", FT_UINT16, BASE_HEX,
1119                      VALS(rsvd_disk_format_vals), 0, "Disk Format", HFILL }},
1120 
1121                 { &hf_svhdx_tunnel_disk_info_is_mounted,
1122                   { "IsMounted", "rsvd.svhdx_tunnel_disk_info_is_mounted", FT_UINT8, BASE_DEC,
1123                     NULL, 0, NULL, HFILL }},
1124 
1125                 { &hf_svhdx_tunnel_disk_info_is_4k_aligned,
1126                   { "Is4KAligned", "rsvd.svhdx_tunnel_disk_info_is_4k_aligned", FT_UINT8, BASE_DEC,
1127                     NULL, 0, NULL, HFILL }},
1128 
1129                 { &hf_svhdx_tunnel_disk_info_reserved,
1130                   { "Reserved", "rsvd.svhdx_disk_info_reserved", FT_UINT16, BASE_DEC,
1131                     NULL, 0, NULL, HFILL }},
1132 
1133                 { &hf_svhdx_tunnel_disk_info_file_size,
1134                   { "FileSize", "rsvd.svhdx_disk_info_file_size", FT_UINT64, BASE_DEC,
1135                     NULL, 0, NULL, HFILL }},
1136 
1137                 { &hf_svhdx_tunnel_disk_info_virtual_disk_id,
1138                   { "VirtualDiskId", "rsvd.svhdx_disk_info_virtual_disk_id", FT_GUID, BASE_NONE,
1139                     NULL, 0, NULL, HFILL }},
1140 
1141                 { &hf_svhdx_tunnel_validate_disk_reserved,
1142                   { "Reserved", "rsvd.svhdx_tunnel_validate_disk_reserved", FT_BYTES, BASE_NONE,
1143                     NULL, 0, NULL, HFILL }},
1144 
1145                 { &hf_svhdx_tunnel_validate_disk_is_valid_disk,
1146                   { "IsValidDisk", "rsvd.svhdx_validate_disk_is_valid_disk", FT_BYTES, BASE_NONE,
1147                     NULL, 0, NULL, HFILL }},
1148 
1149                 { &hf_svhdx_tunnel_srb_status_status_key,
1150                   { "StatusKey", "rsvd.svhdx_srb_status_key", FT_UINT8, BASE_DEC,
1151                     NULL, 0, NULL, HFILL }},
1152 
1153                 { &hf_svhdx_tunnel_srb_status_reserved,
1154                   { "Reserved", "rsvd.svhdx_srb_status_reserved", FT_BYTES, BASE_NONE,
1155                     NULL, 0, NULL, HFILL }},
1156 
1157                 { &hf_svhdx_tunnel_srb_status_sense_info_auto_generated,
1158                   { "SenseInfoAutoGenerated", "rsvd.svhdx_sense_info_auto_generated", FT_UINT8, BASE_HEX,
1159                     VALS(rsvd_sense_info_vals), 0x80, NULL, HFILL }},
1160 
1161                 { &hf_svhdx_tunnel_srb_status_srb_status,
1162                   { "SrbStatus", "rsvd.svhdx_srb_status_srb_status", FT_UINT8, BASE_HEX,
1163                     NULL, 0x7f, NULL, HFILL }},
1164 
1165                 { &hf_svhdx_tunnel_srb_status_scsi_status,
1166                   { "SrbStatus", "rsvd.svhdx_srb_status_scsi_status", FT_UINT8, BASE_DEC,
1167                     NULL, 0, NULL, HFILL }},
1168 
1169                 { &hf_svhdx_tunnel_srb_status_sense_info_ex_length,
1170                   { "SenseInfoExLength", "rsvd.svhdx_srb_status_sense_info_ex_length", FT_UINT8, BASE_DEC,
1171                     NULL, 0, NULL, HFILL }},
1172 
1173                 { &hf_svhdx_tunnel_srb_status_sense_data_ex,
1174                   { "Reserved", "rsvd.svhdx_srb_status_sense_data_ex", FT_BYTES, BASE_NONE,
1175                     NULL, 0, NULL, HFILL }},
1176 
1177                 { &hf_svhdx_tunnel_safe_virtual_size,
1178                   { "SafeVirtualSize", "rsvd.svhdx_safe_size", FT_UINT64, BASE_DEC,
1179                     NULL, 0, NULL, HFILL }},
1180 
1181                 { &hf_svhdx_tunnel_transaction_id,
1182                   { "TransactionId", "rsvd.svhdx_meta_operation.transaction_id", FT_GUID, BASE_NONE,
1183                     NULL, 0, NULL, HFILL }},
1184 
1185                 { &hf_svhdx_tunnel_meta_operation_type,
1186                   { "OperationType", "rsvd.svhdx_meta_operation.type", FT_UINT32, BASE_HEX,
1187                     VALS(rsvd_meta_operation_type_vals), 0, "Type of meta-operation", HFILL }},
1188 
1189                 { &hf_svhdx_tunnel_padding,
1190                   { "Padding", "rsvd.svhdx_padding", FT_UINT32, BASE_DEC,
1191                     NULL, 0, NULL, HFILL }},
1192 
1193                 { &hf_svhdx_tunnel_resize_new_size,
1194                   { "NewSize", "rsvd.svhdx_meta_operation.new_size", FT_UINT64, BASE_DEC,
1195                     NULL, 0, NULL, HFILL }},
1196 
1197                 { &hf_svhdx_tunnel_resize_expand_only_flag,
1198                   { "ExpandOnly", "rsvd.svhdx_meta_operation.expand_only", FT_BOOLEAN, 8,
1199                     NULL, 0, "Indicates that shared virtual disk size can only expand", HFILL }},
1200 
1201                 { &hf_svhdx_tunnel_resize_allow_unsafe_virt_size_flag,
1202                   { "AllowUnsafeVirtualSize", "rsvd.svhdx_meta_operation.allow_unsafe_virt_size", FT_BOOLEAN, 8,
1203                     NULL, 0, "Indicates that the shared virtual disk size can be less than the data it currently contains", HFILL }},
1204 
1205                 { &hf_svhdx_tunnel_resize_shrink_to_minimum_safe_size_flag,
1206                   { "ShrinkToMinimumSafeSize", "rsvd.svhdx_meta_operation.shrink_to_minimum_safe_size", FT_BOOLEAN, 8,
1207                     NULL, 0, "Indicates that the shared virtual disk size can be shrunk to the data it currently contains", HFILL }},
1208 
1209                 { &hf_svhdx_tunnel_meta_operation_start_reserved,
1210                   { "Reserved", "rsvd.svhdx_meta_operation.reserved", FT_UINT8, BASE_DEC,
1211                     NULL, 0, NULL, HFILL }},
1212 
1213                 { &hf_svhdx_tunnel_snapshot_type,
1214                   { "SnapshotType", "rsvd.svhdx_snapshot_type", FT_UINT32, BASE_HEX,
1215                     VALS(svhdx_snapshot_type_vals), 0, "Type of snapshot", HFILL }},
1216 
1217                 { &hf_svhdx_tunnel_snapshot_id,
1218                   { "SnapshotId", "rsvd.svhdx_snapshot_id", FT_GUID, BASE_NONE,
1219                     NULL, 0, NULL, HFILL }},
1220 
1221                 { &hf_svhdx_tunnel_create_snapshot_flags,
1222                   { "Flags", "rsvd.svhdx_meta_operation.create_snapshot_flags", FT_UINT32, BASE_HEX,
1223                     NULL, 0, NULL, HFILL }},
1224 
1225                 { &hf_svhdx_tunnel_create_snapshot_flag_enable_change_tracking,
1226                   { "SVHDX_SNAPSHOT_DISK_FLAG_ENABLE_CHANGE_TRACKING", "rsvd.svhdx_meta_operation.create_snapshot_flag_enable_change_tracking", FT_BOOLEAN, 32,
1227                     NULL, SVHDX_SNAPSHOT_DISK_FLAG_ENABLE_CHANGE_TRACKING, "Change tracking to be enabled when snapshot is taken", HFILL }},
1228 
1229                 { &hf_svhdx_tunnel_create_snapshot_stage1,
1230                   { "Stage1", "rsvd.svhdx_meta_operation.create_snapshot_stage1", FT_UINT32, BASE_HEX,
1231                     VALS(svhdx_snapshot_stage_vals), 0, "The first stage", HFILL }},
1232 
1233                 { &hf_svhdx_tunnel_create_snapshot_stage2,
1234                   { "Stage2", "rsvd.svhdx_meta_operation.create_snapshot_stage2", FT_UINT32, BASE_HEX,
1235                     VALS(svhdx_snapshot_stage_vals), 0, "The second stage", HFILL }},
1236 
1237                 { &hf_svhdx_tunnel_create_snapshot_stage3,
1238                   { "Stage3", "rsvd.svhdx_meta_operation.create_snapshot_stage3", FT_UINT32, BASE_HEX,
1239                     VALS(svhdx_snapshot_stage_vals), 0, "The third stage", HFILL }},
1240 
1241                 { &hf_svhdx_tunnel_create_snapshot_stage4,
1242                   { "Stage4", "rsvd.svhdx_meta_operation.create_snapshot_stage4", FT_UINT32, BASE_HEX,
1243                     VALS(svhdx_snapshot_stage_vals), 0, "The fourth stage", HFILL }},
1244 
1245                 { &hf_svhdx_tunnel_create_snapshot_stage5,
1246                   { "Stage5", "rsvd.svhdx_meta_operation.create_snapshot_stage5", FT_UINT32, BASE_HEX,
1247                     VALS(svhdx_snapshot_stage_vals), 0, "The fifth stage", HFILL }},
1248 
1249                 { &hf_svhdx_tunnel_create_snapshot_stage6,
1250                   { "Stage6", "rsvd.svhdx_meta_operation.create_snapshot_stage6", FT_UINT32, BASE_HEX,
1251                     VALS(svhdx_snapshot_stage_vals), 0, "The sixth stage", HFILL }},
1252 
1253                 { &hf_svhdx_tunnel_create_snapshot_parameters_payload_size,
1254                   { "ParametersPayloadSize", "rsvd.svhdx_meta_operation.create_snapshot_params_payload_size", FT_UINT32, BASE_DEC,
1255                     NULL, 0, NULL, HFILL }},
1256 
1257                 { &hf_svhdx_tunnel_convert_dst_vhdset_name_len,
1258                   { "DestinationVhdSetNameLength", "rsvd.svhdx_meta_operation.dst_vhdset_name_len", FT_UINT32, BASE_DEC,
1259                     NULL, 0, NULL, HFILL }},
1260 
1261                 { &hf_svhdx_tunnel_convert_dst_vhdset_name,
1262                   { "DestinationVhdSetName", "rsvd.svhdx_meta_operation.dst_vhdset_name", FT_STRING, BASE_NONE,
1263                     NULL, 0, "Name for the new VHD set be created", HFILL }},
1264 
1265                 { &hf_svhdx_tunnel_delete_snapshot_persist_reference,
1266                   { "PersistReference", "rsvd.svhdx_delete_snapshot_persist_reference", FT_BOOLEAN, 4,
1267                     NULL, 0, "Indicate if the snapshot needs to be persisted", HFILL }},
1268 
1269                 { &hf_svhdx_tunnel_meta_op_query_progress_current_progress,
1270                   { "CurrentProgressValue", "rsvd.svhdx_query_progress.current_progress", FT_UINT64, BASE_DEC,
1271                     NULL, 0, NULL, HFILL }},
1272 
1273                 { &hf_svhdx_tunnel_meta_op_query_progress_complete_value,
1274                   { "CompleteValue", "rsvd.svhdx_query_progress.complete_value", FT_UINT64, BASE_DEC,
1275                     NULL, 0, NULL, HFILL }},
1276 
1277                 { &hf_svhdx_tunnel_vhdset_information_type,
1278                   { "VHDSetInformationType", "rsvd.svhdx_vhdset_information_type", FT_UINT32, BASE_HEX,
1279                     VALS(svhdx_vhdset_information_type_vals), 0, "The information type requested", HFILL }},
1280 
1281                 { &hf_svhdx_tunnel_vhdset_snapshot_creation_time,
1282                   { "SnapshotCreationTime", "rsvd.svhdx_vhdset_snapshot_creation_time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
1283                     NULL, 0, "Time when this object was created", HFILL }},
1284 
1285                 { &hf_svhdx_tunnel_vhdset_is_valid_snapshot,
1286                   { "IsValidSnapshot", "rsvd.svhdx_vhdset_is_valid_snapshot", FT_BOOLEAN, 4,
1287                     NULL, 0, "Set to 1 when the snapshot is valid", HFILL }},
1288 
1289                 { &hf_svhdx_tunnel_vhdset_parent_snapshot_id,
1290                   { "ParentSnapshotId", "rsvd.svhdx_vhdxset_parent_snapshot_id", FT_GUID, BASE_NONE,
1291                     NULL, 0, NULL, HFILL }},
1292 
1293                 { &hf_svhdx_tunnel_vhdset_log_file_id,
1294                   { "LogFileId", "rsvd.svhdx_vhdxset_log_file_id", FT_GUID, BASE_NONE,
1295                     NULL, 0, NULL, HFILL }}
1296     };
1297 
1298     static gint *ett[] = {
1299         &ett_rsvd,
1300         &ett_svhdx_tunnel_op_header,
1301         &ett_svhdx_tunnel_scsi_request,
1302         &ett_rsvd_create_snapshot_flags
1303     };
1304 
1305     proto_rsvd = proto_register_protocol("Remote Shared Virtual Disk",
1306             "RSVD", "rsvd");
1307 
1308     register_dissector("rsvd", dissect_rsvd, proto_rsvd);
1309     proto_register_field_array(proto_rsvd, hf, array_length(hf));
1310     proto_register_subtree_array(ett, array_length(ett));
1311 }
1312 
1313 /*
1314  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1315  *
1316  * Local variables:
1317  * c-basic-offset: 4
1318  * tab-width: 8
1319  * indent-tabs-mode: nil
1320  * End:
1321  *
1322  * vi: set shiftwidth=4 tabstop=8 expandtab:
1323  * :indentSize=4:tabSize=8:noTabs=true:
1324  */
1325