]> git.lizzy.rs Git - rust.git/blob - library/std/src/os/unix/net/ancillary.rs
Rollup merge of #84500 - tmandry:compiletest-run-flag, r=Mark-Simulacrum
[rust.git] / library / std / src / os / unix / net / ancillary.rs
1 use super::{sockaddr_un, SocketAddr};
2 use crate::convert::TryFrom;
3 use crate::io::{self, IoSlice, IoSliceMut};
4 use crate::marker::PhantomData;
5 use crate::mem::{size_of, zeroed};
6 use crate::os::unix::io::RawFd;
7 use crate::path::Path;
8 use crate::ptr::{eq, read_unaligned};
9 use crate::slice::from_raw_parts;
10 use crate::sys::net::Socket;
11
12 // FIXME(#43348): Make libc adapt #[doc(cfg(...))] so we don't need these fake definitions here?
13 #[cfg(all(doc, not(target_os = "linux"), not(target_os = "android")))]
14 #[allow(non_camel_case_types)]
15 mod libc {
16     pub use libc::c_int;
17     pub struct ucred;
18     pub struct cmsghdr;
19     pub type pid_t = i32;
20     pub type gid_t = u32;
21     pub type uid_t = u32;
22 }
23
24 pub(super) fn recv_vectored_with_ancillary_from(
25     socket: &Socket,
26     bufs: &mut [IoSliceMut<'_>],
27     ancillary: &mut SocketAncillary<'_>,
28 ) -> io::Result<(usize, bool, io::Result<SocketAddr>)> {
29     unsafe {
30         let mut msg_name: libc::sockaddr_un = zeroed();
31         let mut msg: libc::msghdr = zeroed();
32         msg.msg_name = &mut msg_name as *mut _ as *mut _;
33         msg.msg_namelen = size_of::<libc::sockaddr_un>() as libc::socklen_t;
34         msg.msg_iov = bufs.as_mut_ptr().cast();
35         cfg_if::cfg_if! {
36             if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
37                 msg.msg_iovlen = bufs.len() as libc::size_t;
38                 msg.msg_controllen = ancillary.buffer.len() as libc::size_t;
39             } else if #[cfg(any(
40                           target_os = "dragonfly",
41                           target_os = "emscripten",
42                           target_os = "freebsd",
43                           all(target_os = "linux", target_env = "musl",),
44                           target_os = "macos",
45                           target_os = "netbsd",
46                           target_os = "openbsd",
47                       ))] {
48                 msg.msg_iovlen = bufs.len() as libc::c_int;
49                 msg.msg_controllen = ancillary.buffer.len() as libc::socklen_t;
50             }
51         }
52         // macos requires that the control pointer is null when the len is 0.
53         if msg.msg_controllen > 0 {
54             msg.msg_control = ancillary.buffer.as_mut_ptr().cast();
55         }
56
57         let count = socket.recv_msg(&mut msg)?;
58
59         ancillary.length = msg.msg_controllen as usize;
60         ancillary.truncated = msg.msg_flags & libc::MSG_CTRUNC == libc::MSG_CTRUNC;
61
62         let truncated = msg.msg_flags & libc::MSG_TRUNC == libc::MSG_TRUNC;
63         let addr = SocketAddr::from_parts(msg_name, msg.msg_namelen);
64
65         Ok((count, truncated, addr))
66     }
67 }
68
69 pub(super) fn send_vectored_with_ancillary_to(
70     socket: &Socket,
71     path: Option<&Path>,
72     bufs: &[IoSlice<'_>],
73     ancillary: &mut SocketAncillary<'_>,
74 ) -> io::Result<usize> {
75     unsafe {
76         let (mut msg_name, msg_namelen) =
77             if let Some(path) = path { sockaddr_un(path)? } else { (zeroed(), 0) };
78
79         let mut msg: libc::msghdr = zeroed();
80         msg.msg_name = &mut msg_name as *mut _ as *mut _;
81         msg.msg_namelen = msg_namelen;
82         msg.msg_iov = bufs.as_ptr() as *mut _;
83         cfg_if::cfg_if! {
84             if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
85                 msg.msg_iovlen = bufs.len() as libc::size_t;
86                 msg.msg_controllen = ancillary.length as libc::size_t;
87             } else if #[cfg(any(
88                           target_os = "dragonfly",
89                           target_os = "emscripten",
90                           target_os = "freebsd",
91                           all(target_os = "linux", target_env = "musl",),
92                           target_os = "macos",
93                           target_os = "netbsd",
94                           target_os = "openbsd",
95                       ))] {
96                 msg.msg_iovlen = bufs.len() as libc::c_int;
97                 msg.msg_controllen = ancillary.length as libc::socklen_t;
98             }
99         }
100         // macos requires that the control pointer is null when the len is 0.
101         if msg.msg_controllen > 0 {
102             msg.msg_control = ancillary.buffer.as_mut_ptr().cast();
103         }
104
105         ancillary.truncated = false;
106
107         socket.send_msg(&mut msg)
108     }
109 }
110
111 fn add_to_ancillary_data<T>(
112     buffer: &mut [u8],
113     length: &mut usize,
114     source: &[T],
115     cmsg_level: libc::c_int,
116     cmsg_type: libc::c_int,
117 ) -> bool {
118     let source_len = if let Some(source_len) = source.len().checked_mul(size_of::<T>()) {
119         if let Ok(source_len) = u32::try_from(source_len) {
120             source_len
121         } else {
122             return false;
123         }
124     } else {
125         return false;
126     };
127
128     unsafe {
129         let additional_space = libc::CMSG_SPACE(source_len) as usize;
130
131         let new_length = if let Some(new_length) = additional_space.checked_add(*length) {
132             new_length
133         } else {
134             return false;
135         };
136
137         if new_length > buffer.len() {
138             return false;
139         }
140
141         buffer[*length..new_length].fill(0);
142
143         *length = new_length;
144
145         let mut msg: libc::msghdr = zeroed();
146         msg.msg_control = buffer.as_mut_ptr().cast();
147         cfg_if::cfg_if! {
148             if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
149                 msg.msg_controllen = *length as libc::size_t;
150             } else if #[cfg(any(
151                           target_os = "dragonfly",
152                           target_os = "emscripten",
153                           target_os = "freebsd",
154                           all(target_os = "linux", target_env = "musl",),
155                           target_os = "macos",
156                           target_os = "netbsd",
157                           target_os = "openbsd",
158                       ))] {
159                 msg.msg_controllen = *length as libc::socklen_t;
160             }
161         }
162
163         let mut cmsg = libc::CMSG_FIRSTHDR(&msg);
164         let mut previous_cmsg = cmsg;
165         while !cmsg.is_null() {
166             previous_cmsg = cmsg;
167             cmsg = libc::CMSG_NXTHDR(&msg, cmsg);
168
169             // Most operating systems, but not Linux or emscripten, return the previous pointer
170             // when its length is zero. Therefore, check if the previous pointer is the same as
171             // the current one.
172             if eq(cmsg, previous_cmsg) {
173                 break;
174             }
175         }
176
177         if previous_cmsg.is_null() {
178             return false;
179         }
180
181         (*previous_cmsg).cmsg_level = cmsg_level;
182         (*previous_cmsg).cmsg_type = cmsg_type;
183         cfg_if::cfg_if! {
184             if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
185                 (*previous_cmsg).cmsg_len = libc::CMSG_LEN(source_len) as libc::size_t;
186             } else if #[cfg(any(
187                           target_os = "dragonfly",
188                           target_os = "emscripten",
189                           target_os = "freebsd",
190                           all(target_os = "linux", target_env = "musl",),
191                           target_os = "macos",
192                           target_os = "netbsd",
193                           target_os = "openbsd",
194                       ))] {
195                 (*previous_cmsg).cmsg_len = libc::CMSG_LEN(source_len) as libc::socklen_t;
196             }
197         }
198
199         let data = libc::CMSG_DATA(previous_cmsg).cast();
200
201         libc::memcpy(data, source.as_ptr().cast(), source_len as usize);
202     }
203     true
204 }
205
206 struct AncillaryDataIter<'a, T> {
207     data: &'a [u8],
208     phantom: PhantomData<T>,
209 }
210
211 impl<'a, T> AncillaryDataIter<'a, T> {
212     /// Create `AncillaryDataIter` struct to iterate through the data unit in the control message.
213     ///
214     /// # Safety
215     ///
216     /// `data` must contain a valid control message.
217     unsafe fn new(data: &'a [u8]) -> AncillaryDataIter<'a, T> {
218         AncillaryDataIter { data, phantom: PhantomData }
219     }
220 }
221
222 impl<'a, T> Iterator for AncillaryDataIter<'a, T> {
223     type Item = T;
224
225     fn next(&mut self) -> Option<T> {
226         if size_of::<T>() <= self.data.len() {
227             unsafe {
228                 let unit = read_unaligned(self.data.as_ptr().cast());
229                 self.data = &self.data[size_of::<T>()..];
230                 Some(unit)
231             }
232         } else {
233             None
234         }
235     }
236 }
237
238 /// Unix credential.
239 #[cfg(any(doc, target_os = "android", target_os = "linux",))]
240 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
241 #[derive(Clone)]
242 pub struct SocketCred(libc::ucred);
243
244 #[cfg(any(doc, target_os = "android", target_os = "linux",))]
245 impl SocketCred {
246     /// Create a Unix credential struct.
247     ///
248     /// PID, UID and GID is set to 0.
249     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
250     pub fn new() -> SocketCred {
251         SocketCred(libc::ucred { pid: 0, uid: 0, gid: 0 })
252     }
253
254     /// Set the PID.
255     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
256     pub fn set_pid(&mut self, pid: libc::pid_t) {
257         self.0.pid = pid;
258     }
259
260     /// Get the current PID.
261     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
262     pub fn get_pid(&self) -> libc::pid_t {
263         self.0.pid
264     }
265
266     /// Set the UID.
267     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
268     pub fn set_uid(&mut self, uid: libc::uid_t) {
269         self.0.uid = uid;
270     }
271
272     /// Get the current UID.
273     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
274     pub fn get_uid(&self) -> libc::uid_t {
275         self.0.uid
276     }
277
278     /// Set the GID.
279     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
280     pub fn set_gid(&mut self, gid: libc::gid_t) {
281         self.0.gid = gid;
282     }
283
284     /// Get the current GID.
285     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
286     pub fn get_gid(&self) -> libc::gid_t {
287         self.0.gid
288     }
289 }
290
291 /// This control message contains file descriptors.
292 ///
293 /// The level is equal to `SOL_SOCKET` and the type is equal to `SCM_RIGHTS`.
294 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
295 pub struct ScmRights<'a>(AncillaryDataIter<'a, RawFd>);
296
297 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
298 impl<'a> Iterator for ScmRights<'a> {
299     type Item = RawFd;
300
301     fn next(&mut self) -> Option<RawFd> {
302         self.0.next()
303     }
304 }
305
306 /// This control message contains unix credentials.
307 ///
308 /// The level is equal to `SOL_SOCKET` and the type is equal to `SCM_CREDENTIALS` or `SCM_CREDS`.
309 #[cfg(any(doc, target_os = "android", target_os = "linux",))]
310 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
311 pub struct ScmCredentials<'a>(AncillaryDataIter<'a, libc::ucred>);
312
313 #[cfg(any(doc, target_os = "android", target_os = "linux",))]
314 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
315 impl<'a> Iterator for ScmCredentials<'a> {
316     type Item = SocketCred;
317
318     fn next(&mut self) -> Option<SocketCred> {
319         Some(SocketCred(self.0.next()?))
320     }
321 }
322
323 /// The error type which is returned from parsing the type a control message.
324 #[non_exhaustive]
325 #[derive(Debug)]
326 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
327 pub enum AncillaryError {
328     Unknown { cmsg_level: i32, cmsg_type: i32 },
329 }
330
331 /// This enum represent one control message of variable type.
332 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
333 pub enum AncillaryData<'a> {
334     ScmRights(ScmRights<'a>),
335     #[cfg(any(doc, target_os = "android", target_os = "linux",))]
336     ScmCredentials(ScmCredentials<'a>),
337 }
338
339 impl<'a> AncillaryData<'a> {
340     /// Create a `AncillaryData::ScmRights` variant.
341     ///
342     /// # Safety
343     ///
344     /// `data` must contain a valid control message and the control message must be type of
345     /// `SOL_SOCKET` and level of `SCM_RIGHTS`.
346     unsafe fn as_rights(data: &'a [u8]) -> Self {
347         let ancillary_data_iter = AncillaryDataIter::new(data);
348         let scm_rights = ScmRights(ancillary_data_iter);
349         AncillaryData::ScmRights(scm_rights)
350     }
351
352     /// Create a `AncillaryData::ScmCredentials` variant.
353     ///
354     /// # Safety
355     ///
356     /// `data` must contain a valid control message and the control message must be type of
357     /// `SOL_SOCKET` and level of `SCM_CREDENTIALS` or `SCM_CREDENTIALS`.
358     #[cfg(any(doc, target_os = "android", target_os = "linux",))]
359     unsafe fn as_credentials(data: &'a [u8]) -> Self {
360         let ancillary_data_iter = AncillaryDataIter::new(data);
361         let scm_credentials = ScmCredentials(ancillary_data_iter);
362         AncillaryData::ScmCredentials(scm_credentials)
363     }
364
365     fn try_from_cmsghdr(cmsg: &'a libc::cmsghdr) -> Result<Self, AncillaryError> {
366         unsafe {
367             cfg_if::cfg_if! {
368                 if #[cfg(any(
369                         target_os = "android",
370                         all(target_os = "linux", target_env = "gnu"),
371                         all(target_os = "linux", target_env = "uclibc"),
372                    ))] {
373                     let cmsg_len_zero = libc::CMSG_LEN(0) as libc::size_t;
374                 } else if #[cfg(any(
375                               target_os = "dragonfly",
376                               target_os = "emscripten",
377                               target_os = "freebsd",
378                               all(target_os = "linux", target_env = "musl",),
379                               target_os = "macos",
380                               target_os = "netbsd",
381                               target_os = "openbsd",
382                           ))] {
383                     let cmsg_len_zero = libc::CMSG_LEN(0) as libc::socklen_t;
384                 }
385             }
386             let data_len = (*cmsg).cmsg_len - cmsg_len_zero;
387             let data = libc::CMSG_DATA(cmsg).cast();
388             let data = from_raw_parts(data, data_len as usize);
389
390             match (*cmsg).cmsg_level {
391                 libc::SOL_SOCKET => match (*cmsg).cmsg_type {
392                     libc::SCM_RIGHTS => Ok(AncillaryData::as_rights(data)),
393                     #[cfg(any(target_os = "android", target_os = "linux",))]
394                     libc::SCM_CREDENTIALS => Ok(AncillaryData::as_credentials(data)),
395                     cmsg_type => {
396                         Err(AncillaryError::Unknown { cmsg_level: libc::SOL_SOCKET, cmsg_type })
397                     }
398                 },
399                 cmsg_level => {
400                     Err(AncillaryError::Unknown { cmsg_level, cmsg_type: (*cmsg).cmsg_type })
401                 }
402             }
403         }
404     }
405 }
406
407 /// This struct is used to iterate through the control messages.
408 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
409 pub struct Messages<'a> {
410     buffer: &'a [u8],
411     current: Option<&'a libc::cmsghdr>,
412 }
413
414 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
415 impl<'a> Iterator for Messages<'a> {
416     type Item = Result<AncillaryData<'a>, AncillaryError>;
417
418     fn next(&mut self) -> Option<Self::Item> {
419         unsafe {
420             let mut msg: libc::msghdr = zeroed();
421             msg.msg_control = self.buffer.as_ptr() as *mut _;
422             cfg_if::cfg_if! {
423                 if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
424                     msg.msg_controllen = self.buffer.len() as libc::size_t;
425                 } else if #[cfg(any(
426                               target_os = "dragonfly",
427                               target_os = "emscripten",
428                               target_os = "freebsd",
429                               all(target_os = "linux", target_env = "musl",),
430                               target_os = "macos",
431                               target_os = "netbsd",
432                               target_os = "openbsd",
433                           ))] {
434                     msg.msg_controllen = self.buffer.len() as libc::socklen_t;
435                 }
436             }
437
438             let cmsg = if let Some(current) = self.current {
439                 libc::CMSG_NXTHDR(&msg, current)
440             } else {
441                 libc::CMSG_FIRSTHDR(&msg)
442             };
443
444             let cmsg = cmsg.as_ref()?;
445
446             // Most operating systems, but not Linux or emscripten, return the previous pointer
447             // when its length is zero. Therefore, check if the previous pointer is the same as
448             // the current one.
449             if let Some(current) = self.current {
450                 if eq(current, cmsg) {
451                     return None;
452                 }
453             }
454
455             self.current = Some(cmsg);
456             let ancillary_result = AncillaryData::try_from_cmsghdr(cmsg);
457             Some(ancillary_result)
458         }
459     }
460 }
461
462 /// A Unix socket Ancillary data struct.
463 ///
464 /// # Example
465 /// ```no_run
466 /// #![feature(unix_socket_ancillary_data)]
467 /// use std::os::unix::net::{UnixStream, SocketAncillary, AncillaryData};
468 /// use std::io::IoSliceMut;
469 ///
470 /// fn main() -> std::io::Result<()> {
471 ///     let sock = UnixStream::connect("/tmp/sock")?;
472 ///
473 ///     let mut fds = [0; 8];
474 ///     let mut ancillary_buffer = [0; 128];
475 ///     let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
476 ///
477 ///     let mut buf = [1; 8];
478 ///     let mut bufs = &mut [IoSliceMut::new(&mut buf[..])][..];
479 ///     sock.recv_vectored_with_ancillary(bufs, &mut ancillary)?;
480 ///
481 ///     for ancillary_result in ancillary.messages() {
482 ///         if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() {
483 ///             for fd in scm_rights {
484 ///                 println!("receive file descriptor: {}", fd);
485 ///             }
486 ///         }
487 ///     }
488 ///     Ok(())
489 /// }
490 /// ```
491 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
492 #[derive(Debug)]
493 pub struct SocketAncillary<'a> {
494     buffer: &'a mut [u8],
495     length: usize,
496     truncated: bool,
497 }
498
499 impl<'a> SocketAncillary<'a> {
500     /// Create an ancillary data with the given buffer.
501     ///
502     /// # Example
503     ///
504     /// ```no_run
505     /// # #![allow(unused_mut)]
506     /// #![feature(unix_socket_ancillary_data)]
507     /// use std::os::unix::net::SocketAncillary;
508     /// let mut ancillary_buffer = [0; 128];
509     /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
510     /// ```
511     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
512     pub fn new(buffer: &'a mut [u8]) -> Self {
513         SocketAncillary { buffer, length: 0, truncated: false }
514     }
515
516     /// Returns the capacity of the buffer.
517     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
518     pub fn capacity(&self) -> usize {
519         self.buffer.len()
520     }
521
522     /// Returns `true` if the ancillary data is empty.
523     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
524     pub fn is_empty(&self) -> bool {
525         self.length == 0
526     }
527
528     /// Returns the number of used bytes.
529     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
530     pub fn len(&self) -> usize {
531         self.length
532     }
533
534     /// Returns the iterator of the control messages.
535     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
536     pub fn messages(&self) -> Messages<'_> {
537         Messages { buffer: &self.buffer[..self.length], current: None }
538     }
539
540     /// Is `true` if during a recv operation the ancillary was truncated.
541     ///
542     /// # Example
543     ///
544     /// ```no_run
545     /// #![feature(unix_socket_ancillary_data)]
546     /// use std::os::unix::net::{UnixStream, SocketAncillary};
547     /// use std::io::IoSliceMut;
548     ///
549     /// fn main() -> std::io::Result<()> {
550     ///     let sock = UnixStream::connect("/tmp/sock")?;
551     ///
552     ///     let mut ancillary_buffer = [0; 128];
553     ///     let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
554     ///
555     ///     let mut buf = [1; 8];
556     ///     let mut bufs = &mut [IoSliceMut::new(&mut buf[..])][..];
557     ///     sock.recv_vectored_with_ancillary(bufs, &mut ancillary)?;
558     ///
559     ///     println!("Is truncated: {}", ancillary.truncated());
560     ///     Ok(())
561     /// }
562     /// ```
563     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
564     pub fn truncated(&self) -> bool {
565         self.truncated
566     }
567
568     /// Add file descriptors to the ancillary data.
569     ///
570     /// The function returns `true` if there was enough space in the buffer.
571     /// If there was not enough space then no file descriptors was appended.
572     /// Technically, that means this operation adds a control message with the level `SOL_SOCKET`
573     /// and type `SCM_RIGHTS`.
574     ///
575     /// # Example
576     ///
577     /// ```no_run
578     /// #![feature(unix_socket_ancillary_data)]
579     /// use std::os::unix::net::{UnixStream, SocketAncillary};
580     /// use std::os::unix::io::AsRawFd;
581     /// use std::io::IoSlice;
582     ///
583     /// fn main() -> std::io::Result<()> {
584     ///     let sock = UnixStream::connect("/tmp/sock")?;
585     ///
586     ///     let mut ancillary_buffer = [0; 128];
587     ///     let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
588     ///     ancillary.add_fds(&[sock.as_raw_fd()][..]);
589     ///
590     ///     let mut buf = [1; 8];
591     ///     let mut bufs = &mut [IoSlice::new(&mut buf[..])][..];
592     ///     sock.send_vectored_with_ancillary(bufs, &mut ancillary)?;
593     ///     Ok(())
594     /// }
595     /// ```
596     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
597     pub fn add_fds(&mut self, fds: &[RawFd]) -> bool {
598         self.truncated = false;
599         add_to_ancillary_data(
600             &mut self.buffer,
601             &mut self.length,
602             fds,
603             libc::SOL_SOCKET,
604             libc::SCM_RIGHTS,
605         )
606     }
607
608     /// Add credentials to the ancillary data.
609     ///
610     /// The function returns `true` if there was enough space in the buffer.
611     /// If there was not enough space then no credentials was appended.
612     /// Technically, that means this operation adds a control message with the level `SOL_SOCKET`
613     /// and type `SCM_CREDENTIALS` or `SCM_CREDS`.
614     ///
615     #[cfg(any(doc, target_os = "android", target_os = "linux",))]
616     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
617     pub fn add_creds(&mut self, creds: &[SocketCred]) -> bool {
618         self.truncated = false;
619         add_to_ancillary_data(
620             &mut self.buffer,
621             &mut self.length,
622             creds,
623             libc::SOL_SOCKET,
624             libc::SCM_CREDENTIALS,
625         )
626     }
627
628     /// Clears the ancillary data, removing all values.
629     ///
630     /// # Example
631     ///
632     /// ```no_run
633     /// #![feature(unix_socket_ancillary_data)]
634     /// use std::os::unix::net::{UnixStream, SocketAncillary, AncillaryData};
635     /// use std::io::IoSliceMut;
636     ///
637     /// fn main() -> std::io::Result<()> {
638     ///     let sock = UnixStream::connect("/tmp/sock")?;
639     ///
640     ///     let mut fds1 = [0; 8];
641     ///     let mut fds2 = [0; 8];
642     ///     let mut ancillary_buffer = [0; 128];
643     ///     let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
644     ///
645     ///     let mut buf = [1; 8];
646     ///     let mut bufs = &mut [IoSliceMut::new(&mut buf[..])][..];
647     ///
648     ///     sock.recv_vectored_with_ancillary(bufs, &mut ancillary)?;
649     ///     for ancillary_result in ancillary.messages() {
650     ///         if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() {
651     ///             for fd in scm_rights {
652     ///                 println!("receive file descriptor: {}", fd);
653     ///             }
654     ///         }
655     ///     }
656     ///
657     ///     ancillary.clear();
658     ///
659     ///     sock.recv_vectored_with_ancillary(bufs, &mut ancillary)?;
660     ///     for ancillary_result in ancillary.messages() {
661     ///         if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() {
662     ///             for fd in scm_rights {
663     ///                 println!("receive file descriptor: {}", fd);
664     ///             }
665     ///         }
666     ///     }
667     ///     Ok(())
668     /// }
669     /// ```
670     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
671     pub fn clear(&mut self) {
672         self.length = 0;
673         self.truncated = false;
674     }
675 }