diff --git a/library/std/src/os/freebsd/mod.rs b/library/std/src/os/freebsd/mod.rs index c072fae557fe0..39912e6970d45 100644 --- a/library/std/src/os/freebsd/mod.rs +++ b/library/std/src/os/freebsd/mod.rs @@ -3,4 +3,5 @@ #![stable(feature = "raw_ext", since = "1.1.0")] pub mod fs; +pub mod net; pub mod raw; diff --git a/library/std/src/os/freebsd/net.rs b/library/std/src/os/freebsd/net.rs new file mode 100644 index 0000000000000..ffd617e3e9d11 --- /dev/null +++ b/library/std/src/os/freebsd/net.rs @@ -0,0 +1,65 @@ +//! FreeBSD-specific networking functionality. + +#![unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + +use crate::io; +use crate::os::unix::net; +use crate::sealed::Sealed; +use crate::sys_common::AsInner; + +/// OpenBSD-specific functionality for `AF_UNIX` sockets [`UnixDatagram`] +/// and [`UnixStream`]. +/// +/// [`UnixDatagram`]: net::UnixDatagram +/// [`UnixStream`]: net::UnixStream +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +pub trait UnixSocketExt: Sealed { + /// Query the current setting of socket option `LOCAL_CREDS`. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + fn local_creds_persistent(&self) -> io::Result; + + /// Enable or disable socket option `LOCAL_CREDS`. + /// + /// This option enables the credentials of the sending process to be + /// received as a control message in [`AncillaryData`]. + /// + /// [`AncillaryData`]: net::AncillaryData + /// + /// # Examples + /// + /// ```no_run + /// #![feature(unix_socket_ancillary_data)] + /// use std::os::freebsd::net::UnixSocketExt; + /// use std::os::unix::net::UnixDatagram; + /// + /// fn main() -> std::io::Result<()> { + /// let sock = UnixDatagram::unbound()?; + /// sock.set_local_creds_persistent(true).expect("set_local_creds_persistent failed"); + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + fn set_local_creds_persistent(&self, local_creds_persistent: bool) -> io::Result<()>; +} + +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +impl UnixSocketExt for net::UnixDatagram { + fn local_creds_persistent(&self) -> io::Result { + self.as_inner().local_creds_persistent() + } + + fn set_local_creds_persistent(&self, local_creds_persistent: bool) -> io::Result<()> { + self.as_inner().set_local_creds_persistent(local_creds_persistent) + } +} + +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +impl UnixSocketExt for net::UnixStream { + fn local_creds_persistent(&self) -> io::Result { + self.as_inner().local_creds_persistent() + } + + fn set_local_creds_persistent(&self, local_creds_persistent: bool) -> io::Result<()> { + self.as_inner().set_local_creds_persistent(local_creds_persistent) + } +} diff --git a/library/std/src/os/linux/net.rs b/library/std/src/os/linux/net.rs index c8e734d740b68..f898e70548706 100644 --- a/library/std/src/os/linux/net.rs +++ b/library/std/src/os/linux/net.rs @@ -5,5 +5,8 @@ #[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub use crate::os::net::linux_ext::addr::SocketAddrExt; +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +pub use crate::os::net::linux_ext::socket::UnixSocketExt; + #[unstable(feature = "tcp_quickack", issue = "96256")] pub use crate::os::net::linux_ext::tcp::TcpStreamExt; diff --git a/library/std/src/os/net/linux_ext/mod.rs b/library/std/src/os/net/linux_ext/mod.rs index 62e78cc50d4ab..d0979640c32ea 100644 --- a/library/std/src/os/net/linux_ext/mod.rs +++ b/library/std/src/os/net/linux_ext/mod.rs @@ -5,6 +5,9 @@ #[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub(crate) mod addr; +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +pub(crate) mod socket; + #[unstable(feature = "tcp_quickack", issue = "96256")] pub(crate) mod tcp; diff --git a/library/std/src/os/net/linux_ext/socket.rs b/library/std/src/os/net/linux_ext/socket.rs new file mode 100644 index 0000000000000..4e4168f693c34 --- /dev/null +++ b/library/std/src/os/net/linux_ext/socket.rs @@ -0,0 +1,63 @@ +//! Linux and Android-specific socket functionality. + +use crate::io; +use crate::os::unix::net; +use crate::sealed::Sealed; +use crate::sys_common::AsInner; + +/// Linux-specific functionality for `AF_UNIX` sockets [`UnixDatagram`] +/// and [`UnixStream`]. +/// +/// [`UnixDatagram`]: net::UnixDatagram +/// [`UnixStream`]: net::UnixStream +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +pub trait UnixSocketExt: Sealed { + /// Query the current setting of socket option `SO_PASSCRED`. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + fn passcred(&self) -> io::Result; + + /// Enable or disable socket option `SO_PASSCRED`. + /// + /// This option enables the credentials of the sending process to be + /// received as a control message in [`AncillaryData`]. + /// + /// [`AncillaryData`]: net::AncillaryData + /// + /// # Examples + /// + /// ```no_run + /// #![feature(unix_socket_ancillary_data)] + /// use std::os::linux::net::UnixSocketExt; + /// use std::os::unix::net::UnixDatagram; + /// + /// fn main() -> std::io::Result<()> { + /// let sock = UnixDatagram::unbound()?; + /// sock.set_passcred(true).expect("set_passcred failed"); + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + fn set_passcred(&self, passcred: bool) -> io::Result<()>; +} + +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +impl UnixSocketExt for net::UnixDatagram { + fn passcred(&self) -> io::Result { + self.as_inner().passcred() + } + + fn set_passcred(&self, passcred: bool) -> io::Result<()> { + self.as_inner().set_passcred(passcred) + } +} + +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +impl UnixSocketExt for net::UnixStream { + fn passcred(&self) -> io::Result { + self.as_inner().passcred() + } + + fn set_passcred(&self, passcred: bool) -> io::Result<()> { + self.as_inner().set_passcred(passcred) + } +} diff --git a/library/std/src/os/netbsd/mod.rs b/library/std/src/os/netbsd/mod.rs index 497a51a1df6fd..2f21e98a6f4cb 100644 --- a/library/std/src/os/netbsd/mod.rs +++ b/library/std/src/os/netbsd/mod.rs @@ -3,4 +3,5 @@ #![stable(feature = "raw_ext", since = "1.1.0")] pub mod fs; +pub mod net; pub mod raw; diff --git a/library/std/src/os/netbsd/net.rs b/library/std/src/os/netbsd/net.rs new file mode 100644 index 0000000000000..d4c7b0627e135 --- /dev/null +++ b/library/std/src/os/netbsd/net.rs @@ -0,0 +1,65 @@ +//! OpenBSD-specific networking functionality. + +#![unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + +use crate::io; +use crate::os::unix::net; +use crate::sealed::Sealed; +use crate::sys_common::AsInner; + +/// OpenBSD-specific functionality for `AF_UNIX` sockets [`UnixDatagram`] +/// and [`UnixStream`]. +/// +/// [`UnixDatagram`]: net::UnixDatagram +/// [`UnixStream`]: net::UnixStream +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +pub trait UnixSocketExt: Sealed { + /// Query the current setting of socket option `LOCAL_CREDS`. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + fn local_creds(&self) -> io::Result; + + /// Enable or disable socket option `LOCAL_CREDS`. + /// + /// This option enables the credentials of the sending process to be + /// received as a control message in [`AncillaryData`]. + /// + /// [`AncillaryData`]: net::AncillaryData + /// + /// # Examples + /// + /// ```no_run + /// #![feature(unix_socket_ancillary_data)] + /// use std::os::netbsd::net::UnixSocketExt; + /// use std::os::unix::net::UnixDatagram; + /// + /// fn main() -> std::io::Result<()> { + /// let sock = UnixDatagram::unbound()?; + /// sock.set_local_creds(true).expect("set_local_creds failed"); + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + fn set_local_creds(&self, local_creds: bool) -> io::Result<()>; +} + +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +impl UnixSocketExt for net::UnixDatagram { + fn local_creds(&self) -> io::Result { + self.as_inner().local_creds() + } + + fn set_local_creds(&self, local_creds: bool) -> io::Result<()> { + self.as_inner().set_local_creds(local_creds) + } +} + +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +impl UnixSocketExt for net::UnixStream { + fn local_creds(&self) -> io::Result { + self.as_inner().local_creds() + } + + fn set_local_creds(&self, local_creds: bool) -> io::Result<()> { + self.as_inner().set_local_creds(local_creds) + } +} diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index 34db54235f1c2..ab7cf066c904c 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -6,6 +6,7 @@ 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; +use crate::sealed::Sealed; use crate::sys::cvt; use crate::sys::net::Socket; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -54,6 +55,10 @@ const MSG_NOSIGNAL: libc::c_int = 0x0; #[stable(feature = "unix_socket", since = "1.10.0")] pub struct UnixDatagram(Socket); +/// Allows extension traits within `std`. +#[unstable(feature = "sealed", issue = "none")] +impl Sealed for UnixDatagram {} + #[stable(feature = "unix_socket", since = "1.10.0")] impl fmt::Debug for UnixDatagram { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -802,69 +807,6 @@ impl UnixDatagram { self.0.set_nonblocking(nonblocking) } - /// Moves the socket to pass unix credentials as control message in [`SocketAncillary`]. - /// - /// Set the socket option `SO_PASSCRED`. - /// - /// # Examples - /// - #[cfg_attr( - any( - target_os = "android", - target_os = "linux", - target_os = "netbsd", - target_os = "freebsd", - ), - doc = "```no_run" - )] - #[cfg_attr( - not(any( - target_os = "android", - target_os = "linux", - target_os = "netbsd", - target_os = "freebsd" - )), - doc = "```ignore" - )] - /// #![feature(unix_socket_ancillary_data)] - /// use std::os::unix::net::UnixDatagram; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// sock.set_passcred(true).expect("set_passcred function failed"); - /// Ok(()) - /// } - /// ``` - #[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 set_passcred(&self, passcred: bool) -> io::Result<()> { - self.0.set_passcred(passcred) - } - - /// Get the current value of the socket for passing unix credentials in [`SocketAncillary`]. - /// This value can be change by [`set_passcred`]. - /// - /// Get the socket option `SO_PASSCRED`. - /// - /// [`set_passcred`]: UnixDatagram::set_passcred - #[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 passcred(&self) -> io::Result { - self.0.passcred() - } - /// Set the id of the socket for network filtering purpose /// #[cfg_attr( @@ -1037,3 +979,10 @@ impl From for UnixDatagram { unsafe { Self::from_raw_fd(owned.into_raw_fd()) } } } + +impl AsInner for UnixDatagram { + #[inline] + fn as_inner(&self) -> &Socket { + &self.0 + } +} diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index 41290e0017ac3..6d5f667a21b32 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -19,6 +19,7 @@ use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, Owned ))] use crate::os::unix::ucred; use crate::path::Path; +use crate::sealed::Sealed; use crate::sys::cvt; use crate::sys::net::Socket; use crate::sys_common::{AsInner, FromInner}; @@ -59,6 +60,10 @@ pub use ucred::UCred; #[stable(feature = "unix_socket", since = "1.10.0")] pub struct UnixStream(pub(super) Socket); +/// Allows extension traits within `std`. +#[unstable(feature = "sealed", issue = "none")] +impl Sealed for UnixStream {} + #[stable(feature = "unix_socket", since = "1.10.0")] impl fmt::Debug for UnixStream { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -394,69 +399,6 @@ impl UnixStream { self.0.set_nonblocking(nonblocking) } - /// Moves the socket to pass unix credentials as control message in [`SocketAncillary`]. - /// - /// Set the socket option `SO_PASSCRED`. - /// - /// # Examples - /// - #[cfg_attr( - any( - target_os = "android", - target_os = "linux", - target_os = "netbsd", - target_os = "freebsd" - ), - doc = "```no_run" - )] - #[cfg_attr( - not(any( - target_os = "android", - target_os = "linux", - target_os = "netbsd", - target_os = "freebsd" - )), - doc = "```ignore" - )] - /// #![feature(unix_socket_ancillary_data)] - /// use std::os::unix::net::UnixStream; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixStream::connect("/tmp/sock")?; - /// socket.set_passcred(true).expect("Couldn't set passcred"); - /// Ok(()) - /// } - /// ``` - #[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 set_passcred(&self, passcred: bool) -> io::Result<()> { - self.0.set_passcred(passcred) - } - - /// Get the current value of the socket for passing unix credentials in [`SocketAncillary`]. - /// This value can be change by [`set_passcred`]. - /// - /// Get the socket option `SO_PASSCRED`. - /// - /// [`set_passcred`]: UnixStream::set_passcred - #[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 passcred(&self) -> io::Result { - self.0.passcred() - } - /// Set the id of the socket for network filtering purpose /// #[cfg_attr( @@ -765,3 +707,10 @@ impl From for UnixStream { unsafe { Self::from_raw_fd(owned.into_raw_fd()) } } } + +impl AsInner for UnixStream { + #[inline] + fn as_inner(&self) -> &Socket { + &self.0 + } +} diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs index 6a6af9efd78ed..b413f3caa39bc 100644 --- a/library/std/src/os/unix/net/tests.rs +++ b/library/std/src/os/unix/net/tests.rs @@ -13,6 +13,9 @@ 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 { diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index ec861f9cb8696..d884a24c211ba 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -453,25 +453,31 @@ impl Socket { } #[cfg(target_os = "netbsd")] - pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { - setsockopt(self, 0 as libc::c_int, libc::LOCAL_CREDS, passcred as libc::c_int) + pub fn set_local_creds(&self, local_creds: bool) -> io::Result<()> { + setsockopt(self, 0 as libc::c_int, libc::LOCAL_CREDS, local_creds as libc::c_int) } #[cfg(target_os = "netbsd")] - pub fn passcred(&self) -> io::Result { - let passcred: libc::c_int = getsockopt(self, 0 as libc::c_int, libc::LOCAL_CREDS)?; - Ok(passcred != 0) + pub fn local_creds(&self) -> io::Result { + let local_creds: libc::c_int = getsockopt(self, 0 as libc::c_int, libc::LOCAL_CREDS)?; + Ok(local_creds != 0) } #[cfg(target_os = "freebsd")] - pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { - setsockopt(self, libc::AF_LOCAL, libc::LOCAL_CREDS_PERSISTENT, passcred as libc::c_int) + pub fn set_local_creds_persistent(&self, local_creds_persistent: bool) -> io::Result<()> { + setsockopt( + self, + libc::AF_LOCAL, + libc::LOCAL_CREDS_PERSISTENT, + local_creds_persistent as libc::c_int, + ) } #[cfg(target_os = "freebsd")] - pub fn passcred(&self) -> io::Result { - let passcred: libc::c_int = getsockopt(self, libc::AF_LOCAL, libc::LOCAL_CREDS_PERSISTENT)?; - Ok(passcred != 0) + pub fn local_creds_persistent(&self) -> io::Result { + let local_creds_persistent: libc::c_int = + getsockopt(self, libc::AF_LOCAL, libc::LOCAL_CREDS_PERSISTENT)?; + Ok(local_creds_persistent != 0) } #[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "vita")))]