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