Skip to content

Commit 373dd35

Browse files
committed
devices/vsock/tsi: fix parse_address on macOS
The method parse_address generates a SockaddrStorage object from raw socket information from the Linux guest. This doesn't work on macOS because both sockaddr-related structs and definitions differ from Linux. Fix it by manually parsing the address data on macOS. We leave AF_UNIX support for later, since nix doesn't have a way to cast UnixPath to SockaddrStorage. Signed-off-by: Sergio Lopez <[email protected]>
1 parent 30f7073 commit 373dd35

File tree

4 files changed

+59
-11
lines changed

4 files changed

+59
-11
lines changed

src/devices/src/virtio/vsock/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ mod defs {
5959
pub const TSI_ACCEPT: u32 = 1030;
6060
pub const TSI_PROXY_RELEASE: u32 = 1031;
6161

62+
// Linux definitions that we need for cross-platform compatibility.
63+
pub const LINUX_AF_UNIX: u16 = 1;
64+
pub const LINUX_AF_INET: u16 = 2;
65+
pub const LINUX_AF_INET6: u16 = 10;
66+
6267
pub mod uapi {
6368

6469
/// Virtio feature flags.

src/devices/src/virtio/vsock/packet.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,14 @@
1818
use std::convert::TryInto;
1919
use std::ffi::CStr;
2020
use std::net::{Ipv4Addr, SocketAddrV4};
21+
#[cfg(target_os = "macos")]
22+
use std::net::{Ipv6Addr, SocketAddrV6};
2123
use std::os::raw::c_char;
2224
use std::result;
2325

24-
use nix::sys::socket::{sockaddr, AddressFamily, SockaddrLike, SockaddrStorage};
26+
#[cfg(target_os = "linux")]
27+
use nix::sys::socket::{sockaddr, AddressFamily};
28+
use nix::sys::socket::{SockaddrLike, SockaddrStorage};
2529
use utils::byte_order;
2630
use vm_memory::{self, Address, GuestAddress, GuestMemory, GuestMemoryError};
2731

@@ -480,6 +484,7 @@ impl VsockPacket {
480484
}
481485
}
482486

487+
#[cfg(target_os = "linux")]
483488
fn parse_address(buf: &[u8], addr_len: u32) -> Option<SockaddrStorage> {
484489
let sockaddr: SockaddrStorage = unsafe {
485490
SockaddrStorage::from_raw(&buf[0] as *const _ as *const sockaddr, Some(addr_len))?
@@ -502,6 +507,44 @@ impl VsockPacket {
502507
Some(sockaddr)
503508
}
504509

510+
#[cfg(target_os = "macos")]
511+
fn parse_address(buf: &[u8], _addr_len: u32) -> Option<SockaddrStorage> {
512+
let family: u16 = byte_order::read_le_u16(&buf[0..2]);
513+
514+
match family {
515+
defs::LINUX_AF_INET => {
516+
debug!("parse_address: AF_INET");
517+
let in_port: u16 = byte_order::read_be_u16(&buf[2..4]);
518+
let in_addr = Ipv4Addr::new(buf[4], buf[5], buf[6], buf[7]);
519+
Some(SocketAddrV4::new(in_addr, in_port).into())
520+
}
521+
defs::LINUX_AF_INET6 => {
522+
debug!("parse_address: AF_INET6");
523+
let in_port: u16 = byte_order::read_be_u16(&buf[2..4]);
524+
let flowinfo: u32 = byte_order::read_be_u32(&buf[4..8]);
525+
let in6_addr = Ipv6Addr::new(
526+
byte_order::read_be_u16(&buf[8..10]),
527+
byte_order::read_be_u16(&buf[10..12]),
528+
byte_order::read_be_u16(&buf[12..14]),
529+
byte_order::read_be_u16(&buf[14..16]),
530+
byte_order::read_be_u16(&buf[16..18]),
531+
byte_order::read_be_u16(&buf[18..20]),
532+
byte_order::read_be_u16(&buf[20..22]),
533+
byte_order::read_be_u16(&buf[22..24]),
534+
);
535+
let scope_id: u32 = byte_order::read_be_u32(&buf[24..28]);
536+
Some(SocketAddrV6::new(in6_addr, in_port, flowinfo, scope_id).into())
537+
}
538+
defs::LINUX_AF_UNIX => {
539+
// On macOS, SockaddrStorage doesn't implement `from_raw` for
540+
// Unix sockets, nor a way to cast an UnixPath to it.
541+
error!("AF_UNIX sockets aren't yet supported on macOS");
542+
None
543+
}
544+
_ => None,
545+
}
546+
}
547+
505548
pub fn read_proxy_create(&self) -> Option<TsiProxyCreate> {
506549
if self.buf_size >= 6 {
507550
let peer_port: u32 = byte_order::read_le_u32(&self.buf().unwrap()[0..]);

src/devices/src/virtio/vsock/tsi_dgram.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use std::os::fd::OwnedFd;
55
use std::os::unix::io::{AsRawFd, RawFd};
66
use std::sync::{Arc, Mutex};
77

8-
use libc::{AF_INET, AF_INET6, AF_UNIX};
98
use nix::fcntl::{fcntl, FcntlArg, OFlag};
109
use nix::sys::socket::{
1110
bind, connect, getpeername, recv, send, sendto, socket, AddressFamily, MsgFlags, SockFlag,
@@ -55,10 +54,11 @@ impl TsiDgramProxy {
5554
queue: Arc<Mutex<VirtQueue>>,
5655
rxq: Arc<Mutex<MuxerRxQ>>,
5756
) -> Result<Self, ProxyError> {
58-
let family = match family as i32 {
59-
AF_INET => AddressFamily::Inet,
60-
AF_INET6 => AddressFamily::Inet6,
61-
AF_UNIX => AddressFamily::Unix,
57+
let family = match family {
58+
defs::LINUX_AF_INET => AddressFamily::Inet,
59+
defs::LINUX_AF_INET6 => AddressFamily::Inet6,
60+
#[cfg(target_os = "linux")]
61+
defs::LINUX_AF_UNIX => AddressFamily::Unix,
6262
_ => return Err(ProxyError::InvalidFamily),
6363
};
6464

src/devices/src/virtio/vsock/tsi_stream.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use std::sync::{Arc, Mutex};
1313
use libc::EINVAL;
1414
#[cfg(target_os = "macos")]
1515
use libc::EINVAL;
16-
use libc::{AF_INET, AF_INET6, AF_UNIX};
1716
use nix::errno::Errno;
1817
use nix::fcntl::{fcntl, FcntlArg, OFlag};
1918
use nix::sys::socket::{
@@ -74,10 +73,11 @@ impl TsiStreamProxy {
7473
queue: Arc<Mutex<VirtQueue>>,
7574
rxq: Arc<Mutex<MuxerRxQ>>,
7675
) -> Result<Self, ProxyError> {
77-
let family = match family as i32 {
78-
AF_INET => AddressFamily::Inet,
79-
AF_INET6 => AddressFamily::Inet6,
80-
AF_UNIX => AddressFamily::Unix,
76+
let family = match family {
77+
defs::LINUX_AF_INET => AddressFamily::Inet,
78+
defs::LINUX_AF_INET6 => AddressFamily::Inet6,
79+
#[cfg(target_os = "linux")]
80+
defs::LINUX_AF_UNIX => AddressFamily::Unix,
8181
_ => return Err(ProxyError::InvalidFamily),
8282
};
8383
let fd = socket(family, SockType::Stream, SockFlag::empty(), None)

0 commit comments

Comments
 (0)