diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs index 218536689fdbe..e69de29bb2d1d 100644 --- a/library/std/src/os/unix/net/ancillary.rs +++ b/library/std/src/os/unix/net/ancillary.rs @@ -1,798 +0,0 @@ -// FIXME: This is currently disabled on *BSD. - -use super::{sockaddr_un, SocketAddr}; -use crate::io::{self, IoSlice, IoSliceMut}; -use crate::marker::PhantomData; -use crate::mem::{size_of, zeroed}; -use crate::os::unix::io::RawFd; -use crate::path::Path; -use crate::ptr::{eq, read_unaligned}; -use crate::slice::from_raw_parts; -use crate::sys::net::Socket; - -// FIXME(#43348): Make libc adapt #[doc(cfg(...))] so we don't need these fake definitions here? -#[cfg(all( - doc, - not(target_os = "linux"), - not(target_os = "android"), - not(target_os = "netbsd"), - not(target_os = "freebsd") -))] -#[allow(non_camel_case_types)] -mod libc { - pub use libc::c_int; - pub struct ucred; - pub struct cmsghdr; - pub struct sockcred2; - pub type pid_t = i32; - pub type gid_t = u32; - pub type uid_t = u32; -} - -pub(super) fn recv_vectored_with_ancillary_from( - socket: &Socket, - bufs: &mut [IoSliceMut<'_>], - ancillary: &mut SocketAncillary<'_>, -) -> io::Result<(usize, bool, io::Result)> { - unsafe { - let mut msg_name: libc::sockaddr_un = zeroed(); - let mut msg: libc::msghdr = zeroed(); - msg.msg_name = &mut msg_name as *mut _ as *mut _; - msg.msg_namelen = size_of::() as libc::socklen_t; - msg.msg_iov = bufs.as_mut_ptr().cast(); - msg.msg_iovlen = bufs.len() as _; - msg.msg_controllen = ancillary.buffer.len() as _; - // macos requires that the control pointer is null when the len is 0. - if msg.msg_controllen > 0 { - msg.msg_control = ancillary.buffer.as_mut_ptr().cast(); - } - - let count = socket.recv_msg(&mut msg)?; - - ancillary.length = msg.msg_controllen as usize; - 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: &[IoSlice<'_>], - ancillary: &mut SocketAncillary<'_>, -) -> io::Result { - unsafe { - let (mut msg_name, msg_namelen) = - if let Some(path) = path { sockaddr_un(path)? } else { (zeroed(), 0) }; - - let mut msg: libc::msghdr = zeroed(); - msg.msg_name = &mut msg_name as *mut _ as *mut _; - msg.msg_namelen = msg_namelen; - msg.msg_iov = bufs.as_ptr() as *mut _; - msg.msg_iovlen = bufs.len() as _; - msg.msg_controllen = ancillary.length as _; - // macos requires that the control pointer is null when the len is 0. - if msg.msg_controllen > 0 { - msg.msg_control = ancillary.buffer.as_mut_ptr().cast(); - } - - ancillary.truncated = false; - - socket.send_msg(&mut msg) - } -} - -fn add_to_ancillary_data( - buffer: &mut [u8], - length: &mut usize, - source: &[T], - cmsg_level: libc::c_int, - cmsg_type: libc::c_int, -) -> bool { - #[cfg(not(target_os = "freebsd"))] - let cmsg_size = source.len().checked_mul(size_of::()); - #[cfg(target_os = "freebsd")] - let cmsg_size = Some(unsafe { libc::SOCKCRED2SIZE(1) }); - - let source_len = if let Some(source_len) = cmsg_size { - if let Ok(source_len) = u32::try_from(source_len) { - source_len - } else { - return false; - } - } else { - return false; - }; - - unsafe { - let additional_space = libc::CMSG_SPACE(source_len) as usize; - - let new_length = if let Some(new_length) = additional_space.checked_add(*length) { - new_length - } else { - return false; - }; - - if new_length > buffer.len() { - return false; - } - - buffer[*length..new_length].fill(0); - - *length = new_length; - - let mut msg: libc::msghdr = zeroed(); - msg.msg_control = buffer.as_mut_ptr().cast(); - msg.msg_controllen = *length as _; - - let mut cmsg = libc::CMSG_FIRSTHDR(&msg); - let mut previous_cmsg = cmsg; - while !cmsg.is_null() { - previous_cmsg = cmsg; - cmsg = libc::CMSG_NXTHDR(&msg, cmsg); - - // Most operating systems, but not Linux or emscripten, return the previous pointer - // when its length is zero. Therefore, check if the previous pointer is the same as - // the current one. - if eq(cmsg, previous_cmsg) { - break; - } - } - - if previous_cmsg.is_null() { - return false; - } - - (*previous_cmsg).cmsg_level = cmsg_level; - (*previous_cmsg).cmsg_type = cmsg_type; - (*previous_cmsg).cmsg_len = libc::CMSG_LEN(source_len) as _; - - let data = libc::CMSG_DATA(previous_cmsg).cast(); - - libc::memcpy(data, source.as_ptr().cast(), source_len as usize); - } - true -} - -struct AncillaryDataIter<'a, T> { - data: &'a [u8], - phantom: PhantomData, -} - -impl<'a, T> AncillaryDataIter<'a, T> { - /// Create `AncillaryDataIter` struct to iterate through the data unit in the control message. - /// - /// # Safety - /// - /// `data` must contain a valid control message. - unsafe fn new(data: &'a [u8]) -> AncillaryDataIter<'a, T> { - AncillaryDataIter { data, phantom: PhantomData } - } -} - -impl<'a, T> Iterator for AncillaryDataIter<'a, T> { - type Item = T; - - fn next(&mut self) -> Option { - if size_of::() <= self.data.len() { - unsafe { - let unit = read_unaligned(self.data.as_ptr().cast()); - self.data = &self.data[size_of::()..]; - Some(unit) - } - } else { - None - } - } -} - -#[cfg(all( - doc, - not(target_os = "android"), - not(target_os = "linux"), - not(target_os = "netbsd"), - not(target_os = "freebsd") -))] -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -#[derive(Clone)] -pub struct SocketCred(()); - -/// Unix credential. -#[cfg(any(target_os = "android", target_os = "linux",))] -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -#[derive(Clone)] -pub struct SocketCred(libc::ucred); - -#[cfg(target_os = "netbsd")] -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -#[derive(Clone)] -pub struct SocketCred(libc::sockcred); - -#[cfg(target_os = "freebsd")] -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -#[derive(Clone)] -pub struct SocketCred(libc::sockcred2); - -#[doc(cfg(any(target_os = "android", target_os = "linux")))] -#[cfg(any(target_os = "android", target_os = "linux"))] -impl SocketCred { - /// Create a Unix credential struct. - /// - /// PID, UID and GID is set to 0. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - #[must_use] - pub fn new() -> SocketCred { - SocketCred(libc::ucred { pid: 0, uid: 0, gid: 0 }) - } - - /// Set the PID. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn set_pid(&mut self, pid: libc::pid_t) { - self.0.pid = pid; - } - - /// Get the current PID. - #[must_use] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn get_pid(&self) -> libc::pid_t { - self.0.pid - } - - /// Set the UID. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn set_uid(&mut self, uid: libc::uid_t) { - self.0.uid = uid; - } - - /// Get the current UID. - #[must_use] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn get_uid(&self) -> libc::uid_t { - self.0.uid - } - - /// Set the GID. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn set_gid(&mut self, gid: libc::gid_t) { - self.0.gid = gid; - } - - /// Get the current GID. - #[must_use] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn get_gid(&self) -> libc::gid_t { - self.0.gid - } -} - -#[cfg(target_os = "freebsd")] -impl SocketCred { - /// Create a Unix credential struct. - /// - /// PID, UID and GID is set to 0. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - #[must_use] - pub fn new() -> SocketCred { - SocketCred(libc::sockcred2 { - sc_version: 0, - sc_pid: 0, - sc_uid: 0, - sc_euid: 0, - sc_gid: 0, - sc_egid: 0, - sc_ngroups: 0, - sc_groups: [0; 1], - }) - } - - /// Set the PID. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn set_pid(&mut self, pid: libc::pid_t) { - self.0.sc_pid = pid; - } - - /// Get the current PID. - #[must_use] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn get_pid(&self) -> libc::pid_t { - self.0.sc_pid - } - - /// Set the UID. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn set_uid(&mut self, uid: libc::uid_t) { - self.0.sc_euid = uid; - } - - /// Get the current UID. - #[must_use] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn get_uid(&self) -> libc::uid_t { - self.0.sc_euid - } - - /// Set the GID. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn set_gid(&mut self, gid: libc::gid_t) { - self.0.sc_egid = gid; - } - - /// Get the current GID. - #[must_use] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn get_gid(&self) -> libc::gid_t { - self.0.sc_egid - } -} - -#[cfg(target_os = "netbsd")] -impl SocketCred { - /// Create a Unix credential struct. - /// - /// PID, UID and GID is set to 0. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn new() -> SocketCred { - SocketCred(libc::sockcred { - sc_pid: 0, - sc_uid: 0, - sc_euid: 0, - sc_gid: 0, - sc_egid: 0, - sc_ngroups: 0, - sc_groups: [0u32; 1], - }) - } - - /// Set the PID. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn set_pid(&mut self, pid: libc::pid_t) { - self.0.sc_pid = pid; - } - - /// Get the current PID. - #[must_use] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn get_pid(&self) -> libc::pid_t { - self.0.sc_pid - } - - /// Set the UID. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn set_uid(&mut self, uid: libc::uid_t) { - self.0.sc_uid = uid; - } - - /// Get the current UID. - #[must_use] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn get_uid(&self) -> libc::uid_t { - self.0.sc_uid - } - - /// Set the GID. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn set_gid(&mut self, gid: libc::gid_t) { - self.0.sc_gid = gid; - } - - /// Get the current GID. - #[must_use] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn get_gid(&self) -> libc::gid_t { - self.0.sc_gid - } -} - -/// This control message contains file descriptors. -/// -/// The level is equal to `SOL_SOCKET` and the type is equal to `SCM_RIGHTS`. -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -pub struct ScmRights<'a>(AncillaryDataIter<'a, RawFd>); - -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -impl<'a> Iterator for ScmRights<'a> { - type Item = RawFd; - - fn next(&mut self) -> Option { - self.0.next() - } -} - -#[cfg(all( - doc, - not(target_os = "android"), - not(target_os = "linux"), - not(target_os = "netbsd"), - not(target_os = "freebsd") -))] -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -pub struct ScmCredentials<'a>(AncillaryDataIter<'a, ()>); - -/// This control message contains unix credentials. -/// -/// The level is equal to `SOL_SOCKET` and the type is equal to `SCM_CREDENTIALS` or `SCM_CREDS`. -#[cfg(any(target_os = "android", target_os = "linux",))] -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -pub struct ScmCredentials<'a>(AncillaryDataIter<'a, libc::ucred>); - -#[cfg(target_os = "freebsd")] -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -pub struct ScmCredentials<'a>(AncillaryDataIter<'a, libc::sockcred2>); - -#[cfg(target_os = "netbsd")] -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -pub struct ScmCredentials<'a>(AncillaryDataIter<'a, libc::sockcred>); - -#[cfg(any( - doc, - target_os = "android", - target_os = "linux", - target_os = "netbsd", - target_os = "freebsd" -))] -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -impl<'a> Iterator for ScmCredentials<'a> { - type Item = SocketCred; - - fn next(&mut self) -> Option { - Some(SocketCred(self.0.next()?)) - } -} - -/// The error type which is returned from parsing the type a control message. -#[non_exhaustive] -#[derive(Debug)] -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -pub enum AncillaryError { - Unknown { cmsg_level: i32, cmsg_type: i32 }, -} - -/// This enum represent one control message of variable type. -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -pub enum AncillaryData<'a> { - ScmRights(ScmRights<'a>), - #[cfg(any( - doc, - target_os = "android", - target_os = "linux", - target_os = "netbsd", - target_os = "freebsd" - ))] - ScmCredentials(ScmCredentials<'a>), -} - -impl<'a> AncillaryData<'a> { - /// Create an `AncillaryData::ScmRights` variant. - /// - /// # Safety - /// - /// `data` must contain a valid control message and the control message must be type of - /// `SOL_SOCKET` and level of `SCM_RIGHTS`. - unsafe 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) - } - - /// Create an `AncillaryData::ScmCredentials` variant. - /// - /// # Safety - /// - /// `data` must contain a valid control message and the control message must be type of - /// `SOL_SOCKET` and level of `SCM_CREDENTIALS` or `SCM_CREDS`. - #[cfg(any( - doc, - target_os = "android", - target_os = "linux", - target_os = "netbsd", - target_os = "freebsd" - ))] - unsafe 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) - } - - fn try_from_cmsghdr(cmsg: &'a libc::cmsghdr) -> Result { - unsafe { - let cmsg_len_zero = libc::CMSG_LEN(0) as usize; - let data_len = (*cmsg).cmsg_len as usize - cmsg_len_zero; - let data = libc::CMSG_DATA(cmsg).cast(); - let data = from_raw_parts(data, data_len); - - match (*cmsg).cmsg_level { - libc::SOL_SOCKET => match (*cmsg).cmsg_type { - libc::SCM_RIGHTS => Ok(AncillaryData::as_rights(data)), - #[cfg(any(target_os = "android", target_os = "linux",))] - libc::SCM_CREDENTIALS => Ok(AncillaryData::as_credentials(data)), - #[cfg(target_os = "freebsd")] - libc::SCM_CREDS2 => Ok(AncillaryData::as_credentials(data)), - #[cfg(target_os = "netbsd")] - 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 }) - } - } - } - } -} - -/// This struct is used to iterate through the control messages. -#[must_use = "iterators are lazy and do nothing unless consumed"] -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -pub struct Messages<'a> { - buffer: &'a [u8], - current: Option<&'a libc::cmsghdr>, -} - -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -impl<'a> Iterator for Messages<'a> { - type Item = Result, AncillaryError>; - - fn next(&mut self) -> Option { - unsafe { - let mut msg: libc::msghdr = zeroed(); - msg.msg_control = self.buffer.as_ptr() as *mut _; - msg.msg_controllen = self.buffer.len() as _; - - let cmsg = if let Some(current) = self.current { - libc::CMSG_NXTHDR(&msg, current) - } else { - libc::CMSG_FIRSTHDR(&msg) - }; - - let cmsg = cmsg.as_ref()?; - - // Most operating systems, but not Linux or emscripten, return the previous pointer - // when its length is zero. Therefore, check if the previous pointer is the same as - // the current one. - if let Some(current) = self.current { - if eq(current, cmsg) { - return None; - } - } - - self.current = Some(cmsg); - let ancillary_result = AncillaryData::try_from_cmsghdr(cmsg); - Some(ancillary_result) - } - } -} - -/// 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)?; -/// -/// for ancillary_result in ancillary.messages() { -/// if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() { -/// for fd in scm_rights { -/// println!("receive file descriptor: {fd}"); -/// } -/// } -/// } -/// Ok(()) -/// } -/// ``` -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -#[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 = "76915")] - pub fn new(buffer: &'a mut [u8]) -> Self { - SocketAncillary { buffer, length: 0, truncated: false } - } - - /// Returns the capacity of the buffer. - #[must_use] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn capacity(&self) -> usize { - self.buffer.len() - } - - /// Returns `true` if the ancillary data is empty. - #[must_use] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn is_empty(&self) -> bool { - self.length == 0 - } - - /// Returns the number of used bytes. - #[must_use] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn len(&self) -> usize { - self.length - } - - /// Returns the iterator of the control messages. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn messages(&self) -> Messages<'_> { - 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(()) - /// } - /// ``` - #[must_use] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - 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::IoSlice; - /// - /// 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 buf = [1; 8]; - /// let mut bufs = &mut [IoSlice::new(&buf[..])][..]; - /// sock.send_vectored_with_ancillary(bufs, &mut ancillary)?; - /// Ok(()) - /// } - /// ``` - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - 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 is enough space in the buffer. - /// If there is not enough space then no credentials will be appended. - /// Technically, that means this operation adds a control message with the level `SOL_SOCKET` - /// and type `SCM_CREDENTIALS`, `SCM_CREDS`, or `SCM_CREDS2`. - /// - #[cfg(any( - doc, - target_os = "android", - target_os = "linux", - target_os = "netbsd", - target_os = "freebsd" - ))] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn add_creds(&mut self, creds: &[SocketCred]) -> bool { - self.truncated = false; - add_to_ancillary_data( - &mut self.buffer, - &mut self.length, - creds, - libc::SOL_SOCKET, - #[cfg(not(any(target_os = "netbsd", target_os = "freebsd")))] - libc::SCM_CREDENTIALS, - #[cfg(target_os = "freebsd")] - libc::SCM_CREDS2, - #[cfg(target_os = "netbsd")] - 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)?; - /// for ancillary_result in ancillary.messages() { - /// if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() { - /// for fd in scm_rights { - /// println!("receive file descriptor: {fd}"); - /// } - /// } - /// } - /// - /// ancillary.clear(); - /// - /// sock.recv_vectored_with_ancillary(bufs, &mut ancillary)?; - /// for ancillary_result in ancillary.messages() { - /// if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() { - /// for fd in scm_rights { - /// println!("receive file descriptor: {fd}"); - /// } - /// } - /// } - /// Ok(()) - /// } - /// ``` - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn clear(&mut self) { - self.length = 0; - self.truncated = false; - } -} diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index ab7cf066c904c..4f68db2d5d03e 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -1,8 +1,4 @@ -#[cfg(any(doc, target_os = "android", target_os = "linux"))] -use super::{recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to, SocketAncillary}; use super::{sockaddr_un, SocketAddr}; -#[cfg(any(doc, target_os = "android", target_os = "linux"))] -use crate::io::{IoSlice, IoSliceMut}; use crate::net::Shutdown; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::path::Path; @@ -385,106 +381,6 @@ impl UnixDatagram { self.0.read(buf) } - /// Receives data and ancillary data from socket. - /// - /// On success, returns the number of bytes read, if the data was truncated and the address from whence the msg came. - /// - /// # Examples - /// - #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")] - #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")] - /// #![feature(unix_socket_ancillary_data)] - /// use std::os::unix::net::{UnixDatagram, SocketAncillary, AncillaryData}; - /// use std::io::IoSliceMut; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// let mut buf1 = [1; 8]; - /// let mut buf2 = [2; 16]; - /// let mut buf3 = [3; 8]; - /// let mut bufs = &mut [ - /// IoSliceMut::new(&mut buf1), - /// IoSliceMut::new(&mut buf2), - /// IoSliceMut::new(&mut buf3), - /// ][..]; - /// let mut fds = [0; 8]; - /// let mut ancillary_buffer = [0; 128]; - /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); - /// let (size, _truncated, sender) = sock.recv_vectored_with_ancillary_from(bufs, &mut ancillary)?; - /// println!("received {size}"); - /// for ancillary_result in ancillary.messages() { - /// if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() { - /// for fd in scm_rights { - /// println!("receive file descriptor: {fd}"); - /// } - /// } - /// } - /// Ok(()) - /// } - /// ``` - #[cfg(any(doc, target_os = "android", target_os = "linux"))] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn recv_vectored_with_ancillary_from( - &self, - bufs: &mut [IoSliceMut<'_>], - ancillary: &mut SocketAncillary<'_>, - ) -> io::Result<(usize, bool, SocketAddr)> { - let (count, truncated, addr) = recv_vectored_with_ancillary_from(&self.0, bufs, ancillary)?; - let addr = addr?; - - Ok((count, truncated, addr)) - } - - /// Receives data and ancillary data from socket. - /// - /// On success, returns the number of bytes read and if the data was truncated. - /// - /// # Examples - /// - #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")] - #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")] - /// #![feature(unix_socket_ancillary_data)] - /// use std::os::unix::net::{UnixDatagram, SocketAncillary, AncillaryData}; - /// use std::io::IoSliceMut; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// let mut buf1 = [1; 8]; - /// let mut buf2 = [2; 16]; - /// let mut buf3 = [3; 8]; - /// let mut bufs = &mut [ - /// IoSliceMut::new(&mut buf1), - /// IoSliceMut::new(&mut buf2), - /// IoSliceMut::new(&mut buf3), - /// ][..]; - /// let mut fds = [0; 8]; - /// let mut ancillary_buffer = [0; 128]; - /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); - /// let (size, _truncated) = sock.recv_vectored_with_ancillary(bufs, &mut ancillary)?; - /// println!("received {size}"); - /// for ancillary_result in ancillary.messages() { - /// if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() { - /// for fd in scm_rights { - /// println!("receive file descriptor: {fd}"); - /// } - /// } - /// } - /// Ok(()) - /// } - /// ``` - #[cfg(any(doc, target_os = "android", target_os = "linux"))] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn recv_vectored_with_ancillary( - &self, - bufs: &mut [IoSliceMut<'_>], - ancillary: &mut SocketAncillary<'_>, - ) -> io::Result<(usize, bool)> { - let (count, truncated, addr) = recv_vectored_with_ancillary_from(&self.0, bufs, ancillary)?; - addr?; - - Ok((count, truncated)) - } - /// Sends data on the socket to the specified address. /// /// On success, returns the number of bytes written. @@ -576,89 +472,6 @@ impl UnixDatagram { self.0.write(buf) } - /// Sends data and ancillary data on the socket to the specified address. - /// - /// On success, returns the number of bytes written. - /// - /// # Examples - /// - #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")] - #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")] - /// #![feature(unix_socket_ancillary_data)] - /// use std::os::unix::net::{UnixDatagram, SocketAncillary}; - /// use std::io::IoSlice; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// let buf1 = [1; 8]; - /// let buf2 = [2; 16]; - /// let buf3 = [3; 8]; - /// let bufs = &[ - /// IoSlice::new(&buf1), - /// IoSlice::new(&buf2), - /// IoSlice::new(&buf3), - /// ][..]; - /// let fds = [0, 1, 2]; - /// let mut ancillary_buffer = [0; 128]; - /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); - /// ancillary.add_fds(&fds[..]); - /// sock.send_vectored_with_ancillary_to(bufs, &mut ancillary, "/some/sock") - /// .expect("send_vectored_with_ancillary_to function failed"); - /// Ok(()) - /// } - /// ``` - #[cfg(any(doc, target_os = "android", target_os = "linux"))] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn send_vectored_with_ancillary_to>( - &self, - bufs: &[IoSlice<'_>], - ancillary: &mut SocketAncillary<'_>, - path: P, - ) -> io::Result { - send_vectored_with_ancillary_to(&self.0, Some(path.as_ref()), bufs, ancillary) - } - - /// Sends data and ancillary data on the socket. - /// - /// On success, returns the number of bytes written. - /// - /// # Examples - /// - #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")] - #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")] - /// #![feature(unix_socket_ancillary_data)] - /// use std::os::unix::net::{UnixDatagram, SocketAncillary}; - /// use std::io::IoSlice; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// let buf1 = [1; 8]; - /// let buf2 = [2; 16]; - /// let buf3 = [3; 8]; - /// let bufs = &[ - /// IoSlice::new(&buf1), - /// IoSlice::new(&buf2), - /// IoSlice::new(&buf3), - /// ][..]; - /// let fds = [0, 1, 2]; - /// let mut ancillary_buffer = [0; 128]; - /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); - /// ancillary.add_fds(&fds[..]); - /// sock.send_vectored_with_ancillary(bufs, &mut ancillary) - /// .expect("send_vectored_with_ancillary function failed"); - /// Ok(()) - /// } - /// ``` - #[cfg(any(doc, target_os = "android", target_os = "linux"))] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn send_vectored_with_ancillary( - &self, - bufs: &[IoSlice<'_>], - ancillary: &mut SocketAncillary<'_>, - ) -> io::Result { - send_vectored_with_ancillary_to(&self.0, None, bufs, ancillary) - } - /// Sets the read timeout for the socket. /// /// If the provided value is [`None`], then [`recv`] and [`recv_from`] calls will diff --git a/library/std/src/os/unix/net/mod.rs b/library/std/src/os/unix/net/mod.rs index 6da3e350bf12f..5035d2f902bab 100644 --- a/library/std/src/os/unix/net/mod.rs +++ b/library/std/src/os/unix/net/mod.rs @@ -15,7 +15,6 @@ mod tests; #[stable(feature = "unix_socket", since = "1.10.0")] pub use self::addr::*; -#[cfg(any(doc, target_os = "android", target_os = "linux"))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub use self::ancillary::*; #[stable(feature = "unix_socket", since = "1.10.0")] diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index 6d5f667a21b32..8ebac1d92a3e5 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -1,5 +1,3 @@ -#[cfg(any(doc, target_os = "android", target_os = "linux"))] -use super::{recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to, SocketAncillary}; use super::{sockaddr_un, SocketAddr}; use crate::fmt; use crate::io::{self, IoSlice, IoSliceMut}; @@ -495,96 +493,6 @@ impl UnixStream { pub fn peek(&self, buf: &mut [u8]) -> io::Result { self.0.peek(buf) } - - /// Receives data and ancillary data from socket. - /// - /// On success, returns the number of bytes read. - /// - /// # Examples - /// - #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")] - #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")] - /// #![feature(unix_socket_ancillary_data)] - /// use std::os::unix::net::{UnixStream, SocketAncillary, AncillaryData}; - /// use std::io::IoSliceMut; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixStream::connect("/tmp/sock")?; - /// let mut buf1 = [1; 8]; - /// let mut buf2 = [2; 16]; - /// let mut buf3 = [3; 8]; - /// let mut bufs = &mut [ - /// IoSliceMut::new(&mut buf1), - /// IoSliceMut::new(&mut buf2), - /// IoSliceMut::new(&mut buf3), - /// ][..]; - /// let mut fds = [0; 8]; - /// let mut ancillary_buffer = [0; 128]; - /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); - /// let size = socket.recv_vectored_with_ancillary(bufs, &mut ancillary)?; - /// println!("received {size}"); - /// for ancillary_result in ancillary.messages() { - /// if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() { - /// for fd in scm_rights { - /// println!("receive file descriptor: {fd}"); - /// } - /// } - /// } - /// Ok(()) - /// } - /// ``` - #[cfg(any(doc, target_os = "android", target_os = "linux"))] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn recv_vectored_with_ancillary( - &self, - bufs: &mut [IoSliceMut<'_>], - ancillary: &mut SocketAncillary<'_>, - ) -> io::Result { - let (count, _, _) = recv_vectored_with_ancillary_from(&self.0, bufs, ancillary)?; - - Ok(count) - } - - /// Sends data and ancillary data on the socket. - /// - /// On success, returns the number of bytes written. - /// - /// # Examples - /// - #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")] - #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")] - /// #![feature(unix_socket_ancillary_data)] - /// use std::os::unix::net::{UnixStream, SocketAncillary}; - /// use std::io::IoSlice; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixStream::connect("/tmp/sock")?; - /// let buf1 = [1; 8]; - /// let buf2 = [2; 16]; - /// let buf3 = [3; 8]; - /// let bufs = &[ - /// IoSlice::new(&buf1), - /// IoSlice::new(&buf2), - /// IoSlice::new(&buf3), - /// ][..]; - /// let fds = [0, 1, 2]; - /// let mut ancillary_buffer = [0; 128]; - /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); - /// ancillary.add_fds(&fds[..]); - /// socket.send_vectored_with_ancillary(bufs, &mut ancillary) - /// .expect("send_vectored_with_ancillary function failed"); - /// Ok(()) - /// } - /// ``` - #[cfg(any(doc, target_os = "android", target_os = "linux"))] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn send_vectored_with_ancillary( - &self, - bufs: &[IoSlice<'_>], - ancillary: &mut SocketAncillary<'_>, - ) -> io::Result { - send_vectored_with_ancillary_to(&self.0, None, bufs, ancillary) - } } #[stable(feature = "unix_socket", since = "1.10.0")] diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs index b413f3caa39bc..fa4c166ea6662 100644 --- a/library/std/src/os/unix/net/tests.rs +++ b/library/std/src/os/unix/net/tests.rs @@ -1,8 +1,6 @@ use super::*; use crate::io::prelude::*; use crate::io::{self, ErrorKind, IoSlice, IoSliceMut}; -#[cfg(any(target_os = "android", target_os = "linux"))] -use crate::os::unix::io::AsRawFd; use crate::sys_common::io::test::tmpdir; use crate::thread; use crate::time::Duration; @@ -13,9 +11,6 @@ use crate::os::android::net::SocketAddrExt; #[cfg(target_os = "linux")] use crate::os::linux::net::SocketAddrExt; -#[cfg(any(target_os = "android", target_os = "linux"))] -use crate::os::linux::net::UnixSocketExt; - macro_rules! or_panic { ($e:expr) => { match $e { @@ -626,156 +621,3 @@ fn test_unix_datagram_peek_from() { assert_eq!(size, 11); assert_eq!(msg, &buf[..]); } - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[test] -fn test_send_vectored_fds_unix_stream() { - let (s1, s2) = or_panic!(UnixStream::pair()); - - let buf1 = [1; 8]; - let bufs_send = &[IoSlice::new(&buf1[..])][..]; - - let mut ancillary1_buffer = [0; 128]; - let mut ancillary1 = SocketAncillary::new(&mut ancillary1_buffer[..]); - assert!(ancillary1.add_fds(&[s1.as_raw_fd()][..])); - - let usize = or_panic!(s1.send_vectored_with_ancillary(&bufs_send, &mut ancillary1)); - assert_eq!(usize, 8); - - let mut buf2 = [0; 8]; - let mut bufs_recv = &mut [IoSliceMut::new(&mut buf2[..])][..]; - - let mut ancillary2_buffer = [0; 128]; - let mut ancillary2 = SocketAncillary::new(&mut ancillary2_buffer[..]); - - let usize = or_panic!(s2.recv_vectored_with_ancillary(&mut bufs_recv, &mut ancillary2)); - assert_eq!(usize, 8); - assert_eq!(buf1, buf2); - - let mut ancillary_data_vec = Vec::from_iter(ancillary2.messages()); - assert_eq!(ancillary_data_vec.len(), 1); - if let AncillaryData::ScmRights(scm_rights) = ancillary_data_vec.pop().unwrap().unwrap() { - let fd_vec = Vec::from_iter(scm_rights); - assert_eq!(fd_vec.len(), 1); - unsafe { - libc::close(fd_vec[0]); - } - } else { - unreachable!("must be ScmRights"); - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[test] -#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets -fn test_send_vectored_with_ancillary_to_unix_datagram() { - fn getpid() -> libc::pid_t { - unsafe { libc::getpid() } - } - - fn getuid() -> libc::uid_t { - unsafe { libc::getuid() } - } - - fn getgid() -> libc::gid_t { - unsafe { libc::getgid() } - } - - let dir = tmpdir(); - let path1 = dir.path().join("sock1"); - let path2 = dir.path().join("sock2"); - - let bsock1 = or_panic!(UnixDatagram::bind(&path1)); - let bsock2 = or_panic!(UnixDatagram::bind(&path2)); - - or_panic!(bsock2.set_passcred(true)); - - let buf1 = [1; 8]; - let bufs_send = &[IoSlice::new(&buf1[..])][..]; - - let mut ancillary1_buffer = [0; 128]; - let mut ancillary1 = SocketAncillary::new(&mut ancillary1_buffer[..]); - let mut cred1 = SocketCred::new(); - cred1.set_pid(getpid()); - cred1.set_uid(getuid()); - cred1.set_gid(getgid()); - assert!(ancillary1.add_creds(&[cred1.clone()][..])); - - let usize = - or_panic!(bsock1.send_vectored_with_ancillary_to(&bufs_send, &mut ancillary1, &path2)); - assert_eq!(usize, 8); - - let mut buf2 = [0; 8]; - let mut bufs_recv = &mut [IoSliceMut::new(&mut buf2[..])][..]; - - let mut ancillary2_buffer = [0; 128]; - let mut ancillary2 = SocketAncillary::new(&mut ancillary2_buffer[..]); - - let (usize, truncated, _addr) = - or_panic!(bsock2.recv_vectored_with_ancillary_from(&mut bufs_recv, &mut ancillary2)); - assert_eq!(ancillary2.truncated(), false); - assert_eq!(usize, 8); - assert_eq!(truncated, false); - assert_eq!(buf1, buf2); - - let mut ancillary_data_vec = Vec::from_iter(ancillary2.messages()); - assert_eq!(ancillary_data_vec.len(), 1); - if let AncillaryData::ScmCredentials(scm_credentials) = - ancillary_data_vec.pop().unwrap().unwrap() - { - let cred_vec = Vec::from_iter(scm_credentials); - assert_eq!(cred_vec.len(), 1); - assert_eq!(cred1.get_pid(), cred_vec[0].get_pid()); - assert_eq!(cred1.get_uid(), cred_vec[0].get_uid()); - assert_eq!(cred1.get_gid(), cred_vec[0].get_gid()); - } else { - unreachable!("must be ScmCredentials"); - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[test] -#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets -fn test_send_vectored_with_ancillary_unix_datagram() { - let dir = tmpdir(); - let path1 = dir.path().join("sock1"); - let path2 = dir.path().join("sock2"); - - let bsock1 = or_panic!(UnixDatagram::bind(&path1)); - let bsock2 = or_panic!(UnixDatagram::bind(&path2)); - - let buf1 = [1; 8]; - let bufs_send = &[IoSlice::new(&buf1[..])][..]; - - let mut ancillary1_buffer = [0; 128]; - let mut ancillary1 = SocketAncillary::new(&mut ancillary1_buffer[..]); - assert!(ancillary1.add_fds(&[bsock1.as_raw_fd()][..])); - - or_panic!(bsock1.connect(&path2)); - let usize = or_panic!(bsock1.send_vectored_with_ancillary(&bufs_send, &mut ancillary1)); - assert_eq!(usize, 8); - - let mut buf2 = [0; 8]; - let mut bufs_recv = &mut [IoSliceMut::new(&mut buf2[..])][..]; - - let mut ancillary2_buffer = [0; 128]; - let mut ancillary2 = SocketAncillary::new(&mut ancillary2_buffer[..]); - - let (usize, truncated) = - or_panic!(bsock2.recv_vectored_with_ancillary(&mut bufs_recv, &mut ancillary2)); - assert_eq!(usize, 8); - assert_eq!(truncated, false); - assert_eq!(buf1, buf2); - - let mut ancillary_data_vec = Vec::from_iter(ancillary2.messages()); - assert_eq!(ancillary_data_vec.len(), 1); - if let AncillaryData::ScmRights(scm_rights) = ancillary_data_vec.pop().unwrap().unwrap() { - let fd_vec = Vec::from_iter(scm_rights); - assert_eq!(fd_vec.len(), 1); - unsafe { - libc::close(fd_vec[0]); - } - } else { - unreachable!("must be ScmRights"); - } -} diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index d884a24c211ba..7bc591b1df87a 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -327,7 +327,7 @@ impl Socket { self.recv_from_with_flags(buf, 0) } - #[cfg(any(target_os = "android", target_os = "linux"))] + #[allow(dead_code)] pub fn recv_msg(&self, msg: &mut libc::msghdr) -> io::Result { let n = cvt(unsafe { libc::recvmsg(self.as_raw_fd(), msg, libc::MSG_CMSG_CLOEXEC) })?; Ok(n as usize) @@ -350,7 +350,7 @@ impl Socket { self.0.is_write_vectored() } - #[cfg(any(target_os = "android", target_os = "linux"))] + #[allow(dead_code)] pub fn send_msg(&self, msg: &mut libc::msghdr) -> io::Result { let n = cvt(unsafe { libc::sendmsg(self.as_raw_fd(), msg, 0) })?; Ok(n as usize)