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