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