Skip to content

Commit

Permalink
socket: add support for AF_VSOCK
Browse files Browse the repository at this point in the history
This patch add AF_VSOCK support to AddressFamily in order to use
VSOCK socket.

Signed-off-by: Stefano Garzarella <[email protected]>
  • Loading branch information
stefano-garzarella committed Jun 26, 2019
1 parent 7fa4f23 commit 3a23e41
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
([#1069](https://github.com/nix-rust/nix/pull/1069))
- Add `mkdirat`.
([#1084](https://github.com/nix-rust/nix/pull/1084))
- Added `AF_VSOCK` to `AddressFamily`.
([#1091](https://github.com/nix-rust/nix/pull/1091))

### Changed
- Support for `ifaddrs` now present when building for Android.
Expand Down
86 changes: 83 additions & 3 deletions src/sys/socket/addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ use ::sys::socket::addr::sys_control::SysControlAddr;
target_os = "netbsd",
target_os = "openbsd"))]
pub use self::datalink::LinkAddr;
#[cfg(target_os = "linux")]
pub use self::vsock::VsockAddr;

/// These constants specify the protocol family to be used
/// in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
Expand Down Expand Up @@ -241,6 +243,8 @@ impl AddressFamily {
target_os = "netbsd",
target_os = "openbsd"))]
libc::AF_LINK => Some(AddressFamily::Link),
#[cfg(target_os = "linux")]
libc::AF_VSOCK => Some(AddressFamily::Vsock),
_ => None
}
}
Expand Down Expand Up @@ -638,7 +642,9 @@ pub enum SockAddr {
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"))]
Link(LinkAddr)
Link(LinkAddr),
#[cfg(target_os = "linux")]
Vsock(VsockAddr),
}

impl SockAddr {
Expand All @@ -665,6 +671,11 @@ impl SockAddr {
SysControlAddr::from_name(sockfd, name, unit).map(|a| SockAddr::SysControl(a))
}

#[cfg(target_os = "linux")]
pub fn new_vsock(cid: u32, port: u32) -> SockAddr {
SockAddr::Vsock(VsockAddr::new(cid, port))
}

pub fn family(&self) -> AddressFamily {
match *self {
SockAddr::Inet(InetAddr::V4(..)) => AddressFamily::Inet,
Expand All @@ -684,7 +695,9 @@ impl SockAddr {
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"))]
SockAddr::Link(..) => AddressFamily::Link
SockAddr::Link(..) => AddressFamily::Link,
#[cfg(target_os = "linux")]
SockAddr::Vsock(..) => AddressFamily::Vsock,
}
}

Expand Down Expand Up @@ -729,6 +742,9 @@ impl SockAddr {
Some(SockAddr::Link(ether_addr))
}
},
#[cfg(target_os = "linux")]
Some(AddressFamily::Vsock) => Some(SockAddr::Vsock(
VsockAddr(*(addr as *const libc::sockaddr_vm)))),
// Other address families are currently not supported and simply yield a None
// entry instead of a proper conversion to a `SockAddr`.
Some(_) | None => None,
Expand Down Expand Up @@ -763,6 +779,8 @@ impl SockAddr {
target_os = "netbsd",
target_os = "openbsd"))]
SockAddr::Link(LinkAddr(ref ether_addr)) => (mem::transmute(ether_addr), mem::size_of::<libc::sockaddr_dl>() as libc::socklen_t),
#[cfg(target_os = "linux")]
SockAddr::Vsock(VsockAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_vm>() as libc::socklen_t),
}
}
}
Expand All @@ -786,7 +804,9 @@ impl fmt::Display for SockAddr {
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"))]
SockAddr::Link(ref ether_addr) => ether_addr.fmt(f)
SockAddr::Link(ref ether_addr) => ether_addr.fmt(f),
#[cfg(target_os = "linux")]
SockAddr::Vsock(ref svm) => svm.fmt(f),
}
}
}
Expand Down Expand Up @@ -1124,6 +1144,66 @@ mod datalink {
}
}

#[cfg(target_os = "linux")]
pub mod vsock {
use ::sys::socket::addr::AddressFamily;
use libc::{sa_family_t, sockaddr_vm};
use std::{fmt, mem};
use std::hash::{Hash, Hasher};

#[derive(Copy, Clone)]
pub struct VsockAddr(pub sockaddr_vm);

// , PartialEq, Eq, Debug, Hash
impl PartialEq for VsockAddr {
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)
}
}

impl Eq for VsockAddr {}

impl Hash for VsockAddr {
fn hash<H: Hasher>(&self, s: &mut H) {
let inner = self.0;
(inner.svm_family, inner.svm_cid, inner.svm_port).hash(s);
}
}

impl VsockAddr {
pub fn new(cid: u32, port: u32) -> VsockAddr {
let mut addr: sockaddr_vm = unsafe { mem::zeroed() };
addr.svm_family = AddressFamily::Vsock as sa_family_t;
addr.svm_cid = cid;
addr.svm_port = port;

VsockAddr(addr)
}

pub fn cid(&self) -> u32 {
self.0.svm_cid
}

pub fn port(&self) -> u32 {
self.0.svm_port
}
}

impl fmt::Display for VsockAddr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "cid: {} port: {}", self.cid(), self.port())
}
}

impl fmt::Debug for VsockAddr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(self, f)
}
}
}

#[cfg(test)]
mod tests {
#[cfg(any(target_os = "android",
Expand Down
7 changes: 7 additions & 0 deletions src/sys/socket/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ pub use self::addr::{
pub use ::sys::socket::addr::netlink::NetlinkAddr;
#[cfg(any(target_os = "android", target_os = "linux"))]
pub use sys::socket::addr::alg::AlgAddr;
#[cfg(target_os = "linux")]
pub use sys::socket::addr::vsock::VsockAddr;

pub use libc::{
cmsghdr,
Expand Down Expand Up @@ -1254,6 +1256,11 @@ pub unsafe fn sockaddr_storage_to_addr(
use libc::sockaddr_alg;
Ok(SockAddr::Alg(AlgAddr(*(addr as *const _ as *const sockaddr_alg))))
}
#[cfg(target_os = "linux")]
libc::AF_VSOCK => {
use libc::sockaddr_vm;
Ok(SockAddr::Vsock(VsockAddr(*(addr as *const _ as *const sockaddr_vm))))
}
af => panic!("unexpected address family {}", af),
}
}
Expand Down

0 comments on commit 3a23e41

Please sign in to comment.