rustix/net/send_recv/
msg.rs

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