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