diff --git a/library/std/src/sys/unix/ext/net/datagram.rs b/library/std/src/sys/unix/ext/net/datagram.rs index 5df45e6465b4..e5309e54e795 100644 --- a/library/std/src/sys/unix/ext/net/datagram.rs +++ b/library/std/src/sys/unix/ext/net/datagram.rs @@ -735,6 +735,66 @@ 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 + /// + /// ```no_run + /// #![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 = "dragonfly", + target_os = "emscripten", + target_os = "freebsd", + target_os = "fuchsia", + target_os = "ios", + target_os = "linux", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd", + target_env = "uclibc", + ))] + #[unstable(feature = "unix_socket_ancillary_data", issue = "none")] + 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 = "dragonfly", + target_os = "emscripten", + target_os = "freebsd", + target_os = "fuchsia", + target_os = "ios", + target_os = "linux", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd", + target_env = "uclibc", + ))] + #[unstable(feature = "unix_socket_ancillary_data", issue = "none")] + pub fn passcred(&self) -> io::Result { + self.0.passcred() + } + /// Returns the value of the `SO_ERROR` option. /// /// # Examples diff --git a/library/std/src/sys/unix/ext/net/stream.rs b/library/std/src/sys/unix/ext/net/stream.rs index 907832399d84..68e8429dd3b2 100644 --- a/library/std/src/sys/unix/ext/net/stream.rs +++ b/library/std/src/sys/unix/ext/net/stream.rs @@ -366,6 +366,66 @@ 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 + /// + /// ```no_run + /// #![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 = "dragonfly", + target_os = "emscripten", + target_os = "freebsd", + target_os = "fuchsia", + target_os = "ios", + target_os = "linux", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd", + target_env = "uclibc", + ))] + #[unstable(feature = "unix_socket_ancillary_data", issue = "none")] + 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 = "dragonfly", + target_os = "emscripten", + target_os = "freebsd", + target_os = "fuchsia", + target_os = "ios", + target_os = "linux", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd", + target_env = "uclibc", + ))] + #[unstable(feature = "unix_socket_ancillary_data", issue = "none")] + pub fn passcred(&self) -> io::Result { + self.0.passcred() + } + /// Returns the value of the `SO_ERROR` option. /// /// # Examples diff --git a/library/std/src/sys/unix/ext/net/tests.rs b/library/std/src/sys/unix/ext/net/tests.rs index a39b97f2c31b..db6a972e7d2d 100644 --- a/library/std/src/sys/unix/ext/net/tests.rs +++ b/library/std/src/sys/unix/ext/net/tests.rs @@ -2,7 +2,6 @@ use super::*; use crate::io::prelude::*; use crate::io::{self, ErrorKind, IoSlice, IoSliceMut}; use crate::iter::FromIterator; -use crate::mem; use crate::sys::unix::ext::io::AsRawFd; use crate::sys_common::io::test::tmpdir; use crate::thread; @@ -513,16 +512,7 @@ fn test_send_vectored_with_ancillary_to_unix_datagram() { let bsock1 = or_panic!(UnixDatagram::bind(&path1)); let bsock2 = or_panic!(UnixDatagram::bind(&path2)); - unsafe { - let optval: libc::c_int = 1; - libc::setsockopt( - bsock2.as_raw_fd(), - libc::SOL_SOCKET, - libc::SO_PASSCRED, - &optval as *const _ as *const _, - mem::size_of::() as u32, - ); - } + or_panic!(bsock2.set_passcred(true)); let mut buf1 = [1; 8]; let mut bufs_send = &mut [IoSliceMut::new(&mut buf1[..])][..]; diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index 1a514ed0238c..c01d2fa5f23e 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -323,6 +323,16 @@ impl Socket { Ok(raw != 0) } + pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { + let boolean: libc::c_int = if passcred { 1 } else { 0 }; + setsockopt(self, libc::SOL_SOCKET, libc::SO_PASSCRED, boolean) + } + + pub fn passcred(&self) -> io::Result { + let passcred: libc::c_int = getsockopt(self, libc::SOL_SOCKET, libc::SO_PASSCRED)?; + Ok(passcred != 0) + } + #[cfg(not(any(target_os = "solaris", target_os = "illumos")))] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { let mut nonblocking = nonblocking as libc::c_int;