2 * Routines for AF_VSOCK dissection
3 * Copyright 2016, Gerard Garcia <ggarcia@deic.uab.cat>
6 * https://github.com/GerardGarcia/linux/blob/vsockmon/include/uapi/linux/vsockmon.h
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
16 * The AF_VSOCK socket allows zero-configuration communication between guests
17 * and hypervisors using the standard socket API.
21 #include <epan/packet.h>
22 #include <wsutil/pint.h>
23 #include <epan/address_types.h>
24 #include <wiretap/wtap.h>
26 void proto_register_vsock(void);
27 void proto_reg_handoff_vsock(void);
29 static int proto_vsock
;
30 static int vsock_address_type
= -1;
31 static dissector_handle_t vsock_handle
;
33 /* Generic header related fields */
34 static int hf_vsock_src_cid
;
35 static int hf_vsock_src_port
;
36 static int hf_vsock_dst_cid
;
37 static int hf_vsock_dst_port
;
38 static int hf_vsock_op
;
39 static int hf_vsock_t
;
40 static int hf_vsock_t_len
;
41 static int hf_vsock_reserved
;
42 static int hf_vsock_payload
;
44 /* Virtio related fields */
45 static int hf_virtio_src_cid
;
46 static int hf_virtio_dst_cid
;
47 static int hf_virtio_src_port
;
48 static int hf_virtio_dst_port
;
49 static int hf_virtio_len
;
50 static int hf_virtio_type
;
51 static int hf_virtio_op
;
52 static int hf_virtio_flags
;
53 static int hf_virtio_buf_alloc
;
54 static int hf_virtio_fwd_cnt
;
57 static int ett_virtio
;
59 static const value_string af_vsockmon_op_names
[] = {
69 AF_VSOCK_T_UNKNOWN
= 0,
70 AF_VSOCK_T_NO_INFO
= 1,
74 static const value_string af_vsockmon_t_names
[] = {
81 static const value_string virtio_vsock_type_names
[] = {
86 static const value_string virtio_vsock_op_names
[] = {
93 { 6, "Credit update" },
94 { 7, "Credit response" },
98 #define VSOCK_MIN_LENGTH 32
100 static int vsock_addr_to_str(const address
* addr
, char *buf
, int buf_len
)
102 const uint8_t *addrp
= (const uint8_t *)addr
->data
;
104 if(pletoh64(&addrp
[0])==2){
105 (void) g_strlcpy(buf
, "host", buf_len
);
107 snprintf(buf
, buf_len
, "%" PRIu64
, pletoh64(&addrp
[0]));
110 return (int)(strlen(buf
)+1);
113 static int vsock_addr_str_len(const address
* addr _U_
)
115 /* 2^64 unsigned int len */
120 dissect_vsock(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
123 proto_item
*ti
, *virtio_ti
;
124 proto_tree
*vsock_tree
, *virtio_tree
;
126 uint32_t t_len
, payload_len
, virtio_buf_alloc
, op
, type
,
127 virtio_fwd_cnt
, virtio_op
, virtio_type
;
128 uint16_t payload_offset
= 0, offset
= 0;
130 if (tvb_reported_length(tvb
) < VSOCK_MIN_LENGTH
)
133 /* Clear column information before start parsing */
134 col_clear(pinfo
->cinfo
, COL_INFO
);
136 /* Create top tree */
137 ti
= proto_tree_add_item(tree
, proto_vsock
, tvb
, 0, -1, ENC_NA
);
138 vsock_tree
= proto_item_add_subtree(ti
, ett_vsock
);
140 /* Parse generic header part */
141 proto_tree_add_item(vsock_tree
, hf_vsock_src_cid
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
142 set_address_tvb(&pinfo
->src
, vsock_address_type
, 8, tvb
, offset
);
145 proto_tree_add_item(vsock_tree
, hf_vsock_dst_cid
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
146 set_address_tvb(&pinfo
->dst
, vsock_address_type
, 8, tvb
, offset
);
149 proto_tree_add_item_ret_uint(vsock_tree
, hf_vsock_src_port
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &pinfo
->srcport
);
152 proto_tree_add_item_ret_uint(vsock_tree
, hf_vsock_dst_port
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &pinfo
->destport
);
155 proto_tree_add_item_ret_uint(vsock_tree
, hf_vsock_op
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
, &op
);
158 proto_tree_add_item_ret_uint(vsock_tree
, hf_vsock_t
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
, &type
);
161 proto_tree_add_item_ret_uint(vsock_tree
, hf_vsock_t_len
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
, &t_len
);
164 proto_tree_add_item(vsock_tree
, hf_vsock_reserved
, tvb
, offset
, 2, ENC_NA
);
167 payload_offset
= offset
+ t_len
;
169 /* Append summary information to top tree */
170 proto_item_append_text(ti
, ", Op: %s, Transport: %s",
171 val_to_str(op
, af_vsockmon_op_names
, "Unknown (%d)"),
172 val_to_str(type
, af_vsockmon_t_names
, "Unknown (%d)"));
175 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "[%s] %s",
176 val_to_str(op
, af_vsockmon_op_names
, "Unknown (%d)"),
177 val_to_str(type
, af_vsockmon_t_names
, "Unknown (%d)"));
178 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "vSocket");
180 /* Create subtree if there is transport information */
182 case AF_VSOCK_T_UNKNOWN
:
183 case AF_VSOCK_T_NO_INFO
:
185 case AF_VSOCK_T_VIRTIO
:
186 virtio_tree
= proto_tree_add_subtree(vsock_tree
, tvb
, offset
, 44, ett_virtio
, &virtio_ti
, "Virtio transport header");
188 proto_tree_add_item(virtio_tree
, hf_virtio_src_cid
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
190 proto_tree_add_item(virtio_tree
, hf_virtio_dst_cid
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
192 proto_tree_add_item(virtio_tree
, hf_virtio_src_port
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
194 proto_tree_add_item(virtio_tree
, hf_virtio_dst_port
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
196 proto_tree_add_item(virtio_tree
, hf_virtio_len
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
199 proto_tree_add_item_ret_uint(virtio_tree
, hf_virtio_type
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
, &virtio_type
);
202 proto_tree_add_item_ret_uint(virtio_tree
, hf_virtio_op
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
, &virtio_op
);
205 proto_tree_add_item(virtio_tree
, hf_virtio_flags
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
208 proto_tree_add_item_ret_uint(virtio_tree
, hf_virtio_buf_alloc
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &virtio_buf_alloc
);
211 proto_tree_add_item_ret_uint(virtio_tree
, hf_virtio_fwd_cnt
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &virtio_fwd_cnt
);
214 /* Append virtio information */
215 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ": %s, Op: %s, Buf alloc: %u, Fwd cnt: %u",
216 val_to_str(virtio_type
, virtio_vsock_type_names
, "Unknown (%d)"),
217 val_to_str(virtio_op
, virtio_vsock_op_names
, "Unknown (%d)"),
218 virtio_buf_alloc
, virtio_fwd_cnt
);
224 payload_len
= tvb_reported_length_remaining(tvb
, payload_offset
);
226 proto_tree_add_bytes_format(vsock_tree
, hf_vsock_payload
, tvb
, payload_offset
, payload_len
,
227 NULL
, "Payload (%uB)", payload_len
);
229 return tvb_reported_length(tvb
);
233 proto_register_vsock(void)
235 static hf_register_info hf
[] = {
237 {"Source cid", "vsock.src_cid", FT_UINT64
, BASE_DEC
, NULL
,
240 {"Destination cid", "vsock.dst_cid", FT_UINT64
, BASE_DEC
, NULL
,
242 { &hf_vsock_src_port
,
243 {"Source port", "vsock.src_port", FT_UINT32
, BASE_DEC
, NULL
,
245 { &hf_vsock_dst_port
,
246 {"Destination port", "vsock.dst_port", FT_UINT32
, BASE_DEC
, NULL
,
249 {"Operation", "vsock.op", FT_UINT16
, BASE_DEC
, VALS(af_vsockmon_op_names
),
252 {"Transport", "vsock.trans", FT_UINT16
, BASE_DEC
, VALS(af_vsockmon_t_names
),
255 {"Transport length", "vsock.trans_len", FT_UINT16
, BASE_DEC
, NULL
,
257 { &hf_vsock_reserved
,
258 {"Reserved", "vsock.reserved", FT_BYTES
, BASE_NONE
, NULL
,
261 { "Payload", "vsock.payload", FT_BYTES
, BASE_NONE
, NULL
,
263 { &hf_virtio_src_cid
,
264 {"Source cid", "vsock.virtio.src_cid", FT_UINT64
, BASE_DEC
, NULL
,
266 { &hf_virtio_dst_cid
,
267 {"Destination cid", "vsock.virtio.dst_cid", FT_UINT64
, BASE_DEC
, NULL
,
269 { &hf_virtio_src_port
,
270 {"Source port", "vsock.virtio.src_prot", FT_UINT32
, BASE_DEC
, NULL
,
272 { &hf_virtio_dst_port
,
273 {"Destination port", "vsock.virtio.dst_prot", FT_UINT32
, BASE_DEC
, NULL
,
276 {"Length", "vsock.virtio.len", FT_UINT32
, BASE_DEC
, NULL
,
279 {"Type", "vsock.virtio.type", FT_UINT16
, BASE_DEC
, VALS(virtio_vsock_type_names
),
282 {"Operation", "vsock.virtio.op", FT_UINT16
, BASE_DEC
, VALS(virtio_vsock_op_names
),
285 {"Flags", "vsock.virtio.flags", FT_UINT32
, BASE_HEX
, NULL
,
287 { &hf_virtio_buf_alloc
,
288 {"Buf alloc", "vsock.virtio.buf_alloc", FT_UINT32
, BASE_DEC
, NULL
,
290 { &hf_virtio_fwd_cnt
,
291 {"Fwd cnt", "vsock.virtio.fwd_cnt", FT_UINT32
, BASE_DEC
, NULL
,
294 static int *ett
[] = {
299 vsock_address_type
= address_type_dissector_register("AT_VSOCK", "vSocket Address",
300 vsock_addr_to_str
, vsock_addr_str_len
, NULL
, NULL
, NULL
, NULL
, NULL
);
302 proto_vsock
= proto_register_protocol("vSocket", "vsock", "vsock");
303 proto_register_field_array(proto_vsock
, hf
, array_length(hf
));
304 proto_register_subtree_array(ett
, array_length(ett
));
306 vsock_handle
= register_dissector("vsock", dissect_vsock
, proto_vsock
);
310 proto_reg_handoff_vsock(void)
312 dissector_add_uint("wtap_encap", WTAP_ENCAP_VSOCK
, vsock_handle
);
316 * Editor modelines - https://www.wireshark.org/tools/modelines.html
321 * indent-tabs-mode: nil
324 * vi: set shiftwidth=4 tabstop=8 expandtab:
325 * :indentSize=4:tabSize=8:noTabs=true: