nix/sys/socket/
mod.rs

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