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