diff --git a/src/socket.rs b/src/socket.rs index 3291707c..21bcfcb2 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -965,6 +965,37 @@ impl Socket { } } + /// Get value for the `SO_PASSCRED` option on this socket. + /// + /// For more information about this option, see [`set_passcred`]. + /// + /// [`set_passcred`]: Socket::set_passcred + #[cfg(all(unix, target_os = "linux"))] + #[cfg_attr(docsrs, doc(cfg(all(unix, target_os = "linux"))))] + pub fn passcred(&self) -> io::Result { + unsafe { + getsockopt::(self.as_raw(), sys::SOL_SOCKET, sys::SO_PASSCRED) + .map(|passcred| passcred != 0) + } + } + + /// Set value for the `SO_PASSCRED` option on this socket. + /// + /// If this option is enabled, enables the receiving of the `SCM_CREDENTIALS` + /// control messages. + #[cfg(all(unix, target_os = "linux"))] + #[cfg_attr(docsrs, doc(cfg(all(unix, target_os = "linux"))))] + pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { + unsafe { + setsockopt( + self.as_raw(), + sys::SOL_SOCKET, + sys::SO_PASSCRED, + passcred as c_int, + ) + } + } + /// Get value for the `SO_RCVBUF` option on this socket. /// /// For more information about this option, see [`set_recv_buffer_size`]. diff --git a/src/sys/unix.rs b/src/sys/unix.rs index 562cd60f..98c1024b 100644 --- a/src/sys/unix.rs +++ b/src/sys/unix.rs @@ -172,6 +172,8 @@ pub(crate) use libc::SO_LINGER; target_os = "watchos", ))] pub(crate) use libc::SO_LINGER_SEC as SO_LINGER; +#[cfg(target_os = "linux")] +pub(crate) use libc::SO_PASSCRED; pub(crate) use libc::{ ip_mreq as IpMreq, linger, IPPROTO_IP, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, IPV6_MULTICAST_IF, IPV6_MULTICAST_LOOP, IPV6_UNICAST_HOPS, IPV6_V6ONLY, IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP, diff --git a/tests/socket.rs b/tests/socket.rs index 1c83321a..89b79f5f 100644 --- a/tests/socket.rs +++ b/tests/socket.rs @@ -1680,3 +1680,19 @@ fn cookie() { Err(err) => panic!("Could not get socket cookie a second time, err: {err}"), } } + +#[cfg(all(unix, target_os = "linux"))] +#[test] +fn set_passcred() { + let socket = Socket::new(Domain::UNIX, Type::DGRAM, None).unwrap(); + assert!(!socket.passcred().unwrap()); + + socket.set_passcred(true).unwrap(); + assert!(socket.passcred().unwrap()); + + let socket = Socket::new(Domain::UNIX, Type::STREAM, None).unwrap(); + assert!(!socket.passcred().unwrap()); + + socket.set_passcred(true).unwrap(); + assert!(socket.passcred().unwrap()); +}