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