Skip to content

Commit

Permalink
add vsock support for macOS
Browse files Browse the repository at this point in the history
  • Loading branch information
tzneal committed Jun 16, 2023
1 parent 89b4976 commit 7b892bf
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 12 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ targets = [
]

[dependencies]
libc = { version = "0.2.141", features = ["extra_traits"] }
libc = { version = "0.2.146", features = ["extra_traits"] }
bitflags = "1.1"
cfg-if = "1.0"
pin-utils = { version = "0.1.0", optional = true }
Expand Down
37 changes: 27 additions & 10 deletions src/sys/socket/addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
))]
#[cfg(feature = "net")]
pub use self::datalink::LinkAddr;
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
pub use self::vsock::VsockAddr;
use super::sa_family_t;
use crate::errno::Errno;
Expand Down Expand Up @@ -249,7 +249,7 @@ pub enum AddressFamily {
#[cfg_attr(docsrs, doc(cfg(all())))]
Nfc = libc::AF_NFC,
/// VMWare VSockets protocol for hypervisor-guest interaction.
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Vsock = libc::AF_VSOCK,
/// ARPANet IMP addresses
Expand Down Expand Up @@ -444,7 +444,7 @@ impl AddressFamily {
target_os = "openbsd"
))]
libc::AF_LINK => Some(AddressFamily::Link),
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
libc::AF_VSOCK => Some(AddressFamily::Vsock),
_ => None,
}
Expand Down Expand Up @@ -1246,7 +1246,7 @@ pub union SockaddrStorage {
sin6: SockaddrIn6,
ss: libc::sockaddr_storage,
su: UnixAddr,
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos" ))]
#[cfg_attr(docsrs, doc(cfg(all())))]
vsock: VsockAddr,
}
Expand Down Expand Up @@ -1338,7 +1338,7 @@ impl SockaddrLike for SockaddrStorage {
libc::AF_SYSTEM => {
SysControlAddr::from_raw(addr, l).map(|sctl| Self { sctl })
}
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos" ))]
libc::AF_VSOCK => {
VsockAddr::from_raw(addr, l).map(|vsock| Self { vsock })
}
Expand Down Expand Up @@ -1505,7 +1505,7 @@ impl SockaddrStorage {
accessors! {as_sys_control_addr, as_sys_control_addr_mut, SysControlAddr,
AddressFamily::System, libc::sockaddr_ctl, sctl}

#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
accessors! {as_vsock_addr, as_vsock_addr_mut, VsockAddr,
AddressFamily::Vsock, libc::sockaddr_vm, vsock}
Expand Down Expand Up @@ -1555,7 +1555,7 @@ impl fmt::Display for SockaddrStorage {
#[cfg(feature = "ioctl")]
libc::AF_SYSTEM => self.sctl.fmt(f),
libc::AF_UNIX => self.su.fmt(f),
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
libc::AF_VSOCK => self.vsock.fmt(f),
_ => "<Address family unspecified>".fmt(f),
}
Expand Down Expand Up @@ -1629,7 +1629,7 @@ impl Hash for SockaddrStorage {
#[cfg(feature = "ioctl")]
libc::AF_SYSTEM => self.sctl.hash(s),
libc::AF_UNIX => self.su.hash(s),
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
libc::AF_VSOCK => self.vsock.hash(s),
_ => self.ss.hash(s),
}
Expand Down Expand Up @@ -1671,7 +1671,7 @@ impl PartialEq for SockaddrStorage {
#[cfg(feature = "ioctl")]
(libc::AF_SYSTEM, libc::AF_SYSTEM) => self.sctl == other.sctl,
(libc::AF_UNIX, libc::AF_UNIX) => self.su == other.su,
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
(libc::AF_VSOCK, libc::AF_VSOCK) => self.vsock == other.vsock,
_ => false,
}
Expand Down Expand Up @@ -2220,7 +2220,7 @@ mod datalink {
}
}

#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub mod vsock {
use super::*;
Expand Down Expand Up @@ -2266,20 +2266,33 @@ pub mod vsock {
}

impl PartialEq for VsockAddr {
#[cfg(any(target_os = "android", target_os = "linux"))]
fn eq(&self, other: &Self) -> bool {
let (inner, other) = (self.0, other.0);
(inner.svm_family, inner.svm_cid, inner.svm_port)
== (other.svm_family, other.svm_cid, other.svm_port)
}
#[cfg(target_os = "macos")]
fn eq(&self, other: &Self) -> bool {
let (inner, other) = (self.0, other.0);
(inner.svm_family, inner.svm_cid, inner.svm_port, inner.svm_len)
== (other.svm_family, other.svm_cid, other.svm_port, inner.svm_len)
}
}

impl Eq for VsockAddr {}

impl Hash for VsockAddr {
#[cfg(any(target_os = "android", target_os = "linux"))]
fn hash<H: Hasher>(&self, s: &mut H) {
let inner = self.0;
(inner.svm_family, inner.svm_cid, inner.svm_port).hash(s);
}
#[cfg(target_os = "macos")]
fn hash<H: Hasher>(&self, s: &mut H) {
let inner = self.0;
(inner.svm_family, inner.svm_cid, inner.svm_port, inner.svm_len).hash(s);
}
}

/// VSOCK Address
Expand All @@ -2294,6 +2307,10 @@ pub mod vsock {
addr.svm_cid = cid;
addr.svm_port = port;

#[cfg(target_os = "macos")]
{
addr.svm_len = std::mem::size_of::<sockaddr_vm>() as u8;
}
VsockAddr(addr)
}

Expand Down
2 changes: 1 addition & 1 deletion src/sys/socket/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub use crate::sys::socket::addr::netlink::NetlinkAddr;
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(feature = "ioctl")]
pub use crate::sys::socket::addr::sys_control::SysControlAddr;
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
pub use crate::sys::socket::addr::vsock::VsockAddr;

#[cfg(all(feature = "uio", not(target_os = "redox")))]
Expand Down
43 changes: 43 additions & 0 deletions test/sys/test_socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2079,6 +2079,49 @@ pub fn test_vsock() {
assert_eq!(addr3.as_ref().svm_port, addr1.port());
}

#[cfg(target_os = "macos")]
#[test]
pub fn test_vsock() {
use nix::sys::socket::SockaddrLike;
use nix::sys::socket::{AddressFamily, VsockAddr};
use std::mem;

let port: u32 = 3000;

// macOS doesn't have a VMADDR_CID_LOCAL, so test with host again
let addr_host = VsockAddr::new(libc::VMADDR_CID_HOST, port);
assert_eq!(addr_host.cid(), libc::VMADDR_CID_HOST);
assert_eq!(addr_host.port(), port);

let addr_any = VsockAddr::new(libc::VMADDR_CID_ANY, libc::VMADDR_PORT_ANY);
assert_eq!(addr_any.cid(), libc::VMADDR_CID_ANY);
assert_eq!(addr_any.port(), libc::VMADDR_PORT_ANY);

assert_ne!(addr_host, addr_any);
assert_ne!(calculate_hash(&addr_host), calculate_hash(&addr_any));

let addr1 = VsockAddr::new(libc::VMADDR_CID_HOST, port);
let addr2 = VsockAddr::new(libc::VMADDR_CID_HOST, port);
assert_eq!(addr1, addr2);
assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2));

let addr3 = unsafe {
VsockAddr::from_raw(
addr2.as_ref() as *const libc::sockaddr_vm as *const libc::sockaddr,
Some(mem::size_of::<libc::sockaddr_vm>().try_into().unwrap()),
)
}
.unwrap();
assert_eq!(
addr3.as_ref().svm_family,
AddressFamily::Vsock as libc::sa_family_t
);
let cid = addr3.as_ref().svm_cid;
let port = addr3.as_ref().svm_port;
assert_eq!(cid, addr1.cid());
assert_eq!(port, addr1.port());
}

// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack
// of QEMU support is suspected.
#[cfg_attr(qemu, ignore)]
Expand Down

0 comments on commit 7b892bf

Please sign in to comment.