Skip to content

Commit 78a4d9e

Browse files
bors[bot]tznealasomers
authored
Merge #2056
2056: add vsock support for macOS r=asomers a=tzneal Adds vsock support for macOS. It's not possible to create a listening vsock socket on a macOS host, but you can create one from inside a VM and connect back to the host. Co-authored-by: Todd Neal <[email protected]> Co-authored-by: Alan Somers <[email protected]>
2 parents 779b23c + d517f07 commit 78a4d9e

File tree

4 files changed

+72
-11
lines changed

4 files changed

+72
-11
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
2121
- Added `SOF_TIMESTAMPING_OPT_ID` and `SOF_TIMESTAMPING_OPT_TSONLY` to `nix::sys::socket::TimestampingFlag`.
2222
([#2048](https://github.com/nix-rust/nix/pull/2048))
2323
- Enabled socket timestamping options on Android. ([#2077](https://github.com/nix-rust/nix/pull/2077))
24+
- Added vsock support for macOS ([#2056](https://github.com/nix-rust/nix/pull/2056))
2425
- Added `SO_SETFIB` and `SO_USER_COOKIE` to `nix::sys::socket::sockopt` for FreeBSD.
2526
([#2085](https://github.com/nix-rust/nix/pull/2085))
2627

src/sys/socket/addr.rs

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
))]
1414
#[cfg(feature = "net")]
1515
pub use self::datalink::LinkAddr;
16-
#[cfg(any(target_os = "android", target_os = "linux"))]
16+
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
1717
pub use self::vsock::VsockAddr;
1818
use super::sa_family_t;
1919
use crate::errno::Errno;
@@ -248,7 +248,7 @@ pub enum AddressFamily {
248248
#[cfg_attr(docsrs, doc(cfg(all())))]
249249
Nfc = libc::AF_NFC,
250250
/// VMWare VSockets protocol for hypervisor-guest interaction.
251-
#[cfg(any(target_os = "android", target_os = "linux"))]
251+
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
252252
#[cfg_attr(docsrs, doc(cfg(all())))]
253253
Vsock = libc::AF_VSOCK,
254254
/// ARPANet IMP addresses
@@ -443,7 +443,7 @@ impl AddressFamily {
443443
target_os = "openbsd"
444444
))]
445445
libc::AF_LINK => Some(AddressFamily::Link),
446-
#[cfg(any(target_os = "android", target_os = "linux"))]
446+
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
447447
libc::AF_VSOCK => Some(AddressFamily::Vsock),
448448
_ => None,
449449
}
@@ -1286,7 +1286,7 @@ pub union SockaddrStorage {
12861286
sin6: SockaddrIn6,
12871287
ss: libc::sockaddr_storage,
12881288
su: UnixAddr,
1289-
#[cfg(any(target_os = "android", target_os = "linux"))]
1289+
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos" ))]
12901290
#[cfg_attr(docsrs, doc(cfg(all())))]
12911291
vsock: VsockAddr,
12921292
}
@@ -1378,7 +1378,7 @@ impl SockaddrLike for SockaddrStorage {
13781378
libc::AF_SYSTEM => {
13791379
SysControlAddr::from_raw(addr, l).map(|sctl| Self { sctl })
13801380
}
1381-
#[cfg(any(target_os = "android", target_os = "linux"))]
1381+
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos" ))]
13821382
libc::AF_VSOCK => {
13831383
VsockAddr::from_raw(addr, l).map(|vsock| Self { vsock })
13841384
}
@@ -1554,7 +1554,7 @@ impl SockaddrStorage {
15541554
accessors! {as_sys_control_addr, as_sys_control_addr_mut, SysControlAddr,
15551555
AddressFamily::System, libc::sockaddr_ctl, sctl}
15561556

1557-
#[cfg(any(target_os = "android", target_os = "linux"))]
1557+
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
15581558
#[cfg_attr(docsrs, doc(cfg(all())))]
15591559
accessors! {as_vsock_addr, as_vsock_addr_mut, VsockAddr,
15601560
AddressFamily::Vsock, libc::sockaddr_vm, vsock}
@@ -1604,7 +1604,7 @@ impl fmt::Display for SockaddrStorage {
16041604
#[cfg(feature = "ioctl")]
16051605
libc::AF_SYSTEM => self.sctl.fmt(f),
16061606
libc::AF_UNIX => self.su.fmt(f),
1607-
#[cfg(any(target_os = "android", target_os = "linux"))]
1607+
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
16081608
libc::AF_VSOCK => self.vsock.fmt(f),
16091609
_ => "<Address family unspecified>".fmt(f),
16101610
}
@@ -1678,7 +1678,7 @@ impl Hash for SockaddrStorage {
16781678
#[cfg(feature = "ioctl")]
16791679
libc::AF_SYSTEM => self.sctl.hash(s),
16801680
libc::AF_UNIX => self.su.hash(s),
1681-
#[cfg(any(target_os = "android", target_os = "linux"))]
1681+
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
16821682
libc::AF_VSOCK => self.vsock.hash(s),
16831683
_ => self.ss.hash(s),
16841684
}
@@ -1720,7 +1720,7 @@ impl PartialEq for SockaddrStorage {
17201720
#[cfg(feature = "ioctl")]
17211721
(libc::AF_SYSTEM, libc::AF_SYSTEM) => self.sctl == other.sctl,
17221722
(libc::AF_UNIX, libc::AF_UNIX) => self.su == other.su,
1723-
#[cfg(any(target_os = "android", target_os = "linux"))]
1723+
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
17241724
(libc::AF_VSOCK, libc::AF_VSOCK) => self.vsock == other.vsock,
17251725
_ => false,
17261726
}
@@ -2268,7 +2268,7 @@ mod datalink {
22682268
}
22692269
}
22702270

2271-
#[cfg(any(target_os = "android", target_os = "linux"))]
2271+
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
22722272
#[cfg_attr(docsrs, doc(cfg(all())))]
22732273
pub mod vsock {
22742274
use super::*;
@@ -2314,20 +2314,33 @@ pub mod vsock {
23142314
}
23152315

23162316
impl PartialEq for VsockAddr {
2317+
#[cfg(any(target_os = "android", target_os = "linux"))]
23172318
fn eq(&self, other: &Self) -> bool {
23182319
let (inner, other) = (self.0, other.0);
23192320
(inner.svm_family, inner.svm_cid, inner.svm_port)
23202321
== (other.svm_family, other.svm_cid, other.svm_port)
23212322
}
2323+
#[cfg(target_os = "macos")]
2324+
fn eq(&self, other: &Self) -> bool {
2325+
let (inner, other) = (self.0, other.0);
2326+
(inner.svm_family, inner.svm_cid, inner.svm_port, inner.svm_len)
2327+
== (other.svm_family, other.svm_cid, other.svm_port, inner.svm_len)
2328+
}
23222329
}
23232330

23242331
impl Eq for VsockAddr {}
23252332

23262333
impl Hash for VsockAddr {
2334+
#[cfg(any(target_os = "android", target_os = "linux"))]
23272335
fn hash<H: Hasher>(&self, s: &mut H) {
23282336
let inner = self.0;
23292337
(inner.svm_family, inner.svm_cid, inner.svm_port).hash(s);
23302338
}
2339+
#[cfg(target_os = "macos")]
2340+
fn hash<H: Hasher>(&self, s: &mut H) {
2341+
let inner = self.0;
2342+
(inner.svm_family, inner.svm_cid, inner.svm_port, inner.svm_len).hash(s);
2343+
}
23312344
}
23322345

23332346
/// VSOCK Address
@@ -2342,6 +2355,10 @@ pub mod vsock {
23422355
addr.svm_cid = cid;
23432356
addr.svm_port = port;
23442357

2358+
#[cfg(target_os = "macos")]
2359+
{
2360+
addr.svm_len = std::mem::size_of::<sockaddr_vm>() as u8;
2361+
}
23452362
VsockAddr(addr)
23462363
}
23472364

src/sys/socket/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ pub use crate::sys::socket::addr::netlink::NetlinkAddr;
6262
#[cfg(any(target_os = "ios", target_os = "macos"))]
6363
#[cfg(feature = "ioctl")]
6464
pub use crate::sys::socket::addr::sys_control::SysControlAddr;
65-
#[cfg(any(target_os = "android", target_os = "linux"))]
65+
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
6666
pub use crate::sys::socket::addr::vsock::VsockAddr;
6767

6868
#[cfg(all(feature = "uio", not(target_os = "redox")))]

test/sys/test_socket.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2122,6 +2122,49 @@ pub fn test_vsock() {
21222122
assert_eq!(addr3.as_ref().svm_port, addr1.port());
21232123
}
21242124

2125+
#[cfg(target_os = "macos")]
2126+
#[test]
2127+
pub fn test_vsock() {
2128+
use nix::sys::socket::SockaddrLike;
2129+
use nix::sys::socket::{AddressFamily, VsockAddr};
2130+
use std::mem;
2131+
2132+
let port: u32 = 3000;
2133+
2134+
// macOS doesn't have a VMADDR_CID_LOCAL, so test with host again
2135+
let addr_host = VsockAddr::new(libc::VMADDR_CID_HOST, port);
2136+
assert_eq!(addr_host.cid(), libc::VMADDR_CID_HOST);
2137+
assert_eq!(addr_host.port(), port);
2138+
2139+
let addr_any = VsockAddr::new(libc::VMADDR_CID_ANY, libc::VMADDR_PORT_ANY);
2140+
assert_eq!(addr_any.cid(), libc::VMADDR_CID_ANY);
2141+
assert_eq!(addr_any.port(), libc::VMADDR_PORT_ANY);
2142+
2143+
assert_ne!(addr_host, addr_any);
2144+
assert_ne!(calculate_hash(&addr_host), calculate_hash(&addr_any));
2145+
2146+
let addr1 = VsockAddr::new(libc::VMADDR_CID_HOST, port);
2147+
let addr2 = VsockAddr::new(libc::VMADDR_CID_HOST, port);
2148+
assert_eq!(addr1, addr2);
2149+
assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2));
2150+
2151+
let addr3 = unsafe {
2152+
VsockAddr::from_raw(
2153+
addr2.as_ref() as *const libc::sockaddr_vm as *const libc::sockaddr,
2154+
Some(mem::size_of::<libc::sockaddr_vm>().try_into().unwrap()),
2155+
)
2156+
}
2157+
.unwrap();
2158+
assert_eq!(
2159+
addr3.as_ref().svm_family,
2160+
AddressFamily::Vsock as libc::sa_family_t
2161+
);
2162+
let cid = addr3.as_ref().svm_cid;
2163+
let port = addr3.as_ref().svm_port;
2164+
assert_eq!(cid, addr1.cid());
2165+
assert_eq!(port, addr1.port());
2166+
}
2167+
21252168
// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack
21262169
// of QEMU support is suspected.
21272170
#[cfg_attr(qemu, ignore)]

0 commit comments

Comments
 (0)