From e68887e67cc6b7bb4ea5113a40eaa4c0831bda13 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 5 Dec 2021 13:36:06 +0000 Subject: [PATCH] socket ancillary data implementation for dragonflybsd. --- library/std/src/os/unix/net/ancillary.rs | 82 +++++++++++++++++++++++- library/std/src/os/unix/net/datagram.rs | 14 ++-- library/std/src/sys/unix/net.rs | 4 +- 3 files changed, 92 insertions(+), 8 deletions(-) diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs index 6e6f5212b4651..a29008140f784 100644 --- a/library/std/src/os/unix/net/ancillary.rs +++ b/library/std/src/os/unix/net/ancillary.rs @@ -16,6 +16,8 @@ mod libc { pub use libc::c_int; pub struct ucred; pub struct cmsghdr; + #[cfg(target_os = "dragonfly")] + pub struct cmsgcred; pub type pid_t = i32; pub type gid_t = u32; pub type uid_t = u32; @@ -183,6 +185,11 @@ impl<'a, T> Iterator for AncillaryDataIter<'a, T> { #[derive(Clone)] pub struct SocketCred(libc::ucred); +#[cfg(target_os = "dragonfly")] +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +#[derive(Clone)] +pub struct SocketCred(libc::cmsgcred); + #[cfg(any(doc, target_os = "android", target_os = "linux",))] impl SocketCred { /// Create a Unix credential struct. @@ -234,6 +241,57 @@ impl SocketCred { } } +#[cfg(target_os = "dragonfly")] +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::cmsgcred { cmsgcred_pid: 0, cmsgcred_uid: 0, cmsgcred_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.cmsgcred_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.cmsgcred_pid + } + + /// Set the UID. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn set_uid(&mut self, uid: libc::uid_t) { + self.0.cmsgcred_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.cmsgcred_uid + } + + /// Set the GID. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn set_gid(&mut self, gid: libc::gid_t) { + self.0.cmsgcred_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.cmsgcred_gid + } +} + /// This control message contains file descriptors. /// /// The level is equal to `SOL_SOCKET` and the type is equal to `SCM_RIGHTS`. @@ -256,7 +314,11 @@ impl<'a> Iterator for ScmRights<'a> { #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub struct ScmCredentials<'a>(AncillaryDataIter<'a, libc::ucred>); -#[cfg(any(doc, target_os = "android", target_os = "linux",))] +#[cfg(target_os = "dragonfly")] +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +pub struct ScmCredentials<'a>(AncillaryDataIter<'a, libc::cmsgcred>); + +#[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "dragonfly",))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] impl<'a> Iterator for ScmCredentials<'a> { type Item = SocketCred; @@ -300,7 +362,7 @@ impl<'a> AncillaryData<'a> { /// # 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_CREDENTIALS`. + /// `SOL_SOCKET` and level of `SCM_CREDENTIALS` or `SCM_CREDS`. #[cfg(any(doc, target_os = "android", target_os = "linux",))] unsafe fn as_credentials(data: &'a [u8]) -> Self { let ancillary_data_iter = AncillaryDataIter::new(data); @@ -320,6 +382,9 @@ impl<'a> AncillaryData<'a> { 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 = "dragonfly")] + libc::SCM_CREDS => Ok(AncillaryData::as_credentials(data)), + cmsg_type => { Err(AncillaryError::Unknown { cmsg_level: libc::SOL_SOCKET, cmsg_type }) } @@ -544,6 +609,19 @@ impl<'a> SocketAncillary<'a> { ) } + #[cfg(target_os = "dragonfly")] + #[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, + libc::SCM_CREDS, + ) + } + /// Clears the ancillary data, removing all values. /// /// # Example diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index a2caccc784917..f23f8f94a242f 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -854,8 +854,14 @@ impl UnixDatagram { /// /// # 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")] + #[cfg_attr( + any(target_os = "android", target_os = "linux", target_os = "dragonfly"), + doc = "```no_run" + )] + #[cfg_attr( + not(any(target_os = "android", target_os = "linux", target_os = "dragonfly")), + doc = "```ignore" + )] /// #![feature(unix_socket_ancillary_data)] /// use std::os::unix::net::UnixDatagram; /// @@ -865,7 +871,7 @@ impl UnixDatagram { /// Ok(()) /// } /// ``` - #[cfg(any(doc, target_os = "android", target_os = "linux",))] + #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "dragonfly",))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { self.0.set_passcred(passcred) @@ -877,7 +883,7 @@ impl UnixDatagram { /// Get the socket option `SO_PASSCRED`. /// /// [`set_passcred`]: UnixDatagram::set_passcred - #[cfg(any(doc, target_os = "android", target_os = "linux",))] + #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "dragonfly",))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn passcred(&self) -> io::Result { self.0.passcred() diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index a82a0172126d4..15d0dbe07fe7e 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -408,12 +408,12 @@ impl Socket { Ok(raw != 0) } - #[cfg(any(target_os = "android", target_os = "linux",))] + #[cfg(any(target_os = "android", target_os = "linux", target_os = "dragonfly",))] pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { setsockopt(self, libc::SOL_SOCKET, libc::SO_PASSCRED, passcred as libc::c_int) } - #[cfg(any(target_os = "android", target_os = "linux",))] + #[cfg(any(target_os = "android", target_os = "linux", target_os = "dragonfly",))] pub fn passcred(&self) -> io::Result { let passcred: libc::c_int = getsockopt(self, libc::SOL_SOCKET, libc::SO_PASSCRED)?; Ok(passcred != 0)