From e68887e67cc6b7bb4ea5113a40eaa4c0831bda13 Mon Sep 17 00:00:00 2001
From: David Carlier <devnexen@gmail.com>
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<bool> {
         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<bool> {
         let passcred: libc::c_int = getsockopt(self, libc::SOL_SOCKET, libc::SO_PASSCRED)?;
         Ok(passcred != 0)