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§ion=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§ion=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§ion=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}