nix/sys/socket/
mod.rs

1//! Socket interface functions
2//!
3//! [Further reading](https://man7.org/linux/man-pages/man7/socket.7.html)
4#[cfg(any(target_os = "freebsd", linux_android))]
5#[cfg(feature = "uio")]
6use crate::sys::time::TimeSpec;
7#[cfg(not(target_os = "redox"))]
8#[cfg(feature = "uio")]
9use crate::sys::time::TimeVal;
10use crate::{errno::Errno, Result};
11use cfg_if::cfg_if;
12use libc::{self, c_int, size_t, socklen_t};
13#[cfg(all(feature = "uio", not(target_os = "redox")))]
14use libc::{
15    c_void, iovec, CMSG_DATA, CMSG_FIRSTHDR, CMSG_LEN, CMSG_NXTHDR, CMSG_SPACE,
16    MSG_CTRUNC,
17};
18#[cfg(not(target_os = "redox"))]
19use std::io::{IoSlice, IoSliceMut};
20#[cfg(feature = "net")]
21use std::net;
22use std::os::unix::io::{AsFd, AsRawFd, FromRawFd, OwnedFd, RawFd};
23use std::{mem, ptr};
24
25#[deny(missing_docs)]
26mod addr;
27#[deny(missing_docs)]
28pub mod sockopt;
29
30/*
31 *
32 * ===== Re-exports =====
33 *
34 */
35
36pub use self::addr::{SockaddrLike, SockaddrStorage};
37
38#[cfg(solarish)]
39pub use self::addr::{AddressFamily, UnixAddr};
40#[cfg(not(solarish))]
41pub use self::addr::{AddressFamily, UnixAddr};
42#[cfg(not(any(
43    solarish,
44    target_os = "haiku",
45    target_os = "hurd",
46    target_os = "redox",
47    target_os = "cygwin",
48)))]
49#[cfg(feature = "net")]
50pub use self::addr::{LinkAddr, SockaddrIn, SockaddrIn6};
51#[cfg(any(
52    solarish,
53    target_os = "haiku",
54    target_os = "hurd",
55    target_os = "redox",
56    target_os = "cygwin",
57))]
58#[cfg(feature = "net")]
59pub use self::addr::{SockaddrIn, SockaddrIn6};
60
61#[cfg(linux_android)]
62pub use crate::sys::socket::addr::alg::AlgAddr;
63#[cfg(linux_android)]
64pub use crate::sys::socket::addr::netlink::NetlinkAddr;
65#[cfg(apple_targets)]
66#[cfg(feature = "ioctl")]
67pub use crate::sys::socket::addr::sys_control::SysControlAddr;
68#[cfg(any(linux_android, apple_targets))]
69pub use crate::sys::socket::addr::vsock::VsockAddr;
70
71#[cfg(all(feature = "uio", not(target_os = "redox")))]
72pub use libc::{cmsghdr, msghdr};
73pub use libc::{sa_family_t, sockaddr, sockaddr_storage, sockaddr_un};
74#[cfg(feature = "net")]
75pub use libc::{sockaddr_in, sockaddr_in6};
76
77#[cfg(feature = "net")]
78use crate::sys::socket::addr::{ipv4addr_to_libc, ipv6addr_to_libc};
79
80/// These constants are used to specify the communication semantics
81/// when creating a socket with [`socket()`](fn.socket.html)
82#[derive(Clone, Copy, PartialEq, Eq, Debug)]
83#[repr(i32)]
84#[non_exhaustive]
85pub enum SockType {
86    /// Provides sequenced, reliable, two-way, connection-
87    /// based byte streams.  An out-of-band data transmission
88    /// mechanism may be supported.
89    Stream = libc::SOCK_STREAM,
90    /// Supports datagrams (connectionless, unreliable
91    /// messages of a fixed maximum length).
92    Datagram = libc::SOCK_DGRAM,
93    /// Provides a sequenced, reliable, two-way connection-
94    /// based data transmission path for datagrams of fixed
95    /// maximum length; a consumer is required to read an
96    /// entire packet with each input system call.
97    SeqPacket = libc::SOCK_SEQPACKET,
98    /// Provides raw network protocol access.
99    #[cfg(not(target_os = "redox"))]
100    Raw = libc::SOCK_RAW,
101    /// Provides a reliable datagram layer that does not
102    /// guarantee ordering.
103    #[cfg(not(any(target_os = "haiku", target_os = "redox")))]
104    Rdm = libc::SOCK_RDM,
105}
106// The TryFrom impl could've been derived using libc_enum!.  But for
107// backwards-compatibility with Nix-0.25.0 we manually implement it, so as to
108// keep the old variant names.
109impl TryFrom<i32> for SockType {
110    type Error = crate::Error;
111
112    fn try_from(x: i32) -> Result<Self> {
113        match x {
114            libc::SOCK_STREAM => Ok(Self::Stream),
115            libc::SOCK_DGRAM => Ok(Self::Datagram),
116            libc::SOCK_SEQPACKET => Ok(Self::SeqPacket),
117            #[cfg(not(target_os = "redox"))]
118            libc::SOCK_RAW => Ok(Self::Raw),
119            #[cfg(not(any(target_os = "haiku", target_os = "redox")))]
120            libc::SOCK_RDM => Ok(Self::Rdm),
121            _ => Err(Errno::EINVAL),
122        }
123    }
124}
125
126/// Constants used in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
127/// to specify the protocol to use.
128#[repr(i32)]
129#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
130#[non_exhaustive]
131pub enum SockProtocol {
132    /// TCP protocol ([ip(7)](https://man7.org/linux/man-pages/man7/ip.7.html))
133    Tcp = libc::IPPROTO_TCP,
134    /// UDP protocol ([ip(7)](https://man7.org/linux/man-pages/man7/ip.7.html))
135    Udp = libc::IPPROTO_UDP,
136    /// Raw sockets ([raw(7)](https://man7.org/linux/man-pages/man7/raw.7.html))
137    Raw = libc::IPPROTO_RAW,
138    /// Allows applications to configure and control a KEXT
139    /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
140    #[cfg(apple_targets)]
141    KextControl = libc::SYSPROTO_CONTROL,
142    /// Receives routing and link updates and may be used to modify the routing tables (both IPv4 and IPv6), IP addresses, link
143    // parameters, neighbor setups, queueing disciplines, traffic classes and packet classifiers
144    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
145    #[cfg(linux_android)]
146    NetlinkRoute = libc::NETLINK_ROUTE,
147    /// Reserved for user-mode socket protocols
148    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
149    #[cfg(linux_android)]
150    NetlinkUserSock = libc::NETLINK_USERSOCK,
151    /// Query information about sockets of various protocol families from the kernel
152    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
153    #[cfg(linux_android)]
154    NetlinkSockDiag = libc::NETLINK_SOCK_DIAG,
155    /// Netfilter/iptables ULOG.
156    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
157    #[cfg(linux_android)]
158    NetlinkNFLOG = libc::NETLINK_NFLOG,
159    /// SELinux event notifications.
160    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
161    #[cfg(linux_android)]
162    NetlinkSELinux = libc::NETLINK_SELINUX,
163    /// Open-iSCSI
164    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
165    #[cfg(linux_android)]
166    NetlinkISCSI = libc::NETLINK_ISCSI,
167    /// Auditing
168    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
169    #[cfg(linux_android)]
170    NetlinkAudit = libc::NETLINK_AUDIT,
171    /// Access to FIB lookup from user space
172    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
173    #[cfg(linux_android)]
174    NetlinkFIBLookup = libc::NETLINK_FIB_LOOKUP,
175    /// Netfilter subsystem
176    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
177    #[cfg(linux_android)]
178    NetlinkNetFilter = libc::NETLINK_NETFILTER,
179    /// SCSI Transports
180    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
181    #[cfg(linux_android)]
182    NetlinkSCSITransport = libc::NETLINK_SCSITRANSPORT,
183    /// Infiniband RDMA
184    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
185    #[cfg(linux_android)]
186    NetlinkRDMA = libc::NETLINK_RDMA,
187    /// Transport IPv6 packets from netfilter to user space.  Used by ip6_queue kernel module.
188    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
189    #[cfg(linux_android)]
190    NetlinkIPv6Firewall = libc::NETLINK_IP6_FW,
191    /// DECnet routing messages
192    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
193    #[cfg(linux_android)]
194    NetlinkDECNetRoutingMessage = libc::NETLINK_DNRTMSG,
195    /// Kernel messages to user space
196    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
197    #[cfg(linux_android)]
198    NetlinkKObjectUEvent = libc::NETLINK_KOBJECT_UEVENT,
199    /// Generic netlink family for simplified netlink usage.
200    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
201    #[cfg(linux_android)]
202    NetlinkGeneric = libc::NETLINK_GENERIC,
203    /// Netlink interface to request information about ciphers registered with the kernel crypto API as well as allow
204    /// configuration of the kernel crypto API.
205    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
206    #[cfg(linux_android)]
207    NetlinkCrypto = libc::NETLINK_CRYPTO,
208    /// Non-DIX type protocol number defined for the Ethernet IEEE 802.3 interface that allows packets of all protocols
209    /// defined in the interface to be received.
210    /// ([ref](https://man7.org/linux/man-pages/man7/packet.7.html))
211    // The protocol number is fed into the socket syscall in network byte order.
212    #[cfg(linux_android)]
213    EthAll = (libc::ETH_P_ALL as u16).to_be() as i32,
214    #[cfg(linux_android)]
215    /// Packet filter on loopback traffic
216    EthLoop = (libc::ETH_P_LOOP as u16).to_be() as i32,
217    /// Packet filter on IPv4 traffic
218    #[cfg(linux_android)]
219    #[cfg(target_endian = "big")]
220    EthIp = libc::ETH_P_IP,
221    /// Packet filter on IPv6 traffic
222    #[cfg(linux_android)]
223    EthIpv6 = (libc::ETH_P_IPV6 as u16).to_be() as i32,
224    /// ICMP protocol ([icmp(7)](https://man7.org/linux/man-pages/man7/icmp.7.html))
225    Icmp = libc::IPPROTO_ICMP,
226    /// ICMPv6 protocol (ICMP over IPv6)
227    IcmpV6 = libc::IPPROTO_ICMPV6,
228    /// SCTP ([sctp(7)](https://man7.org/linux/man-pages/man7/sctp.7.html))
229    #[cfg(any(
230        apple_targets,
231        linux_android,
232        target_os = "freebsd",
233        target_os = "netbsd"
234    ))]
235    Sctp = libc::IPPROTO_SCTP,
236}
237
238impl SockProtocol {
239    /// The Controller Area Network raw socket protocol
240    /// ([ref](https://docs.kernel.org/networking/can.html#how-to-use-socketcan))
241    #[cfg(target_os = "linux")]
242    #[allow(non_upper_case_globals)]
243    pub const CanRaw: SockProtocol = SockProtocol::Icmp; // Matches libc::CAN_RAW
244
245    /// The Controller Area Network broadcast manager protocol
246    /// ([ref](https://docs.kernel.org/networking/can.html#how-to-use-socketcan))
247    #[cfg(target_os = "linux")]
248    #[allow(non_upper_case_globals)]
249    pub const CanBcm: SockProtocol = SockProtocol::NetlinkUserSock; // Matches libc::CAN_BCM
250
251    /// Allows applications and other KEXTs to be notified when certain kernel events occur
252    /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
253    #[cfg(apple_targets)]
254    #[allow(non_upper_case_globals)]
255    pub const KextEvent: SockProtocol = SockProtocol::Icmp; // Matches libc::SYSPROTO_EVENT
256
257    /// Packet filter on IPv4 traffic
258    // NOTE: placed here due to conflict (little endian arch) with SockProtocol::NetLinkISCI
259    #[cfg(linux_android)]
260    #[allow(non_upper_case_globals)]
261    #[cfg(target_endian = "little")]
262    pub const EthIp: SockProtocol = unsafe { std::mem::transmute::<i32, SockProtocol>((libc::ETH_P_IP as u16).to_be() as i32) };
263
264}
265#[cfg(linux_android)]
266libc_bitflags! {
267    /// Configuration flags for `SO_TIMESTAMPING` interface
268    ///
269    /// For use with [`Timestamping`][sockopt::Timestamping].
270    /// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
271    pub struct TimestampingFlag: libc::c_uint {
272        /// Report any software timestamps when available.
273        SOF_TIMESTAMPING_SOFTWARE;
274        /// Report hardware timestamps as generated by SOF_TIMESTAMPING_TX_HARDWARE when available.
275        SOF_TIMESTAMPING_RAW_HARDWARE;
276        /// Collect transmitting timestamps as reported by hardware
277        SOF_TIMESTAMPING_TX_HARDWARE;
278        /// Collect transmitting timestamps as reported by software
279        SOF_TIMESTAMPING_TX_SOFTWARE;
280        /// Collect receiving timestamps as reported by hardware
281        SOF_TIMESTAMPING_RX_HARDWARE;
282        /// Collect receiving timestamps as reported by software
283        SOF_TIMESTAMPING_RX_SOFTWARE;
284        /// Generate a unique identifier along with each transmitted packet
285        SOF_TIMESTAMPING_OPT_ID;
286        /// Return transmit timestamps alongside an empty packet instead of the original packet
287        SOF_TIMESTAMPING_OPT_TSONLY;
288    }
289}
290
291libc_bitflags! {
292    /// Additional socket options
293    pub struct SockFlag: c_int {
294        /// Set non-blocking mode on the new socket
295        #[cfg(any(linux_android,
296                  freebsdlike,
297                  netbsdlike,
298                  solarish))]
299        SOCK_NONBLOCK;
300        /// Set close-on-exec on the new descriptor
301        #[cfg(any(linux_android,
302                  freebsdlike,
303                  netbsdlike,
304                  solarish))]
305        SOCK_CLOEXEC;
306        /// Return `EPIPE` instead of raising `SIGPIPE`
307        #[cfg(target_os = "netbsd")]
308        SOCK_NOSIGPIPE;
309        /// For domains `AF_INET(6)`, only allow `connect(2)`, `sendto(2)`, or `sendmsg(2)`
310        /// to the DNS port (typically 53)
311        #[cfg(target_os = "openbsd")]
312        SOCK_DNS;
313    }
314}
315
316libc_bitflags! {
317    /// Flags for send/recv and their relatives
318    pub struct MsgFlags: c_int {
319        /// Sends or requests out-of-band data on sockets that support this notion
320        /// (e.g., of type [`Stream`](enum.SockType.html)); the underlying protocol must also
321        /// support out-of-band data.
322        MSG_OOB;
323        /// Peeks at an incoming message. The data is treated as unread and the next
324        /// [`recv()`](fn.recv.html)
325        /// or similar function shall still return this data.
326        MSG_PEEK;
327        /// Receive operation blocks until the full amount of data can be
328        /// returned. The function may return smaller amount of data if a signal
329        /// is caught, an error or disconnect occurs.
330        MSG_WAITALL;
331        /// Enables nonblocking operation; if the operation would block,
332        /// `EAGAIN` or `EWOULDBLOCK` is returned.  This provides similar
333        /// behavior to setting the `O_NONBLOCK` flag
334        /// (via the [`fcntl`](../../fcntl/fn.fcntl.html)
335        /// `F_SETFL` operation), but differs in that `MSG_DONTWAIT` is a per-
336        /// call option, whereas `O_NONBLOCK` is a setting on the open file
337        /// description (see [open(2)](https://man7.org/linux/man-pages/man2/open.2.html)),
338        /// which will affect all threads in
339        /// the calling process and as well as other processes that hold
340        /// file descriptors referring to the same open file description.
341        #[cfg(not(target_os = "aix"))]
342        MSG_DONTWAIT;
343        /// Receive flags: Control Data was discarded (buffer too small)
344        MSG_CTRUNC;
345        /// For raw ([`Packet`](addr/enum.AddressFamily.html)), Internet datagram
346        /// (since Linux 2.4.27/2.6.8),
347        /// netlink (since Linux 2.6.22) and UNIX datagram (since Linux 3.4)
348        /// sockets: return the real length of the packet or datagram, even
349        /// when it was longer than the passed buffer. Not implemented for UNIX
350        /// domain ([unix(7)](https://linux.die.net/man/7/unix)) sockets.
351        ///
352        /// For use with Internet stream sockets, see [tcp(7)](https://linux.die.net/man/7/tcp).
353        MSG_TRUNC;
354        /// Terminates a record (when this notion is supported, as for
355        /// sockets of type [`SeqPacket`](enum.SockType.html)).
356        MSG_EOR;
357        /// This flag specifies that queued errors should be received from
358        /// the socket error queue. (For more details, see
359        /// [recvfrom(2)](https://linux.die.net/man/2/recvfrom))
360        #[cfg(linux_android)]
361        MSG_ERRQUEUE;
362        /// Set the `close-on-exec` flag for the file descriptor received via a UNIX domain
363        /// file descriptor using the `SCM_RIGHTS` operation (described in
364        /// [unix(7)](https://linux.die.net/man/7/unix)).
365        /// This flag is useful for the same reasons as the `O_CLOEXEC` flag of
366        /// [open(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html).
367        ///
368        /// Only used in [`recvmsg`](fn.recvmsg.html) function.
369        #[cfg(any(linux_android, freebsdlike, netbsdlike))]
370        MSG_CMSG_CLOEXEC;
371        /// Requests not to send `SIGPIPE` errors when the other end breaks the connection.
372        /// (For more details, see [send(2)](https://linux.die.net/man/2/send)).
373        #[cfg(any(linux_android,
374                  freebsdlike,
375                  solarish,
376                  netbsdlike,
377                  target_os = "fuchsia",
378                  target_os = "haiku"))]
379        MSG_NOSIGNAL;
380        /// Turns on [`MSG_DONTWAIT`] after the first message has been received (only for
381        /// `recvmmsg()`).
382        #[cfg(any(linux_android,
383                  netbsdlike,
384                  target_os = "fuchsia",
385                  target_os = "freebsd"))]
386        MSG_WAITFORONE;
387        /// Indicates that this message is not a user message but an SCTP notification.
388        #[cfg(target_os = "linux")]
389        MSG_NOTIFICATION;
390    }
391}
392
393#[cfg(target_os = "freebsd")]
394libc_enum! {
395    /// A selector for which clock to use when generating packet timestamps.
396    /// Used when setting [`TsClock`](crate::sys::socket::sockopt::TsClock) on a socket.
397    /// (For more details, see [setsockopt(2)](https://man.freebsd.org/cgi/man.cgi?setsockopt)).
398    #[repr(i32)]
399    #[non_exhaustive]
400    pub enum SocketTimestamp {
401        /// Microsecond resolution, realtime. This is the default.
402        SO_TS_REALTIME_MICRO,
403        /// Sub-nanosecond resolution, realtime.
404        SO_TS_BINTIME,
405        /// Nanosecond resolution, realtime.
406        SO_TS_REALTIME,
407        /// Nanosecond resolution, monotonic.
408        SO_TS_MONOTONIC,
409    }
410}
411
412cfg_if! {
413    if #[cfg(linux_android)] {
414        /// Unix credentials of the sending process.
415        ///
416        /// This struct is used with the `SO_PEERCRED` ancillary message
417        /// and the `SCM_CREDENTIALS` control message for UNIX sockets.
418        #[repr(transparent)]
419        #[derive(Clone, Copy, Debug, Eq, PartialEq)]
420        pub struct UnixCredentials(libc::ucred);
421
422        impl UnixCredentials {
423            /// Creates a new instance with the credentials of the current process
424            pub fn new() -> Self {
425                // Safe because these FFI functions are inherently safe
426                unsafe {
427                    UnixCredentials(libc::ucred {
428                        pid: libc::getpid(),
429                        uid: libc::getuid(),
430                        gid: libc::getgid()
431                    })
432                }
433            }
434
435            /// Returns the process identifier
436            pub fn pid(&self) -> libc::pid_t {
437                self.0.pid
438            }
439
440            /// Returns the user identifier
441            pub fn uid(&self) -> libc::uid_t {
442                self.0.uid
443            }
444
445            /// Returns the group identifier
446            pub fn gid(&self) -> libc::gid_t {
447                self.0.gid
448            }
449        }
450
451        impl Default for UnixCredentials {
452            fn default() -> Self {
453                Self::new()
454            }
455        }
456
457        impl From<libc::ucred> for UnixCredentials {
458            fn from(cred: libc::ucred) -> Self {
459                UnixCredentials(cred)
460            }
461        }
462
463        impl From<UnixCredentials> for libc::ucred {
464            fn from(uc: UnixCredentials) -> Self {
465                uc.0
466            }
467        }
468    } else if #[cfg(freebsdlike)] {
469        /// Unix credentials of the sending process.
470        ///
471        /// This struct is used with the `SCM_CREDS` ancillary message for UNIX sockets.
472        #[repr(transparent)]
473        #[derive(Clone, Copy, Debug, Eq, PartialEq)]
474        pub struct UnixCredentials(libc::cmsgcred);
475
476        impl UnixCredentials {
477            /// Returns the process identifier
478            pub fn pid(&self) -> libc::pid_t {
479                self.0.cmcred_pid
480            }
481
482            /// Returns the real user identifier
483            pub fn uid(&self) -> libc::uid_t {
484                self.0.cmcred_uid
485            }
486
487            /// Returns the effective user identifier
488            pub fn euid(&self) -> libc::uid_t {
489                self.0.cmcred_euid
490            }
491
492            /// Returns the real group identifier
493            pub fn gid(&self) -> libc::gid_t {
494                self.0.cmcred_gid
495            }
496
497            /// Returns a list group identifiers (the first one being the effective GID)
498            pub fn groups(&self) -> &[libc::gid_t] {
499                unsafe {
500                    std::slice::from_raw_parts(
501                        self.0.cmcred_groups.as_ptr(),
502                        self.0.cmcred_ngroups as _
503                    )
504                }
505            }
506        }
507
508        impl From<libc::cmsgcred> for UnixCredentials {
509            fn from(cred: libc::cmsgcred) -> Self {
510                UnixCredentials(cred)
511            }
512        }
513    }
514}
515
516cfg_if! {
517    if #[cfg(any(freebsdlike, apple_targets))] {
518        /// Return type of [`LocalPeerCred`](crate::sys::socket::sockopt::LocalPeerCred)
519        #[repr(transparent)]
520        #[derive(Clone, Copy, Debug, Eq, PartialEq)]
521        pub struct XuCred(libc::xucred);
522
523        impl XuCred {
524            /// Structure layout version
525            pub fn version(&self) -> u32 {
526                self.0.cr_version
527            }
528
529            /// Effective user ID
530            pub fn uid(&self) -> libc::uid_t {
531                self.0.cr_uid
532            }
533
534            /// Returns a list of group identifiers (the first one being the
535            /// effective GID)
536            pub fn groups(&self) -> &[libc::gid_t] {
537                &self.0.cr_groups
538            }
539        }
540    }
541}
542
543cfg_if! {
544    if #[cfg(apple_targets)] {
545        use std::fmt;
546
547        /// Return type of [`LocalPeerToken`].
548        ///
549        /// The audit token is an opaque token which identifies Mach tasks and
550        /// senders of Mach messages as subjects to the BSM audit system. Only
551        /// the appropriate BSM library routines should be used to interpret
552        /// the contents of the audit token as the representation of the
553        /// subject identity within the token may change over time.
554        ///
555        /// Starting with macOS 11, almost all audit functions have been
556        /// deprecated (see the system header `bsm/libbsm.h`), do not use them
557        /// if your program target more recent versions of macOS.
558        ///
559        /// [`LocalPeerToken`]: crate::sys::socket::sockopt::LocalPeerToken
560        #[repr(C)]
561        #[derive(Default, Copy, Clone, PartialEq, Eq, Hash)]
562        pub struct audit_token_t {
563            /// Value of the token.
564            ///
565            /// This is considered an opaque value, do not rely on its format.
566            pub val: [libc::c_uint; 8],
567        }
568
569        // Make the debug representation a hex string to make it shorter and clearer.
570        impl fmt::Debug for audit_token_t {
571            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
572                f.debug_tuple("audit_token_t")
573                    .field(&format!("0x{:08X}", self))
574                    .finish()
575            }
576        }
577
578        impl fmt::LowerHex for audit_token_t {
579            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
580                for v in self.val {
581                    fmt::LowerHex::fmt(&v, f)?;
582                }
583
584                Ok(())
585            }
586        }
587
588        impl fmt::UpperHex for audit_token_t {
589            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
590                for v in self.val {
591                    fmt::UpperHex::fmt(&v, f)?;
592                }
593
594                Ok(())
595            }
596        }
597    }
598}
599
600feature! {
601#![feature = "net"]
602/// Request for multicast socket operations
603///
604/// This is a wrapper type around `ip_mreq`.
605#[repr(transparent)]
606#[derive(Clone, Copy, Debug, Eq, PartialEq)]
607pub struct IpMembershipRequest(libc::ip_mreq);
608
609impl IpMembershipRequest {
610    /// Instantiate a new `IpMembershipRequest`
611    ///
612    /// If `interface` is `None`, then `Ipv4Addr::any()` will be used for the interface.
613    pub fn new(group: net::Ipv4Addr, interface: Option<net::Ipv4Addr>)
614        -> Self
615    {
616        let imr_addr = match interface {
617            None => net::Ipv4Addr::UNSPECIFIED,
618            Some(addr) => addr
619        };
620        IpMembershipRequest(libc::ip_mreq {
621            imr_multiaddr: ipv4addr_to_libc(group),
622            imr_interface: ipv4addr_to_libc(imr_addr)
623        })
624    }
625}
626
627/// Request for ipv6 multicast socket operations
628///
629/// This is a wrapper type around `ipv6_mreq`.
630#[repr(transparent)]
631#[derive(Clone, Copy, Debug, Eq, PartialEq)]
632pub struct Ipv6MembershipRequest(libc::ipv6_mreq);
633
634impl Ipv6MembershipRequest {
635    /// Instantiate a new `Ipv6MembershipRequest`
636    pub const fn new(group: net::Ipv6Addr) -> Self {
637        Ipv6MembershipRequest(libc::ipv6_mreq {
638            ipv6mr_multiaddr: ipv6addr_to_libc(&group),
639            ipv6mr_interface: 0,
640        })
641    }
642}
643}
644
645#[cfg(not(target_os = "redox"))]
646feature! {
647#![feature = "uio"]
648
649/// Create a buffer large enough for storing some control messages as returned
650/// by [`recvmsg`](fn.recvmsg.html).
651///
652/// # Examples
653///
654/// ```
655/// # #[macro_use] extern crate nix;
656/// # use nix::sys::time::TimeVal;
657/// # use std::os::unix::io::RawFd;
658/// # fn main() {
659/// // Create a buffer for a `ControlMessageOwned::ScmTimestamp` message
660/// let _ = cmsg_space!(TimeVal);
661/// // Create a buffer big enough for a `ControlMessageOwned::ScmRights` message
662/// // with two file descriptors
663/// let _ = cmsg_space!([RawFd; 2]);
664/// // Create a buffer big enough for a `ControlMessageOwned::ScmRights` message
665/// // and a `ControlMessageOwned::ScmTimestamp` message
666/// let _ = cmsg_space!(RawFd, TimeVal);
667/// # }
668/// ```
669#[macro_export]
670macro_rules! cmsg_space {
671    ( $( $x:ty ),* ) => {
672        {
673            let space = 0 $(+ $crate::sys::socket::cmsg_space::<$x>())*;
674            vec![0u8; space]
675        }
676    }
677}
678
679#[inline]
680#[doc(hidden)]
681pub const fn cmsg_space<T>() -> usize {
682    // SAFETY: CMSG_SPACE is always safe
683    unsafe { libc::CMSG_SPACE(mem::size_of::<T>() as libc::c_uint) as usize }
684}
685
686#[derive(Clone, Copy, Debug, Eq, PartialEq)]
687/// Contains outcome of sending or receiving a message
688///
689/// Use [`cmsgs`][RecvMsg::cmsgs] to access all the control messages present, and
690/// [`iovs`][RecvMsg::iovs`] to access underlying io slices.
691pub struct RecvMsg<'a, 's, S> {
692    pub bytes: usize,
693    cmsghdr: Option<&'a cmsghdr>,
694    pub address: Option<S>,
695    pub flags: MsgFlags,
696    iobufs: std::marker::PhantomData<& 's()>,
697    mhdr: msghdr,
698}
699
700impl<S> RecvMsg<'_, '_, S> {
701    /// Iterate over the valid control messages pointed to by this msghdr. If
702    /// allocated space for CMSGs was too small it is not safe to iterate,
703    /// instead return an `Error::ENOBUFS` error.
704    pub fn cmsgs(&self) -> Result<CmsgIterator> {
705
706        if self.mhdr.msg_flags & MSG_CTRUNC == MSG_CTRUNC {
707            return Err(Errno::ENOBUFS);
708        }
709
710        Ok(CmsgIterator {
711            cmsghdr: self.cmsghdr,
712            mhdr: &self.mhdr
713        })
714    }
715}
716
717#[derive(Clone, Copy, Debug, Eq, PartialEq)]
718pub struct CmsgIterator<'a> {
719    /// Control message buffer to decode from. Must adhere to cmsg alignment.
720    cmsghdr: Option<&'a cmsghdr>,
721    mhdr: &'a msghdr
722}
723
724impl Iterator for CmsgIterator<'_> {
725    type Item = ControlMessageOwned;
726
727    fn next(&mut self) -> Option<ControlMessageOwned> {
728        match self.cmsghdr {
729            None => None,   // No more messages
730            Some(hdr) => {
731                // Get the data.
732                // Safe if cmsghdr points to valid data returned by recvmsg(2)
733                let cm = unsafe { Some(ControlMessageOwned::decode_from(hdr))};
734                // Advance the internal pointer.  Safe if mhdr and cmsghdr point
735                // to valid data returned by recvmsg(2)
736                self.cmsghdr = unsafe {
737                    let p = CMSG_NXTHDR(self.mhdr as *const _, hdr as *const _);
738                    p.as_ref()
739                };
740                cm
741            }
742        }
743    }
744}
745
746/// A type-safe wrapper around a single control message, as used with
747/// [`recvmsg`].
748///
749/// [Further reading](https://man7.org/linux/man-pages/man3/cmsg.3.html)
750//  Nix version 0.13.0 and earlier used ControlMessage for both recvmsg and
751//  sendmsg.  However, on some platforms the messages returned by recvmsg may be
752//  unaligned.  ControlMessageOwned takes those messages by copy, obviating any
753//  alignment issues.
754//
755//  See https://github.com/nix-rust/nix/issues/999
756#[derive(Clone, Debug, Eq, PartialEq)]
757#[non_exhaustive]
758pub enum ControlMessageOwned {
759    /// Received version of [`ControlMessage::ScmRights`]
760    ScmRights(Vec<RawFd>),
761    /// Received version of [`ControlMessage::ScmCredentials`]
762    #[cfg(linux_android)]
763    ScmCredentials(UnixCredentials),
764    /// Received version of [`ControlMessage::ScmCreds`]
765    #[cfg(freebsdlike)]
766    ScmCreds(UnixCredentials),
767    /// A message of type `SCM_TIMESTAMP`, containing the time the
768    /// packet was received by the kernel.
769    ///
770    /// See the kernel's explanation in "SO_TIMESTAMP" of
771    /// [networking/timestamping](https://www.kernel.org/doc/Documentation/networking/timestamping.txt).
772    ///
773    /// # Examples
774    ///
775    /// ```
776    /// # #[macro_use] extern crate nix;
777    /// # use nix::sys::socket::*;
778    /// # use nix::sys::time::*;
779    /// # use std::io::{IoSlice, IoSliceMut};
780    /// # use std::time::*;
781    /// # use std::str::FromStr;
782    /// # use std::os::unix::io::AsRawFd;
783    /// # fn main() {
784    /// // Set up
785    /// let message = "Ohayō!".as_bytes();
786    /// let in_socket = socket(
787    ///     AddressFamily::Inet,
788    ///     SockType::Datagram,
789    ///     SockFlag::empty(),
790    ///     None).unwrap();
791    /// setsockopt(&in_socket, sockopt::ReceiveTimestamp, &true).unwrap();
792    /// let localhost = SockaddrIn::from_str("127.0.0.1:0").unwrap();
793    /// bind(in_socket.as_raw_fd(), &localhost).unwrap();
794    /// let address: SockaddrIn = getsockname(in_socket.as_raw_fd()).unwrap();
795    /// // Get initial time
796    /// let time0 = SystemTime::now();
797    /// // Send the message
798    /// let iov = [IoSlice::new(message)];
799    /// let flags = MsgFlags::empty();
800    /// let l = sendmsg(in_socket.as_raw_fd(), &iov, &[], flags, Some(&address)).unwrap();
801    /// assert_eq!(message.len(), l);
802    /// // Receive the message
803    /// let mut buffer = vec![0u8; message.len()];
804    /// let mut cmsgspace = cmsg_space!(TimeVal);
805    /// let mut iov = [IoSliceMut::new(&mut buffer)];
806    /// let r = recvmsg::<SockaddrIn>(in_socket.as_raw_fd(), &mut iov, Some(&mut cmsgspace), flags)
807    ///     .unwrap();
808    /// let rtime = match r.cmsgs().unwrap().next() {
809    ///     Some(ControlMessageOwned::ScmTimestamp(rtime)) => rtime,
810    ///     Some(_) => panic!("Unexpected control message"),
811    ///     None => panic!("No control message")
812    /// };
813    /// // Check the final time
814    /// let time1 = SystemTime::now();
815    /// // the packet's received timestamp should lie in-between the two system
816    /// // times, unless the system clock was adjusted in the meantime.
817    /// let rduration = Duration::new(rtime.tv_sec() as u64,
818    ///                               rtime.tv_usec() as u32 * 1000);
819    /// assert!(time0.duration_since(UNIX_EPOCH).unwrap() <= rduration);
820    /// assert!(rduration <= time1.duration_since(UNIX_EPOCH).unwrap());
821    /// // Close socket
822    /// # }
823    /// ```
824    ScmTimestamp(TimeVal),
825    /// A set of nanosecond resolution timestamps
826    ///
827    /// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
828    #[cfg(linux_android)]
829    ScmTimestampsns(Timestamps),
830    /// Nanoseconds resolution timestamp
831    ///
832    /// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
833    #[cfg(linux_android)]
834    ScmTimestampns(TimeSpec),
835    /// Realtime clock timestamp
836    ///
837    /// [Further reading](https://man.freebsd.org/cgi/man.cgi?setsockopt)
838    #[cfg(target_os = "freebsd")]
839    ScmRealtime(TimeSpec),
840    /// Monotonic clock timestamp
841    ///
842    /// [Further reading](https://man.freebsd.org/cgi/man.cgi?setsockopt)
843    #[cfg(target_os = "freebsd")]
844    ScmMonotonic(TimeSpec),
845    #[cfg(any(linux_android, apple_targets, target_os = "netbsd"))]
846    #[cfg(feature = "net")]
847    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
848    Ipv4PacketInfo(libc::in_pktinfo),
849    #[cfg(any(linux_android, bsd))]
850    #[cfg(feature = "net")]
851    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
852    Ipv6PacketInfo(libc::in6_pktinfo),
853    #[cfg(bsd)]
854    #[cfg(feature = "net")]
855    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
856    Ipv4RecvIf(libc::sockaddr_dl),
857    #[cfg(bsd)]
858    #[cfg(feature = "net")]
859    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
860    Ipv4RecvDstAddr(libc::in_addr),
861    #[cfg(any(linux_android, target_os = "freebsd"))]
862    #[cfg(feature = "net")]
863    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
864    Ipv4OrigDstAddr(libc::sockaddr_in),
865    #[cfg(any(linux_android, target_os = "freebsd"))]
866    #[cfg(feature = "net")]
867    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
868    Ipv6OrigDstAddr(libc::sockaddr_in6),
869
870    /// Time-to-Live (TTL) header field of the incoming IPv4 packet.
871    ///
872    /// [Further reading](https://www.man7.org/linux/man-pages/man7/ip.7.html)
873    #[cfg(linux_android)]
874    #[cfg(feature = "net")]
875    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
876    Ipv4Ttl(i32),
877
878    /// Time-to-Live (TTL) header field of the incoming IPv4 packet.
879    ///
880    /// [Further reading](https://datatracker.ietf.org/doc/html/rfc3542.html)
881    #[cfg(target_os = "freebsd")]
882    #[cfg(feature = "net")]
883    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
884    Ipv4Ttl(u8),
885
886    /// Hop Limit header field of the incoming IPv6 packet.
887    ///
888    /// [Further reading for Linux](https://www.man7.org/linux/man-pages/man7/ip.7.html)
889    /// [Further reading for FreeBSD](https://datatracker.ietf.org/doc/html/rfc3542.html)
890    #[cfg(any(linux_android, target_os = "freebsd"))]
891    #[cfg(feature = "net")]
892    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
893    Ipv6HopLimit(i32),
894
895    /// Retrieve the DSCP (ToS) header field of the incoming IPv4 packet.
896    #[cfg(any(linux_android, target_os = "freebsd"))]
897    #[cfg(feature = "net")]
898    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
899    Ipv4Tos(u8),
900
901    /// Retrieve the DSCP (Traffic Class) header field of the incoming IPv6 packet.
902    #[cfg(any(linux_android, target_os = "freebsd"))]
903    #[cfg(feature = "net")]
904    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
905    Ipv6TClass(i32),
906
907    /// UDP Generic Receive Offload (GRO) allows receiving multiple UDP
908    /// packets from a single sender.
909    /// Fixed-size payloads are following one by one in a receive buffer.
910    /// This Control Message indicates the size of all smaller packets,
911    /// except, maybe, the last one.
912    ///
913    /// `UdpGroSegment` socket option should be enabled on a socket
914    /// to allow receiving GRO packets.
915    #[cfg(target_os = "linux")]
916    #[cfg(feature = "net")]
917    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
918    UdpGroSegments(i32),
919
920    /// SO_RXQ_OVFL indicates that an unsigned 32 bit value
921    /// ancilliary msg (cmsg) should be attached to recieved
922    /// skbs indicating the number of packets dropped by the
923    /// socket between the last recieved packet and this
924    /// received packet.
925    ///
926    /// `RxqOvfl` socket option should be enabled on a socket
927    /// to allow receiving the drop counter.
928    #[cfg(any(linux_android, target_os = "fuchsia"))]
929    RxqOvfl(u32),
930
931    /// Socket error queue control messages read with the `MSG_ERRQUEUE` flag.
932    #[cfg(linux_android)]
933    #[cfg(feature = "net")]
934    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
935    Ipv4RecvErr(libc::sock_extended_err, Option<sockaddr_in>),
936    /// Socket error queue control messages read with the `MSG_ERRQUEUE` flag.
937    #[cfg(linux_android)]
938    #[cfg(feature = "net")]
939    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
940    Ipv6RecvErr(libc::sock_extended_err, Option<sockaddr_in6>),
941
942    /// `SOL_TLS` messages of type `TLS_GET_RECORD_TYPE`
943    #[cfg(any(target_os = "linux"))]
944    TlsGetRecordType(TlsGetRecordType),
945
946    /// Catch-all variant for unimplemented cmsg types.
947    Unknown(UnknownCmsg),
948}
949
950/// For representing packet timestamps via `SO_TIMESTAMPING` interface
951#[cfg(linux_android)]
952#[derive(Copy, Clone, Debug, Eq, PartialEq)]
953pub struct Timestamps {
954    /// software based timestamp, usually one containing data
955    pub system: TimeSpec,
956    /// legacy timestamp, usually empty
957    pub hw_trans: TimeSpec,
958    /// hardware based timestamp
959    pub hw_raw: TimeSpec,
960}
961
962/// These constants correspond to TLS 1.2 message types, as defined in
963/// RFC 5246, Appendix A.1
964#[cfg(any(target_os = "linux"))]
965#[derive(Clone, Copy, PartialEq, Eq, Debug)]
966#[repr(u8)]
967#[non_exhaustive]
968pub enum TlsGetRecordType {
969    ChangeCipherSpec ,
970    Alert,
971    Handshake,
972    ApplicationData,
973    Unknown(u8),
974}
975
976#[cfg(any(target_os = "linux"))]
977impl From<u8> for TlsGetRecordType {
978    fn from(x: u8) -> Self {
979        match x {
980            20 => TlsGetRecordType::ChangeCipherSpec,
981            21 => TlsGetRecordType::Alert,
982            22 => TlsGetRecordType::Handshake,
983            23 => TlsGetRecordType::ApplicationData,
984            _ => TlsGetRecordType::Unknown(x),
985        }
986    }
987}
988
989impl ControlMessageOwned {
990    /// Decodes a `ControlMessageOwned` from raw bytes.
991    ///
992    /// This is only safe to call if the data is correct for the message type
993    /// specified in the header. Normally, the kernel ensures that this is the
994    /// case. "Correct" in this case includes correct length, alignment and
995    /// actual content.
996    // Clippy complains about the pointer alignment of `p`, not understanding
997    // that it's being fed to a function that can handle that.
998    #[allow(clippy::cast_ptr_alignment)]
999    unsafe fn decode_from(header: &cmsghdr) -> ControlMessageOwned
1000    {
1001        let p = unsafe { CMSG_DATA(header) };
1002        // The cast is not unnecessary on all platforms.
1003        #[allow(clippy::unnecessary_cast)]
1004        let len = header as *const _ as usize + header.cmsg_len as usize
1005            - p as usize;
1006        match (header.cmsg_level, header.cmsg_type) {
1007            (libc::SOL_SOCKET, libc::SCM_RIGHTS) => {
1008                let n = len / mem::size_of::<RawFd>();
1009                let mut fds = Vec::with_capacity(n);
1010                for i in 0..n {
1011                    unsafe {
1012                        let fdp = (p as *const RawFd).add(i);
1013                        fds.push(ptr::read_unaligned(fdp));
1014                    }
1015                }
1016                ControlMessageOwned::ScmRights(fds)
1017            },
1018            #[cfg(linux_android)]
1019            (libc::SOL_SOCKET, libc::SCM_CREDENTIALS) => {
1020                let cred: libc::ucred = unsafe { ptr::read_unaligned(p as *const _) };
1021                ControlMessageOwned::ScmCredentials(cred.into())
1022            }
1023            #[cfg(freebsdlike)]
1024            (libc::SOL_SOCKET, libc::SCM_CREDS) => {
1025                let cred: libc::cmsgcred = unsafe { ptr::read_unaligned(p as *const _) };
1026                ControlMessageOwned::ScmCreds(cred.into())
1027            }
1028            #[cfg(not(any(target_os = "aix", target_os = "haiku", target_os = "cygwin")))]
1029            (libc::SOL_SOCKET, libc::SCM_TIMESTAMP) => {
1030                let tv: libc::timeval = unsafe { ptr::read_unaligned(p as *const _) };
1031                ControlMessageOwned::ScmTimestamp(TimeVal::from(tv))
1032            },
1033            #[cfg(linux_android)]
1034            (libc::SOL_SOCKET, libc::SCM_TIMESTAMPNS) => {
1035                let ts: libc::timespec = unsafe { ptr::read_unaligned(p as *const _) };
1036                ControlMessageOwned::ScmTimestampns(TimeSpec::from(ts))
1037            }
1038            #[cfg(target_os = "freebsd")]
1039            (libc::SOL_SOCKET, libc::SCM_REALTIME) => {
1040                let ts: libc::timespec = unsafe { ptr::read_unaligned(p as *const _) };
1041                ControlMessageOwned::ScmRealtime(TimeSpec::from(ts))
1042            }
1043            #[cfg(target_os = "freebsd")]
1044            (libc::SOL_SOCKET, libc::SCM_MONOTONIC) => {
1045                let ts: libc::timespec = unsafe { ptr::read_unaligned(p as *const _) };
1046                ControlMessageOwned::ScmMonotonic(TimeSpec::from(ts))
1047            }
1048            #[cfg(linux_android)]
1049            (libc::SOL_SOCKET, libc::SCM_TIMESTAMPING) => {
1050                let tp = p as *const libc::timespec;
1051                let ts: libc::timespec = unsafe { ptr::read_unaligned(tp) };
1052                let system = TimeSpec::from(ts);
1053                let ts: libc::timespec = unsafe { ptr::read_unaligned(tp.add(1)) };
1054                let hw_trans = TimeSpec::from(ts);
1055                let ts: libc::timespec = unsafe { ptr::read_unaligned(tp.add(2)) };
1056                let hw_raw = TimeSpec::from(ts);
1057                let timestamping = Timestamps { system, hw_trans, hw_raw };
1058                ControlMessageOwned::ScmTimestampsns(timestamping)
1059            }
1060            #[cfg(any(target_os = "freebsd", linux_android, apple_targets))]
1061            #[cfg(feature = "net")]
1062            (libc::IPPROTO_IPV6, libc::IPV6_PKTINFO) => {
1063                let info = unsafe { ptr::read_unaligned(p as *const libc::in6_pktinfo) };
1064                ControlMessageOwned::Ipv6PacketInfo(info)
1065            }
1066            #[cfg(any(linux_android, apple_targets, target_os = "netbsd"))]
1067            #[cfg(feature = "net")]
1068            (libc::IPPROTO_IP, libc::IP_PKTINFO) => {
1069                let info = unsafe { ptr::read_unaligned(p as *const libc::in_pktinfo) };
1070                ControlMessageOwned::Ipv4PacketInfo(info)
1071            }
1072            #[cfg(bsd)]
1073            #[cfg(feature = "net")]
1074            (libc::IPPROTO_IP, libc::IP_RECVIF) => {
1075                let dl = unsafe { ptr::read_unaligned(p as *const libc::sockaddr_dl) };
1076                ControlMessageOwned::Ipv4RecvIf(dl)
1077            },
1078            #[cfg(bsd)]
1079            #[cfg(feature = "net")]
1080            (libc::IPPROTO_IP, libc::IP_RECVDSTADDR) => {
1081                let dl = unsafe { ptr::read_unaligned(p as *const libc::in_addr) };
1082                ControlMessageOwned::Ipv4RecvDstAddr(dl)
1083            },
1084            #[cfg(any(linux_android, target_os = "freebsd"))]
1085            #[cfg(feature = "net")]
1086            (libc::IPPROTO_IP, libc::IP_ORIGDSTADDR) => {
1087                let dl = unsafe { ptr::read_unaligned(p as *const libc::sockaddr_in) };
1088                ControlMessageOwned::Ipv4OrigDstAddr(dl)
1089            },
1090            #[cfg(target_os = "linux")]
1091            #[cfg(feature = "net")]
1092            (libc::SOL_UDP, libc::UDP_GRO) => {
1093                let gso_size: i32 = unsafe { ptr::read_unaligned(p as *const _) };
1094                ControlMessageOwned::UdpGroSegments(gso_size)
1095            },
1096            #[cfg(any(linux_android, target_os = "fuchsia"))]
1097            (libc::SOL_SOCKET, libc::SO_RXQ_OVFL) => {
1098                let drop_counter = unsafe { ptr::read_unaligned(p as *const u32) };
1099                ControlMessageOwned::RxqOvfl(drop_counter)
1100            },
1101            #[cfg(linux_android)]
1102            #[cfg(feature = "net")]
1103            (libc::IPPROTO_IP, libc::IP_RECVERR) => {
1104                let (err, addr) = unsafe { Self::recv_err_helper::<sockaddr_in>(p, len) };
1105                ControlMessageOwned::Ipv4RecvErr(err, addr)
1106            },
1107            #[cfg(linux_android)]
1108            #[cfg(feature = "net")]
1109            (libc::IPPROTO_IPV6, libc::IPV6_RECVERR) => {
1110                let (err, addr) = unsafe { Self::recv_err_helper::<sockaddr_in6>(p, len) };
1111                ControlMessageOwned::Ipv6RecvErr(err, addr)
1112            },
1113            #[cfg(any(linux_android, target_os = "freebsd"))]
1114            #[cfg(feature = "net")]
1115            (libc::IPPROTO_IPV6, libc::IPV6_ORIGDSTADDR) => {
1116                let dl = unsafe { ptr::read_unaligned(p as *const libc::sockaddr_in6) };
1117                ControlMessageOwned::Ipv6OrigDstAddr(dl)
1118            },
1119            #[cfg(any(target_os = "linux"))]
1120            (libc::SOL_TLS, libc::TLS_GET_RECORD_TYPE) => {
1121                let content_type = unsafe { ptr::read_unaligned(p as *const u8) };
1122                ControlMessageOwned::TlsGetRecordType(content_type.into())
1123            },
1124            #[cfg(linux_android)]
1125            #[cfg(feature = "net")]
1126            (libc::IPPROTO_IP, libc::IP_TTL) => {
1127                let ttl = unsafe { ptr::read_unaligned(p as *const i32) };
1128                ControlMessageOwned::Ipv4Ttl(ttl)
1129            },
1130            #[cfg(target_os = "freebsd")]
1131            #[cfg(feature = "net")]
1132            (libc::IPPROTO_IP, libc::IP_RECVTTL) => {
1133                let ttl: u8 = unsafe { ptr::read_unaligned(p as *const u8) };
1134                ControlMessageOwned::Ipv4Ttl(ttl)
1135            },
1136            #[cfg(any(linux_android, target_os = "freebsd"))]
1137            #[cfg(feature = "net")]
1138            (libc::IPPROTO_IPV6, libc::IPV6_HOPLIMIT) => {
1139                let ttl = unsafe { ptr::read_unaligned(p as *const i32) };
1140                ControlMessageOwned::Ipv6HopLimit(ttl)
1141            },
1142            #[cfg(linux_android)]
1143            #[cfg(feature = "net")]
1144            (libc::IPPROTO_IP, libc::IP_TOS) => {
1145                let tos = unsafe { ptr::read_unaligned(p as *const u8) };
1146                ControlMessageOwned::Ipv4Tos(tos)
1147            },
1148            #[cfg(target_os = "freebsd")]
1149            #[cfg(feature = "net")]
1150            (libc::IPPROTO_IP, libc::IP_RECVTOS) => {
1151                let tos = unsafe { ptr::read_unaligned(p as *const u8) };
1152                ControlMessageOwned::Ipv4Tos(tos)
1153            },
1154            #[cfg(any(linux_android, target_os = "freebsd"))]
1155            #[cfg(feature = "net")]
1156            (libc::IPPROTO_IPV6, libc::IPV6_TCLASS) => {
1157                let tc = unsafe { ptr::read_unaligned(p as *const i32) };
1158                ControlMessageOwned::Ipv6TClass(tc)
1159            },
1160            (_, _) => {
1161                let sl = unsafe { std::slice::from_raw_parts(p, len) };
1162                let ucmsg = UnknownCmsg {
1163                    cmsg_header: *header,
1164                    data_bytes: Vec::<u8>::from(sl),
1165                };
1166                ControlMessageOwned::Unknown(ucmsg)
1167            }
1168        }
1169    }
1170
1171    #[cfg(linux_android)]
1172    #[cfg(feature = "net")]
1173    #[allow(clippy::cast_ptr_alignment)]    // False positive
1174    unsafe fn recv_err_helper<T>(p: *mut libc::c_uchar, len: usize) -> (libc::sock_extended_err, Option<T>) {
1175        let ee = p as *const libc::sock_extended_err;
1176        let err = unsafe { ptr::read_unaligned(ee) };
1177
1178        // For errors originating on the network, SO_EE_OFFENDER(ee) points inside the p[..len]
1179        // CMSG_DATA buffer.  For local errors, there is no address included in the control
1180        // message, and SO_EE_OFFENDER(ee) points beyond the end of the buffer.  So, we need to
1181        // validate that the address object is in-bounds before we attempt to copy it.
1182        let addrp = unsafe { libc::SO_EE_OFFENDER(ee) as *const T };
1183
1184        if unsafe { addrp.offset(1) } as usize - (p as usize) > len {
1185            (err, None)
1186        } else {
1187            (err, Some(unsafe { ptr::read_unaligned(addrp) }))
1188        }
1189    }
1190}
1191
1192/// A type-safe zero-copy wrapper around a single control message, as used with
1193/// [`sendmsg`].  More types may be added to this enum; do not exhaustively
1194/// pattern-match it.
1195///
1196/// [Further reading](https://man7.org/linux/man-pages/man3/cmsg.3.html)
1197#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1198#[non_exhaustive]
1199pub enum ControlMessage<'a> {
1200    /// A message of type `SCM_RIGHTS`, containing an array of file
1201    /// descriptors passed between processes.
1202    ///
1203    /// See the description in the "Ancillary messages" section of the
1204    /// [unix(7) man page](https://man7.org/linux/man-pages/man7/unix.7.html).
1205    ///
1206    /// Using multiple `ScmRights` messages for a single `sendmsg` call isn't
1207    /// recommended since it causes platform-dependent behaviour: It might
1208    /// swallow all but the first `ScmRights` message or fail with `EINVAL`.
1209    /// Instead, you can put all fds to be passed into a single `ScmRights`
1210    /// message.
1211    ScmRights(&'a [RawFd]),
1212    /// A message of type `SCM_CREDENTIALS`, containing the pid, uid and gid of
1213    /// a process connected to the socket.
1214    ///
1215    /// This is similar to the socket option `SO_PEERCRED`, but requires a
1216    /// process to explicitly send its credentials. A process running as root is
1217    /// allowed to specify any credentials, while credentials sent by other
1218    /// processes are verified by the kernel.
1219    ///
1220    /// For further information, please refer to the
1221    /// [`unix(7)`](https://man7.org/linux/man-pages/man7/unix.7.html) man page.
1222    #[cfg(linux_android)]
1223    ScmCredentials(&'a UnixCredentials),
1224    /// A message of type `SCM_CREDS`, containing the pid, uid, euid, gid and groups of
1225    /// a process connected to the socket.
1226    ///
1227    /// This is similar to the socket options `LOCAL_CREDS` and `LOCAL_PEERCRED`, but
1228    /// requires a process to explicitly send its credentials.
1229    ///
1230    /// Credentials are always overwritten by the kernel, so this variant does have
1231    /// any data, unlike the receive-side
1232    /// [`ControlMessageOwned::ScmCreds`].
1233    ///
1234    /// For further information, please refer to the
1235    /// [`unix(4)`](https://www.freebsd.org/cgi/man.cgi?query=unix) man page.
1236    #[cfg(freebsdlike)]
1237    ScmCreds,
1238
1239    /// Set IV for `AF_ALG` crypto API.
1240    ///
1241    /// For further information, please refer to the
1242    /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
1243    #[cfg(linux_android)]
1244    AlgSetIv(&'a [u8]),
1245    /// Set crypto operation for `AF_ALG` crypto API. It may be one of
1246    /// `ALG_OP_ENCRYPT` or `ALG_OP_DECRYPT`
1247    ///
1248    /// For further information, please refer to the
1249    /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
1250    #[cfg(linux_android)]
1251    AlgSetOp(&'a libc::c_int),
1252    /// Set the length of associated authentication data (AAD) (applicable only to AEAD algorithms)
1253    /// for `AF_ALG` crypto API.
1254    ///
1255    /// For further information, please refer to the
1256    /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
1257    #[cfg(linux_android)]
1258    AlgSetAeadAssoclen(&'a u32),
1259
1260    /// UDP GSO makes it possible for applications to generate network packets
1261    /// for a virtual MTU much greater than the real one.
1262    /// The length of the send data no longer matches the expected length on
1263    /// the wire.
1264    /// The size of the datagram payload as it should appear on the wire may be
1265    /// passed through this control message.
1266    /// Send buffer should consist of multiple fixed-size wire payloads
1267    /// following one by one, and the last, possibly smaller one.
1268    #[cfg(target_os = "linux")]
1269    #[cfg(feature = "net")]
1270    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1271    UdpGsoSegments(&'a u16),
1272
1273    /// Configure the sending addressing and interface for v4.
1274    ///
1275    /// For further information, please refer to the
1276    /// [`ip(7)`](https://man7.org/linux/man-pages/man7/ip.7.html) man page.
1277    #[cfg(any(linux_android, target_os = "netbsd", apple_targets))]
1278    #[cfg(feature = "net")]
1279    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1280    Ipv4PacketInfo(&'a libc::in_pktinfo),
1281
1282    /// Configure the sending addressing and interface for v6.
1283    ///
1284    /// For further information, please refer to the
1285    /// [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html) man page.
1286    #[cfg(any(linux_android,
1287              target_os = "netbsd",
1288              target_os = "freebsd",
1289              apple_targets))]
1290    #[cfg(feature = "net")]
1291    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1292    Ipv6PacketInfo(&'a libc::in6_pktinfo),
1293
1294    /// Configure the IPv4 source address with `IP_SENDSRCADDR`.
1295    #[cfg(any(freebsdlike, netbsdlike))]
1296    #[cfg(feature = "net")]
1297    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1298    Ipv4SendSrcAddr(&'a libc::in_addr),
1299
1300    /// Configure the Time-to-Live for v4 traffic.
1301    #[cfg(linux_android)]
1302    #[cfg(feature = "net")]
1303    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1304    Ipv4Ttl(&'a libc::c_int),
1305
1306    /// Configure the Time-to-Live for v4 traffic.
1307    #[cfg(target_os = "freebsd")]
1308    #[cfg(feature = "net")]
1309    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1310    Ipv4Ttl(&'a libc::c_uchar),
1311
1312    /// Configure the hop limit for v6 multicast traffic.
1313    ///
1314    /// Set the IPv6 hop limit for this message. The argument is an integer
1315    /// between 0 and 255. A value of -1 will set the hop limit to the route
1316    /// default if possible on the interface. Without this cmsg,  packets sent
1317    /// with sendmsg have a hop limit of 1 and will not leave the local network.
1318    /// For further information, please refer to the
1319    /// [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html) man page.
1320    #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
1321    #[cfg(feature = "net")]
1322    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1323    Ipv6HopLimit(&'a libc::c_int),
1324
1325    /// SO_RXQ_OVFL indicates that an unsigned 32 bit value
1326    /// ancillary msg (cmsg) should be attached to received
1327    /// skbs indicating the number of packets dropped by the
1328    /// socket between the last received packet and this
1329    /// received packet.
1330    #[cfg(any(linux_android, target_os = "fuchsia"))]
1331    RxqOvfl(&'a u32),
1332
1333    /// Configure the transmission time of packets.
1334    ///
1335    /// For further information, please refer to the
1336    /// [`tc-etf(8)`](https://man7.org/linux/man-pages/man8/tc-etf.8.html) man
1337    /// page.
1338    #[cfg(target_os = "linux")]
1339    TxTime(&'a u64),
1340
1341    /// Configure DSCP / IP TOS for outgoing v4 packets.
1342    ///
1343    /// Further information can be found [here](https://en.wikipedia.org/wiki/Differentiated_services).
1344    #[cfg(any(linux_android, target_os = "freebsd"))]
1345    #[cfg(feature = "net")]
1346    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1347    Ipv4Tos(&'a u8),
1348
1349    /// Configure DSCP / IPv6 TCLASS for outgoing v6 packets.
1350    ///
1351    /// Further information can be found [here](https://en.wikipedia.org/wiki/Differentiated_services).
1352    #[cfg(any(linux_android, target_os = "freebsd"))]
1353    #[cfg(feature = "net")]
1354    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1355    Ipv6TClass(&'a i32),
1356}
1357
1358/// Control messages that are currently not supported by Nix.
1359#[derive(Clone, Debug, Eq, PartialEq)]
1360pub struct UnknownCmsg {
1361    /// Control message header.
1362    pub cmsg_header: cmsghdr,
1363    /// Bytes of the control message data.
1364    pub data_bytes: Vec<u8>
1365}
1366
1367impl ControlMessage<'_> {
1368    /// The value of CMSG_SPACE on this message.
1369    /// Safe because CMSG_SPACE is always safe
1370    fn space(&self) -> usize {
1371        unsafe{CMSG_SPACE(self.len() as libc::c_uint) as usize}
1372    }
1373
1374    /// The value of CMSG_LEN on this message.
1375    /// Safe because CMSG_LEN is always safe
1376    #[cfg(any(target_os = "android",
1377              all(target_os = "linux", not(any(target_env = "musl", target_env = "ohos"))),
1378              target_os = "cygwin"))]
1379    fn cmsg_len(&self) -> usize {
1380        unsafe{CMSG_LEN(self.len() as libc::c_uint) as usize}
1381    }
1382
1383    #[cfg(not(any(target_os = "android",
1384              all(target_os = "linux", not(any(target_env = "musl", target_env = "ohos"))),
1385              target_os = "cygwin")))]
1386    fn cmsg_len(&self) -> libc::c_uint {
1387        unsafe{CMSG_LEN(self.len() as libc::c_uint)}
1388    }
1389
1390    /// Return a reference to the payload data as a byte pointer
1391    fn copy_to_cmsg_data(&self, cmsg_data: *mut u8) {
1392        let data_ptr = match *self {
1393            ControlMessage::ScmRights(fds) => {
1394                fds as *const _ as *const u8
1395            },
1396            #[cfg(linux_android)]
1397            ControlMessage::ScmCredentials(creds) => {
1398                &creds.0 as *const libc::ucred as *const u8
1399            }
1400            #[cfg(freebsdlike)]
1401            ControlMessage::ScmCreds => {
1402                // The kernel overwrites the data, we just zero it
1403                // to make sure it's not uninitialized memory
1404                unsafe { ptr::write_bytes(cmsg_data, 0, self.len()) };
1405                return
1406            }
1407            #[cfg(linux_android)]
1408            ControlMessage::AlgSetIv(iv) => {
1409                #[allow(deprecated)] // https://github.com/rust-lang/libc/issues/1501
1410                let af_alg_iv = libc::af_alg_iv {
1411                    ivlen: iv.len() as u32,
1412                    iv: [0u8; 0],
1413                };
1414
1415                let size = mem::size_of_val(&af_alg_iv);
1416
1417                unsafe {
1418                    ptr::copy_nonoverlapping(
1419                        &af_alg_iv as *const _ as *const u8,
1420                        cmsg_data,
1421                        size,
1422                    );
1423                    ptr::copy_nonoverlapping(
1424                        iv.as_ptr(),
1425                        cmsg_data.add(size),
1426                        iv.len()
1427                    );
1428                };
1429
1430                return
1431            },
1432            #[cfg(linux_android)]
1433            ControlMessage::AlgSetOp(op) => {
1434                op as *const _ as *const u8
1435            },
1436            #[cfg(linux_android)]
1437            ControlMessage::AlgSetAeadAssoclen(len) => {
1438                len as *const _ as *const u8
1439            },
1440            #[cfg(target_os = "linux")]
1441            #[cfg(feature = "net")]
1442            ControlMessage::UdpGsoSegments(gso_size) => {
1443                gso_size as *const _ as *const u8
1444            },
1445            #[cfg(any(linux_android, target_os = "netbsd", apple_targets))]
1446            #[cfg(feature = "net")]
1447            ControlMessage::Ipv4PacketInfo(info) => info as *const _ as *const u8,
1448            #[cfg(any(linux_android, target_os = "netbsd",
1449                      target_os = "freebsd", apple_targets))]
1450            #[cfg(feature = "net")]
1451            ControlMessage::Ipv6PacketInfo(info) => info as *const _ as *const u8,
1452            #[cfg(any(freebsdlike, netbsdlike))]
1453            #[cfg(feature = "net")]
1454            ControlMessage::Ipv4SendSrcAddr(addr) => addr as *const _ as *const u8,
1455            #[cfg(linux_android)]
1456            #[cfg(feature = "net")]
1457            ControlMessage::Ipv4Ttl(ttl) => ttl as *const i32 as *const u8,
1458            #[cfg(target_os = "freebsd")]
1459            #[cfg(feature = "net")]
1460            ControlMessage::Ipv4Ttl(ttl) => ttl as *const u8,
1461            #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
1462            #[cfg(feature = "net")]
1463            ControlMessage::Ipv6HopLimit(limit) => limit as *const _ as *const u8,
1464            #[cfg(any(linux_android, target_os = "fuchsia"))]
1465            ControlMessage::RxqOvfl(drop_count) => {
1466                drop_count as *const _ as *const u8
1467            },
1468            #[cfg(target_os = "linux")]
1469            ControlMessage::TxTime(tx_time) => {
1470                tx_time as *const _ as *const u8
1471            },
1472            #[cfg(any(linux_android, target_os = "freebsd"))]
1473            #[cfg(feature = "net")]
1474            ControlMessage::Ipv4Tos(tos) => {
1475                tos as *const _
1476            },
1477            #[cfg(any(linux_android, target_os = "freebsd"))]
1478            #[cfg(feature = "net")]
1479            ControlMessage::Ipv6TClass(tclass) => {
1480                tclass as *const _ as *const u8
1481            },
1482        };
1483        unsafe {
1484            ptr::copy_nonoverlapping(
1485                data_ptr,
1486                cmsg_data,
1487                self.len()
1488            )
1489        };
1490    }
1491
1492    /// The size of the payload, excluding its cmsghdr
1493    fn len(&self) -> usize {
1494        match *self {
1495            ControlMessage::ScmRights(fds) => {
1496                mem::size_of_val(fds)
1497            },
1498            #[cfg(linux_android)]
1499            ControlMessage::ScmCredentials(creds) => {
1500                mem::size_of_val(creds)
1501            }
1502            #[cfg(freebsdlike)]
1503            ControlMessage::ScmCreds => {
1504                mem::size_of::<libc::cmsgcred>()
1505            }
1506            #[cfg(linux_android)]
1507            ControlMessage::AlgSetIv(iv) => {
1508                mem::size_of::<&[u8]>() + iv.len()
1509            },
1510            #[cfg(linux_android)]
1511            ControlMessage::AlgSetOp(op) => {
1512                mem::size_of_val(op)
1513            },
1514            #[cfg(linux_android)]
1515            ControlMessage::AlgSetAeadAssoclen(len) => {
1516                mem::size_of_val(len)
1517            },
1518            #[cfg(target_os = "linux")]
1519            #[cfg(feature = "net")]
1520            ControlMessage::UdpGsoSegments(gso_size) => {
1521                mem::size_of_val(gso_size)
1522            },
1523            #[cfg(any(linux_android, target_os = "netbsd", apple_targets))]
1524            #[cfg(feature = "net")]
1525            ControlMessage::Ipv4PacketInfo(info) => mem::size_of_val(info),
1526            #[cfg(any(linux_android, target_os = "netbsd",
1527                      target_os = "freebsd", apple_targets))]
1528            #[cfg(feature = "net")]
1529            ControlMessage::Ipv6PacketInfo(info) => mem::size_of_val(info),
1530            #[cfg(any(freebsdlike, netbsdlike))]
1531            #[cfg(feature = "net")]
1532            ControlMessage::Ipv4SendSrcAddr(addr) => mem::size_of_val(addr),
1533            #[cfg(any(linux_android, target_os = "freebsd"))]
1534            #[cfg(feature = "net")]
1535            ControlMessage::Ipv4Ttl(ttl) => {
1536                mem::size_of_val(ttl)
1537            },
1538            #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
1539            #[cfg(feature = "net")]
1540            ControlMessage::Ipv6HopLimit(limit) => {
1541                mem::size_of_val(limit)
1542            },
1543            #[cfg(any(linux_android, target_os = "fuchsia"))]
1544            ControlMessage::RxqOvfl(drop_count) => {
1545                mem::size_of_val(drop_count)
1546            },
1547            #[cfg(target_os = "linux")]
1548            ControlMessage::TxTime(tx_time) => {
1549                mem::size_of_val(tx_time)
1550            },
1551            #[cfg(any(linux_android, target_os = "freebsd"))]
1552            #[cfg(feature = "net")]
1553            ControlMessage::Ipv4Tos(tos) => {
1554                mem::size_of_val(tos)
1555            },
1556            #[cfg(any(linux_android, target_os = "freebsd"))]
1557            #[cfg(feature = "net")]
1558            ControlMessage::Ipv6TClass(tclass) => {
1559                mem::size_of_val(tclass)
1560            },
1561        }
1562    }
1563
1564    /// Returns the value to put into the `cmsg_level` field of the header.
1565    fn cmsg_level(&self) -> libc::c_int {
1566        match *self {
1567            ControlMessage::ScmRights(_) => libc::SOL_SOCKET,
1568            #[cfg(linux_android)]
1569            ControlMessage::ScmCredentials(_) => libc::SOL_SOCKET,
1570            #[cfg(freebsdlike)]
1571            ControlMessage::ScmCreds => libc::SOL_SOCKET,
1572            #[cfg(linux_android)]
1573            ControlMessage::AlgSetIv(_) | ControlMessage::AlgSetOp(_) |
1574                ControlMessage::AlgSetAeadAssoclen(_) => libc::SOL_ALG,
1575            #[cfg(target_os = "linux")]
1576            #[cfg(feature = "net")]
1577            ControlMessage::UdpGsoSegments(_) => libc::SOL_UDP,
1578            #[cfg(any(linux_android, target_os = "netbsd", apple_targets))]
1579            #[cfg(feature = "net")]
1580            ControlMessage::Ipv4PacketInfo(_) => libc::IPPROTO_IP,
1581            #[cfg(any(linux_android, target_os = "netbsd",
1582                      target_os = "freebsd", apple_targets))]
1583            #[cfg(feature = "net")]
1584            ControlMessage::Ipv6PacketInfo(_) => libc::IPPROTO_IPV6,
1585            #[cfg(any(freebsdlike, netbsdlike))]
1586            #[cfg(feature = "net")]
1587            ControlMessage::Ipv4SendSrcAddr(_) => libc::IPPROTO_IP,
1588            #[cfg(any(linux_android, target_os = "freebsd"))]
1589            #[cfg(feature = "net")]
1590            ControlMessage::Ipv4Ttl(_) => libc::IPPROTO_IP,
1591            #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
1592            #[cfg(feature = "net")]
1593            ControlMessage::Ipv6HopLimit(_) => libc::IPPROTO_IPV6,
1594            #[cfg(any(linux_android, target_os = "fuchsia"))]
1595            ControlMessage::RxqOvfl(_) => libc::SOL_SOCKET,
1596            #[cfg(target_os = "linux")]
1597            ControlMessage::TxTime(_) => libc::SOL_SOCKET,
1598            #[cfg(any(linux_android, target_os = "freebsd"))]
1599            #[cfg(feature = "net")]
1600            ControlMessage::Ipv4Tos(_) => libc::IPPROTO_IP,
1601            #[cfg(any(linux_android, target_os = "freebsd"))]
1602            #[cfg(feature = "net")]
1603            ControlMessage::Ipv6TClass(_) => libc::IPPROTO_IPV6,
1604        }
1605    }
1606
1607    /// Returns the value to put into the `cmsg_type` field of the header.
1608    fn cmsg_type(&self) -> libc::c_int {
1609        match *self {
1610            ControlMessage::ScmRights(_) => libc::SCM_RIGHTS,
1611            #[cfg(linux_android)]
1612            ControlMessage::ScmCredentials(_) => libc::SCM_CREDENTIALS,
1613            #[cfg(freebsdlike)]
1614            ControlMessage::ScmCreds => libc::SCM_CREDS,
1615            #[cfg(linux_android)]
1616            ControlMessage::AlgSetIv(_) => {
1617                libc::ALG_SET_IV
1618            },
1619            #[cfg(linux_android)]
1620            ControlMessage::AlgSetOp(_) => {
1621                libc::ALG_SET_OP
1622            },
1623            #[cfg(linux_android)]
1624            ControlMessage::AlgSetAeadAssoclen(_) => {
1625                libc::ALG_SET_AEAD_ASSOCLEN
1626            },
1627            #[cfg(target_os = "linux")]
1628            #[cfg(feature = "net")]
1629            ControlMessage::UdpGsoSegments(_) => {
1630                libc::UDP_SEGMENT
1631            },
1632            #[cfg(any(linux_android, target_os = "netbsd", apple_targets))]
1633            #[cfg(feature = "net")]
1634            ControlMessage::Ipv4PacketInfo(_) => libc::IP_PKTINFO,
1635            #[cfg(any(linux_android, target_os = "netbsd",
1636                      target_os = "freebsd", apple_targets))]
1637            #[cfg(feature = "net")]
1638            ControlMessage::Ipv6PacketInfo(_) => libc::IPV6_PKTINFO,
1639            #[cfg(any(freebsdlike, netbsdlike))]
1640            #[cfg(feature = "net")]
1641            ControlMessage::Ipv4SendSrcAddr(_) => libc::IP_SENDSRCADDR,
1642            #[cfg(any(linux_android, target_os = "freebsd"))]
1643            #[cfg(feature = "net")]
1644            ControlMessage::Ipv4Ttl(_) => libc::IP_TTL,
1645            #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
1646            #[cfg(feature = "net")]
1647            ControlMessage::Ipv6HopLimit(_) => libc::IPV6_HOPLIMIT,
1648            #[cfg(any(linux_android, target_os = "fuchsia"))]
1649            ControlMessage::RxqOvfl(_) => {
1650                libc::SO_RXQ_OVFL
1651            },
1652            #[cfg(target_os = "linux")]
1653            ControlMessage::TxTime(_) => {
1654                libc::SCM_TXTIME
1655            },
1656            #[cfg(any(linux_android, target_os = "freebsd"))]
1657            #[cfg(feature = "net")]
1658            ControlMessage::Ipv4Tos(_) => {
1659                libc::IP_TOS
1660            },
1661            #[cfg(any(linux_android, target_os = "freebsd"))]
1662            #[cfg(feature = "net")]
1663            ControlMessage::Ipv6TClass(_) => {
1664                libc::IPV6_TCLASS
1665            },
1666        }
1667    }
1668
1669    // Unsafe: cmsg must point to a valid cmsghdr with enough space to
1670    // encode self.
1671    unsafe fn encode_into(&self, cmsg: *mut cmsghdr) {
1672        unsafe {
1673            (*cmsg).cmsg_level = self.cmsg_level();
1674            (*cmsg).cmsg_type = self.cmsg_type();
1675            (*cmsg).cmsg_len = self.cmsg_len();
1676            self.copy_to_cmsg_data( CMSG_DATA(cmsg) );
1677        }
1678    }
1679}
1680
1681
1682/// Send data in scatter-gather vectors to a socket, possibly accompanied
1683/// by ancillary data. Optionally direct the message at the given address,
1684/// as with sendto.
1685///
1686/// Allocates if cmsgs is nonempty.
1687///
1688/// # Examples
1689/// When not directing to any specific address, use `()` for the generic type
1690/// ```
1691/// # use nix::sys::socket::*;
1692/// # use nix::unistd::pipe;
1693/// # use std::io::IoSlice;
1694/// # use std::os::unix::io::AsRawFd;
1695/// let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None,
1696///     SockFlag::empty())
1697///     .unwrap();
1698/// let (r, w) = pipe().unwrap();
1699///
1700/// let iov = [IoSlice::new(b"hello")];
1701/// let fds = [r.as_raw_fd()];
1702/// let cmsg = ControlMessage::ScmRights(&fds);
1703/// sendmsg::<()>(fd1.as_raw_fd(), &iov, &[cmsg], MsgFlags::empty(), None).unwrap();
1704/// ```
1705/// When directing to a specific address, the generic type will be inferred.
1706/// Note that SCM_RIGHTS ancillary data are valid only for AF_UNIX sockets on Solaris.
1707/// ```
1708/// # use nix::sys::socket::*;
1709/// # use nix::unistd::pipe;
1710/// # use std::io::IoSlice;
1711/// # use std::str::FromStr;
1712/// # use std::os::unix::io::AsRawFd;
1713/// let localhost = SockaddrIn::from_str("1.2.3.4:8080").unwrap();
1714/// let fd = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(),
1715///     None).unwrap();
1716/// let (r, w) = pipe().unwrap();
1717///
1718/// let iov = [IoSlice::new(b"hello")];
1719/// let fds = [r.as_raw_fd()];
1720/// let cmsg = ControlMessage::ScmRights(&fds);
1721/// #[cfg(not(target_os = "solaris"))]
1722/// sendmsg(fd.as_raw_fd(), &iov, &[cmsg], MsgFlags::empty(), Some(&localhost)).unwrap();
1723/// ```
1724pub fn sendmsg<S>(fd: RawFd, iov: &[IoSlice<'_>], cmsgs: &[ControlMessage],
1725               flags: MsgFlags, addr: Option<&S>) -> Result<usize>
1726    where S: SockaddrLike
1727{
1728    let capacity = cmsgs.iter().map(|c| c.space()).sum();
1729
1730    // First size the buffer needed to hold the cmsgs.  It must be zeroed,
1731    // because subsequent code will not clear the padding bytes.
1732    let mut cmsg_buffer = vec![0u8; capacity];
1733
1734    let mhdr = pack_mhdr_to_send(&mut cmsg_buffer[..], iov, cmsgs, addr);
1735
1736    let ret = unsafe { libc::sendmsg(fd, &mhdr, flags.bits()) };
1737
1738    Errno::result(ret).map(|r| r as usize)
1739}
1740
1741
1742/// An extension of `sendmsg` that allows the caller to transmit multiple
1743/// messages on a socket using a single system call. This has performance
1744/// benefits for some applications.
1745///
1746/// Allocations are performed for cmsgs and to build `msghdr` buffer
1747///
1748/// # Arguments
1749///
1750/// * `fd`:             Socket file descriptor
1751/// * `data`:           Struct that implements `IntoIterator` with `SendMmsgData` items
1752/// * `flags`:          Optional flags passed directly to the operating system.
1753///
1754/// # Returns
1755/// `Vec` with numbers of sent bytes on each sent message.
1756///
1757/// # References
1758/// [`sendmsg`](fn.sendmsg.html)
1759#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
1760pub fn sendmmsg<'a, XS, AS, C, I, S>(
1761    fd: RawFd,
1762    data: &'a mut MultiHeaders<S>,
1763    slices: XS,
1764    // one address per group of slices
1765    addrs: AS,
1766    // shared across all the messages
1767    cmsgs: C,
1768    flags: MsgFlags
1769) -> crate::Result<MultiResults<'a, S>>
1770    where
1771        XS: IntoIterator<Item = &'a I>,
1772        AS: AsRef<[Option<S>]>,
1773        I: AsRef<[IoSlice<'a>]> + 'a,
1774        C: AsRef<[ControlMessage<'a>]> + 'a,
1775        S: SockaddrLike + 'a,
1776{
1777
1778    let mut count = 0;
1779
1780
1781    for (i, ((slice, addr), mmsghdr)) in slices.into_iter().zip(addrs.as_ref()).zip(data.items.iter_mut() ).enumerate() {
1782        let p = &mut mmsghdr.msg_hdr;
1783        p.msg_iov = slice.as_ref().as_ptr().cast_mut().cast();
1784        p.msg_iovlen = slice.as_ref().len() as _;
1785
1786        p.msg_namelen = addr.as_ref().map_or(0, S::len);
1787        p.msg_name = addr.as_ref().map_or(ptr::null(), S::as_ptr).cast_mut().cast();
1788
1789        // Encode each cmsg.  This must happen after initializing the header because
1790        // CMSG_NEXT_HDR and friends read the msg_control and msg_controllen fields.
1791        // CMSG_FIRSTHDR is always safe
1792        let mut pmhdr: *mut cmsghdr = unsafe { CMSG_FIRSTHDR(p) };
1793        for cmsg in cmsgs.as_ref() {
1794            assert_ne!(pmhdr, ptr::null_mut());
1795            // Safe because we know that pmhdr is valid, and we initialized it with
1796            // sufficient space
1797            unsafe { cmsg.encode_into(pmhdr) };
1798            // Safe because mhdr is valid
1799            pmhdr = unsafe { CMSG_NXTHDR(p, pmhdr) };
1800        }
1801
1802        // Doing an unchecked addition is alright here, as the only way to obtain an instance of `MultiHeaders`
1803        // is through the `preallocate` function, which takes an `usize` as an argument to define its size,
1804        // which also provides an upper bound for the size of this zipped iterator. Thus, `i < usize::MAX` or in
1805        // other words: `count` doesn't overflow
1806        count = i + 1;
1807    }
1808
1809    // SAFETY: all pointers are guaranteed to be valid for the scope of this function. `count` does represent the
1810    // maximum number of messages that can be sent safely (i.e. `count` is the minimum of the sizes of `slices`,
1811    // `data.items` and `addrs`)
1812    let sent = Errno::result(unsafe {
1813        libc::sendmmsg(
1814            fd,
1815            data.items.as_mut_ptr(),
1816            count as _,
1817            flags.bits() as _
1818        )
1819    })? as usize;
1820
1821    Ok(MultiResults {
1822        rmm: data,
1823        current_index: 0,
1824        received: sent
1825    })
1826
1827}
1828
1829
1830#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
1831#[derive(Debug)]
1832/// Preallocated structures needed for [`recvmmsg`] and [`sendmmsg`] functions
1833pub struct MultiHeaders<S> {
1834    // preallocated boxed slice of mmsghdr
1835    items: Box<[libc::mmsghdr]>,
1836    addresses: Box<[mem::MaybeUninit<S>]>,
1837    // while we are not using it directly - this is used to store control messages
1838    // and we retain pointers to them inside items array
1839    _cmsg_buffers: Option<Box<[u8]>>,
1840    msg_controllen: usize,
1841}
1842
1843#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
1844impl<S> MultiHeaders<S> {
1845    /// Preallocate structure used by [`recvmmsg`] and [`sendmmsg`] takes number of headers to preallocate
1846    ///
1847    /// `cmsg_buffer` should be created with [`cmsg_space!`] if needed
1848    pub fn preallocate(num_slices: usize, cmsg_buffer: Option<Vec<u8>>) -> Self
1849    where
1850        S: Copy + SockaddrLike,
1851    {
1852        // we will be storing pointers to addresses inside mhdr - convert it into boxed
1853        // slice so it can'be changed later by pushing anything into self.addresses
1854        let mut addresses = vec![std::mem::MaybeUninit::<S>::uninit(); num_slices].into_boxed_slice();
1855
1856        let msg_controllen = cmsg_buffer.as_ref().map_or(0, |v| v.capacity());
1857
1858        // we'll need a cmsg_buffer for each slice, we preallocate a vector and split
1859        // it into "slices" parts
1860        let mut cmsg_buffers =
1861            cmsg_buffer.map(|v| vec![0u8; v.capacity() * num_slices].into_boxed_slice());
1862
1863        let items = addresses
1864            .iter_mut()
1865            .enumerate()
1866            .map(|(ix, address)| {
1867                let (ptr, cap) = match &mut cmsg_buffers {
1868                    Some(v) => (&mut v[ix * msg_controllen] as *mut u8, msg_controllen),
1869                    None => (std::ptr::null_mut(), 0),
1870                };
1871                let msg_hdr = unsafe { pack_mhdr_to_receive(std::ptr::null_mut(), 0, ptr, cap, address.as_mut_ptr()) };
1872                libc::mmsghdr {
1873                    msg_hdr,
1874                    msg_len: 0,
1875                }
1876            })
1877            .collect::<Vec<_>>();
1878
1879        Self {
1880            items: items.into_boxed_slice(),
1881            addresses,
1882            _cmsg_buffers: cmsg_buffers,
1883            msg_controllen,
1884        }
1885    }
1886}
1887
1888/// An extension of recvmsg that allows the caller to receive multiple messages from a socket using a single system call.
1889///
1890/// This has performance benefits for some applications.
1891///
1892/// This method performs no allocations.
1893///
1894/// Returns an iterator producing [`RecvMsg`], one per received messages. Each `RecvMsg` can produce
1895/// iterators over [`IoSlice`] with [`iovs`][RecvMsg::iovs`] and
1896/// `ControlMessageOwned` with [`cmsgs`][RecvMsg::cmsgs].
1897///
1898/// # Bugs (in underlying implementation, at least in Linux)
1899/// The timeout argument does not work as intended. The timeout is checked only after the receipt
1900/// of each datagram, so that if up to `vlen`-1 datagrams are received before the timeout expires,
1901/// but then no further datagrams are received, the call will block forever.
1902///
1903/// If an error occurs after at least one message has been received, the call succeeds, and returns
1904/// the number of messages received. The error code is expected to be returned on a subsequent
1905/// call to recvmmsg(). In the current implementation, however, the error code can be
1906/// overwritten in the meantime by an unrelated network event on a socket, for example an
1907/// incoming ICMP packet.
1908// On aarch64 linux using recvmmsg and trying to get hardware/kernel timestamps might not
1909// always produce the desired results - see https://github.com/nix-rust/nix/pull/1744 for more
1910// details
1911#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
1912pub fn recvmmsg<'a, XS, S, I>(
1913    fd: RawFd,
1914    data: &'a mut MultiHeaders<S>,
1915    slices: XS,
1916    flags: MsgFlags,
1917    mut timeout: Option<crate::sys::time::TimeSpec>,
1918) -> crate::Result<MultiResults<'a, S>>
1919where
1920    XS: IntoIterator<Item = &'a mut I>,
1921    I: AsMut<[IoSliceMut<'a>]> + 'a,
1922{
1923    let mut count = 0;
1924    for (i, (slice, mmsghdr)) in slices.into_iter().zip(data.items.iter_mut()).enumerate() {
1925        let p = &mut mmsghdr.msg_hdr;
1926        p.msg_iov = slice.as_mut().as_mut_ptr().cast();
1927        p.msg_iovlen = slice.as_mut().len() as _;
1928
1929        // Doing an unchecked addition is alright here, as the only way to obtain an instance of `MultiHeaders`
1930        // is through the `preallocate` function, which takes an `usize` as an argument to define its size,
1931        // which also provides an upper bound for the size of this zipped iterator. Thus, `i < usize::MAX` or in
1932        // other words: `count` doesn't overflow
1933        count = i + 1;
1934    }
1935
1936    let timeout_ptr = timeout
1937        .as_mut()
1938        .map_or_else(std::ptr::null_mut, |t| t as *mut _ as *mut libc::timespec);
1939
1940    // SAFETY: all pointers are guaranteed to be valid for the scope of this function. `count` does represent the
1941    // maximum number of messages that can be received safely (i.e. `count` is the minimum of the sizes of `slices` and `data.items`)
1942    let received = Errno::result(unsafe {
1943        libc::recvmmsg(
1944            fd,
1945            data.items.as_mut_ptr(),
1946            count as _,
1947            flags.bits() as _,
1948            timeout_ptr,
1949        )
1950    })? as usize;
1951
1952    Ok(MultiResults {
1953        rmm: data,
1954        current_index: 0,
1955        received,
1956    })
1957}
1958
1959/// Iterator over results of [`recvmmsg`]/[`sendmmsg`]
1960#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
1961#[derive(Debug)]
1962pub struct MultiResults<'a, S> {
1963    // preallocated structures
1964    rmm: &'a MultiHeaders<S>,
1965    current_index: usize,
1966    received: usize,
1967}
1968
1969#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
1970impl<'a, S> Iterator for MultiResults<'a, S>
1971where
1972    S: Copy + SockaddrLike,
1973{
1974    type Item = RecvMsg<'a, 'a, S>;
1975
1976    // The cast is not unnecessary on all platforms.
1977    #[allow(clippy::unnecessary_cast)]
1978    fn next(&mut self) -> Option<Self::Item> {
1979        if self.current_index >= self.received {
1980            return None;
1981        }
1982        let mmsghdr = self.rmm.items[self.current_index];
1983
1984        // as long as we are not reading past the index writen by recvmmsg - address
1985        // will be initialized
1986        let address = unsafe { self.rmm.addresses[self.current_index].assume_init() };
1987
1988        self.current_index += 1;
1989        Some(unsafe {
1990            read_mhdr(
1991                mmsghdr.msg_hdr,
1992                mmsghdr.msg_len as isize,
1993                self.rmm.msg_controllen,
1994                address,
1995            )
1996        })
1997    }
1998}
1999
2000impl<'a, S> RecvMsg<'_, 'a, S> {
2001    /// Iterate over the filled io slices pointed by this msghdr
2002    pub fn iovs(&self) -> IoSliceIterator<'a> {
2003        IoSliceIterator {
2004            index: 0,
2005            remaining: self.bytes,
2006            slices: unsafe {
2007                // safe for as long as mgdr is properly initialized and references are valid.
2008                // for multi messages API we initialize it with an empty
2009                // slice and replace with a concrete buffer
2010                // for single message API we hold a lifetime reference to ioslices
2011                std::slice::from_raw_parts(self.mhdr.msg_iov as *const _, self.mhdr.msg_iovlen as _)
2012            },
2013        }
2014    }
2015}
2016
2017#[derive(Debug)]
2018pub struct IoSliceIterator<'a> {
2019    index: usize,
2020    remaining: usize,
2021    slices: &'a [IoSlice<'a>],
2022}
2023
2024impl<'a> Iterator for IoSliceIterator<'a> {
2025    type Item = &'a [u8];
2026
2027    fn next(&mut self) -> Option<Self::Item> {
2028        if self.index >= self.slices.len() {
2029            return None;
2030        }
2031        let slice = &self.slices[self.index][..self.remaining.min(self.slices[self.index].len())];
2032        self.remaining -= slice.len();
2033        self.index += 1;
2034        if slice.is_empty() {
2035            return None;
2036        }
2037
2038        Some(slice)
2039    }
2040}
2041
2042unsafe fn read_mhdr<'a, 'i, S>(
2043    mhdr: msghdr,
2044    r: isize,
2045    msg_controllen: usize,
2046    mut address: S,
2047) -> RecvMsg<'a, 'i, S>
2048    where S: SockaddrLike
2049{
2050    // The cast is not unnecessary on all platforms.
2051    #[allow(clippy::unnecessary_cast)]
2052    let cmsghdr = {
2053        let ptr = if mhdr.msg_controllen > 0 {
2054            debug_assert!(!mhdr.msg_control.is_null());
2055            debug_assert!(msg_controllen >= mhdr.msg_controllen as usize);
2056            unsafe { CMSG_FIRSTHDR(&mhdr as *const msghdr) }
2057        } else {
2058            ptr::null()
2059        };
2060
2061        unsafe {
2062            ptr.as_ref()
2063        }
2064    };
2065
2066    // Ignore errors if this socket address has statically-known length
2067    //
2068    // This is to ensure that unix socket addresses have their length set appropriately.
2069    let _ = unsafe { address.set_length(mhdr.msg_namelen as usize) };
2070
2071    RecvMsg {
2072        bytes: r as usize,
2073        cmsghdr,
2074        address: Some(address),
2075        flags: MsgFlags::from_bits_truncate(mhdr.msg_flags),
2076        mhdr,
2077        iobufs: std::marker::PhantomData,
2078    }
2079}
2080
2081/// Pack pointers to various structures into into msghdr
2082///
2083/// # Safety
2084/// `iov_buffer` and `iov_buffer_len` must point to a slice
2085/// of `IoSliceMut` and number of available elements or be a null pointer and 0
2086///
2087/// `cmsg_buffer` and `cmsg_capacity` must point to a byte buffer used
2088/// to store control headers later or be a null pointer and 0 if control
2089/// headers are not used
2090///
2091/// Buffers must remain valid for the whole lifetime of msghdr
2092unsafe fn pack_mhdr_to_receive<S>(
2093    iov_buffer: *mut IoSliceMut,
2094    iov_buffer_len: usize,
2095    cmsg_buffer: *mut u8,
2096    cmsg_capacity: usize,
2097    address: *mut S,
2098) -> msghdr
2099    where
2100        S: SockaddrLike
2101{
2102    // Musl's msghdr has private fields, so this is the only way to
2103    // initialize it.
2104    let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
2105    let p = mhdr.as_mut_ptr();
2106    unsafe {
2107        // it is important to use as_mut_ptr() here since S can be
2108        // a zero sized type representing by a dangling pointer.
2109        // as_mut_ptr() handles this case and uses a null pointer instead
2110        (*p).msg_name = (*address).as_mut_ptr() as *mut c_void;
2111        (*p).msg_namelen = S::size();
2112        (*p).msg_iov = iov_buffer as *mut iovec;
2113        (*p).msg_iovlen = iov_buffer_len as _;
2114        (*p).msg_control = cmsg_buffer as *mut c_void;
2115        (*p).msg_controllen = cmsg_capacity as _;
2116        (*p).msg_flags = 0;
2117        mhdr.assume_init()
2118    }
2119}
2120
2121fn pack_mhdr_to_send<'a, I, C, S>(
2122    cmsg_buffer: &mut [u8],
2123    iov: I,
2124    cmsgs: C,
2125    addr: Option<&S>
2126) -> msghdr
2127    where
2128        I: AsRef<[IoSlice<'a>]>,
2129        C: AsRef<[ControlMessage<'a>]>,
2130        S: SockaddrLike + 'a
2131{
2132    let capacity = cmsg_buffer.len();
2133
2134    // The message header must be initialized before the individual cmsgs.
2135    let cmsg_ptr = if capacity > 0 {
2136        cmsg_buffer.as_mut_ptr().cast()
2137    } else {
2138        ptr::null_mut()
2139    };
2140
2141    let mhdr = unsafe {
2142        // Musl's msghdr has private fields, so this is the only way to
2143        // initialize it.
2144        let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
2145        let p = mhdr.as_mut_ptr();
2146        (*p).msg_name = addr.map(S::as_ptr).unwrap_or(ptr::null()).cast_mut().cast();
2147        (*p).msg_namelen = addr.map(S::len).unwrap_or(0);
2148        // transmute iov into a mutable pointer.  sendmsg doesn't really mutate
2149        // the buffer, but the standard says that it takes a mutable pointer
2150        (*p).msg_iov = iov.as_ref().as_ptr().cast_mut().cast();
2151        (*p).msg_iovlen = iov.as_ref().len() as _;
2152        (*p).msg_control = cmsg_ptr;
2153        (*p).msg_controllen = capacity as _;
2154        (*p).msg_flags = 0;
2155        mhdr.assume_init()
2156    };
2157
2158    // Encode each cmsg.  This must happen after initializing the header because
2159    // CMSG_NEXT_HDR and friends read the msg_control and msg_controllen fields.
2160    // CMSG_FIRSTHDR is always safe
2161    let mut pmhdr: *mut cmsghdr = unsafe { CMSG_FIRSTHDR(&mhdr as *const msghdr) };
2162    for cmsg in cmsgs.as_ref() {
2163        assert_ne!(pmhdr, ptr::null_mut());
2164        // Safe because we know that pmhdr is valid, and we initialized it with
2165        // sufficient space
2166        unsafe { cmsg.encode_into(pmhdr) };
2167        // Safe because mhdr is valid
2168        pmhdr = unsafe { CMSG_NXTHDR(&mhdr as *const msghdr, pmhdr) };
2169    }
2170
2171    mhdr
2172}
2173
2174/// Receive message in scatter-gather vectors from a socket, and
2175/// optionally receive ancillary data into the provided buffer.
2176/// If no ancillary data is desired, use () as the type parameter.
2177///
2178/// # Arguments
2179///
2180/// * `fd`:             Socket file descriptor
2181/// * `iov`:            Scatter-gather list of buffers to receive the message
2182/// * `cmsg_buffer`:    Space to receive ancillary data.  Should be created by
2183///                     [`cmsg_space!`](../../macro.cmsg_space.html)
2184/// * `flags`:          Optional flags passed directly to the operating system.
2185///
2186/// # References
2187/// [recvmsg(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html)
2188pub fn recvmsg<'a, 'outer, 'inner, S>(fd: RawFd, iov: &'outer mut [IoSliceMut<'inner>],
2189                   mut cmsg_buffer: Option<&'a mut [u8]>,
2190                   flags: MsgFlags) -> Result<RecvMsg<'a, 'outer, S>>
2191    where S: SockaddrLike + 'a,
2192    'inner: 'outer
2193{
2194    let mut address = mem::MaybeUninit::uninit();
2195
2196    let (msg_control, msg_controllen) = cmsg_buffer.as_mut()
2197        .map(|v| (v.as_mut_ptr(), v.len()))
2198        .unwrap_or((ptr::null_mut(), 0));
2199    let mut mhdr = unsafe {
2200        pack_mhdr_to_receive(iov.as_mut().as_mut_ptr(), iov.len(), msg_control, msg_controllen, address.as_mut_ptr())
2201    };
2202
2203    let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) };
2204
2205    let r = Errno::result(ret)?;
2206
2207    Ok(unsafe { read_mhdr(mhdr, r, msg_controllen, address.assume_init()) })
2208}
2209}
2210
2211/// Create an endpoint for communication
2212///
2213/// The `protocol` specifies a particular protocol to be used with the
2214/// socket.  Normally only a single protocol exists to support a
2215/// particular socket type within a given protocol family, in which case
2216/// protocol can be specified as `None`.  However, it is possible that many
2217/// protocols may exist, in which case a particular protocol must be
2218/// specified in this manner.
2219///
2220/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html)
2221pub fn socket<T: Into<Option<SockProtocol>>>(
2222    domain: AddressFamily,
2223    ty: SockType,
2224    flags: SockFlag,
2225    protocol: T,
2226) -> Result<OwnedFd> {
2227    let protocol = match protocol.into() {
2228        None => 0,
2229        Some(p) => p as c_int,
2230    };
2231
2232    // SockFlags are usually embedded into `ty`, but we don't do that in `nix` because it's a
2233    // little easier to understand by separating it out. So we have to merge these bitfields
2234    // here.
2235    let mut ty = ty as c_int;
2236    ty |= flags.bits();
2237
2238    let res = unsafe { libc::socket(domain as c_int, ty, protocol) };
2239
2240    match res {
2241        -1 => Err(Errno::last()),
2242        fd => {
2243            // Safe because libc::socket returned success
2244            unsafe { Ok(OwnedFd::from_raw_fd(fd)) }
2245        }
2246    }
2247}
2248
2249/// Create a pair of connected sockets
2250///
2251/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/socketpair.html)
2252pub fn socketpair<T: Into<Option<SockProtocol>>>(
2253    domain: AddressFamily,
2254    ty: SockType,
2255    protocol: T,
2256    flags: SockFlag,
2257) -> Result<(OwnedFd, OwnedFd)> {
2258    let protocol = match protocol.into() {
2259        None => 0,
2260        Some(p) => p as c_int,
2261    };
2262
2263    // SockFlags are usually embedded into `ty`, but we don't do that in `nix` because it's a
2264    // little easier to understand by separating it out. So we have to merge these bitfields
2265    // here.
2266    let mut ty = ty as c_int;
2267    ty |= flags.bits();
2268
2269    let mut fds = [-1, -1];
2270
2271    let res = unsafe {
2272        libc::socketpair(domain as c_int, ty, protocol, fds.as_mut_ptr())
2273    };
2274    Errno::result(res)?;
2275
2276    // Safe because socketpair returned success.
2277    unsafe { Ok((OwnedFd::from_raw_fd(fds[0]), OwnedFd::from_raw_fd(fds[1]))) }
2278}
2279
2280#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2281pub struct Backlog(i32);
2282
2283impl Backlog {
2284    /// Sets the listen queue size to system `SOMAXCONN` value
2285    pub const MAXCONN: Self = Self(libc::SOMAXCONN);
2286    /// Sets the listen queue size to -1 for system supporting it
2287    #[cfg(any(target_os = "linux", target_os = "freebsd"))]
2288    pub const MAXALLOWABLE: Self = Self(-1);
2289
2290    /// Create a `Backlog`, an `EINVAL` will be returned if `val` is invalid.
2291    pub fn new<I: Into<i32>>(val: I) -> Result<Self> {
2292        cfg_if! {
2293            if #[cfg(any(target_os = "linux", target_os = "freebsd"))] {
2294                const MIN: i32 = -1;
2295            } else {
2296                const MIN: i32 = 0;
2297            }
2298        }
2299
2300        let val = val.into();
2301
2302        if !(MIN..=Self::MAXCONN.0).contains(&val) {
2303            return Err(Errno::EINVAL);
2304        }
2305
2306        Ok(Self(val))
2307    }
2308}
2309
2310impl From<Backlog> for i32 {
2311    fn from(backlog: Backlog) -> Self {
2312        backlog.0
2313    }
2314}
2315
2316/// Listen for connections on a socket
2317///
2318/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html)
2319pub fn listen<F: AsFd>(sock: &F, backlog: Backlog) -> Result<()> {
2320    let fd = sock.as_fd().as_raw_fd();
2321    let res = unsafe { libc::listen(fd, backlog.into()) };
2322
2323    Errno::result(res).map(drop)
2324}
2325
2326/// Bind a name to a socket
2327///
2328/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html)
2329pub fn bind(fd: RawFd, addr: &dyn SockaddrLike) -> Result<()> {
2330    let res = unsafe { libc::bind(fd, addr.as_ptr(), addr.len()) };
2331
2332    Errno::result(res).map(drop)
2333}
2334
2335/// Accept a connection on a socket
2336///
2337/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html)
2338pub fn accept(sockfd: RawFd) -> Result<RawFd> {
2339    let res = unsafe { libc::accept(sockfd, ptr::null_mut(), ptr::null_mut()) };
2340
2341    Errno::result(res)
2342}
2343
2344/// Accept a connection on a socket
2345///
2346/// [Further reading](https://man7.org/linux/man-pages/man2/accept.2.html)
2347#[cfg(any(
2348    all(
2349        target_os = "android",
2350        any(
2351            target_arch = "aarch64",
2352            target_arch = "x86",
2353            target_arch = "x86_64"
2354        )
2355    ),
2356    freebsdlike,
2357    netbsdlike,
2358    target_os = "emscripten",
2359    target_os = "fuchsia",
2360    solarish,
2361    target_os = "linux",
2362))]
2363pub fn accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd> {
2364    let res = unsafe {
2365        libc::accept4(sockfd, ptr::null_mut(), ptr::null_mut(), flags.bits())
2366    };
2367
2368    Errno::result(res)
2369}
2370
2371/// Initiate a connection on a socket
2372///
2373/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html)
2374pub fn connect(fd: RawFd, addr: &dyn SockaddrLike) -> Result<()> {
2375    let res = unsafe { libc::connect(fd, addr.as_ptr(), addr.len()) };
2376
2377    Errno::result(res).map(drop)
2378}
2379
2380/// Receive data from a connection-oriented socket. Returns the number of
2381/// bytes read
2382///
2383/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html)
2384pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
2385    unsafe {
2386        let ret = libc::recv(
2387            sockfd,
2388            buf.as_mut_ptr().cast(),
2389            buf.len() as size_t,
2390            flags.bits(),
2391        );
2392
2393        Errno::result(ret).map(|r| r as usize)
2394    }
2395}
2396
2397/// Receive data from a connectionless or connection-oriented socket. Returns
2398/// the number of bytes read and, for connectionless sockets,  the socket
2399/// address of the sender.
2400///
2401/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html)
2402pub fn recvfrom<T: SockaddrLike>(
2403    sockfd: RawFd,
2404    buf: &mut [u8],
2405) -> Result<(usize, Option<T>)> {
2406    unsafe {
2407        let mut addr = mem::MaybeUninit::<T>::uninit();
2408        let mut len = mem::size_of_val(&addr) as socklen_t;
2409
2410        let ret = Errno::result(libc::recvfrom(
2411            sockfd,
2412            buf.as_mut_ptr().cast(),
2413            buf.len() as size_t,
2414            0,
2415            addr.as_mut_ptr().cast(),
2416            &mut len as *mut socklen_t,
2417        ))? as usize;
2418
2419        Ok((ret, T::from_raw(addr.assume_init().as_ptr(), Some(len))))
2420    }
2421}
2422
2423/// Send a message to a socket
2424///
2425/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html)
2426pub fn sendto(
2427    fd: RawFd,
2428    buf: &[u8],
2429    addr: &dyn SockaddrLike,
2430    flags: MsgFlags,
2431) -> Result<usize> {
2432    let ret = unsafe {
2433        libc::sendto(
2434            fd,
2435            buf.as_ptr().cast(),
2436            buf.len() as size_t,
2437            flags.bits(),
2438            addr.as_ptr(),
2439            addr.len(),
2440        )
2441    };
2442
2443    Errno::result(ret).map(|r| r as usize)
2444}
2445
2446/// Send data to a connection-oriented socket. Returns the number of bytes read
2447///
2448/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html)
2449pub fn send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize> {
2450    let ret = unsafe {
2451        libc::send(fd, buf.as_ptr().cast(), buf.len() as size_t, flags.bits())
2452    };
2453
2454    Errno::result(ret).map(|r| r as usize)
2455}
2456
2457/*
2458 *
2459 * ===== Socket Options =====
2460 *
2461 */
2462
2463/// Represents a socket option that can be retrieved.
2464pub trait GetSockOpt: Copy {
2465    type Val;
2466
2467    /// Look up the value of this socket option on the given socket.
2468    fn get<F: AsFd>(&self, fd: &F) -> Result<Self::Val>;
2469}
2470
2471/// Represents a socket option that can be set.
2472pub trait SetSockOpt: Clone {
2473    type Val: ?Sized;
2474
2475    /// Set the value of this socket option on the given socket.
2476    fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()>;
2477}
2478
2479/// Get the current value for the requested socket option
2480///
2481/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html)
2482pub fn getsockopt<F: AsFd, O: GetSockOpt>(fd: &F, opt: O) -> Result<O::Val> {
2483    opt.get(fd)
2484}
2485
2486/// Sets the value for the requested socket option
2487///
2488/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
2489///
2490/// # Examples
2491///
2492/// ```
2493/// use nix::sys::socket::setsockopt;
2494/// use nix::sys::socket::sockopt::KeepAlive;
2495/// use std::net::TcpListener;
2496///
2497/// let listener = TcpListener::bind("0.0.0.0:0").unwrap();
2498/// let fd = listener;
2499/// let res = setsockopt(&fd, KeepAlive, &true);
2500/// assert!(res.is_ok());
2501/// ```
2502pub fn setsockopt<F: AsFd, O: SetSockOpt>(
2503    fd: &F,
2504    opt: O,
2505    val: &O::Val,
2506) -> Result<()> {
2507    opt.set(fd, val)
2508}
2509
2510/// Get the address of the peer connected to the socket `fd`.
2511///
2512/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html)
2513pub fn getpeername<T: SockaddrLike>(fd: RawFd) -> Result<T> {
2514    unsafe {
2515        let mut addr = mem::MaybeUninit::<T>::uninit();
2516        let mut len = T::size();
2517
2518        let ret = libc::getpeername(fd, addr.as_mut_ptr().cast(), &mut len);
2519
2520        Errno::result(ret)?;
2521
2522        T::from_raw(addr.assume_init().as_ptr(), Some(len)).ok_or(Errno::EINVAL)
2523    }
2524}
2525
2526/// Get the current address to which the socket `fd` is bound.
2527///
2528/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html)
2529pub fn getsockname<T: SockaddrLike>(fd: RawFd) -> Result<T> {
2530    unsafe {
2531        let mut addr = mem::MaybeUninit::<T>::uninit();
2532        let mut len = T::size();
2533
2534        let ret = libc::getsockname(fd, addr.as_mut_ptr().cast(), &mut len);
2535
2536        Errno::result(ret)?;
2537
2538        T::from_raw(addr.assume_init().as_ptr(), Some(len)).ok_or(Errno::EINVAL)
2539    }
2540}
2541
2542#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
2543pub enum Shutdown {
2544    /// Further receptions will be disallowed.
2545    Read,
2546    /// Further  transmissions will be disallowed.
2547    Write,
2548    /// Further receptions and transmissions will be disallowed.
2549    Both,
2550}
2551
2552/// Shut down part of a full-duplex connection.
2553///
2554/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html)
2555pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> {
2556    unsafe {
2557        use libc::shutdown;
2558
2559        let how = match how {
2560            Shutdown::Read => libc::SHUT_RD,
2561            Shutdown::Write => libc::SHUT_WR,
2562            Shutdown::Both => libc::SHUT_RDWR,
2563        };
2564
2565        Errno::result(shutdown(df, how)).map(drop)
2566    }
2567}