1 //! [`recvmsg`], [`sendmsg`], and related functions.
2 
3 #![allow(unsafe_code)]
4 
5 use crate::backend::{self, c};
6 use crate::fd::{AsFd, BorrowedFd, OwnedFd};
7 use crate::io::{self, IoSlice, IoSliceMut};
8 #[cfg(linux_kernel)]
9 use crate::net::UCred;
10 
11 use core::iter::FusedIterator;
12 use core::marker::PhantomData;
13 use core::mem::{align_of, size_of, size_of_val, take};
14 #[cfg(linux_kernel)]
15 use core::ptr::addr_of;
16 use core::{ptr, slice};
17 
18 use super::{RecvFlags, SendFlags, SocketAddrAny, SocketAddrV4, SocketAddrV6};
19 
20 /// Macro for defining the amount of space to allocate in a buffer for use with
21 /// [`RecvAncillaryBuffer::new`] and [`SendAncillaryBuffer::new`].
22 ///
23 /// # Examples
24 ///
25 /// Allocate a buffer for a single file descriptor:
26 /// ```
27 /// # use rustix::cmsg_space;
28 /// let mut space = [0; rustix::cmsg_space!(ScmRights(1))];
29 /// ```
30 ///
31 /// Allocate a buffer for credentials:
32 /// ```
33 /// # #[cfg(linux_kernel)]
34 /// # {
35 /// # use rustix::cmsg_space;
36 /// let mut space = [0; rustix::cmsg_space!(ScmCredentials(1))];
37 /// # }
38 /// ```
39 ///
40 /// Allocate a buffer for two file descriptors and credentials:
41 /// ```
42 /// # #[cfg(linux_kernel)]
43 /// # {
44 /// # use rustix::cmsg_space;
45 /// let mut space = [0; rustix::cmsg_space!(ScmRights(2), ScmCredentials(1))];
46 /// # }
47 /// ```
48 #[macro_export]
49 macro_rules! cmsg_space {
50     // Base Rules
51     (ScmRights($len:expr)) => {
52         $crate::net::__cmsg_space(
53             $len * ::core::mem::size_of::<$crate::fd::BorrowedFd<'static>>(),
54         )
55     };
56     (ScmCredentials($len:expr)) => {
57         $crate::net::__cmsg_space(
58             $len * ::core::mem::size_of::<$crate::net::UCred>(),
59         )
60     };
61 
62     // Combo Rules
63     ($firstid:ident($firstex:expr), $($restid:ident($restex:expr)),*) => {{
64         // We only have to add `cmsghdr` alignment once; all other times we can
65         // use `cmsg_aligned_space`.
66         let sum = $crate::cmsg_space!($firstid($firstex));
67         $(
68             let sum = sum + $crate::cmsg_aligned_space!($restid($restex));
69         )*
70         sum
71     }};
72 }
73 
74 /// Like `cmsg_space`, but doesn't add padding for `cmsghdr` alignment.
75 #[doc(hidden)]
76 #[macro_export]
77 macro_rules! cmsg_aligned_space {
78     // Base Rules
79     (ScmRights($len:expr)) => {
80         $crate::net::__cmsg_aligned_space(
81             $len * ::core::mem::size_of::<$crate::fd::BorrowedFd<'static>>(),
82         )
83     };
84     (ScmCredentials($len:expr)) => {
85         $crate::net::__cmsg_aligned_space(
86             $len * ::core::mem::size_of::<$crate::net::UCred>(),
87         )
88     };
89 
90     // Combo Rules
91     ($firstid:ident($firstex:expr), $($restid:ident($restex:expr)),*) => {{
92         let sum = cmsg_aligned_space!($firstid($firstex));
93         $(
94             let sum = sum + cmsg_aligned_space!($restid($restex));
95         )*
96         sum
97     }};
98 }
99 
100 #[doc(hidden)]
__cmsg_space(len: usize) -> usize101 pub const fn __cmsg_space(len: usize) -> usize {
102     // Add `align_of::<c::cmsghdr>()` so that we can align the user-provided
103     // `&[u8]` to the required alignment boundary.
104     let len = len + align_of::<c::cmsghdr>();
105 
106     __cmsg_aligned_space(len)
107 }
108 
109 #[doc(hidden)]
__cmsg_aligned_space(len: usize) -> usize110 pub const fn __cmsg_aligned_space(len: usize) -> usize {
111     // Convert `len` to `u32` for `CMSG_SPACE`. This would be `try_into()` if
112     // we could call that in a `const fn`.
113     let converted_len = len as u32;
114     if converted_len as usize != len {
115         unreachable!(); // `CMSG_SPACE` size overflow
116     }
117 
118     unsafe { c::CMSG_SPACE(converted_len) as usize }
119 }
120 
121 /// Ancillary message for [`sendmsg`], [`sendmsg_v4`], [`sendmsg_v6`],
122 /// [`sendmsg_unix`], and [`sendmsg_any`].
123 #[non_exhaustive]
124 pub enum SendAncillaryMessage<'slice, 'fd> {
125     /// Send file descriptors.
126     #[doc(alias = "SCM_RIGHTS")]
127     ScmRights(&'slice [BorrowedFd<'fd>]),
128     /// Send process credentials.
129     #[cfg(linux_kernel)]
130     #[doc(alias = "SCM_CREDENTIAL")]
131     ScmCredentials(UCred),
132 }
133 
134 impl SendAncillaryMessage<'_, '_> {
135     /// Get the maximum size of an ancillary message.
136     ///
137     /// This can be helpful in determining the size of the buffer you allocate.
size(&self) -> usize138     pub const fn size(&self) -> usize {
139         match self {
140             Self::ScmRights(slice) => cmsg_space!(ScmRights(slice.len())),
141             #[cfg(linux_kernel)]
142             Self::ScmCredentials(_) => cmsg_space!(ScmCredentials(1)),
143         }
144     }
145 }
146 
147 /// Ancillary message for [`recvmsg`].
148 #[non_exhaustive]
149 pub enum RecvAncillaryMessage<'a> {
150     /// Received file descriptors.
151     #[doc(alias = "SCM_RIGHTS")]
152     ScmRights(AncillaryIter<'a, OwnedFd>),
153     /// Received process credentials.
154     #[cfg(linux_kernel)]
155     #[doc(alias = "SCM_CREDENTIALS")]
156     ScmCredentials(UCred),
157 }
158 
159 /// Buffer for sending ancillary messages with [`sendmsg`], [`sendmsg_v4`],
160 /// [`sendmsg_v6`], [`sendmsg_unix`], and [`sendmsg_any`].
161 ///
162 /// Use the [`push`] function to add messages to send.
163 ///
164 /// [`push`]: SendAncillaryBuffer::push
165 pub struct SendAncillaryBuffer<'buf, 'slice, 'fd> {
166     /// Raw byte buffer for messages.
167     buffer: &'buf mut [u8],
168 
169     /// The amount of the buffer that is used.
170     length: usize,
171 
172     /// Phantom data for lifetime of `&'slice [BorrowedFd<'fd>]`.
173     _phantom: PhantomData<&'slice [BorrowedFd<'fd>]>,
174 }
175 
176 impl<'buf> From<&'buf mut [u8]> for SendAncillaryBuffer<'buf, '_, '_> {
from(buffer: &'buf mut [u8]) -> Self177     fn from(buffer: &'buf mut [u8]) -> Self {
178         Self::new(buffer)
179     }
180 }
181 
182 impl Default for SendAncillaryBuffer<'_, '_, '_> {
default() -> Self183     fn default() -> Self {
184         Self {
185             buffer: &mut [],
186             length: 0,
187             _phantom: PhantomData,
188         }
189     }
190 }
191 
192 impl<'buf, 'slice, 'fd> SendAncillaryBuffer<'buf, 'slice, 'fd> {
193     /// Create a new, empty `SendAncillaryBuffer` from a raw byte buffer.
194     ///
195     /// The buffer size may be computed with [`cmsg_space`], or it may be
196     /// zero for an empty buffer, however in that case, consider `default()`
197     /// instead, or even using [`send`] instead of `sendmsg`.
198     ///
199     /// # Examples
200     ///
201     /// Allocate a buffer for a single file descriptor:
202     /// ```
203     /// # use rustix::cmsg_space;
204     /// # use rustix::net::SendAncillaryBuffer;
205     /// let mut space = [0; rustix::cmsg_space!(ScmRights(1))];
206     /// let mut cmsg_buffer = SendAncillaryBuffer::new(&mut space);
207     /// ```
208     ///
209     /// Allocate a buffer for credentials:
210     /// ```
211     /// # #[cfg(linux_kernel)]
212     /// # {
213     /// # use rustix::cmsg_space;
214     /// # use rustix::net::SendAncillaryBuffer;
215     /// let mut space = [0; rustix::cmsg_space!(ScmCredentials(1))];
216     /// let mut cmsg_buffer = SendAncillaryBuffer::new(&mut space);
217     /// # }
218     /// ```
219     ///
220     /// Allocate a buffer for two file descriptors and credentials:
221     /// ```
222     /// # #[cfg(linux_kernel)]
223     /// # {
224     /// # use rustix::cmsg_space;
225     /// # use rustix::net::SendAncillaryBuffer;
226     /// let mut space = [0; rustix::cmsg_space!(ScmRights(2), ScmCredentials(1))];
227     /// let mut cmsg_buffer = SendAncillaryBuffer::new(&mut space);
228     /// # }
229     /// ```
230     ///
231     /// [`send`]: crate::net::send
232     #[inline]
new(buffer: &'buf mut [u8]) -> Self233     pub fn new(buffer: &'buf mut [u8]) -> Self {
234         Self {
235             buffer: align_for_cmsghdr(buffer),
236             length: 0,
237             _phantom: PhantomData,
238         }
239     }
240 
241     /// Returns a pointer to the message data.
as_control_ptr(&mut self) -> *mut u8242     pub(crate) fn as_control_ptr(&mut self) -> *mut u8 {
243         // When the length is zero, we may be using a `&[]` address, which may
244         // be an invalid but non-null pointer, and on some platforms, that
245         // causes `sendmsg` to fail with `EFAULT` or `EINVAL`
246         #[cfg(not(linux_kernel))]
247         if self.length == 0 {
248             return core::ptr::null_mut();
249         }
250 
251         self.buffer.as_mut_ptr()
252     }
253 
254     /// Returns the length of the message data.
control_len(&self) -> usize255     pub(crate) fn control_len(&self) -> usize {
256         self.length
257     }
258 
259     /// Delete all messages from the buffer.
clear(&mut self)260     pub fn clear(&mut self) {
261         self.length = 0;
262     }
263 
264     /// Add an ancillary message to the buffer.
265     ///
266     /// Returns `true` if the message was added successfully.
push(&mut self, msg: SendAncillaryMessage<'slice, 'fd>) -> bool267     pub fn push(&mut self, msg: SendAncillaryMessage<'slice, 'fd>) -> bool {
268         match msg {
269             SendAncillaryMessage::ScmRights(fds) => {
270                 let fds_bytes =
271                     unsafe { slice::from_raw_parts(fds.as_ptr().cast::<u8>(), size_of_val(fds)) };
272                 self.push_ancillary(fds_bytes, c::SOL_SOCKET as _, c::SCM_RIGHTS as _)
273             }
274             #[cfg(linux_kernel)]
275             SendAncillaryMessage::ScmCredentials(ucred) => {
276                 let ucred_bytes = unsafe {
277                     slice::from_raw_parts(addr_of!(ucred).cast::<u8>(), size_of_val(&ucred))
278                 };
279                 self.push_ancillary(ucred_bytes, c::SOL_SOCKET as _, c::SCM_CREDENTIALS as _)
280             }
281         }
282     }
283 
284     /// Pushes an ancillary message to the buffer.
push_ancillary(&mut self, source: &[u8], cmsg_level: c::c_int, cmsg_type: c::c_int) -> bool285     fn push_ancillary(&mut self, source: &[u8], cmsg_level: c::c_int, cmsg_type: c::c_int) -> bool {
286         macro_rules! leap {
287             ($e:expr) => {{
288                 match ($e) {
289                     Some(x) => x,
290                     None => return false,
291                 }
292             }};
293         }
294 
295         // Calculate the length of the message.
296         let source_len = leap!(u32::try_from(source.len()).ok());
297 
298         // Calculate the new length of the buffer.
299         let additional_space = unsafe { c::CMSG_SPACE(source_len) };
300         let new_length = leap!(self.length.checked_add(additional_space as usize));
301         let buffer = leap!(self.buffer.get_mut(..new_length));
302 
303         // Fill the new part of the buffer with zeroes.
304         buffer[self.length..new_length].fill(0);
305         self.length = new_length;
306 
307         // Get the last header in the buffer.
308         let last_header = leap!(messages::Messages::new(buffer).last());
309 
310         // Set the header fields.
311         last_header.cmsg_len = unsafe { c::CMSG_LEN(source_len) } as _;
312         last_header.cmsg_level = cmsg_level;
313         last_header.cmsg_type = cmsg_type;
314 
315         // Get the pointer to the payload and copy the data.
316         unsafe {
317             let payload = c::CMSG_DATA(last_header);
318             ptr::copy_nonoverlapping(source.as_ptr(), payload, source_len as _);
319         }
320 
321         true
322     }
323 }
324 
325 impl<'slice, 'fd> Extend<SendAncillaryMessage<'slice, 'fd>>
326     for SendAncillaryBuffer<'_, 'slice, 'fd>
327 {
extend<T: IntoIterator<Item = SendAncillaryMessage<'slice, 'fd>>>(&mut self, iter: T)328     fn extend<T: IntoIterator<Item = SendAncillaryMessage<'slice, 'fd>>>(&mut self, iter: T) {
329         // TODO: This could be optimized to add every message in one go.
330         iter.into_iter().all(|msg| self.push(msg));
331     }
332 }
333 
334 /// Buffer for receiving ancillary messages with [`recvmsg`].
335 ///
336 /// Use the [`drain`] function to iterate over the received messages.
337 ///
338 /// [`drain`]: RecvAncillaryBuffer::drain
339 #[derive(Default)]
340 pub struct RecvAncillaryBuffer<'buf> {
341     /// Raw byte buffer for messages.
342     buffer: &'buf mut [u8],
343 
344     /// The portion of the buffer we've read from already.
345     read: usize,
346 
347     /// The amount of the buffer that is used.
348     length: usize,
349 }
350 
351 impl<'buf> From<&'buf mut [u8]> for RecvAncillaryBuffer<'buf> {
from(buffer: &'buf mut [u8]) -> Self352     fn from(buffer: &'buf mut [u8]) -> Self {
353         Self::new(buffer)
354     }
355 }
356 
357 impl<'buf> RecvAncillaryBuffer<'buf> {
358     /// Create a new, empty `RecvAncillaryBuffer` from a raw byte buffer.
359     ///
360     /// The buffer size may be computed with [`cmsg_space`], or it may be
361     /// zero for an empty buffer, however in that case, consider `default()`
362     /// instead, or even using [`recv`] instead of `recvmsg`.
363     ///
364     /// # Examples
365     ///
366     /// Allocate a buffer for a single file descriptor:
367     /// ```
368     /// # use rustix::cmsg_space;
369     /// # use rustix::net::RecvAncillaryBuffer;
370     /// let mut space = [0; rustix::cmsg_space!(ScmRights(1))];
371     /// let mut cmsg_buffer = RecvAncillaryBuffer::new(&mut space);
372     /// ```
373     ///
374     /// Allocate a buffer for credentials:
375     /// ```
376     /// # #[cfg(linux_kernel)]
377     /// # {
378     /// # use rustix::cmsg_space;
379     /// # use rustix::net::RecvAncillaryBuffer;
380     /// let mut space = [0; rustix::cmsg_space!(ScmCredentials(1))];
381     /// let mut cmsg_buffer = RecvAncillaryBuffer::new(&mut space);
382     /// # }
383     /// ```
384     ///
385     /// Allocate a buffer for two file descriptors and credentials:
386     /// ```
387     /// # #[cfg(linux_kernel)]
388     /// # {
389     /// # use rustix::cmsg_space;
390     /// # use rustix::net::RecvAncillaryBuffer;
391     /// let mut space = [0; rustix::cmsg_space!(ScmRights(2), ScmCredentials(1))];
392     /// let mut cmsg_buffer = RecvAncillaryBuffer::new(&mut space);
393     /// # }
394     /// ```
395     ///
396     /// [`recv`]: crate::net::recv
397     #[inline]
new(buffer: &'buf mut [u8]) -> Self398     pub fn new(buffer: &'buf mut [u8]) -> Self {
399         Self {
400             buffer: align_for_cmsghdr(buffer),
401             read: 0,
402             length: 0,
403         }
404     }
405 
406     /// Returns a pointer to the message data.
as_control_ptr(&mut self) -> *mut u8407     pub(crate) fn as_control_ptr(&mut self) -> *mut u8 {
408         // When the length is zero, we may be using a `&[]` address, which may
409         // be an invalid but non-null pointer, and on some platforms, that
410         // causes `sendmsg` to fail with `EFAULT` or `EINVAL`
411         #[cfg(not(linux_kernel))]
412         if self.buffer.is_empty() {
413             return core::ptr::null_mut();
414         }
415 
416         self.buffer.as_mut_ptr()
417     }
418 
419     /// Returns the length of the message data.
control_len(&self) -> usize420     pub(crate) fn control_len(&self) -> usize {
421         self.buffer.len()
422     }
423 
424     /// Set the length of the message data.
425     ///
426     /// # Safety
427     ///
428     /// The buffer must be filled with valid message data.
set_control_len(&mut self, len: usize)429     pub(crate) unsafe fn set_control_len(&mut self, len: usize) {
430         self.length = len;
431         self.read = 0;
432     }
433 
434     /// Delete all messages from the buffer.
clear(&mut self)435     pub(crate) fn clear(&mut self) {
436         self.drain().for_each(drop);
437     }
438 
439     /// Drain all messages from the buffer.
drain(&mut self) -> AncillaryDrain<'_>440     pub fn drain(&mut self) -> AncillaryDrain<'_> {
441         AncillaryDrain {
442             messages: messages::Messages::new(&mut self.buffer[self.read..][..self.length]),
443             read: &mut self.read,
444             length: &mut self.length,
445         }
446     }
447 }
448 
449 impl Drop for RecvAncillaryBuffer<'_> {
drop(&mut self)450     fn drop(&mut self) {
451         self.clear();
452     }
453 }
454 
455 /// Return a slice of `buffer` starting at the first `cmsghdr` alignment
456 /// boundary.
457 #[inline]
align_for_cmsghdr(buffer: &mut [u8]) -> &mut [u8]458 fn align_for_cmsghdr(buffer: &mut [u8]) -> &mut [u8] {
459     // If the buffer is empty, we won't be writing anything into it, so it
460     // doesn't need to be aligned.
461     if buffer.is_empty() {
462         return buffer;
463     }
464 
465     let align = align_of::<c::cmsghdr>();
466     let addr = buffer.as_ptr() as usize;
467     let adjusted = (addr + (align - 1)) & align.wrapping_neg();
468     &mut buffer[adjusted - addr..]
469 }
470 
471 /// An iterator that drains messages from a [`RecvAncillaryBuffer`].
472 pub struct AncillaryDrain<'buf> {
473     /// Inner iterator over messages.
474     messages: messages::Messages<'buf>,
475 
476     /// Increment the number of messages we've read.
477     read: &'buf mut usize,
478 
479     /// Decrement the total length.
480     length: &'buf mut usize,
481 }
482 
483 impl<'buf> AncillaryDrain<'buf> {
484     /// A closure that converts a message into a [`RecvAncillaryMessage`].
cvt_msg( read: &mut usize, length: &mut usize, msg: &c::cmsghdr, ) -> Option<RecvAncillaryMessage<'buf>>485     fn cvt_msg(
486         read: &mut usize,
487         length: &mut usize,
488         msg: &c::cmsghdr,
489     ) -> Option<RecvAncillaryMessage<'buf>> {
490         unsafe {
491             // Advance the `read` pointer.
492             let msg_len = msg.cmsg_len as usize;
493             *read += msg_len;
494             *length -= msg_len;
495 
496             // Get a pointer to the payload.
497             let payload = c::CMSG_DATA(msg);
498             let payload_len = msg.cmsg_len as usize - c::CMSG_LEN(0) as usize;
499 
500             // Get a mutable slice of the payload.
501             let payload: &'buf mut [u8] = slice::from_raw_parts_mut(payload, payload_len);
502 
503             // Determine what type it is.
504             let (level, msg_type) = (msg.cmsg_level, msg.cmsg_type);
505             match (level as _, msg_type as _) {
506                 (c::SOL_SOCKET, c::SCM_RIGHTS) => {
507                     // Create an iterator that reads out the file descriptors.
508                     let fds = AncillaryIter::new(payload);
509 
510                     Some(RecvAncillaryMessage::ScmRights(fds))
511                 }
512                 #[cfg(linux_kernel)]
513                 (c::SOL_SOCKET, c::SCM_CREDENTIALS) => {
514                     if payload_len >= size_of::<UCred>() {
515                         let ucred = payload.as_ptr().cast::<UCred>().read_unaligned();
516                         Some(RecvAncillaryMessage::ScmCredentials(ucred))
517                     } else {
518                         None
519                     }
520                 }
521                 _ => None,
522             }
523         }
524     }
525 }
526 
527 impl<'buf> Iterator for AncillaryDrain<'buf> {
528     type Item = RecvAncillaryMessage<'buf>;
529 
next(&mut self) -> Option<Self::Item>530     fn next(&mut self) -> Option<Self::Item> {
531         let read = &mut self.read;
532         let length = &mut self.length;
533         self.messages.find_map(|ev| Self::cvt_msg(read, length, ev))
534     }
535 
size_hint(&self) -> (usize, Option<usize>)536     fn size_hint(&self) -> (usize, Option<usize>) {
537         let (_, max) = self.messages.size_hint();
538         (0, max)
539     }
540 
fold<B, F>(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B,541     fn fold<B, F>(self, init: B, f: F) -> B
542     where
543         Self: Sized,
544         F: FnMut(B, Self::Item) -> B,
545     {
546         let read = self.read;
547         let length = self.length;
548         self.messages
549             .filter_map(|ev| Self::cvt_msg(read, length, ev))
550             .fold(init, f)
551     }
552 
count(self) -> usize553     fn count(self) -> usize {
554         let read = self.read;
555         let length = self.length;
556         self.messages
557             .filter_map(|ev| Self::cvt_msg(read, length, ev))
558             .count()
559     }
560 
last(self) -> Option<Self::Item> where Self: Sized,561     fn last(self) -> Option<Self::Item>
562     where
563         Self: Sized,
564     {
565         let read = self.read;
566         let length = self.length;
567         self.messages
568             .filter_map(|ev| Self::cvt_msg(read, length, ev))
569             .last()
570     }
571 
collect<B: FromIterator<Self::Item>>(self) -> B where Self: Sized,572     fn collect<B: FromIterator<Self::Item>>(self) -> B
573     where
574         Self: Sized,
575     {
576         let read = self.read;
577         let length = self.length;
578         self.messages
579             .filter_map(|ev| Self::cvt_msg(read, length, ev))
580             .collect()
581     }
582 }
583 
584 impl FusedIterator for AncillaryDrain<'_> {}
585 
586 /// `sendmsg(msghdr)`—Sends a message on a socket.
587 ///
588 /// # References
589 ///  - [POSIX]
590 ///  - [Linux]
591 ///  - [Apple]
592 ///  - [FreeBSD]
593 ///  - [NetBSD]
594 ///  - [OpenBSD]
595 ///  - [DragonFly BSD]
596 ///  - [illumos]
597 ///
598 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html
599 /// [Linux]: https://man7.org/linux/man-pages/man2/sendmsg.2.html
600 /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendmsg.2.html
601 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendmsg&sektion=2
602 /// [NetBSD]: https://man.netbsd.org/sendmsg.2
603 /// [OpenBSD]: https://man.openbsd.org/sendmsg.2
604 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendmsg&section=2
605 /// [illumos]: https://illumos.org/man/3SOCKET/sendmsg
606 #[inline]
sendmsg( socket: impl AsFd, iov: &[IoSlice<'_>], control: &mut SendAncillaryBuffer<'_, '_, '_>, flags: SendFlags, ) -> io::Result<usize>607 pub fn sendmsg(
608     socket: impl AsFd,
609     iov: &[IoSlice<'_>],
610     control: &mut SendAncillaryBuffer<'_, '_, '_>,
611     flags: SendFlags,
612 ) -> io::Result<usize> {
613     backend::net::syscalls::sendmsg(socket.as_fd(), iov, control, flags)
614 }
615 
616 /// `sendmsg(msghdr)`—Sends a message on a socket to a specific IPv4 address.
617 ///
618 /// # References
619 ///  - [POSIX]
620 ///  - [Linux]
621 ///  - [Apple]
622 ///  - [FreeBSD]
623 ///  - [NetBSD]
624 ///  - [OpenBSD]
625 ///  - [DragonFly BSD]
626 ///  - [illumos]
627 ///
628 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html
629 /// [Linux]: https://man7.org/linux/man-pages/man2/sendmsg.2.html
630 /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendmsg.2.html
631 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendmsg&sektion=2
632 /// [NetBSD]: https://man.netbsd.org/sendmsg.2
633 /// [OpenBSD]: https://man.openbsd.org/sendmsg.2
634 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendmsg&section=2
635 /// [illumos]: https://illumos.org/man/3SOCKET/sendmsg
636 #[inline]
sendmsg_v4( socket: impl AsFd, addr: &SocketAddrV4, iov: &[IoSlice<'_>], control: &mut SendAncillaryBuffer<'_, '_, '_>, flags: SendFlags, ) -> io::Result<usize>637 pub fn sendmsg_v4(
638     socket: impl AsFd,
639     addr: &SocketAddrV4,
640     iov: &[IoSlice<'_>],
641     control: &mut SendAncillaryBuffer<'_, '_, '_>,
642     flags: SendFlags,
643 ) -> io::Result<usize> {
644     backend::net::syscalls::sendmsg_v4(socket.as_fd(), addr, iov, control, flags)
645 }
646 
647 /// `sendmsg(msghdr)`—Sends a message on a socket to a specific IPv6 address.
648 ///
649 /// # References
650 ///  - [POSIX]
651 ///  - [Linux]
652 ///  - [Apple]
653 ///  - [FreeBSD]
654 ///  - [NetBSD]
655 ///  - [OpenBSD]
656 ///  - [DragonFly BSD]
657 ///  - [illumos]
658 ///
659 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html
660 /// [Linux]: https://man7.org/linux/man-pages/man2/sendmsg.2.html
661 /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendmsg.2.html
662 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendmsg&sektion=2
663 /// [NetBSD]: https://man.netbsd.org/sendmsg.2
664 /// [OpenBSD]: https://man.openbsd.org/sendmsg.2
665 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendmsg&section=2
666 /// [illumos]: https://illumos.org/man/3SOCKET/sendmsg
667 #[inline]
sendmsg_v6( socket: impl AsFd, addr: &SocketAddrV6, iov: &[IoSlice<'_>], control: &mut SendAncillaryBuffer<'_, '_, '_>, flags: SendFlags, ) -> io::Result<usize>668 pub fn sendmsg_v6(
669     socket: impl AsFd,
670     addr: &SocketAddrV6,
671     iov: &[IoSlice<'_>],
672     control: &mut SendAncillaryBuffer<'_, '_, '_>,
673     flags: SendFlags,
674 ) -> io::Result<usize> {
675     backend::net::syscalls::sendmsg_v6(socket.as_fd(), addr, iov, control, flags)
676 }
677 
678 /// `sendmsg(msghdr)`—Sends a message on a socket to a specific Unix-domain
679 /// address.
680 ///
681 /// # References
682 ///  - [POSIX]
683 ///  - [Linux]
684 ///  - [Apple]
685 ///  - [FreeBSD]
686 ///  - [NetBSD]
687 ///  - [OpenBSD]
688 ///  - [DragonFly BSD]
689 ///  - [illumos]
690 ///
691 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html
692 /// [Linux]: https://man7.org/linux/man-pages/man2/sendmsg.2.html
693 /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendmsg.2.html
694 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendmsg&sektion=2
695 /// [NetBSD]: https://man.netbsd.org/sendmsg.2
696 /// [OpenBSD]: https://man.openbsd.org/sendmsg.2
697 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendmsg&section=2
698 /// [illumos]: https://illumos.org/man/3SOCKET/sendmsg
699 #[inline]
700 #[cfg(unix)]
sendmsg_unix( socket: impl AsFd, addr: &super::SocketAddrUnix, iov: &[IoSlice<'_>], control: &mut SendAncillaryBuffer<'_, '_, '_>, flags: SendFlags, ) -> io::Result<usize>701 pub fn sendmsg_unix(
702     socket: impl AsFd,
703     addr: &super::SocketAddrUnix,
704     iov: &[IoSlice<'_>],
705     control: &mut SendAncillaryBuffer<'_, '_, '_>,
706     flags: SendFlags,
707 ) -> io::Result<usize> {
708     backend::net::syscalls::sendmsg_unix(socket.as_fd(), addr, iov, control, flags)
709 }
710 
711 /// `sendmsg(msghdr)`—Sends a message on a socket to a specific XDP address.
712 ///
713 /// # References
714 ///  - [Linux]
715 ///
716 /// [Linux]: https://man7.org/linux/man-pages/man2/sendmsg.2.html
717 #[inline]
718 #[cfg(target_os = "linux")]
sendmsg_xdp( socket: impl AsFd, addr: &super::SocketAddrXdp, iov: &[IoSlice<'_>], control: &mut SendAncillaryBuffer<'_, '_, '_>, flags: SendFlags, ) -> io::Result<usize>719 pub fn sendmsg_xdp(
720     socket: impl AsFd,
721     addr: &super::SocketAddrXdp,
722     iov: &[IoSlice<'_>],
723     control: &mut SendAncillaryBuffer<'_, '_, '_>,
724     flags: SendFlags,
725 ) -> io::Result<usize> {
726     backend::net::syscalls::sendmsg_xdp(socket.as_fd(), addr, iov, control, flags)
727 }
728 
729 /// `sendmsg(msghdr)`—Sends a message on a socket to a specific address.
730 ///
731 /// # References
732 ///  - [POSIX]
733 ///  - [Linux]
734 ///  - [Apple]
735 ///  - [FreeBSD]
736 ///  - [NetBSD]
737 ///  - [OpenBSD]
738 ///  - [DragonFly BSD]
739 ///  - [illumos]
740 ///
741 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html
742 /// [Linux]: https://man7.org/linux/man-pages/man2/sendmsg.2.html
743 /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendmsg.2.html
744 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendmsg&sektion=2
745 /// [NetBSD]: https://man.netbsd.org/sendmsg.2
746 /// [OpenBSD]: https://man.openbsd.org/sendmsg.2
747 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendmsg&section=2
748 /// [illumos]: https://illumos.org/man/3SOCKET/sendmsg
749 #[inline]
sendmsg_any( socket: impl AsFd, addr: Option<&SocketAddrAny>, iov: &[IoSlice<'_>], control: &mut SendAncillaryBuffer<'_, '_, '_>, flags: SendFlags, ) -> io::Result<usize>750 pub fn sendmsg_any(
751     socket: impl AsFd,
752     addr: Option<&SocketAddrAny>,
753     iov: &[IoSlice<'_>],
754     control: &mut SendAncillaryBuffer<'_, '_, '_>,
755     flags: SendFlags,
756 ) -> io::Result<usize> {
757     match addr {
758         None => backend::net::syscalls::sendmsg(socket.as_fd(), iov, control, flags),
759         Some(SocketAddrAny::V4(addr)) => {
760             backend::net::syscalls::sendmsg_v4(socket.as_fd(), addr, iov, control, flags)
761         }
762         Some(SocketAddrAny::V6(addr)) => {
763             backend::net::syscalls::sendmsg_v6(socket.as_fd(), addr, iov, control, flags)
764         }
765         #[cfg(unix)]
766         Some(SocketAddrAny::Unix(addr)) => {
767             backend::net::syscalls::sendmsg_unix(socket.as_fd(), addr, iov, control, flags)
768         }
769         #[cfg(target_os = "linux")]
770         Some(SocketAddrAny::Xdp(addr)) => {
771             backend::net::syscalls::sendmsg_xdp(socket.as_fd(), addr, iov, control, flags)
772         }
773     }
774 }
775 
776 /// `recvmsg(msghdr)`—Receives a message from a socket.
777 ///
778 /// # References
779 ///  - [POSIX]
780 ///  - [Linux]
781 ///  - [Apple]
782 ///  - [FreeBSD]
783 ///  - [NetBSD]
784 ///  - [OpenBSD]
785 ///  - [DragonFly BSD]
786 ///  - [illumos]
787 ///
788 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html
789 /// [Linux]: https://man7.org/linux/man-pages/man2/recvmsg.2.html
790 /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/recvmsg.2.html
791 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=recvmsg&sektion=2
792 /// [NetBSD]: https://man.netbsd.org/recvmsg.2
793 /// [OpenBSD]: https://man.openbsd.org/recvmsg.2
794 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=recvmsg&section=2
795 /// [illumos]: https://illumos.org/man/3SOCKET/recvmsg
796 #[inline]
recvmsg( socket: impl AsFd, iov: &mut [IoSliceMut<'_>], control: &mut RecvAncillaryBuffer<'_>, flags: RecvFlags, ) -> io::Result<RecvMsgReturn>797 pub fn recvmsg(
798     socket: impl AsFd,
799     iov: &mut [IoSliceMut<'_>],
800     control: &mut RecvAncillaryBuffer<'_>,
801     flags: RecvFlags,
802 ) -> io::Result<RecvMsgReturn> {
803     backend::net::syscalls::recvmsg(socket.as_fd(), iov, control, flags)
804 }
805 
806 /// The result of a successful [`recvmsg`] call.
807 pub struct RecvMsgReturn {
808     /// The number of bytes received.
809     pub bytes: usize,
810 
811     /// The flags received.
812     pub flags: RecvFlags,
813 
814     /// The address of the socket we received from, if any.
815     pub address: Option<SocketAddrAny>,
816 }
817 
818 /// An iterator over data in an ancillary buffer.
819 pub struct AncillaryIter<'data, T> {
820     /// The data we're iterating over.
821     data: &'data mut [u8],
822 
823     /// The raw data we're removing.
824     _marker: PhantomData<T>,
825 }
826 
827 impl<'data, T> AncillaryIter<'data, T> {
828     /// Create a new iterator over data in an ancillary buffer.
829     ///
830     /// # Safety
831     ///
832     /// The buffer must contain valid ancillary data.
new(data: &'data mut [u8]) -> Self833     unsafe fn new(data: &'data mut [u8]) -> Self {
834         assert_eq!(data.len() % size_of::<T>(), 0);
835 
836         Self {
837             data,
838             _marker: PhantomData,
839         }
840     }
841 }
842 
843 impl<'data, T> Drop for AncillaryIter<'data, T> {
drop(&mut self)844     fn drop(&mut self) {
845         self.for_each(drop);
846     }
847 }
848 
849 impl<T> Iterator for AncillaryIter<'_, T> {
850     type Item = T;
851 
next(&mut self) -> Option<Self::Item>852     fn next(&mut self) -> Option<Self::Item> {
853         // See if there is a next item.
854         if self.data.len() < size_of::<T>() {
855             return None;
856         }
857 
858         // Get the next item.
859         let item = unsafe { self.data.as_ptr().cast::<T>().read_unaligned() };
860 
861         // Move forward.
862         let data = take(&mut self.data);
863         self.data = &mut data[size_of::<T>()..];
864 
865         Some(item)
866     }
867 
size_hint(&self) -> (usize, Option<usize>)868     fn size_hint(&self) -> (usize, Option<usize>) {
869         let len = self.len();
870         (len, Some(len))
871     }
872 
count(self) -> usize873     fn count(self) -> usize {
874         self.len()
875     }
876 
last(mut self) -> Option<Self::Item>877     fn last(mut self) -> Option<Self::Item> {
878         self.next_back()
879     }
880 }
881 
882 impl<T> FusedIterator for AncillaryIter<'_, T> {}
883 
884 impl<T> ExactSizeIterator for AncillaryIter<'_, T> {
len(&self) -> usize885     fn len(&self) -> usize {
886         self.data.len() / size_of::<T>()
887     }
888 }
889 
890 impl<T> DoubleEndedIterator for AncillaryIter<'_, T> {
next_back(&mut self) -> Option<Self::Item>891     fn next_back(&mut self) -> Option<Self::Item> {
892         // See if there is a next item.
893         if self.data.len() < size_of::<T>() {
894             return None;
895         }
896 
897         // Get the next item.
898         let item = unsafe {
899             let ptr = self.data.as_ptr().add(self.data.len() - size_of::<T>());
900             ptr.cast::<T>().read_unaligned()
901         };
902 
903         // Move forward.
904         let len = self.data.len();
905         let data = take(&mut self.data);
906         self.data = &mut data[..len - size_of::<T>()];
907 
908         Some(item)
909     }
910 }
911 
912 mod messages {
913     use crate::backend::c;
914     use crate::backend::net::msghdr;
915     use core::iter::FusedIterator;
916     use core::marker::PhantomData;
917     use core::ptr::NonNull;
918 
919     /// An iterator over the messages in an ancillary buffer.
920     pub(super) struct Messages<'buf> {
921         /// The message header we're using to iterate over the messages.
922         msghdr: c::msghdr,
923 
924         /// The current pointer to the next message header to return.
925         ///
926         /// This has a lifetime of `'buf`.
927         header: Option<NonNull<c::cmsghdr>>,
928 
929         /// Capture the original lifetime of the buffer.
930         _buffer: PhantomData<&'buf mut [u8]>,
931     }
932 
933     impl<'buf> Messages<'buf> {
934         /// Create a new iterator over messages from a byte buffer.
new(buf: &'buf mut [u8]) -> Self935         pub(super) fn new(buf: &'buf mut [u8]) -> Self {
936             let msghdr = {
937                 let mut h = msghdr::zero_msghdr();
938                 h.msg_control = buf.as_mut_ptr().cast();
939                 h.msg_controllen = buf.len().try_into().expect("buffer too large for msghdr");
940                 h
941             };
942 
943             // Get the first header.
944             let header = NonNull::new(unsafe { c::CMSG_FIRSTHDR(&msghdr) });
945 
946             Self {
947                 msghdr,
948                 header,
949                 _buffer: PhantomData,
950             }
951         }
952     }
953 
954     impl<'a> Iterator for Messages<'a> {
955         type Item = &'a mut c::cmsghdr;
956 
957         #[inline]
next(&mut self) -> Option<Self::Item>958         fn next(&mut self) -> Option<Self::Item> {
959             // Get the current header.
960             let header = self.header?;
961 
962             // Get the next header.
963             self.header = NonNull::new(unsafe { c::CMSG_NXTHDR(&self.msghdr, header.as_ptr()) });
964 
965             // If the headers are equal, we're done.
966             if Some(header) == self.header {
967                 self.header = None;
968             }
969 
970             // SAFETY: The lifetime of `header` is tied to this.
971             Some(unsafe { &mut *header.as_ptr() })
972         }
973 
size_hint(&self) -> (usize, Option<usize>)974         fn size_hint(&self) -> (usize, Option<usize>) {
975             if self.header.is_some() {
976                 // The remaining buffer *could* be filled with zero-length
977                 // messages.
978                 let max_size = unsafe { c::CMSG_LEN(0) } as usize;
979                 let remaining_count = self.msghdr.msg_controllen as usize / max_size;
980                 (1, Some(remaining_count))
981             } else {
982                 (0, Some(0))
983             }
984         }
985     }
986 
987     impl FusedIterator for Messages<'_> {}
988 }
989