2020-08-22 20:25:43 +02:00
|
|
|
use crate::convert::TryFrom;
|
2020-08-22 17:27:43 +02:00
|
|
|
use crate::io::{self, IoSliceMut};
|
|
|
|
|
use crate::mem;
|
|
|
|
|
use crate::os::unix::io::RawFd;
|
|
|
|
|
use crate::path::Path;
|
|
|
|
|
use crate::ptr::null_mut;
|
|
|
|
|
use crate::slice::from_raw_parts;
|
|
|
|
|
use crate::sys::unix::ext::net::addr::{sockaddr_un, SocketAddr};
|
|
|
|
|
use crate::sys::unix::net::{add_to_ancillary_data, AncillaryDataIter, Socket};
|
|
|
|
|
|
|
|
|
|
pub(super) fn recv_vectored_with_ancillary_from(
|
|
|
|
|
socket: &Socket,
|
|
|
|
|
bufs: &mut [IoSliceMut<'_>],
|
|
|
|
|
ancillary: &mut SocketAncillary<'_>,
|
|
|
|
|
) -> io::Result<(usize, bool, io::Result<SocketAddr>)> {
|
|
|
|
|
unsafe {
|
|
|
|
|
let mut msg_name: libc::sockaddr_un = mem::zeroed();
|
|
|
|
|
|
|
|
|
|
let mut msg = libc::msghdr {
|
|
|
|
|
msg_name: &mut msg_name as *mut _ as *mut _,
|
|
|
|
|
msg_namelen: mem::size_of::<libc::sockaddr_un>() as libc::socklen_t,
|
|
|
|
|
msg_iov: bufs.as_mut_ptr().cast(),
|
|
|
|
|
msg_iovlen: bufs.len(),
|
|
|
|
|
msg_control: ancillary.buffer.as_mut_ptr().cast(),
|
|
|
|
|
msg_controllen: ancillary.buffer.len(),
|
|
|
|
|
msg_flags: 0,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let count = socket.recv_msg(&mut msg)?;
|
|
|
|
|
|
|
|
|
|
ancillary.length = msg.msg_controllen;
|
|
|
|
|
ancillary.truncated = msg.msg_flags & libc::MSG_CTRUNC == libc::MSG_CTRUNC;
|
|
|
|
|
|
|
|
|
|
let truncated = msg.msg_flags & libc::MSG_TRUNC == libc::MSG_TRUNC;
|
|
|
|
|
let addr = SocketAddr::from_parts(msg_name, msg.msg_namelen);
|
|
|
|
|
|
|
|
|
|
Ok((count, truncated, addr))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(super) fn send_vectored_with_ancillary_to(
|
|
|
|
|
socket: &Socket,
|
|
|
|
|
path: Option<&Path>,
|
|
|
|
|
bufs: &mut [IoSliceMut<'_>],
|
|
|
|
|
ancillary: &mut SocketAncillary<'_>,
|
|
|
|
|
) -> io::Result<usize> {
|
|
|
|
|
unsafe {
|
|
|
|
|
let (mut msg_name, msg_namelen) =
|
|
|
|
|
if let Some(path) = path { sockaddr_un(path)? } else { (mem::zeroed(), 0) };
|
|
|
|
|
|
|
|
|
|
let mut msg = libc::msghdr {
|
|
|
|
|
msg_name: &mut msg_name as *mut _ as *mut _,
|
|
|
|
|
msg_namelen,
|
|
|
|
|
msg_iov: bufs.as_mut_ptr().cast(),
|
|
|
|
|
msg_iovlen: bufs.len(),
|
|
|
|
|
msg_control: ancillary.buffer.as_mut_ptr().cast(),
|
|
|
|
|
msg_controllen: ancillary.length,
|
|
|
|
|
msg_flags: 0,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ancillary.truncated = false;
|
|
|
|
|
|
|
|
|
|
socket.send_msg(&mut msg)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-23 14:34:12 +02:00
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct UCred(libc::ucred);
|
|
|
|
|
|
|
|
|
|
impl UCred {
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
pub fn new() -> UCred {
|
|
|
|
|
UCred(libc::ucred { pid: 0, uid: 0, gid: 0 })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
pub fn set_pid(&mut self, pid: i32) {
|
|
|
|
|
self.0.pid = pid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
pub fn get_pid(&self) -> i32 {
|
|
|
|
|
self.0.pid
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
pub fn set_uid(&mut self, uid: u32) {
|
|
|
|
|
self.0.uid = uid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
pub fn get_uid(&self) -> u32 {
|
|
|
|
|
self.0.uid
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
pub fn set_gid(&mut self, gid: u32) {
|
|
|
|
|
self.0.gid = gid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
pub fn get_gid(&self) -> u32 {
|
|
|
|
|
self.0.gid
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-22 17:27:43 +02:00
|
|
|
#[cfg(any(
|
|
|
|
|
target_os = "haiku",
|
|
|
|
|
target_os = "solaris",
|
|
|
|
|
target_os = "illumos",
|
|
|
|
|
target_os = "macos",
|
|
|
|
|
target_os = "ios",
|
|
|
|
|
target_os = "freebsd",
|
|
|
|
|
target_os = "dragonfly",
|
|
|
|
|
target_os = "openbsd",
|
|
|
|
|
target_os = "netbsd",
|
|
|
|
|
target_os = "linux",
|
|
|
|
|
target_os = "android",
|
|
|
|
|
target_os = "emscripten",
|
|
|
|
|
target_os = "fuchsia",
|
|
|
|
|
target_env = "uclibc",
|
|
|
|
|
))]
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
pub struct ScmRights<'a>(AncillaryDataIter<'a, RawFd>);
|
|
|
|
|
|
|
|
|
|
#[cfg(any(
|
|
|
|
|
target_os = "haiku",
|
|
|
|
|
target_os = "solaris",
|
|
|
|
|
target_os = "illumos",
|
|
|
|
|
target_os = "macos",
|
|
|
|
|
target_os = "ios",
|
|
|
|
|
target_os = "freebsd",
|
|
|
|
|
target_os = "dragonfly",
|
|
|
|
|
target_os = "openbsd",
|
|
|
|
|
target_os = "netbsd",
|
|
|
|
|
target_os = "linux",
|
|
|
|
|
target_os = "android",
|
|
|
|
|
target_os = "emscripten",
|
|
|
|
|
target_os = "fuchsia",
|
|
|
|
|
target_env = "uclibc",
|
|
|
|
|
))]
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
impl<'a> Iterator for ScmRights<'a> {
|
|
|
|
|
type Item = RawFd;
|
|
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<RawFd> {
|
|
|
|
|
self.0.next()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(any(
|
|
|
|
|
target_os = "netbsd",
|
|
|
|
|
target_os = "openbsd",
|
|
|
|
|
target_os = "freebsd",
|
|
|
|
|
target_os = "dragonfly",
|
|
|
|
|
target_os = "macos",
|
|
|
|
|
target_os = "ios",
|
|
|
|
|
target_os = "linux",
|
|
|
|
|
target_os = "android",
|
|
|
|
|
target_os = "emscripten",
|
|
|
|
|
target_os = "fuchsia",
|
|
|
|
|
target_env = "uclibc",
|
|
|
|
|
))]
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
pub struct ScmCredentials<'a>(AncillaryDataIter<'a, libc::ucred>);
|
|
|
|
|
|
|
|
|
|
#[cfg(any(
|
|
|
|
|
target_os = "netbsd",
|
|
|
|
|
target_os = "openbsd",
|
|
|
|
|
target_os = "freebsd",
|
|
|
|
|
target_os = "dragonfly",
|
|
|
|
|
target_os = "macos",
|
|
|
|
|
target_os = "ios",
|
|
|
|
|
target_os = "linux",
|
|
|
|
|
target_os = "android",
|
|
|
|
|
target_os = "emscripten",
|
|
|
|
|
target_os = "fuchsia",
|
|
|
|
|
target_env = "uclibc",
|
|
|
|
|
))]
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
impl<'a> Iterator for ScmCredentials<'a> {
|
2020-08-23 14:34:12 +02:00
|
|
|
type Item = UCred;
|
2020-08-22 17:27:43 +02:00
|
|
|
|
2020-08-23 14:34:12 +02:00
|
|
|
fn next(&mut self) -> Option<UCred> {
|
|
|
|
|
Some(UCred(self.0.next()?))
|
2020-08-22 17:27:43 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-22 20:25:43 +02:00
|
|
|
#[non_exhaustive]
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
pub enum AncillaryError {
|
|
|
|
|
Unknown { cmsg_level: i32, cmsg_type: i32 },
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-22 17:27:43 +02:00
|
|
|
#[cfg(any(
|
|
|
|
|
target_os = "haiku",
|
|
|
|
|
target_os = "solaris",
|
|
|
|
|
target_os = "illumos",
|
|
|
|
|
target_os = "macos",
|
|
|
|
|
target_os = "ios",
|
|
|
|
|
target_os = "freebsd",
|
|
|
|
|
target_os = "dragonfly",
|
|
|
|
|
target_os = "openbsd",
|
|
|
|
|
target_os = "netbsd",
|
|
|
|
|
target_os = "linux",
|
|
|
|
|
target_os = "android",
|
|
|
|
|
target_os = "emscripten",
|
|
|
|
|
target_os = "fuchsia",
|
|
|
|
|
target_env = "uclibc",
|
|
|
|
|
))]
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
pub enum AncillaryData<'a> {
|
|
|
|
|
ScmRights(ScmRights<'a>),
|
|
|
|
|
#[cfg(any(
|
|
|
|
|
target_os = "netbsd",
|
|
|
|
|
target_os = "openbsd",
|
|
|
|
|
target_os = "freebsd",
|
|
|
|
|
target_os = "dragonfly",
|
|
|
|
|
target_os = "macos",
|
|
|
|
|
target_os = "ios",
|
|
|
|
|
target_os = "linux",
|
|
|
|
|
target_os = "android",
|
|
|
|
|
target_os = "emscripten",
|
|
|
|
|
target_os = "fuchsia",
|
|
|
|
|
target_env = "uclibc",
|
|
|
|
|
))]
|
|
|
|
|
ScmCredentials(ScmCredentials<'a>),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a> AncillaryData<'a> {
|
|
|
|
|
#[cfg(any(
|
|
|
|
|
target_os = "haiku",
|
|
|
|
|
target_os = "solaris",
|
|
|
|
|
target_os = "illumos",
|
|
|
|
|
target_os = "macos",
|
|
|
|
|
target_os = "ios",
|
|
|
|
|
target_os = "freebsd",
|
|
|
|
|
target_os = "dragonfly",
|
|
|
|
|
target_os = "openbsd",
|
|
|
|
|
target_os = "netbsd",
|
|
|
|
|
target_os = "linux",
|
|
|
|
|
target_os = "android",
|
|
|
|
|
target_os = "emscripten",
|
|
|
|
|
target_os = "fuchsia",
|
|
|
|
|
target_env = "uclibc",
|
|
|
|
|
))]
|
|
|
|
|
fn as_rights(data: &'a [u8]) -> Self {
|
|
|
|
|
let ancillary_data_iter = AncillaryDataIter::new(data);
|
|
|
|
|
let scm_rights = ScmRights(ancillary_data_iter);
|
|
|
|
|
AncillaryData::ScmRights(scm_rights)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(any(
|
|
|
|
|
target_os = "netbsd",
|
|
|
|
|
target_os = "openbsd",
|
|
|
|
|
target_os = "freebsd",
|
|
|
|
|
target_os = "dragonfly",
|
|
|
|
|
target_os = "macos",
|
|
|
|
|
target_os = "ios",
|
|
|
|
|
target_os = "linux",
|
|
|
|
|
target_os = "android",
|
|
|
|
|
target_os = "emscripten",
|
|
|
|
|
target_os = "fuchsia",
|
|
|
|
|
target_env = "uclibc",
|
|
|
|
|
))]
|
|
|
|
|
fn as_credentials(data: &'a [u8]) -> Self {
|
|
|
|
|
let ancillary_data_iter = AncillaryDataIter::new(data);
|
|
|
|
|
let scm_credentials = ScmCredentials(ancillary_data_iter);
|
|
|
|
|
AncillaryData::ScmCredentials(scm_credentials)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(any(
|
|
|
|
|
target_os = "haiku",
|
|
|
|
|
target_os = "solaris",
|
|
|
|
|
target_os = "illumos",
|
|
|
|
|
target_os = "macos",
|
|
|
|
|
target_os = "ios",
|
|
|
|
|
target_os = "freebsd",
|
|
|
|
|
target_os = "dragonfly",
|
|
|
|
|
target_os = "openbsd",
|
|
|
|
|
target_os = "netbsd",
|
|
|
|
|
target_os = "linux",
|
|
|
|
|
target_os = "android",
|
|
|
|
|
target_os = "emscripten",
|
|
|
|
|
target_os = "fuchsia",
|
|
|
|
|
target_env = "uclibc",
|
|
|
|
|
))]
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
2020-08-22 20:25:43 +02:00
|
|
|
impl<'a> TryFrom<&'a libc::cmsghdr> for AncillaryData<'a> {
|
|
|
|
|
type Error = AncillaryError;
|
|
|
|
|
|
|
|
|
|
fn try_from(cmsg: &'a libc::cmsghdr) -> Result<Self, Self::Error> {
|
2020-08-22 17:27:43 +02:00
|
|
|
unsafe {
|
|
|
|
|
let cmsg_len_zero = libc::CMSG_LEN(0) as usize;
|
|
|
|
|
let data_len = (*cmsg).cmsg_len - cmsg_len_zero;
|
|
|
|
|
let data = libc::CMSG_DATA(cmsg).cast();
|
|
|
|
|
let data = from_raw_parts(data, data_len);
|
|
|
|
|
|
2020-08-22 20:25:43 +02:00
|
|
|
match (*cmsg).cmsg_level {
|
|
|
|
|
libc::SOL_SOCKET => match (*cmsg).cmsg_type {
|
|
|
|
|
libc::SCM_RIGHTS => Ok(AncillaryData::as_rights(data)),
|
2020-08-22 17:27:43 +02:00
|
|
|
#[cfg(any(
|
|
|
|
|
target_os = "linux",
|
|
|
|
|
target_os = "android",
|
|
|
|
|
target_os = "emscripten",
|
|
|
|
|
target_os = "fuchsia",
|
|
|
|
|
target_env = "uclibc",
|
|
|
|
|
))]
|
2020-08-22 20:25:43 +02:00
|
|
|
libc::SCM_CREDENTIALS => Ok(AncillaryData::as_credentials(data)),
|
2020-08-22 17:27:43 +02:00
|
|
|
#[cfg(any(
|
|
|
|
|
target_os = "netbsd",
|
|
|
|
|
target_os = "openbsd",
|
|
|
|
|
target_os = "freebsd",
|
|
|
|
|
target_os = "dragonfly",
|
|
|
|
|
target_os = "macos",
|
|
|
|
|
target_os = "ios",
|
|
|
|
|
))]
|
2020-08-22 20:25:43 +02:00
|
|
|
libc::SCM_CREDS => Ok(AncillaryData::as_credentials(data)),
|
|
|
|
|
cmsg_type => {
|
|
|
|
|
Err(AncillaryError::Unknown { cmsg_level: libc::SOL_SOCKET, cmsg_type })
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
cmsg_level => {
|
|
|
|
|
Err(AncillaryError::Unknown { cmsg_level, cmsg_type: (*cmsg).cmsg_type })
|
2020-08-22 17:27:43 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(any(
|
|
|
|
|
target_os = "haiku",
|
|
|
|
|
target_os = "solaris",
|
|
|
|
|
target_os = "illumos",
|
|
|
|
|
target_os = "macos",
|
|
|
|
|
target_os = "ios",
|
|
|
|
|
target_os = "freebsd",
|
|
|
|
|
target_os = "dragonfly",
|
|
|
|
|
target_os = "openbsd",
|
|
|
|
|
target_os = "netbsd",
|
|
|
|
|
target_os = "linux",
|
|
|
|
|
target_os = "android",
|
|
|
|
|
target_os = "emscripten",
|
|
|
|
|
target_os = "fuchsia",
|
|
|
|
|
target_env = "uclibc",
|
|
|
|
|
))]
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
pub struct Messages<'a> {
|
|
|
|
|
buffer: &'a [u8],
|
|
|
|
|
current: Option<&'a libc::cmsghdr>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(any(
|
|
|
|
|
target_os = "haiku",
|
|
|
|
|
target_os = "solaris",
|
|
|
|
|
target_os = "illumos",
|
|
|
|
|
target_os = "macos",
|
|
|
|
|
target_os = "ios",
|
|
|
|
|
target_os = "freebsd",
|
|
|
|
|
target_os = "dragonfly",
|
|
|
|
|
target_os = "openbsd",
|
|
|
|
|
target_os = "netbsd",
|
|
|
|
|
target_os = "linux",
|
|
|
|
|
target_os = "android",
|
|
|
|
|
target_os = "emscripten",
|
|
|
|
|
target_os = "fuchsia",
|
|
|
|
|
target_env = "uclibc",
|
|
|
|
|
))]
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
impl<'a> Iterator for Messages<'a> {
|
2020-08-22 20:25:43 +02:00
|
|
|
type Item = Result<AncillaryData<'a>, AncillaryError>;
|
2020-08-22 17:27:43 +02:00
|
|
|
|
2020-08-22 20:25:43 +02:00
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
2020-08-22 17:27:43 +02:00
|
|
|
unsafe {
|
|
|
|
|
let msg = libc::msghdr {
|
|
|
|
|
msg_name: null_mut(),
|
|
|
|
|
msg_namelen: 0,
|
|
|
|
|
msg_iov: null_mut(),
|
|
|
|
|
msg_iovlen: 0,
|
|
|
|
|
msg_control: self.buffer.as_ptr() as *mut _,
|
|
|
|
|
msg_controllen: self.buffer.len(),
|
|
|
|
|
msg_flags: 0,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let cmsg = if let Some(current) = self.current {
|
|
|
|
|
libc::CMSG_NXTHDR(&msg, current)
|
|
|
|
|
} else {
|
|
|
|
|
libc::CMSG_FIRSTHDR(&msg)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let cmsg = cmsg.as_ref()?;
|
|
|
|
|
self.current = Some(cmsg);
|
2020-08-22 20:25:43 +02:00
|
|
|
let ancillary_result = AncillaryData::try_from(cmsg);
|
|
|
|
|
Some(ancillary_result)
|
2020-08-22 17:27:43 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// A Unix socket Ancillary data struct.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// #![feature(unix_socket_ancillary_data)]
|
|
|
|
|
/// use std::os::unix::net::{UnixStream, SocketAncillary, AncillaryData};
|
|
|
|
|
/// use std::io::IoSliceMut;
|
|
|
|
|
///
|
|
|
|
|
/// fn main() -> std::io::Result<()> {
|
|
|
|
|
/// let sock = UnixStream::connect("/tmp/sock")?;
|
|
|
|
|
///
|
|
|
|
|
/// let mut fds = [0; 8];
|
|
|
|
|
/// let mut ancillary_buffer = [0; 128];
|
|
|
|
|
/// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
|
|
|
|
|
///
|
|
|
|
|
/// let mut buf = [1; 8];
|
|
|
|
|
/// let mut bufs = &mut [IoSliceMut::new(&mut buf[..])][..];
|
|
|
|
|
/// sock.recv_vectored_with_ancillary(bufs, &mut ancillary)?;
|
|
|
|
|
///
|
2020-08-22 20:25:43 +02:00
|
|
|
/// for ancillary_result in ancillary.messages() {
|
|
|
|
|
/// if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() {
|
2020-08-22 17:27:43 +02:00
|
|
|
/// for fd in scm_rights {
|
|
|
|
|
/// println!("receive file descriptor: {}", fd);
|
|
|
|
|
/// }
|
|
|
|
|
/// }
|
|
|
|
|
/// }
|
|
|
|
|
/// Ok(())
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub struct SocketAncillary<'a> {
|
|
|
|
|
buffer: &'a mut [u8],
|
|
|
|
|
length: usize,
|
|
|
|
|
truncated: bool,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a> SocketAncillary<'a> {
|
|
|
|
|
/// Create an ancillary data with the given buffer.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// # #![allow(unused_mut)]
|
|
|
|
|
/// #![feature(unix_socket_ancillary_data)]
|
|
|
|
|
/// use std::os::unix::net::SocketAncillary;
|
|
|
|
|
/// let mut ancillary_buffer = [0; 128];
|
|
|
|
|
/// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
|
|
|
|
|
/// ```
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
pub fn new(buffer: &'a mut [u8]) -> Self {
|
|
|
|
|
SocketAncillary { buffer, length: 0, truncated: false }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the capacity of the buffer.
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
pub fn capacity(&self) -> usize {
|
|
|
|
|
self.buffer.len()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the number of used bytes.
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
pub fn len(&self) -> usize {
|
|
|
|
|
self.length
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(any(
|
|
|
|
|
target_os = "haiku",
|
|
|
|
|
target_os = "solaris",
|
|
|
|
|
target_os = "illumos",
|
|
|
|
|
target_os = "macos",
|
|
|
|
|
target_os = "ios",
|
|
|
|
|
target_os = "freebsd",
|
|
|
|
|
target_os = "dragonfly",
|
|
|
|
|
target_os = "openbsd",
|
|
|
|
|
target_os = "netbsd",
|
|
|
|
|
target_os = "linux",
|
|
|
|
|
target_os = "android",
|
|
|
|
|
target_os = "emscripten",
|
|
|
|
|
target_os = "fuchsia",
|
|
|
|
|
target_env = "uclibc",
|
|
|
|
|
))]
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
pub fn messages(&'a self) -> Messages<'a> {
|
|
|
|
|
Messages { buffer: &self.buffer[..self.length], current: None }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Is `true` if during a recv operation the ancillary was truncated.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// #![feature(unix_socket_ancillary_data)]
|
|
|
|
|
/// use std::os::unix::net::{UnixStream, SocketAncillary};
|
|
|
|
|
/// use std::io::IoSliceMut;
|
|
|
|
|
///
|
|
|
|
|
/// fn main() -> std::io::Result<()> {
|
|
|
|
|
/// let sock = UnixStream::connect("/tmp/sock")?;
|
|
|
|
|
///
|
|
|
|
|
/// let mut ancillary_buffer = [0; 128];
|
|
|
|
|
/// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
|
|
|
|
|
///
|
|
|
|
|
/// let mut buf = [1; 8];
|
|
|
|
|
/// let mut bufs = &mut [IoSliceMut::new(&mut buf[..])][..];
|
|
|
|
|
/// sock.recv_vectored_with_ancillary(bufs, &mut ancillary)?;
|
|
|
|
|
///
|
|
|
|
|
/// println!("Is truncated: {}", ancillary.truncated());
|
|
|
|
|
/// Ok(())
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
pub fn truncated(&self) -> bool {
|
|
|
|
|
self.truncated
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Add file descriptors to the ancillary data.
|
|
|
|
|
///
|
|
|
|
|
/// The function returns `true` if there was enough space in the buffer.
|
|
|
|
|
/// If there was not enough space then no file descriptors was appended.
|
|
|
|
|
/// Technically, that means this operation adds a control message with the level `SOL_SOCKET`
|
|
|
|
|
/// and type `SCM_RIGHTS`.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// #![feature(unix_socket_ancillary_data)]
|
|
|
|
|
/// use std::os::unix::net::{UnixStream, SocketAncillary};
|
|
|
|
|
/// use std::os::unix::io::AsRawFd;
|
|
|
|
|
/// use std::io::IoSliceMut;
|
|
|
|
|
///
|
|
|
|
|
/// fn main() -> std::io::Result<()> {
|
|
|
|
|
/// let sock = UnixStream::connect("/tmp/sock")?;
|
|
|
|
|
///
|
|
|
|
|
/// let mut ancillary_buffer = [0; 128];
|
|
|
|
|
/// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
|
|
|
|
|
/// ancillary.add_fds(&[sock.as_raw_fd()][..]);
|
|
|
|
|
///
|
|
|
|
|
/// let mut buf = [1; 8];
|
|
|
|
|
/// let mut bufs = &mut [IoSliceMut::new(&mut buf[..])][..];
|
|
|
|
|
/// sock.send_vectored_with_ancillary(bufs, &mut ancillary)?;
|
|
|
|
|
/// Ok(())
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
|
|
|
|
#[cfg(any(
|
|
|
|
|
target_os = "haiku",
|
|
|
|
|
target_os = "solaris",
|
|
|
|
|
target_os = "illumos",
|
|
|
|
|
target_os = "macos",
|
|
|
|
|
target_os = "ios",
|
|
|
|
|
target_os = "freebsd",
|
|
|
|
|
target_os = "dragonfly",
|
|
|
|
|
target_os = "openbsd",
|
|
|
|
|
target_os = "netbsd",
|
|
|
|
|
target_os = "linux",
|
|
|
|
|
target_os = "android",
|
|
|
|
|
target_os = "emscripten",
|
|
|
|
|
target_os = "fuchsia",
|
|
|
|
|
target_env = "uclibc",
|
|
|
|
|
))]
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
pub fn add_fds(&mut self, fds: &[RawFd]) -> bool {
|
|
|
|
|
self.truncated = false;
|
|
|
|
|
add_to_ancillary_data(
|
|
|
|
|
&mut self.buffer,
|
|
|
|
|
&mut self.length,
|
|
|
|
|
fds,
|
|
|
|
|
libc::SOL_SOCKET,
|
|
|
|
|
libc::SCM_RIGHTS,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Add credentials to the ancillary data.
|
|
|
|
|
///
|
|
|
|
|
/// The function returns `true` if there was enough space in the buffer.
|
|
|
|
|
/// If there was not enough space then no credentials was appended.
|
|
|
|
|
/// Technically, that means this operation adds a control message with the level `SOL_SOCKET`
|
|
|
|
|
/// and type `SCM_CREDENTIALS`.
|
|
|
|
|
///
|
|
|
|
|
#[cfg(any(
|
|
|
|
|
target_os = "netbsd",
|
|
|
|
|
target_os = "openbsd",
|
|
|
|
|
target_os = "freebsd",
|
|
|
|
|
target_os = "dragonfly",
|
|
|
|
|
target_os = "macos",
|
|
|
|
|
target_os = "ios",
|
|
|
|
|
target_os = "linux",
|
|
|
|
|
target_os = "android",
|
|
|
|
|
target_os = "emscripten",
|
|
|
|
|
target_os = "fuchsia",
|
|
|
|
|
target_env = "uclibc",
|
|
|
|
|
))]
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
2020-08-23 14:34:12 +02:00
|
|
|
pub fn add_creds(&mut self, creds: &[UCred]) -> bool {
|
2020-08-22 17:27:43 +02:00
|
|
|
self.truncated = false;
|
|
|
|
|
add_to_ancillary_data(
|
|
|
|
|
&mut self.buffer,
|
|
|
|
|
&mut self.length,
|
|
|
|
|
creds,
|
|
|
|
|
libc::SOL_SOCKET,
|
|
|
|
|
#[cfg(any(
|
|
|
|
|
target_os = "linux",
|
|
|
|
|
target_os = "android",
|
|
|
|
|
target_os = "emscripten",
|
|
|
|
|
target_os = "fuchsia",
|
|
|
|
|
target_env = "uclibc",
|
|
|
|
|
))]
|
|
|
|
|
libc::SCM_CREDENTIALS,
|
|
|
|
|
#[cfg(any(
|
|
|
|
|
target_os = "netbsd",
|
|
|
|
|
target_os = "openbsd",
|
|
|
|
|
target_os = "freebsd",
|
|
|
|
|
target_os = "dragonfly",
|
|
|
|
|
target_os = "macos",
|
|
|
|
|
target_os = "ios",
|
|
|
|
|
))]
|
|
|
|
|
libc::SCM_CREDS,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Clears the ancillary data, removing all values.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// #![feature(unix_socket_ancillary_data)]
|
|
|
|
|
/// use std::os::unix::net::{UnixStream, SocketAncillary, AncillaryData};
|
|
|
|
|
/// use std::io::IoSliceMut;
|
|
|
|
|
///
|
|
|
|
|
/// fn main() -> std::io::Result<()> {
|
|
|
|
|
/// let sock = UnixStream::connect("/tmp/sock")?;
|
|
|
|
|
///
|
|
|
|
|
/// let mut fds1 = [0; 8];
|
|
|
|
|
/// let mut fds2 = [0; 8];
|
|
|
|
|
/// let mut ancillary_buffer = [0; 128];
|
|
|
|
|
/// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
|
|
|
|
|
///
|
|
|
|
|
/// let mut buf = [1; 8];
|
|
|
|
|
/// let mut bufs = &mut [IoSliceMut::new(&mut buf[..])][..];
|
|
|
|
|
///
|
|
|
|
|
/// sock.recv_vectored_with_ancillary(bufs, &mut ancillary)?;
|
2020-08-22 20:25:43 +02:00
|
|
|
/// for ancillary_result in ancillary.messages() {
|
|
|
|
|
/// if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() {
|
2020-08-22 17:27:43 +02:00
|
|
|
/// for fd in scm_rights {
|
|
|
|
|
/// println!("receive file descriptor: {}", fd);
|
|
|
|
|
/// }
|
|
|
|
|
/// }
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// ancillary.clear();
|
|
|
|
|
///
|
|
|
|
|
/// sock.recv_vectored_with_ancillary(bufs, &mut ancillary)?;
|
2020-08-22 20:25:43 +02:00
|
|
|
/// for ancillary_result in ancillary.messages() {
|
|
|
|
|
/// if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() {
|
2020-08-22 17:27:43 +02:00
|
|
|
/// for fd in scm_rights {
|
|
|
|
|
/// println!("receive file descriptor: {}", fd);
|
|
|
|
|
/// }
|
|
|
|
|
/// }
|
|
|
|
|
/// }
|
|
|
|
|
/// Ok(())
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
|
|
|
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "none")]
|
|
|
|
|
pub fn clear(&mut self) {
|
|
|
|
|
self.length = 0;
|
|
|
|
|
self.truncated = false;
|
|
|
|
|
}
|
|
|
|
|
}
|