nix/sys/socket/
mod.rs

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