about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-03-11 07:46:01 +0000
committerbors <bors@rust-lang.org>2024-03-11 07:46:01 +0000
commit66396725541ac7920439876fc79cbc7b604b82e0 (patch)
treeaa85460d353495c0388e86419eff9fed91d35a70
parenta6d93acf5fdeb020ab86cc0d30d5672c23a7dba6 (diff)
parent93f2f2c8ee44a8cb469fd7e656599c2b9546a1af (diff)
downloadrust-66396725541ac7920439876fc79cbc7b604b82e0.tar.gz
rust-66396725541ac7920439876fc79cbc7b604b82e0.zip
Auto merge of #117156 - jmillikin:os-unix-socket-ext, r=Amanieu,dtolnay
Convert `Unix{Datagram,Stream}::{set_}passcred()` to per-OS traits

These methods are the pre-stabilized API for obtaining peer credentials from an `AF_UNIX` socket, part of the `unix_socket_ancillary_data` feature.

Their current behavior is to get/set one of the `SO_PASSCRED` (Linux), `LOCAL_CREDS_PERSISTENT` (FreeBSD), or `LOCAL_CREDS` (NetBSD) socket options. On other targets the `{set_}passcred()` methods do not exist.

There are two problems with this approach:

1. Having public methods only exist for certain targets isn't permitted in a stable `std` API.

2. These options have generally similar purposes, but they are non-POSIX and their details can differ in subtle and surprising ways (such as whether they continue to be set after the next call to `recvmsg()`).

Splitting into OS-specific extension traits is the preferred solution to both problems.
-rw-r--r--library/std/src/os/android/net.rs3
-rw-r--r--library/std/src/os/freebsd/mod.rs1
-rw-r--r--library/std/src/os/freebsd/net.rs65
-rw-r--r--library/std/src/os/linux/net.rs3
-rw-r--r--library/std/src/os/net/linux_ext/mod.rs3
-rw-r--r--library/std/src/os/net/linux_ext/socket.rs63
-rw-r--r--library/std/src/os/netbsd/mod.rs1
-rw-r--r--library/std/src/os/netbsd/net.rs65
-rw-r--r--library/std/src/os/unix/net/datagram.rs75
-rw-r--r--library/std/src/os/unix/net/stream.rs75
-rw-r--r--library/std/src/os/unix/net/tests.rs4
-rw-r--r--library/std/src/sys/pal/unix/net.rs26
12 files changed, 246 insertions, 138 deletions
diff --git a/library/std/src/os/android/net.rs b/library/std/src/os/android/net.rs
index fe40d6319c2..349e73eaabd 100644
--- a/library/std/src/os/android/net.rs
+++ b/library/std/src/os/android/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/freebsd/mod.rs b/library/std/src/os/freebsd/mod.rs
index c072fae557f..39912e6970d 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 00000000000..33990d54caa
--- /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;
+
+/// FreeBSD-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_PERSISTENT`.
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    fn local_creds_persistent(&self) -> io::Result<bool>;
+
+    /// Enable or disable socket option `LOCAL_CREDS_PERSISTENT`.
+    ///
+    /// 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<bool> {
+        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<bool> {
+        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 c8e734d740b..f898e705487 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 62e78cc50d4..d0979640c32 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 00000000000..4e4168f693c
--- /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<bool>;
+
+    /// 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<bool> {
+        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<bool> {
+        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 497a51a1df6..2f21e98a6f4 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 00000000000..5c82f43077d
--- /dev/null
+++ b/library/std/src/os/netbsd/net.rs
@@ -0,0 +1,65 @@
+//! NetBSD-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;
+
+/// NetBSD-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<bool>;
+
+    /// 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<bool> {
+        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<bool> {
+        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 0b4d955294c..df698c17f6c 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<bool> {
-        self.0.passcred()
-    }
-
     /// Set the id of the socket for network filtering purpose
     ///
     #[cfg_attr(
@@ -1038,3 +980,10 @@ impl From<OwnedFd> for UnixDatagram {
         unsafe { Self::from_raw_fd(owned.into_raw_fd()) }
     }
 }
+
+impl AsInner<Socket> 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 069cb299e28..d2e23bdee6c 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::io::{self, 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};
@@ -44,6 +45,10 @@ use crate::time::Duration;
 #[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 {
@@ -379,69 +384,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<bool> {
-        self.0.passcred()
-    }
-
     /// Set the id of the socket for network filtering purpose
     ///
     #[cfg_attr(
@@ -751,3 +693,10 @@ impl From<OwnedFd> for UnixStream {
         unsafe { Self::from_raw_fd(owned.into_raw_fd()) }
     }
 }
+
+impl AsInner<Socket> 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 6a6af9efd78..e456e41b21c 100644
--- a/library/std/src/os/unix/net/tests.rs
+++ b/library/std/src/os/unix/net/tests.rs
@@ -8,10 +8,10 @@ use crate::thread;
 use crate::time::Duration;
 
 #[cfg(target_os = "android")]
-use crate::os::android::net::SocketAddrExt;
+use crate::os::android::net::{SocketAddrExt, UnixSocketExt};
 
 #[cfg(target_os = "linux")]
-use crate::os::linux::net::SocketAddrExt;
+use crate::os::linux::net::{SocketAddrExt, UnixSocketExt};
 
 macro_rules! or_panic {
     ($e:expr) => {
diff --git a/library/std/src/sys/pal/unix/net.rs b/library/std/src/sys/pal/unix/net.rs
index 60546a3de45..09750b6ffc8 100644
--- a/library/std/src/sys/pal/unix/net.rs
+++ b/library/std/src/sys/pal/unix/net.rs
@@ -465,25 +465,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<bool> {
-        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<bool> {
+        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<bool> {
-        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<bool> {
+        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")))]