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