Skip to main content

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#[cfg_attr(all(target_env = "musl", target_pointer_width = "32"), doc = "See <https://github.com/nix-rust/nix/issues/2698> for notes regarding 32-bit musl")]
776#[cfg_attr(all(target_env = "musl", target_pointer_width = "32"), doc = "```no_run")]
777#[cfg_attr(any(not(target_env = "musl"), target_pointer_width = "64"), doc="```")]
778    /// # #[macro_use] extern crate nix;
779    /// # use nix::sys::socket::*;
780    /// # use nix::sys::time::*;
781    /// # use std::io::{IoSlice, IoSliceMut};
782    /// # use std::time::*;
783    /// # use std::str::FromStr;
784    /// # use std::os::unix::io::AsRawFd;
785    /// # fn main() {
786    /// // Set up
787    /// let message = "Ohayō!".as_bytes();
788    /// let in_socket = socket(
789    ///     AddressFamily::Inet,
790    ///     SockType::Datagram,
791    ///     SockFlag::empty(),
792    ///     None).unwrap();
793    /// setsockopt(&in_socket, sockopt::ReceiveTimestamp, &true).unwrap();
794    /// let localhost = SockaddrIn::from_str("127.0.0.1:0").unwrap();
795    /// bind(in_socket.as_raw_fd(), &localhost).unwrap();
796    /// let address: SockaddrIn = getsockname(in_socket.as_raw_fd()).unwrap();
797    /// // Get initial time
798    /// let time0 = SystemTime::now();
799    /// // Send the message
800    /// let iov = [IoSlice::new(message)];
801    /// let flags = MsgFlags::empty();
802    /// let l = sendmsg(in_socket.as_raw_fd(), &iov, &[], flags, Some(&address)).unwrap();
803    /// assert_eq!(message.len(), l);
804    /// // Receive the message
805    /// let mut buffer = vec![0u8; message.len()];
806    /// let mut cmsgspace = cmsg_space!(TimeVal);
807    /// let mut iov = [IoSliceMut::new(&mut buffer)];
808    /// let r = recvmsg::<SockaddrIn>(in_socket.as_raw_fd(), &mut iov, Some(&mut cmsgspace), flags)
809    ///     .unwrap();
810    /// let rtime = match r.cmsgs().unwrap().next() {
811    ///     Some(ControlMessageOwned::ScmTimestamp(rtime)) => rtime,
812    ///     Some(_) => panic!("Unexpected control message"),
813    ///     None => panic!("No control message")
814    /// };
815    /// // Check the final time
816    /// let time1 = SystemTime::now();
817    /// // the packet's received timestamp should lie in-between the two system
818    /// // times, unless the system clock was adjusted in the meantime.
819    /// let rduration = Duration::new(rtime.tv_sec() as u64,
820    ///                               rtime.tv_usec() as u32 * 1000);
821    /// assert!(time0.duration_since(UNIX_EPOCH).unwrap() <= rduration);
822    /// assert!(rduration <= time1.duration_since(UNIX_EPOCH).unwrap());
823    /// // Close socket
824    /// # }
825    /// ```
826    ScmTimestamp(TimeVal),
827    /// A set of nanosecond resolution timestamps
828    ///
829    /// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
830    #[cfg(linux_android)]
831    ScmTimestampsns(Timestamps),
832    /// Nanoseconds resolution timestamp
833    ///
834    /// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
835    #[cfg(linux_android)]
836    ScmTimestampns(TimeSpec),
837    /// Realtime clock timestamp
838    ///
839    /// [Further reading](https://man.freebsd.org/cgi/man.cgi?setsockopt)
840    #[cfg(target_os = "freebsd")]
841    ScmRealtime(TimeSpec),
842    /// Monotonic clock timestamp
843    ///
844    /// [Further reading](https://man.freebsd.org/cgi/man.cgi?setsockopt)
845    #[cfg(target_os = "freebsd")]
846    ScmMonotonic(TimeSpec),
847    #[cfg(any(linux_android, apple_targets, target_os = "netbsd"))]
848    #[cfg(feature = "net")]
849    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
850    Ipv4PacketInfo(libc::in_pktinfo),
851    #[cfg(any(linux_android, bsd))]
852    #[cfg(feature = "net")]
853    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
854    Ipv6PacketInfo(libc::in6_pktinfo),
855    #[cfg(bsd)]
856    #[cfg(feature = "net")]
857    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
858    Ipv4RecvIf(libc::sockaddr_dl),
859    #[cfg(bsd)]
860    #[cfg(feature = "net")]
861    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
862    Ipv4RecvDstAddr(libc::in_addr),
863    #[cfg(any(linux_android, target_os = "freebsd"))]
864    #[cfg(feature = "net")]
865    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
866    Ipv4OrigDstAddr(libc::sockaddr_in),
867    #[cfg(any(linux_android, target_os = "freebsd"))]
868    #[cfg(feature = "net")]
869    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
870    Ipv6OrigDstAddr(libc::sockaddr_in6),
871
872    /// Time-to-Live (TTL) header field of the incoming IPv4 packet.
873    ///
874    /// [Further reading](https://www.man7.org/linux/man-pages/man7/ip.7.html)
875    #[cfg(linux_android)]
876    #[cfg(feature = "net")]
877    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
878    Ipv4Ttl(i32),
879
880    /// Time-to-Live (TTL) header field of the incoming IPv4 packet.
881    ///
882    /// [Further reading](https://datatracker.ietf.org/doc/html/rfc3542.html)
883    #[cfg(target_os = "freebsd")]
884    #[cfg(feature = "net")]
885    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
886    Ipv4Ttl(u8),
887
888    /// Hop Limit header field of the incoming IPv6 packet.
889    ///
890    /// [Further reading for Linux](https://www.man7.org/linux/man-pages/man7/ip.7.html)
891    /// [Further reading for FreeBSD](https://datatracker.ietf.org/doc/html/rfc3542.html)
892    #[cfg(any(linux_android, target_os = "freebsd"))]
893    #[cfg(feature = "net")]
894    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
895    Ipv6HopLimit(i32),
896
897    /// Retrieve the DSCP (ToS) header field of the incoming IPv4 packet.
898    #[cfg(any(linux_android, target_os = "freebsd"))]
899    #[cfg(feature = "net")]
900    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
901    Ipv4Tos(u8),
902
903    /// Retrieve the DSCP (Traffic Class) header field of the incoming IPv6 packet.
904    #[cfg(any(linux_android, target_os = "freebsd"))]
905    #[cfg(feature = "net")]
906    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
907    Ipv6TClass(i32),
908
909    /// UDP Generic Receive Offload (GRO) allows receiving multiple UDP
910    /// packets from a single sender.
911    /// Fixed-size payloads are following one by one in a receive buffer.
912    /// This Control Message indicates the size of all smaller packets,
913    /// except, maybe, the last one.
914    ///
915    /// `UdpGroSegment` socket option should be enabled on a socket
916    /// to allow receiving GRO packets.
917    #[cfg(linux_android)]
918    #[cfg(feature = "net")]
919    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
920    UdpGroSegments(i32),
921
922    /// SO_RXQ_OVFL indicates that an unsigned 32 bit value
923    /// ancilliary msg (cmsg) should be attached to recieved
924    /// skbs indicating the number of packets dropped by the
925    /// socket between the last recieved packet and this
926    /// received packet.
927    ///
928    /// `RxqOvfl` socket option should be enabled on a socket
929    /// to allow receiving the drop counter.
930    #[cfg(any(linux_android, target_os = "fuchsia"))]
931    RxqOvfl(u32),
932
933    /// Socket error queue control messages read with the `MSG_ERRQUEUE` flag.
934    #[cfg(linux_android)]
935    #[cfg(feature = "net")]
936    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
937    Ipv4RecvErr(libc::sock_extended_err, Option<sockaddr_in>),
938    /// Socket error queue control messages read with the `MSG_ERRQUEUE` flag.
939    #[cfg(linux_android)]
940    #[cfg(feature = "net")]
941    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
942    Ipv6RecvErr(libc::sock_extended_err, Option<sockaddr_in6>),
943
944    /// `SOL_TLS` messages of type `TLS_GET_RECORD_TYPE`
945    #[cfg(any(target_os = "linux"))]
946    TlsGetRecordType(TlsGetRecordType),
947
948    /// Catch-all variant for unimplemented cmsg types.
949    Unknown(UnknownCmsg),
950}
951
952/// For representing packet timestamps via `SO_TIMESTAMPING` interface
953#[cfg(linux_android)]
954#[derive(Copy, Clone, Debug, Eq, PartialEq)]
955pub struct Timestamps {
956    /// software based timestamp, usually one containing data
957    pub system: TimeSpec,
958    /// legacy timestamp, usually empty
959    pub hw_trans: TimeSpec,
960    /// hardware based timestamp
961    pub hw_raw: TimeSpec,
962}
963
964/// These constants correspond to TLS 1.2 message types, as defined in
965/// RFC 5246, Appendix A.1
966#[cfg(any(target_os = "linux"))]
967#[derive(Clone, Copy, PartialEq, Eq, Debug)]
968#[repr(u8)]
969#[non_exhaustive]
970pub enum TlsGetRecordType {
971    ChangeCipherSpec ,
972    Alert,
973    Handshake,
974    ApplicationData,
975    Unknown(u8),
976}
977
978#[cfg(any(target_os = "linux"))]
979impl From<u8> for TlsGetRecordType {
980    fn from(x: u8) -> Self {
981        match x {
982            20 => TlsGetRecordType::ChangeCipherSpec,
983            21 => TlsGetRecordType::Alert,
984            22 => TlsGetRecordType::Handshake,
985            23 => TlsGetRecordType::ApplicationData,
986            _ => TlsGetRecordType::Unknown(x),
987        }
988    }
989}
990
991impl ControlMessageOwned {
992    /// Decodes a `ControlMessageOwned` from raw bytes.
993    ///
994    /// This is only safe to call if the data is correct for the message type
995    /// specified in the header. Normally, the kernel ensures that this is the
996    /// case. "Correct" in this case includes correct length, alignment and
997    /// actual content.
998    // Clippy complains about the pointer alignment of `p`, not understanding
999    // that it's being fed to a function that can handle that.
1000    #[allow(clippy::cast_ptr_alignment)]
1001    unsafe fn decode_from(header: &cmsghdr) -> ControlMessageOwned
1002    {
1003        let p = unsafe { CMSG_DATA(header) };
1004        // The cast is not unnecessary on all platforms.
1005        #[allow(clippy::unnecessary_cast)]
1006        let len = header as *const _ as usize + header.cmsg_len as usize
1007            - p as usize;
1008        match (header.cmsg_level, header.cmsg_type) {
1009            (libc::SOL_SOCKET, libc::SCM_RIGHTS) => {
1010                let n = len / mem::size_of::<RawFd>();
1011                let mut fds = Vec::with_capacity(n);
1012                for i in 0..n {
1013                    unsafe {
1014                        let fdp = (p as *const RawFd).add(i);
1015                        fds.push(ptr::read_unaligned(fdp));
1016                    }
1017                }
1018                ControlMessageOwned::ScmRights(fds)
1019            },
1020            #[cfg(linux_android)]
1021            (libc::SOL_SOCKET, libc::SCM_CREDENTIALS) => {
1022                let cred: libc::ucred = unsafe { ptr::read_unaligned(p as *const _) };
1023                ControlMessageOwned::ScmCredentials(cred.into())
1024            }
1025            #[cfg(freebsdlike)]
1026            (libc::SOL_SOCKET, libc::SCM_CREDS) => {
1027                let cred: libc::cmsgcred = unsafe { ptr::read_unaligned(p as *const _) };
1028                ControlMessageOwned::ScmCreds(cred.into())
1029            }
1030            #[cfg(not(any(target_os = "aix", target_os = "haiku", target_os = "cygwin")))]
1031            (libc::SOL_SOCKET, libc::SCM_TIMESTAMP) => {
1032                let tv: libc::timeval = unsafe { ptr::read_unaligned(p as *const _) };
1033                ControlMessageOwned::ScmTimestamp(TimeVal::from(tv))
1034            },
1035            #[cfg(linux_android)]
1036            (libc::SOL_SOCKET, libc::SCM_TIMESTAMPNS) => {
1037                let ts: libc::timespec = unsafe { ptr::read_unaligned(p as *const _) };
1038                ControlMessageOwned::ScmTimestampns(TimeSpec::from(ts))
1039            }
1040            #[cfg(target_os = "freebsd")]
1041            (libc::SOL_SOCKET, libc::SCM_REALTIME) => {
1042                let ts: libc::timespec = unsafe { ptr::read_unaligned(p as *const _) };
1043                ControlMessageOwned::ScmRealtime(TimeSpec::from(ts))
1044            }
1045            #[cfg(target_os = "freebsd")]
1046            (libc::SOL_SOCKET, libc::SCM_MONOTONIC) => {
1047                let ts: libc::timespec = unsafe { ptr::read_unaligned(p as *const _) };
1048                ControlMessageOwned::ScmMonotonic(TimeSpec::from(ts))
1049            }
1050            #[cfg(linux_android)]
1051            (libc::SOL_SOCKET, libc::SCM_TIMESTAMPING) => {
1052                let tp = p as *const libc::timespec;
1053                let ts: libc::timespec = unsafe { ptr::read_unaligned(tp) };
1054                let system = TimeSpec::from(ts);
1055                let ts: libc::timespec = unsafe { ptr::read_unaligned(tp.add(1)) };
1056                let hw_trans = TimeSpec::from(ts);
1057                let ts: libc::timespec = unsafe { ptr::read_unaligned(tp.add(2)) };
1058                let hw_raw = TimeSpec::from(ts);
1059                let timestamping = Timestamps { system, hw_trans, hw_raw };
1060                ControlMessageOwned::ScmTimestampsns(timestamping)
1061            }
1062            #[cfg(any(target_os = "freebsd", linux_android, apple_targets))]
1063            #[cfg(feature = "net")]
1064            (libc::IPPROTO_IPV6, libc::IPV6_PKTINFO) => {
1065                let info = unsafe { ptr::read_unaligned(p as *const libc::in6_pktinfo) };
1066                ControlMessageOwned::Ipv6PacketInfo(info)
1067            }
1068            #[cfg(any(linux_android, apple_targets, target_os = "netbsd"))]
1069            #[cfg(feature = "net")]
1070            (libc::IPPROTO_IP, libc::IP_PKTINFO) => {
1071                let info = unsafe { ptr::read_unaligned(p as *const libc::in_pktinfo) };
1072                ControlMessageOwned::Ipv4PacketInfo(info)
1073            }
1074            #[cfg(bsd)]
1075            #[cfg(feature = "net")]
1076            (libc::IPPROTO_IP, libc::IP_RECVIF) => {
1077                let dl = unsafe { ptr::read_unaligned(p as *const libc::sockaddr_dl) };
1078                ControlMessageOwned::Ipv4RecvIf(dl)
1079            },
1080            #[cfg(bsd)]
1081            #[cfg(feature = "net")]
1082            (libc::IPPROTO_IP, libc::IP_RECVDSTADDR) => {
1083                let dl = unsafe { ptr::read_unaligned(p as *const libc::in_addr) };
1084                ControlMessageOwned::Ipv4RecvDstAddr(dl)
1085            },
1086            #[cfg(any(linux_android, target_os = "freebsd"))]
1087            #[cfg(feature = "net")]
1088            (libc::IPPROTO_IP, libc::IP_ORIGDSTADDR) => {
1089                let dl = unsafe { ptr::read_unaligned(p as *const libc::sockaddr_in) };
1090                ControlMessageOwned::Ipv4OrigDstAddr(dl)
1091            },
1092            #[cfg(linux_android)]
1093            #[cfg(feature = "net")]
1094            (libc::SOL_UDP, libc::UDP_GRO) => {
1095                let gso_size: i32 = unsafe { ptr::read_unaligned(p as *const _) };
1096                ControlMessageOwned::UdpGroSegments(gso_size)
1097            },
1098            #[cfg(any(linux_android, target_os = "fuchsia"))]
1099            (libc::SOL_SOCKET, libc::SO_RXQ_OVFL) => {
1100                let drop_counter = unsafe { ptr::read_unaligned(p as *const u32) };
1101                ControlMessageOwned::RxqOvfl(drop_counter)
1102            },
1103            #[cfg(linux_android)]
1104            #[cfg(feature = "net")]
1105            (libc::IPPROTO_IP, libc::IP_RECVERR) => {
1106                let (err, addr) = unsafe { Self::recv_err_helper::<sockaddr_in>(p, len) };
1107                ControlMessageOwned::Ipv4RecvErr(err, addr)
1108            },
1109            #[cfg(linux_android)]
1110            #[cfg(feature = "net")]
1111            (libc::IPPROTO_IPV6, libc::IPV6_RECVERR) => {
1112                let (err, addr) = unsafe { Self::recv_err_helper::<sockaddr_in6>(p, len) };
1113                ControlMessageOwned::Ipv6RecvErr(err, addr)
1114            },
1115            #[cfg(any(
1116                all(linux_android, not(target_env = "uclibc")),
1117                target_os = "freebsd"
1118            ))]
1119            #[cfg(feature = "net")]
1120            (libc::IPPROTO_IPV6, libc::IPV6_ORIGDSTADDR) => {
1121                let dl = unsafe { ptr::read_unaligned(p as *const libc::sockaddr_in6) };
1122                ControlMessageOwned::Ipv6OrigDstAddr(dl)
1123            },
1124            #[cfg(any(target_os = "linux"))]
1125            (libc::SOL_TLS, libc::TLS_GET_RECORD_TYPE) => {
1126                let content_type = unsafe { ptr::read_unaligned(p as *const u8) };
1127                ControlMessageOwned::TlsGetRecordType(content_type.into())
1128            },
1129            #[cfg(linux_android)]
1130            #[cfg(feature = "net")]
1131            (libc::IPPROTO_IP, libc::IP_TTL) => {
1132                let ttl = unsafe { ptr::read_unaligned(p as *const i32) };
1133                ControlMessageOwned::Ipv4Ttl(ttl)
1134            },
1135            #[cfg(target_os = "freebsd")]
1136            #[cfg(feature = "net")]
1137            (libc::IPPROTO_IP, libc::IP_RECVTTL) => {
1138                let ttl: u8 = unsafe { ptr::read_unaligned(p as *const u8) };
1139                ControlMessageOwned::Ipv4Ttl(ttl)
1140            },
1141            #[cfg(any(linux_android, target_os = "freebsd"))]
1142            #[cfg(feature = "net")]
1143            (libc::IPPROTO_IPV6, libc::IPV6_HOPLIMIT) => {
1144                let ttl = unsafe { ptr::read_unaligned(p as *const i32) };
1145                ControlMessageOwned::Ipv6HopLimit(ttl)
1146            },
1147            #[cfg(linux_android)]
1148            #[cfg(feature = "net")]
1149            (libc::IPPROTO_IP, libc::IP_TOS) => {
1150                let tos = unsafe { ptr::read_unaligned(p as *const u8) };
1151                ControlMessageOwned::Ipv4Tos(tos)
1152            },
1153            #[cfg(target_os = "freebsd")]
1154            #[cfg(feature = "net")]
1155            (libc::IPPROTO_IP, libc::IP_RECVTOS) => {
1156                let tos = unsafe { ptr::read_unaligned(p as *const u8) };
1157                ControlMessageOwned::Ipv4Tos(tos)
1158            },
1159            #[cfg(any(linux_android, target_os = "freebsd"))]
1160            #[cfg(feature = "net")]
1161            (libc::IPPROTO_IPV6, libc::IPV6_TCLASS) => {
1162                let tc = unsafe { ptr::read_unaligned(p as *const i32) };
1163                ControlMessageOwned::Ipv6TClass(tc)
1164            },
1165            (_, _) => {
1166                let sl = unsafe { std::slice::from_raw_parts(p, len) };
1167                let ucmsg = UnknownCmsg {
1168                    cmsg_header: *header,
1169                    data_bytes: Vec::<u8>::from(sl),
1170                };
1171                ControlMessageOwned::Unknown(ucmsg)
1172            }
1173        }
1174    }
1175
1176    #[cfg(linux_android)]
1177    #[cfg(feature = "net")]
1178    #[allow(clippy::cast_ptr_alignment)]    // False positive
1179    unsafe fn recv_err_helper<T>(p: *mut libc::c_uchar, len: usize) -> (libc::sock_extended_err, Option<T>) {
1180        let ee = p as *const libc::sock_extended_err;
1181        let err = unsafe { ptr::read_unaligned(ee) };
1182
1183        // For errors originating on the network, SO_EE_OFFENDER(ee) points inside the p[..len]
1184        // CMSG_DATA buffer.  For local errors, there is no address included in the control
1185        // message, and SO_EE_OFFENDER(ee) points beyond the end of the buffer.  So, we need to
1186        // validate that the address object is in-bounds before we attempt to copy it.
1187        let addrp = unsafe { libc::SO_EE_OFFENDER(ee) as *const T };
1188
1189        if unsafe { addrp.offset(1) } as usize - (p as usize) > len {
1190            (err, None)
1191        } else {
1192            (err, Some(unsafe { ptr::read_unaligned(addrp) }))
1193        }
1194    }
1195}
1196
1197/// A type-safe zero-copy wrapper around a single control message, as used with
1198/// [`sendmsg`].  More types may be added to this enum; do not exhaustively
1199/// pattern-match it.
1200///
1201/// [Further reading](https://man7.org/linux/man-pages/man3/cmsg.3.html)
1202#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1203#[non_exhaustive]
1204pub enum ControlMessage<'a> {
1205    /// A message of type `SCM_RIGHTS`, containing an array of file
1206    /// descriptors passed between processes.
1207    ///
1208    /// See the description in the "Ancillary messages" section of the
1209    /// [unix(7) man page](https://man7.org/linux/man-pages/man7/unix.7.html).
1210    ///
1211    /// Using multiple `ScmRights` messages for a single `sendmsg` call isn't
1212    /// recommended since it causes platform-dependent behaviour: It might
1213    /// swallow all but the first `ScmRights` message or fail with `EINVAL`.
1214    /// Instead, you can put all fds to be passed into a single `ScmRights`
1215    /// message.
1216    ScmRights(&'a [RawFd]),
1217    /// A message of type `SCM_CREDENTIALS`, containing the pid, uid and gid of
1218    /// a process connected to the socket.
1219    ///
1220    /// This is similar to the socket option `SO_PEERCRED`, but requires a
1221    /// process to explicitly send its credentials. A process running as root is
1222    /// allowed to specify any credentials, while credentials sent by other
1223    /// processes are verified by the kernel.
1224    ///
1225    /// For further information, please refer to the
1226    /// [`unix(7)`](https://man7.org/linux/man-pages/man7/unix.7.html) man page.
1227    #[cfg(linux_android)]
1228    ScmCredentials(&'a UnixCredentials),
1229    /// A message of type `SCM_CREDS`, containing the pid, uid, euid, gid and groups of
1230    /// a process connected to the socket.
1231    ///
1232    /// This is similar to the socket options `LOCAL_CREDS` and `LOCAL_PEERCRED`, but
1233    /// requires a process to explicitly send its credentials.
1234    ///
1235    /// Credentials are always overwritten by the kernel, so this variant does have
1236    /// any data, unlike the receive-side
1237    /// [`ControlMessageOwned::ScmCreds`].
1238    ///
1239    /// For further information, please refer to the
1240    /// [`unix(4)`](https://www.freebsd.org/cgi/man.cgi?query=unix) man page.
1241    #[cfg(freebsdlike)]
1242    ScmCreds,
1243
1244    /// Set IV for `AF_ALG` crypto API.
1245    ///
1246    /// For further information, please refer to the
1247    /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
1248    #[cfg(linux_android)]
1249    AlgSetIv(&'a [u8]),
1250    /// Set crypto operation for `AF_ALG` crypto API. It may be one of
1251    /// `ALG_OP_ENCRYPT` or `ALG_OP_DECRYPT`
1252    ///
1253    /// For further information, please refer to the
1254    /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
1255    #[cfg(linux_android)]
1256    AlgSetOp(&'a libc::c_int),
1257    /// Set the length of associated authentication data (AAD) (applicable only to AEAD algorithms)
1258    /// for `AF_ALG` crypto API.
1259    ///
1260    /// For further information, please refer to the
1261    /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
1262    #[cfg(linux_android)]
1263    AlgSetAeadAssoclen(&'a u32),
1264
1265    /// UDP GSO makes it possible for applications to generate network packets
1266    /// for a virtual MTU much greater than the real one.
1267    /// The length of the send data no longer matches the expected length on
1268    /// the wire.
1269    /// The size of the datagram payload as it should appear on the wire may be
1270    /// passed through this control message.
1271    /// Send buffer should consist of multiple fixed-size wire payloads
1272    /// following one by one, and the last, possibly smaller one.
1273    #[cfg(linux_android)]
1274    #[cfg(feature = "net")]
1275    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1276    UdpGsoSegments(&'a u16),
1277
1278    /// Configure the sending addressing and interface for v4.
1279    ///
1280    /// For further information, please refer to the
1281    /// [`ip(7)`](https://man7.org/linux/man-pages/man7/ip.7.html) man page.
1282    #[cfg(any(linux_android, target_os = "netbsd", apple_targets))]
1283    #[cfg(feature = "net")]
1284    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1285    Ipv4PacketInfo(&'a libc::in_pktinfo),
1286
1287    /// Configure the sending addressing and interface for v6.
1288    ///
1289    /// For further information, please refer to the
1290    /// [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html) man page.
1291    #[cfg(any(linux_android,
1292              target_os = "netbsd",
1293              target_os = "freebsd",
1294              apple_targets))]
1295    #[cfg(feature = "net")]
1296    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1297    Ipv6PacketInfo(&'a libc::in6_pktinfo),
1298
1299    /// Configure the IPv4 source address with `IP_SENDSRCADDR`.
1300    #[cfg(any(freebsdlike, netbsdlike))]
1301    #[cfg(feature = "net")]
1302    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1303    Ipv4SendSrcAddr(&'a libc::in_addr),
1304
1305    /// Configure the Time-to-Live for v4 traffic.
1306    #[cfg(linux_android)]
1307    #[cfg(feature = "net")]
1308    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1309    Ipv4Ttl(&'a libc::c_int),
1310
1311    /// Configure the Time-to-Live for v4 traffic.
1312    #[cfg(target_os = "freebsd")]
1313    #[cfg(feature = "net")]
1314    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1315    Ipv4Ttl(&'a libc::c_uchar),
1316
1317    /// Configure the hop limit for v6 multicast traffic.
1318    ///
1319    /// Set the IPv6 hop limit for this message. The argument is an integer
1320    /// between 0 and 255. A value of -1 will set the hop limit to the route
1321    /// default if possible on the interface. Without this cmsg,  packets sent
1322    /// with sendmsg have a hop limit of 1 and will not leave the local network.
1323    /// For further information, please refer to the
1324    /// [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html) man page.
1325    #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
1326    #[cfg(feature = "net")]
1327    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1328    Ipv6HopLimit(&'a libc::c_int),
1329
1330    /// SO_RXQ_OVFL indicates that an unsigned 32 bit value
1331    /// ancillary msg (cmsg) should be attached to received
1332    /// skbs indicating the number of packets dropped by the
1333    /// socket between the last received packet and this
1334    /// received packet.
1335    #[cfg(any(linux_android, target_os = "fuchsia"))]
1336    RxqOvfl(&'a u32),
1337
1338    /// Configure the transmission time of packets.
1339    ///
1340    /// For further information, please refer to the
1341    /// [`tc-etf(8)`](https://man7.org/linux/man-pages/man8/tc-etf.8.html) man
1342    /// page.
1343    #[cfg(target_os = "linux")]
1344    TxTime(&'a u64),
1345
1346    /// Configure DSCP / IP TOS for outgoing v4 packets.
1347    ///
1348    /// Further information can be found [here](https://en.wikipedia.org/wiki/Differentiated_services).
1349    #[cfg(any(linux_android, target_os = "freebsd"))]
1350    #[cfg(feature = "net")]
1351    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1352    Ipv4Tos(&'a u8),
1353
1354    /// Configure DSCP / IPv6 TCLASS for outgoing v6 packets.
1355    ///
1356    /// Further information can be found [here](https://en.wikipedia.org/wiki/Differentiated_services).
1357    #[cfg(any(linux_android, target_os = "freebsd"))]
1358    #[cfg(feature = "net")]
1359    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1360    Ipv6TClass(&'a i32),
1361}
1362
1363/// Control messages that are currently not supported by Nix.
1364#[derive(Clone, Debug, Eq, PartialEq)]
1365pub struct UnknownCmsg {
1366    /// Control message header.
1367    pub cmsg_header: cmsghdr,
1368    /// Bytes of the control message data.
1369    pub data_bytes: Vec<u8>
1370}
1371
1372impl ControlMessage<'_> {
1373    /// The value of CMSG_SPACE on this message.
1374    /// Safe because CMSG_SPACE is always safe
1375    fn space(&self) -> usize {
1376        unsafe{CMSG_SPACE(self.len() as libc::c_uint) as usize}
1377    }
1378
1379    /// The value of CMSG_LEN on this message.
1380    /// Safe because CMSG_LEN is always safe
1381    #[cfg(any(target_os = "android",
1382              all(target_os = "linux", not(any(target_env = "musl", target_env = "ohos"))),
1383              target_os = "cygwin"))]
1384    fn cmsg_len(&self) -> usize {
1385        unsafe{CMSG_LEN(self.len() as libc::c_uint) as usize}
1386    }
1387
1388    #[cfg(not(any(target_os = "android",
1389              all(target_os = "linux", not(any(target_env = "musl", target_env = "ohos"))),
1390              target_os = "cygwin")))]
1391    fn cmsg_len(&self) -> libc::c_uint {
1392        unsafe{CMSG_LEN(self.len() as libc::c_uint)}
1393    }
1394
1395    /// Return a reference to the payload data as a byte pointer
1396    fn copy_to_cmsg_data(&self, cmsg_data: *mut u8) {
1397        let data_ptr = match *self {
1398            ControlMessage::ScmRights(fds) => {
1399                fds as *const _ as *const u8
1400            },
1401            #[cfg(linux_android)]
1402            ControlMessage::ScmCredentials(creds) => {
1403                &creds.0 as *const libc::ucred as *const u8
1404            }
1405            #[cfg(freebsdlike)]
1406            ControlMessage::ScmCreds => {
1407                // The kernel overwrites the data, we just zero it
1408                // to make sure it's not uninitialized memory
1409                unsafe { ptr::write_bytes(cmsg_data, 0, self.len()) };
1410                return
1411            }
1412            #[cfg(linux_android)]
1413            ControlMessage::AlgSetIv(iv) => {
1414                #[allow(deprecated)] // https://github.com/rust-lang/libc/issues/1501
1415                let af_alg_iv = libc::af_alg_iv {
1416                    ivlen: iv.len() as u32,
1417                    iv: [0u8; 0],
1418                };
1419
1420                let size = mem::size_of_val(&af_alg_iv);
1421
1422                unsafe {
1423                    ptr::copy_nonoverlapping(
1424                        &af_alg_iv as *const _ as *const u8,
1425                        cmsg_data,
1426                        size,
1427                    );
1428                    ptr::copy_nonoverlapping(
1429                        iv.as_ptr(),
1430                        cmsg_data.add(size),
1431                        iv.len()
1432                    );
1433                };
1434
1435                return
1436            },
1437            #[cfg(linux_android)]
1438            ControlMessage::AlgSetOp(op) => {
1439                op as *const _ as *const u8
1440            },
1441            #[cfg(linux_android)]
1442            ControlMessage::AlgSetAeadAssoclen(len) => {
1443                len as *const _ as *const u8
1444            },
1445            #[cfg(linux_android)]
1446            #[cfg(feature = "net")]
1447            ControlMessage::UdpGsoSegments(gso_size) => {
1448                gso_size as *const _ as *const u8
1449            },
1450            #[cfg(any(linux_android, target_os = "netbsd", apple_targets))]
1451            #[cfg(feature = "net")]
1452            ControlMessage::Ipv4PacketInfo(info) => info as *const _ as *const u8,
1453            #[cfg(any(linux_android, target_os = "netbsd",
1454                      target_os = "freebsd", apple_targets))]
1455            #[cfg(feature = "net")]
1456            ControlMessage::Ipv6PacketInfo(info) => info as *const _ as *const u8,
1457            #[cfg(any(freebsdlike, netbsdlike))]
1458            #[cfg(feature = "net")]
1459            ControlMessage::Ipv4SendSrcAddr(addr) => addr as *const _ as *const u8,
1460            #[cfg(linux_android)]
1461            #[cfg(feature = "net")]
1462            ControlMessage::Ipv4Ttl(ttl) => ttl as *const i32 as *const u8,
1463            #[cfg(target_os = "freebsd")]
1464            #[cfg(feature = "net")]
1465            ControlMessage::Ipv4Ttl(ttl) => ttl as *const u8,
1466            #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
1467            #[cfg(feature = "net")]
1468            ControlMessage::Ipv6HopLimit(limit) => limit as *const _ as *const u8,
1469            #[cfg(any(linux_android, target_os = "fuchsia"))]
1470            ControlMessage::RxqOvfl(drop_count) => {
1471                drop_count as *const _ as *const u8
1472            },
1473            #[cfg(target_os = "linux")]
1474            ControlMessage::TxTime(tx_time) => {
1475                tx_time as *const _ as *const u8
1476            },
1477            #[cfg(any(linux_android, target_os = "freebsd"))]
1478            #[cfg(feature = "net")]
1479            ControlMessage::Ipv4Tos(tos) => {
1480                tos as *const _
1481            },
1482            #[cfg(any(linux_android, target_os = "freebsd"))]
1483            #[cfg(feature = "net")]
1484            ControlMessage::Ipv6TClass(tclass) => {
1485                tclass as *const _ as *const u8
1486            },
1487        };
1488        unsafe {
1489            ptr::copy_nonoverlapping(
1490                data_ptr,
1491                cmsg_data,
1492                self.len()
1493            )
1494        };
1495    }
1496
1497    /// The size of the payload, excluding its cmsghdr
1498    fn len(&self) -> usize {
1499        match *self {
1500            ControlMessage::ScmRights(fds) => {
1501                mem::size_of_val(fds)
1502            },
1503            #[cfg(linux_android)]
1504            ControlMessage::ScmCredentials(creds) => {
1505                mem::size_of_val(creds)
1506            }
1507            #[cfg(freebsdlike)]
1508            ControlMessage::ScmCreds => {
1509                mem::size_of::<libc::cmsgcred>()
1510            }
1511            #[cfg(linux_android)]
1512            ControlMessage::AlgSetIv(iv) => {
1513                mem::size_of::<&[u8]>() + iv.len()
1514            },
1515            #[cfg(linux_android)]
1516            ControlMessage::AlgSetOp(op) => {
1517                mem::size_of_val(op)
1518            },
1519            #[cfg(linux_android)]
1520            ControlMessage::AlgSetAeadAssoclen(len) => {
1521                mem::size_of_val(len)
1522            },
1523            #[cfg(linux_android)]
1524            #[cfg(feature = "net")]
1525            ControlMessage::UdpGsoSegments(gso_size) => {
1526                mem::size_of_val(gso_size)
1527            },
1528            #[cfg(any(linux_android, target_os = "netbsd", apple_targets))]
1529            #[cfg(feature = "net")]
1530            ControlMessage::Ipv4PacketInfo(info) => mem::size_of_val(info),
1531            #[cfg(any(linux_android, target_os = "netbsd",
1532                      target_os = "freebsd", apple_targets))]
1533            #[cfg(feature = "net")]
1534            ControlMessage::Ipv6PacketInfo(info) => mem::size_of_val(info),
1535            #[cfg(any(freebsdlike, netbsdlike))]
1536            #[cfg(feature = "net")]
1537            ControlMessage::Ipv4SendSrcAddr(addr) => mem::size_of_val(addr),
1538            #[cfg(any(linux_android, target_os = "freebsd"))]
1539            #[cfg(feature = "net")]
1540            ControlMessage::Ipv4Ttl(ttl) => {
1541                mem::size_of_val(ttl)
1542            },
1543            #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
1544            #[cfg(feature = "net")]
1545            ControlMessage::Ipv6HopLimit(limit) => {
1546                mem::size_of_val(limit)
1547            },
1548            #[cfg(any(linux_android, target_os = "fuchsia"))]
1549            ControlMessage::RxqOvfl(drop_count) => {
1550                mem::size_of_val(drop_count)
1551            },
1552            #[cfg(target_os = "linux")]
1553            ControlMessage::TxTime(tx_time) => {
1554                mem::size_of_val(tx_time)
1555            },
1556            #[cfg(any(linux_android, target_os = "freebsd"))]
1557            #[cfg(feature = "net")]
1558            ControlMessage::Ipv4Tos(tos) => {
1559                mem::size_of_val(tos)
1560            },
1561            #[cfg(any(linux_android, target_os = "freebsd"))]
1562            #[cfg(feature = "net")]
1563            ControlMessage::Ipv6TClass(tclass) => {
1564                mem::size_of_val(tclass)
1565            },
1566        }
1567    }
1568
1569    /// Returns the value to put into the `cmsg_level` field of the header.
1570    fn cmsg_level(&self) -> libc::c_int {
1571        match *self {
1572            ControlMessage::ScmRights(_) => libc::SOL_SOCKET,
1573            #[cfg(linux_android)]
1574            ControlMessage::ScmCredentials(_) => libc::SOL_SOCKET,
1575            #[cfg(freebsdlike)]
1576            ControlMessage::ScmCreds => libc::SOL_SOCKET,
1577            #[cfg(linux_android)]
1578            ControlMessage::AlgSetIv(_) | ControlMessage::AlgSetOp(_) |
1579                ControlMessage::AlgSetAeadAssoclen(_) => libc::SOL_ALG,
1580            #[cfg(linux_android)]
1581            #[cfg(feature = "net")]
1582            ControlMessage::UdpGsoSegments(_) => libc::SOL_UDP,
1583            #[cfg(any(linux_android, target_os = "netbsd", apple_targets))]
1584            #[cfg(feature = "net")]
1585            ControlMessage::Ipv4PacketInfo(_) => libc::IPPROTO_IP,
1586            #[cfg(any(linux_android, target_os = "netbsd",
1587                      target_os = "freebsd", apple_targets))]
1588            #[cfg(feature = "net")]
1589            ControlMessage::Ipv6PacketInfo(_) => libc::IPPROTO_IPV6,
1590            #[cfg(any(freebsdlike, netbsdlike))]
1591            #[cfg(feature = "net")]
1592            ControlMessage::Ipv4SendSrcAddr(_) => libc::IPPROTO_IP,
1593            #[cfg(any(linux_android, target_os = "freebsd"))]
1594            #[cfg(feature = "net")]
1595            ControlMessage::Ipv4Ttl(_) => libc::IPPROTO_IP,
1596            #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
1597            #[cfg(feature = "net")]
1598            ControlMessage::Ipv6HopLimit(_) => libc::IPPROTO_IPV6,
1599            #[cfg(any(linux_android, target_os = "fuchsia"))]
1600            ControlMessage::RxqOvfl(_) => libc::SOL_SOCKET,
1601            #[cfg(target_os = "linux")]
1602            ControlMessage::TxTime(_) => libc::SOL_SOCKET,
1603            #[cfg(any(linux_android, target_os = "freebsd"))]
1604            #[cfg(feature = "net")]
1605            ControlMessage::Ipv4Tos(_) => libc::IPPROTO_IP,
1606            #[cfg(any(linux_android, target_os = "freebsd"))]
1607            #[cfg(feature = "net")]
1608            ControlMessage::Ipv6TClass(_) => libc::IPPROTO_IPV6,
1609        }
1610    }
1611
1612    /// Returns the value to put into the `cmsg_type` field of the header.
1613    fn cmsg_type(&self) -> libc::c_int {
1614        match *self {
1615            ControlMessage::ScmRights(_) => libc::SCM_RIGHTS,
1616            #[cfg(linux_android)]
1617            ControlMessage::ScmCredentials(_) => libc::SCM_CREDENTIALS,
1618            #[cfg(freebsdlike)]
1619            ControlMessage::ScmCreds => libc::SCM_CREDS,
1620            #[cfg(linux_android)]
1621            ControlMessage::AlgSetIv(_) => {
1622                libc::ALG_SET_IV
1623            },
1624            #[cfg(linux_android)]
1625            ControlMessage::AlgSetOp(_) => {
1626                libc::ALG_SET_OP
1627            },
1628            #[cfg(linux_android)]
1629            ControlMessage::AlgSetAeadAssoclen(_) => {
1630                libc::ALG_SET_AEAD_ASSOCLEN
1631            },
1632            #[cfg(linux_android)]
1633            #[cfg(feature = "net")]
1634            ControlMessage::UdpGsoSegments(_) => {
1635                libc::UDP_SEGMENT
1636            },
1637            #[cfg(any(linux_android, target_os = "netbsd", apple_targets))]
1638            #[cfg(feature = "net")]
1639            ControlMessage::Ipv4PacketInfo(_) => libc::IP_PKTINFO,
1640            #[cfg(any(linux_android, target_os = "netbsd",
1641                      target_os = "freebsd", apple_targets))]
1642            #[cfg(feature = "net")]
1643            ControlMessage::Ipv6PacketInfo(_) => libc::IPV6_PKTINFO,
1644            #[cfg(any(freebsdlike, netbsdlike))]
1645            #[cfg(feature = "net")]
1646            ControlMessage::Ipv4SendSrcAddr(_) => libc::IP_SENDSRCADDR,
1647            #[cfg(any(linux_android, target_os = "freebsd"))]
1648            #[cfg(feature = "net")]
1649            ControlMessage::Ipv4Ttl(_) => libc::IP_TTL,
1650            #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))]
1651            #[cfg(feature = "net")]
1652            ControlMessage::Ipv6HopLimit(_) => libc::IPV6_HOPLIMIT,
1653            #[cfg(any(linux_android, target_os = "fuchsia"))]
1654            ControlMessage::RxqOvfl(_) => {
1655                libc::SO_RXQ_OVFL
1656            },
1657            #[cfg(target_os = "linux")]
1658            ControlMessage::TxTime(_) => {
1659                libc::SCM_TXTIME
1660            },
1661            #[cfg(any(linux_android, target_os = "freebsd"))]
1662            #[cfg(feature = "net")]
1663            ControlMessage::Ipv4Tos(_) => {
1664                libc::IP_TOS
1665            },
1666            #[cfg(any(linux_android, target_os = "freebsd"))]
1667            #[cfg(feature = "net")]
1668            ControlMessage::Ipv6TClass(_) => {
1669                libc::IPV6_TCLASS
1670            },
1671        }
1672    }
1673
1674    // Unsafe: cmsg must point to a valid cmsghdr with enough space to
1675    // encode self.
1676    unsafe fn encode_into(&self, cmsg: *mut cmsghdr) {
1677        unsafe {
1678            (*cmsg).cmsg_level = self.cmsg_level();
1679            (*cmsg).cmsg_type = self.cmsg_type();
1680            (*cmsg).cmsg_len = self.cmsg_len();
1681            self.copy_to_cmsg_data( CMSG_DATA(cmsg) );
1682        }
1683    }
1684}
1685
1686
1687/// Send data in scatter-gather vectors to a socket, possibly accompanied
1688/// by ancillary data. Optionally direct the message at the given address,
1689/// as with sendto.
1690///
1691/// Allocates if cmsgs is nonempty.
1692///
1693/// # Examples
1694/// When not directing to any specific address, use `()` for the generic type
1695/// ```
1696/// # use nix::sys::socket::*;
1697/// # use nix::unistd::pipe;
1698/// # use std::io::IoSlice;
1699/// # use std::os::unix::io::AsRawFd;
1700/// let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None,
1701///     SockFlag::empty())
1702///     .unwrap();
1703/// let (r, w) = pipe().unwrap();
1704///
1705/// let iov = [IoSlice::new(b"hello")];
1706/// let fds = [r.as_raw_fd()];
1707/// let cmsg = ControlMessage::ScmRights(&fds);
1708/// sendmsg::<()>(fd1.as_raw_fd(), &iov, &[cmsg], MsgFlags::empty(), None).unwrap();
1709/// ```
1710/// When directing to a specific address, the generic type will be inferred.
1711/// Note that SCM_RIGHTS ancillary data are valid only for AF_UNIX sockets on Solaris.
1712/// ```
1713/// # use nix::sys::socket::*;
1714/// # use nix::unistd::pipe;
1715/// # use std::io::IoSlice;
1716/// # use std::str::FromStr;
1717/// # use std::os::unix::io::AsRawFd;
1718/// let localhost = SockaddrIn::from_str("1.2.3.4:8080").unwrap();
1719/// let fd = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(),
1720///     None).unwrap();
1721/// let (r, w) = pipe().unwrap();
1722///
1723/// let iov = [IoSlice::new(b"hello")];
1724/// let fds = [r.as_raw_fd()];
1725/// let cmsg = ControlMessage::ScmRights(&fds);
1726/// #[cfg(not(target_os = "solaris"))]
1727/// sendmsg(fd.as_raw_fd(), &iov, &[cmsg], MsgFlags::empty(), Some(&localhost)).unwrap();
1728/// ```
1729pub fn sendmsg<S>(fd: RawFd, iov: &[IoSlice<'_>], cmsgs: &[ControlMessage],
1730               flags: MsgFlags, addr: Option<&S>) -> Result<usize>
1731    where S: SockaddrLike
1732{
1733    let capacity = cmsgs.iter().map(|c| c.space()).sum();
1734
1735    // First size the buffer needed to hold the cmsgs.  It must be zeroed,
1736    // because subsequent code will not clear the padding bytes.
1737    let mut cmsg_buffer = vec![0u8; capacity];
1738
1739    let mhdr = pack_mhdr_to_send(&mut cmsg_buffer[..], iov, cmsgs, addr);
1740
1741    let ret = unsafe { libc::sendmsg(fd, &mhdr, flags.bits()) };
1742
1743    Errno::result(ret).map(|r| r as usize)
1744}
1745
1746
1747/// An extension of `sendmsg` that allows the caller to transmit multiple
1748/// messages on a socket using a single system call. This has performance
1749/// benefits for some applications.
1750///
1751/// Allocations are performed for cmsgs and to build `msghdr` buffer
1752///
1753/// # Arguments
1754///
1755/// * `fd`:             Socket file descriptor
1756/// * `data`:           Struct that implements `IntoIterator` with `SendMmsgData` items
1757/// * `flags`:          Optional flags passed directly to the operating system.
1758///
1759/// # Returns
1760/// `Vec` with numbers of sent bytes on each sent message.
1761///
1762/// # References
1763/// [`sendmsg`](fn.sendmsg.html)
1764#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
1765pub fn sendmmsg<'a, XS, AS, C, I, S>(
1766    fd: RawFd,
1767    data: &'a mut MultiHeaders<S>,
1768    slices: XS,
1769    // one address per group of slices
1770    addrs: AS,
1771    // shared across all the messages
1772    cmsgs: C,
1773    flags: MsgFlags
1774) -> crate::Result<MultiResults<'a, S>>
1775    where
1776        XS: IntoIterator<Item = &'a I>,
1777        AS: AsRef<[Option<S>]>,
1778        I: AsRef<[IoSlice<'a>]> + 'a,
1779        C: AsRef<[ControlMessage<'a>]> + 'a,
1780        S: SockaddrLike + 'a,
1781{
1782
1783    let mut count = 0;
1784
1785
1786    for (i, ((slice, addr), mmsghdr)) in slices.into_iter().zip(addrs.as_ref()).zip(data.items.iter_mut() ).enumerate() {
1787        let p = &mut mmsghdr.msg_hdr;
1788        p.msg_iov = slice.as_ref().as_ptr().cast_mut().cast();
1789        p.msg_iovlen = slice.as_ref().len() as _;
1790
1791        p.msg_namelen = addr.as_ref().map_or(0, S::len);
1792        p.msg_name = addr.as_ref().map_or(ptr::null(), S::as_ptr).cast_mut().cast();
1793
1794        // Encode each cmsg.  This must happen after initializing the header because
1795        // CMSG_NEXT_HDR and friends read the msg_control and msg_controllen fields.
1796        // CMSG_FIRSTHDR is always safe
1797        let mut pmhdr: *mut cmsghdr = unsafe { CMSG_FIRSTHDR(p) };
1798        for cmsg in cmsgs.as_ref() {
1799            assert_ne!(pmhdr, ptr::null_mut());
1800            // Safe because we know that pmhdr is valid, and we initialized it with
1801            // sufficient space
1802            unsafe { cmsg.encode_into(pmhdr) };
1803            // Safe because mhdr is valid
1804            pmhdr = unsafe { CMSG_NXTHDR(p, pmhdr) };
1805        }
1806
1807        // Doing an unchecked addition is alright here, as the only way to obtain an instance of `MultiHeaders`
1808        // is through the `preallocate` function, which takes an `usize` as an argument to define its size,
1809        // which also provides an upper bound for the size of this zipped iterator. Thus, `i < usize::MAX` or in
1810        // other words: `count` doesn't overflow
1811        count = i + 1;
1812    }
1813
1814    // SAFETY: all pointers are guaranteed to be valid for the scope of this function. `count` does represent the
1815    // maximum number of messages that can be sent safely (i.e. `count` is the minimum of the sizes of `slices`,
1816    // `data.items` and `addrs`)
1817    let sent = Errno::result(unsafe {
1818        libc::sendmmsg(
1819            fd,
1820            data.items.as_mut_ptr(),
1821            count as _,
1822            flags.bits() as _
1823        )
1824    })? as usize;
1825
1826    Ok(MultiResults {
1827        rmm: data,
1828        current_index: 0,
1829        received: sent
1830    })
1831
1832}
1833
1834
1835#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
1836#[derive(Debug)]
1837/// Preallocated structures needed for [`recvmmsg`] and [`sendmmsg`] functions
1838pub struct MultiHeaders<S> {
1839    // preallocated boxed slice of mmsghdr
1840    items: Box<[libc::mmsghdr]>,
1841    addresses: Box<[mem::MaybeUninit<S>]>,
1842    // while we are not using it directly - this is used to store control messages
1843    // and we retain pointers to them inside items array
1844    _cmsg_buffers: Option<Box<[u8]>>,
1845    msg_controllen: usize,
1846}
1847
1848#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
1849impl<S> MultiHeaders<S> {
1850    /// Preallocate structure used by [`recvmmsg`] and [`sendmmsg`] takes number of headers to preallocate
1851    ///
1852    /// `cmsg_buffer` should be created with [`cmsg_space!`] if needed
1853    pub fn preallocate(num_slices: usize, cmsg_buffer: Option<Vec<u8>>) -> Self
1854    where
1855        S: Copy + SockaddrLike,
1856    {
1857        // we will be storing pointers to addresses inside mhdr - convert it into boxed
1858        // slice so it can'be changed later by pushing anything into self.addresses
1859        let mut addresses = vec![std::mem::MaybeUninit::<S>::uninit(); num_slices].into_boxed_slice();
1860
1861        let msg_controllen = cmsg_buffer.as_ref().map_or(0, |v| v.capacity());
1862
1863        // we'll need a cmsg_buffer for each slice, we preallocate a vector and split
1864        // it into "slices" parts
1865        let mut cmsg_buffers =
1866            cmsg_buffer.map(|v| vec![0u8; v.capacity() * num_slices].into_boxed_slice());
1867
1868        let items = addresses
1869            .iter_mut()
1870            .enumerate()
1871            .map(|(ix, address)| {
1872                let (ptr, cap) = match &mut cmsg_buffers {
1873                    Some(v) => (&mut v[ix * msg_controllen] as *mut u8, msg_controllen),
1874                    None => (std::ptr::null_mut(), 0),
1875                };
1876                let msg_hdr = unsafe { pack_mhdr_to_receive(std::ptr::null_mut(), 0, ptr, cap, address.as_mut_ptr()) };
1877                libc::mmsghdr {
1878                    msg_hdr,
1879                    msg_len: 0,
1880                }
1881            })
1882            .collect::<Vec<_>>();
1883
1884        Self {
1885            items: items.into_boxed_slice(),
1886            addresses,
1887            _cmsg_buffers: cmsg_buffers,
1888            msg_controllen,
1889        }
1890    }
1891}
1892
1893/// An extension of recvmsg that allows the caller to receive multiple messages from a socket using a single system call.
1894///
1895/// This has performance benefits for some applications.
1896///
1897/// This method performs no allocations.
1898///
1899/// Returns an iterator producing [`RecvMsg`], one per received messages. Each `RecvMsg` can produce
1900/// iterators over [`IoSlice`] with [`iovs`][RecvMsg::iovs`] and
1901/// `ControlMessageOwned` with [`cmsgs`][RecvMsg::cmsgs].
1902///
1903/// # Bugs (in underlying implementation, at least in Linux)
1904/// The timeout argument does not work as intended. The timeout is checked only after the receipt
1905/// of each datagram, so that if up to `vlen`-1 datagrams are received before the timeout expires,
1906/// but then no further datagrams are received, the call will block forever.
1907///
1908/// If an error occurs after at least one message has been received, the call succeeds, and returns
1909/// the number of messages received. The error code is expected to be returned on a subsequent
1910/// call to recvmmsg(). In the current implementation, however, the error code can be
1911/// overwritten in the meantime by an unrelated network event on a socket, for example an
1912/// incoming ICMP packet.
1913// On aarch64 linux using recvmmsg and trying to get hardware/kernel timestamps might not
1914// always produce the desired results - see https://github.com/nix-rust/nix/pull/1744 for more
1915// details
1916#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
1917pub fn recvmmsg<'a, XS, S, I>(
1918    fd: RawFd,
1919    data: &'a mut MultiHeaders<S>,
1920    slices: XS,
1921    flags: MsgFlags,
1922    mut timeout: Option<crate::sys::time::TimeSpec>,
1923) -> crate::Result<MultiResults<'a, S>>
1924where
1925    XS: IntoIterator<Item = &'a mut I>,
1926    I: AsMut<[IoSliceMut<'a>]> + 'a,
1927{
1928    let mut count = 0;
1929    for (i, (slice, mmsghdr)) in slices.into_iter().zip(data.items.iter_mut()).enumerate() {
1930        let p = &mut mmsghdr.msg_hdr;
1931        p.msg_iov = slice.as_mut().as_mut_ptr().cast();
1932        p.msg_iovlen = slice.as_mut().len() as _;
1933
1934        // Doing an unchecked addition is alright here, as the only way to obtain an instance of `MultiHeaders`
1935        // is through the `preallocate` function, which takes an `usize` as an argument to define its size,
1936        // which also provides an upper bound for the size of this zipped iterator. Thus, `i < usize::MAX` or in
1937        // other words: `count` doesn't overflow
1938        count = i + 1;
1939    }
1940
1941    let timeout_ptr = timeout
1942        .as_mut()
1943        .map_or_else(std::ptr::null_mut, |t| t as *mut _ as *mut libc::timespec);
1944
1945    // SAFETY: all pointers are guaranteed to be valid for the scope of this function. `count` does represent the
1946    // maximum number of messages that can be received safely (i.e. `count` is the minimum of the sizes of `slices` and `data.items`)
1947    let received = Errno::result(unsafe {
1948        libc::recvmmsg(
1949            fd,
1950            data.items.as_mut_ptr(),
1951            count as _,
1952            flags.bits() as _,
1953            timeout_ptr,
1954        )
1955    })? as usize;
1956
1957    Ok(MultiResults {
1958        rmm: data,
1959        current_index: 0,
1960        received,
1961    })
1962}
1963
1964/// Iterator over results of [`recvmmsg`]/[`sendmmsg`]
1965#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
1966#[derive(Debug)]
1967pub struct MultiResults<'a, S> {
1968    // preallocated structures
1969    rmm: &'a MultiHeaders<S>,
1970    current_index: usize,
1971    received: usize,
1972}
1973
1974#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
1975impl<'a, S> Iterator for MultiResults<'a, S>
1976where
1977    S: Copy + SockaddrLike,
1978{
1979    type Item = RecvMsg<'a, 'a, S>;
1980
1981    // The cast is not unnecessary on all platforms.
1982    #[allow(clippy::unnecessary_cast)]
1983    fn next(&mut self) -> Option<Self::Item> {
1984        if self.current_index >= self.received {
1985            return None;
1986        }
1987        let mmsghdr = self.rmm.items[self.current_index];
1988
1989        // as long as we are not reading past the index writen by recvmmsg - address
1990        // will be initialized
1991        let address = unsafe { self.rmm.addresses[self.current_index].assume_init() };
1992
1993        self.current_index += 1;
1994        Some(unsafe {
1995            read_mhdr(
1996                mmsghdr.msg_hdr,
1997                mmsghdr.msg_len as isize,
1998                self.rmm.msg_controllen,
1999                address,
2000            )
2001        })
2002    }
2003}
2004
2005impl<'a, S> RecvMsg<'_, 'a, S> {
2006    /// Iterate over the filled io slices pointed by this msghdr
2007    pub fn iovs(&self) -> IoSliceIterator<'a> {
2008        IoSliceIterator {
2009            index: 0,
2010            remaining: self.bytes,
2011            slices: unsafe {
2012                // safe for as long as mgdr is properly initialized and references are valid.
2013                // for multi messages API we initialize it with an empty
2014                // slice and replace with a concrete buffer
2015                // for single message API we hold a lifetime reference to ioslices
2016                std::slice::from_raw_parts(self.mhdr.msg_iov as *const _, self.mhdr.msg_iovlen as _)
2017            },
2018        }
2019    }
2020}
2021
2022#[derive(Debug)]
2023pub struct IoSliceIterator<'a> {
2024    index: usize,
2025    remaining: usize,
2026    slices: &'a [IoSlice<'a>],
2027}
2028
2029impl<'a> Iterator for IoSliceIterator<'a> {
2030    type Item = &'a [u8];
2031
2032    fn next(&mut self) -> Option<Self::Item> {
2033        if self.index >= self.slices.len() {
2034            return None;
2035        }
2036        let slice = &self.slices[self.index][..self.remaining.min(self.slices[self.index].len())];
2037        self.remaining -= slice.len();
2038        self.index += 1;
2039        if slice.is_empty() {
2040            return None;
2041        }
2042
2043        Some(slice)
2044    }
2045}
2046
2047unsafe fn read_mhdr<'a, 'i, S>(
2048    mhdr: msghdr,
2049    r: isize,
2050    msg_controllen: usize,
2051    mut address: S,
2052) -> RecvMsg<'a, 'i, S>
2053    where S: SockaddrLike
2054{
2055    // The cast is not unnecessary on all platforms.
2056    #[allow(clippy::unnecessary_cast)]
2057    let cmsghdr = {
2058        let ptr = if mhdr.msg_controllen > 0 {
2059            debug_assert!(!mhdr.msg_control.is_null());
2060            debug_assert!(msg_controllen >= mhdr.msg_controllen as usize);
2061            unsafe { CMSG_FIRSTHDR(&mhdr as *const msghdr) }
2062        } else {
2063            ptr::null()
2064        };
2065
2066        unsafe {
2067            ptr.as_ref()
2068        }
2069    };
2070
2071    // Ignore errors if this socket address has statically-known length
2072    //
2073    // This is to ensure that unix socket addresses have their length set appropriately.
2074    let _ = unsafe { address.set_length(mhdr.msg_namelen as usize) };
2075
2076    RecvMsg {
2077        bytes: r as usize,
2078        cmsghdr,
2079        address: Some(address),
2080        flags: MsgFlags::from_bits_truncate(mhdr.msg_flags),
2081        mhdr,
2082        iobufs: std::marker::PhantomData,
2083    }
2084}
2085
2086/// Pack pointers to various structures into into msghdr
2087///
2088/// # Safety
2089/// `iov_buffer` and `iov_buffer_len` must point to a slice
2090/// of `IoSliceMut` and number of available elements or be a null pointer and 0
2091///
2092/// `cmsg_buffer` and `cmsg_capacity` must point to a byte buffer used
2093/// to store control headers later or be a null pointer and 0 if control
2094/// headers are not used
2095///
2096/// Buffers must remain valid for the whole lifetime of msghdr
2097unsafe fn pack_mhdr_to_receive<S>(
2098    iov_buffer: *mut IoSliceMut,
2099    iov_buffer_len: usize,
2100    cmsg_buffer: *mut u8,
2101    cmsg_capacity: usize,
2102    address: *mut S,
2103) -> msghdr
2104    where
2105        S: SockaddrLike
2106{
2107    // Musl's msghdr has private fields, so this is the only way to
2108    // initialize it.
2109    let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
2110    let p = mhdr.as_mut_ptr();
2111    unsafe {
2112        // it is important to use as_mut_ptr() here since S can be
2113        // a zero sized type representing by a dangling pointer.
2114        // as_mut_ptr() handles this case and uses a null pointer instead
2115        (*p).msg_name = (*address).as_mut_ptr() as *mut c_void;
2116        (*p).msg_namelen = S::size();
2117        (*p).msg_iov = iov_buffer as *mut iovec;
2118        (*p).msg_iovlen = iov_buffer_len as _;
2119        (*p).msg_control = cmsg_buffer as *mut c_void;
2120        (*p).msg_controllen = cmsg_capacity as _;
2121        (*p).msg_flags = 0;
2122        mhdr.assume_init()
2123    }
2124}
2125
2126fn pack_mhdr_to_send<'a, I, C, S>(
2127    cmsg_buffer: &mut [u8],
2128    iov: I,
2129    cmsgs: C,
2130    addr: Option<&S>
2131) -> msghdr
2132    where
2133        I: AsRef<[IoSlice<'a>]>,
2134        C: AsRef<[ControlMessage<'a>]>,
2135        S: SockaddrLike + 'a
2136{
2137    let capacity = cmsg_buffer.len();
2138
2139    // The message header must be initialized before the individual cmsgs.
2140    let cmsg_ptr = if capacity > 0 {
2141        cmsg_buffer.as_mut_ptr().cast()
2142    } else {
2143        ptr::null_mut()
2144    };
2145
2146    let mhdr = unsafe {
2147        // Musl's msghdr has private fields, so this is the only way to
2148        // initialize it.
2149        let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
2150        let p = mhdr.as_mut_ptr();
2151        (*p).msg_name = addr.map(S::as_ptr).unwrap_or(ptr::null()).cast_mut().cast();
2152        (*p).msg_namelen = addr.map(S::len).unwrap_or(0);
2153        // transmute iov into a mutable pointer.  sendmsg doesn't really mutate
2154        // the buffer, but the standard says that it takes a mutable pointer
2155        (*p).msg_iov = iov.as_ref().as_ptr().cast_mut().cast();
2156        (*p).msg_iovlen = iov.as_ref().len() as _;
2157        (*p).msg_control = cmsg_ptr;
2158        (*p).msg_controllen = capacity as _;
2159        (*p).msg_flags = 0;
2160        mhdr.assume_init()
2161    };
2162
2163    // Encode each cmsg.  This must happen after initializing the header because
2164    // CMSG_NEXT_HDR and friends read the msg_control and msg_controllen fields.
2165    // CMSG_FIRSTHDR is always safe
2166    let mut pmhdr: *mut cmsghdr = unsafe { CMSG_FIRSTHDR(&mhdr as *const msghdr) };
2167    for cmsg in cmsgs.as_ref() {
2168        assert_ne!(pmhdr, ptr::null_mut());
2169        // Safe because we know that pmhdr is valid, and we initialized it with
2170        // sufficient space
2171        unsafe { cmsg.encode_into(pmhdr) };
2172        // Safe because mhdr is valid
2173        pmhdr = unsafe { CMSG_NXTHDR(&mhdr as *const msghdr, pmhdr) };
2174    }
2175
2176    mhdr
2177}
2178
2179/// Receive message in scatter-gather vectors from a socket, and
2180/// optionally receive ancillary data into the provided buffer.
2181/// If no ancillary data is desired, use () as the type parameter.
2182///
2183/// # Arguments
2184///
2185/// * `fd`:             Socket file descriptor
2186/// * `iov`:            Scatter-gather list of buffers to receive the message
2187/// * `cmsg_buffer`:    Space to receive ancillary data.  Should be created by
2188///                     [`cmsg_space!`](../../macro.cmsg_space.html)
2189/// * `flags`:          Optional flags passed directly to the operating system.
2190///
2191/// # References
2192/// [recvmsg(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html)
2193pub fn recvmsg<'a, 'outer, 'inner, S>(fd: RawFd, iov: &'outer mut [IoSliceMut<'inner>],
2194                   mut cmsg_buffer: Option<&'a mut [u8]>,
2195                   flags: MsgFlags) -> Result<RecvMsg<'a, 'outer, S>>
2196    where S: SockaddrLike + 'a,
2197    'inner: 'outer
2198{
2199    let mut address = mem::MaybeUninit::uninit();
2200
2201    let (msg_control, msg_controllen) = cmsg_buffer.as_mut()
2202        .map(|v| (v.as_mut_ptr(), v.len()))
2203        .unwrap_or((ptr::null_mut(), 0));
2204    let mut mhdr = unsafe {
2205        pack_mhdr_to_receive(iov.as_mut().as_mut_ptr(), iov.len(), msg_control, msg_controllen, address.as_mut_ptr())
2206    };
2207
2208    let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) };
2209
2210    let r = Errno::result(ret)?;
2211
2212    Ok(unsafe { read_mhdr(mhdr, r, msg_controllen, address.assume_init()) })
2213}
2214}
2215
2216/// Create an endpoint for communication
2217///
2218/// The `protocol` specifies a particular protocol to be used with the
2219/// socket.  Normally only a single protocol exists to support a
2220/// particular socket type within a given protocol family, in which case
2221/// protocol can be specified as `None`.  However, it is possible that many
2222/// protocols may exist, in which case a particular protocol must be
2223/// specified in this manner.
2224///
2225/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html)
2226pub fn socket<T: Into<Option<SockProtocol>>>(
2227    domain: AddressFamily,
2228    ty: SockType,
2229    flags: SockFlag,
2230    protocol: T,
2231) -> Result<OwnedFd> {
2232    let protocol = match protocol.into() {
2233        None => 0,
2234        Some(p) => p as c_int,
2235    };
2236
2237    // SockFlags are usually embedded into `ty`, but we don't do that in `nix` because it's a
2238    // little easier to understand by separating it out. So we have to merge these bitfields
2239    // here.
2240    let mut ty = ty as c_int;
2241    ty |= flags.bits();
2242
2243    let res = unsafe { libc::socket(domain as c_int, ty, protocol) };
2244
2245    match res {
2246        -1 => Err(Errno::last()),
2247        fd => {
2248            // Safe because libc::socket returned success
2249            unsafe { Ok(OwnedFd::from_raw_fd(fd)) }
2250        }
2251    }
2252}
2253
2254/// Create a pair of connected sockets
2255///
2256/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/socketpair.html)
2257pub fn socketpair<T: Into<Option<SockProtocol>>>(
2258    domain: AddressFamily,
2259    ty: SockType,
2260    protocol: T,
2261    flags: SockFlag,
2262) -> Result<(OwnedFd, OwnedFd)> {
2263    let protocol = match protocol.into() {
2264        None => 0,
2265        Some(p) => p as c_int,
2266    };
2267
2268    // SockFlags are usually embedded into `ty`, but we don't do that in `nix` because it's a
2269    // little easier to understand by separating it out. So we have to merge these bitfields
2270    // here.
2271    let mut ty = ty as c_int;
2272    ty |= flags.bits();
2273
2274    let mut fds = [-1, -1];
2275
2276    let res = unsafe {
2277        libc::socketpair(domain as c_int, ty, protocol, fds.as_mut_ptr())
2278    };
2279    Errno::result(res)?;
2280
2281    // Safe because socketpair returned success.
2282    unsafe { Ok((OwnedFd::from_raw_fd(fds[0]), OwnedFd::from_raw_fd(fds[1]))) }
2283}
2284
2285#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2286pub struct Backlog(i32);
2287
2288impl Backlog {
2289    /// Sets the listen queue size to system `SOMAXCONN` value
2290    pub const MAXCONN: Self = Self(libc::SOMAXCONN);
2291    /// Sets the listen queue size to -1 for system supporting it
2292    #[cfg(any(target_os = "linux", target_os = "freebsd"))]
2293    pub const MAXALLOWABLE: Self = Self(-1);
2294
2295    /// Create a `Backlog`, an `EINVAL` will be returned if `val` is invalid.
2296    pub fn new<I: Into<i32>>(val: I) -> Result<Self> {
2297        cfg_if! {
2298            if #[cfg(any(target_os = "linux", target_os = "freebsd"))] {
2299                const MIN: i32 = -1;
2300            } else {
2301                const MIN: i32 = 0;
2302            }
2303        }
2304
2305        let val = val.into();
2306
2307        if !(MIN..=Self::MAXCONN.0).contains(&val) {
2308            return Err(Errno::EINVAL);
2309        }
2310
2311        Ok(Self(val))
2312    }
2313}
2314
2315impl From<Backlog> for i32 {
2316    fn from(backlog: Backlog) -> Self {
2317        backlog.0
2318    }
2319}
2320
2321/// Listen for connections on a socket
2322///
2323/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html)
2324pub fn listen<F: AsFd>(sock: &F, backlog: Backlog) -> Result<()> {
2325    let fd = sock.as_fd().as_raw_fd();
2326    let res = unsafe { libc::listen(fd, backlog.into()) };
2327
2328    Errno::result(res).map(drop)
2329}
2330
2331/// Bind a name to a socket
2332///
2333/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html)
2334pub fn bind(fd: RawFd, addr: &dyn SockaddrLike) -> Result<()> {
2335    let res = unsafe { libc::bind(fd, addr.as_ptr(), addr.len()) };
2336
2337    Errno::result(res).map(drop)
2338}
2339
2340/// Accept a connection on a socket
2341///
2342/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html)
2343pub fn accept(sockfd: RawFd) -> Result<RawFd> {
2344    let res = unsafe { libc::accept(sockfd, ptr::null_mut(), ptr::null_mut()) };
2345
2346    Errno::result(res)
2347}
2348
2349/// Accept a connection on a socket
2350///
2351/// [Further reading](https://man7.org/linux/man-pages/man2/accept.2.html)
2352#[cfg(any(
2353    all(
2354        target_os = "android",
2355        any(
2356            target_arch = "aarch64",
2357            target_arch = "x86",
2358            target_arch = "x86_64"
2359        )
2360    ),
2361    freebsdlike,
2362    netbsdlike,
2363    target_os = "emscripten",
2364    target_os = "fuchsia",
2365    solarish,
2366    target_os = "linux",
2367))]
2368pub fn accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd> {
2369    let res = unsafe {
2370        libc::accept4(sockfd, ptr::null_mut(), ptr::null_mut(), flags.bits())
2371    };
2372
2373    Errno::result(res)
2374}
2375
2376/// Initiate a connection on a socket
2377///
2378/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html)
2379pub fn connect(fd: RawFd, addr: &dyn SockaddrLike) -> Result<()> {
2380    let res = unsafe { libc::connect(fd, addr.as_ptr(), addr.len()) };
2381
2382    Errno::result(res).map(drop)
2383}
2384
2385/// Receive data from a connection-oriented socket. Returns the number of
2386/// bytes read
2387///
2388/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html)
2389pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
2390    unsafe {
2391        let ret = libc::recv(
2392            sockfd,
2393            buf.as_mut_ptr().cast(),
2394            buf.len() as size_t,
2395            flags.bits(),
2396        );
2397
2398        Errno::result(ret).map(|r| r as usize)
2399    }
2400}
2401
2402/// Receive data from a connectionless or connection-oriented socket. Returns
2403/// the number of bytes read and, for connectionless sockets,  the socket
2404/// address of the sender.
2405///
2406/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html)
2407pub fn recvfrom<T: SockaddrLike>(
2408    sockfd: RawFd,
2409    buf: &mut [u8],
2410) -> Result<(usize, Option<T>)> {
2411    unsafe {
2412        let mut addr = mem::MaybeUninit::<T>::uninit();
2413        let mut len = mem::size_of_val(&addr) as socklen_t;
2414
2415        let ret = Errno::result(libc::recvfrom(
2416            sockfd,
2417            buf.as_mut_ptr().cast(),
2418            buf.len() as size_t,
2419            0,
2420            addr.as_mut_ptr().cast(),
2421            &mut len as *mut socklen_t,
2422        ))? as usize;
2423
2424        Ok((ret, T::from_raw(addr.assume_init().as_ptr(), Some(len))))
2425    }
2426}
2427
2428/// Send a message to a socket
2429///
2430/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html)
2431pub fn sendto(
2432    fd: RawFd,
2433    buf: &[u8],
2434    addr: &dyn SockaddrLike,
2435    flags: MsgFlags,
2436) -> Result<usize> {
2437    let ret = unsafe {
2438        libc::sendto(
2439            fd,
2440            buf.as_ptr().cast(),
2441            buf.len() as size_t,
2442            flags.bits(),
2443            addr.as_ptr(),
2444            addr.len(),
2445        )
2446    };
2447
2448    Errno::result(ret).map(|r| r as usize)
2449}
2450
2451/// Send data to a connection-oriented socket. Returns the number of bytes read
2452///
2453/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html)
2454pub fn send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize> {
2455    let ret = unsafe {
2456        libc::send(fd, buf.as_ptr().cast(), buf.len() as size_t, flags.bits())
2457    };
2458
2459    Errno::result(ret).map(|r| r as usize)
2460}
2461
2462/*
2463 *
2464 * ===== Socket Options =====
2465 *
2466 */
2467
2468/// Represents a socket option that can be retrieved.
2469pub trait GetSockOpt: Copy {
2470    type Val;
2471
2472    /// Look up the value of this socket option on the given socket.
2473    fn get<F: AsFd>(&self, fd: &F) -> Result<Self::Val>;
2474}
2475
2476/// Represents a socket option that can be set.
2477pub trait SetSockOpt: Clone {
2478    type Val: ?Sized;
2479
2480    /// Set the value of this socket option on the given socket.
2481    fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()>;
2482}
2483
2484/// Get the current value for the requested socket option
2485///
2486/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html)
2487pub fn getsockopt<F: AsFd, O: GetSockOpt>(fd: &F, opt: O) -> Result<O::Val> {
2488    opt.get(fd)
2489}
2490
2491/// Sets the value for the requested socket option
2492///
2493/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
2494///
2495/// # Examples
2496///
2497/// ```
2498/// use nix::sys::socket::setsockopt;
2499/// use nix::sys::socket::sockopt::KeepAlive;
2500/// use std::net::TcpListener;
2501///
2502/// let listener = TcpListener::bind("0.0.0.0:0").unwrap();
2503/// let fd = listener;
2504/// let res = setsockopt(&fd, KeepAlive, &true);
2505/// assert!(res.is_ok());
2506/// ```
2507pub fn setsockopt<F: AsFd, O: SetSockOpt>(
2508    fd: &F,
2509    opt: O,
2510    val: &O::Val,
2511) -> Result<()> {
2512    opt.set(fd, val)
2513}
2514
2515/// Get the address of the peer connected to the socket `fd`.
2516///
2517/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html)
2518pub fn getpeername<T: SockaddrLike>(fd: RawFd) -> Result<T> {
2519    unsafe {
2520        let mut addr = mem::MaybeUninit::<T>::uninit();
2521        let mut len = T::size();
2522
2523        let ret = libc::getpeername(fd, addr.as_mut_ptr().cast(), &mut len);
2524
2525        Errno::result(ret)?;
2526
2527        T::from_raw(addr.assume_init().as_ptr(), Some(len)).ok_or(Errno::EINVAL)
2528    }
2529}
2530
2531/// Get the current address to which the socket `fd` is bound.
2532///
2533/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html)
2534pub fn getsockname<T: SockaddrLike>(fd: RawFd) -> Result<T> {
2535    unsafe {
2536        let mut addr = mem::MaybeUninit::<T>::uninit();
2537        let mut len = T::size();
2538
2539        let ret = libc::getsockname(fd, addr.as_mut_ptr().cast(), &mut len);
2540
2541        Errno::result(ret)?;
2542
2543        T::from_raw(addr.assume_init().as_ptr(), Some(len)).ok_or(Errno::EINVAL)
2544    }
2545}
2546
2547#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
2548pub enum Shutdown {
2549    /// Further receptions will be disallowed.
2550    Read,
2551    /// Further  transmissions will be disallowed.
2552    Write,
2553    /// Further receptions and transmissions will be disallowed.
2554    Both,
2555}
2556
2557/// Shut down part of a full-duplex connection.
2558///
2559/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html)
2560pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> {
2561    unsafe {
2562        use libc::shutdown;
2563
2564        let how = match how {
2565            Shutdown::Read => libc::SHUT_RD,
2566            Shutdown::Write => libc::SHUT_WR,
2567            Shutdown::Both => libc::SHUT_RDWR,
2568        };
2569
2570        Errno::result(shutdown(df, how)).map(drop)
2571    }
2572}