1#![expect(unsafe_code)]
8
9use crate::VmListener;
10use crate::VmSocket;
11use crate::VmStream;
12use guid::Guid;
13use mesh::payload::os_resource;
14use socket2::SockAddr;
15use socket2::Socket;
16use socket2::Type;
17use std::io;
18use std::os::raw::c_int;
19use std::os::windows::prelude::*;
20use std::time::Duration;
21use windows_sys::Win32::Networking::WinSock::AF_HYPERV;
22use windows_sys::Win32::Networking::WinSock::SOCKET_ERROR;
23use windows_sys::Win32::Networking::WinSock::WSAGetLastError;
24use windows_sys::Win32::Networking::WinSock::setsockopt;
25use windows_sys::Win32::System::Hypervisor::HV_GUID_PARENT;
26use windows_sys::Win32::System::Hypervisor::HV_GUID_ZERO;
27use windows_sys::Win32::System::Hypervisor::HV_PROTOCOL_RAW;
28use windows_sys::Win32::System::Hypervisor::HVSOCKET_CONNECT_TIMEOUT;
29use windows_sys::Win32::System::Hypervisor::SOCKADDR_HV;
30
31fn service_id_from_vsock_port(port: u32) -> Guid {
33 Guid {
34 data1: port,
35 .."00000000-facb-11e6-bd58-64006a7986d3".parse().unwrap()
36 }
37}
38
39#[derive(Debug)]
40pub struct Address {
41 pub(crate) vm_id: Guid,
42 pub(crate) service_id: Guid,
43}
44
45impl Address {
46 pub fn new(vm_id: Guid, service_id: Guid) -> Self {
47 Self { vm_id, service_id }
48 }
49
50 pub fn vsock(vm_id: Guid, port: u32) -> Self {
51 Self::new(vm_id, service_id_from_vsock_port(port))
52 }
53
54 pub fn hyperv_any(service_id: Guid) -> Self {
55 Self::new(HV_GUID_ZERO.into(), service_id)
56 }
57
58 pub fn hyperv_host(service_id: Guid) -> Self {
59 Self::new(HV_GUID_PARENT.into(), service_id)
60 }
61
62 pub fn vsock_any(port: u32) -> Self {
63 Self::hyperv_any(service_id_from_vsock_port(port))
64 }
65
66 pub fn vsock_host(port: u32) -> Self {
67 Self::hyperv_host(service_id_from_vsock_port(port))
68 }
69
70 pub fn into_sock_addr(self) -> SockAddr {
71 let address = SOCKADDR_HV {
72 Family: AF_HYPERV,
73 Reserved: 0,
74 VmId: self.vm_id.into(),
75 ServiceId: self.service_id.into(),
76 };
77
78 let (_, address) = unsafe {
80 SockAddr::try_init(|storage, len| {
81 assert!(*len as usize >= size_of_val(&address));
82 let storage: &mut SOCKADDR_HV = &mut *storage.cast();
83 *storage = address;
84 *len = size_of_val(&address) as i32;
85 Ok(())
86 })
87 .unwrap()
88 };
89
90 address
91 }
92
93 pub fn try_from_sock_addr(addr: &SockAddr) -> Option<Self> {
94 if (addr.len() as usize) < size_of::<SOCKADDR_HV>() {
95 return None;
96 }
97 let addr = unsafe { &*addr.as_ptr().cast::<SOCKADDR_HV>() };
99 if addr.Family != AF_HYPERV {
100 return None;
101 }
102 Some(Self::new(addr.VmId.into(), addr.ServiceId.into()))
103 }
104}
105
106impl VmSocket {
107 pub(crate) fn new_inner() -> io::Result<Self> {
108 Ok(Self(Socket::new(
109 (AF_HYPERV as c_int).into(),
110 Type::STREAM,
111 Some((HV_PROTOCOL_RAW as c_int).into()),
112 )?))
113 }
114
115 pub fn set_connect_timeout(&self, duration: Duration) -> io::Result<()> {
117 let timeout = duration.as_millis().min(u32::MAX as u128) as u32;
118 unsafe {
120 if setsockopt(
121 self.as_socket().as_raw_socket() as _,
122 HV_PROTOCOL_RAW as _,
123 HVSOCKET_CONNECT_TIMEOUT as i32,
124 std::ptr::from_ref::<u32>(&timeout) as *mut u8,
125 size_of_val(&timeout) as _,
126 ) == SOCKET_ERROR
127 {
128 return Err(io::Error::from_raw_os_error(WSAGetLastError()));
129 }
130 Ok(())
131 }
132 }
133
134 pub fn set_high_vtl(&self, high_vtl: bool) -> io::Result<()> {
136 const HVSOCKET_HIGH_VTL: i32 = 8;
137 let high_vtl: u32 = high_vtl.into();
138 unsafe {
140 if setsockopt(
141 self.as_socket().as_raw_socket() as _,
142 HV_PROTOCOL_RAW as _,
143 HVSOCKET_HIGH_VTL,
144 std::ptr::from_ref::<u32>(&high_vtl) as *mut u8,
145 size_of_val(&high_vtl) as _,
146 ) == SOCKET_ERROR
147 {
148 return Err(io::Error::from_raw_os_error(WSAGetLastError()));
149 }
150 }
151 Ok(())
152 }
153}
154
155impl From<OwnedSocket> for VmSocket {
156 fn from(socket: OwnedSocket) -> Self {
157 Self(socket.into())
158 }
159}
160
161impl From<VmSocket> for OwnedSocket {
162 fn from(socket: VmSocket) -> Self {
163 socket.0.into()
164 }
165}
166
167impl AsSocket for VmSocket {
168 fn as_socket(&self) -> BorrowedSocket<'_> {
169 self.0.as_socket()
170 }
171}
172
173impl From<OwnedSocket> for VmListener {
174 fn from(socket: OwnedSocket) -> Self {
175 Self(socket.into())
176 }
177}
178
179impl From<VmListener> for OwnedSocket {
180 fn from(socket: VmListener) -> Self {
181 socket.0.into()
182 }
183}
184
185impl AsSocket for VmListener {
186 fn as_socket(&self) -> BorrowedSocket<'_> {
187 self.0.as_socket()
188 }
189}
190
191impl From<OwnedSocket> for VmStream {
192 fn from(socket: OwnedSocket) -> Self {
193 Self(socket.into())
194 }
195}
196
197impl From<VmStream> for OwnedSocket {
198 fn from(socket: VmStream) -> Self {
199 socket.0.into()
200 }
201}
202
203impl AsSocket for VmStream {
204 fn as_socket(&self) -> BorrowedSocket<'_> {
205 self.0.as_socket()
206 }
207}
208
209os_resource!(VmSocket, OwnedSocket);
210os_resource!(VmStream, OwnedSocket);
211os_resource!(VmListener, OwnedSocket);