rustix/net/send_recv/
msg.rs

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