1 use super::socket_addr;
2 use crate::net::{SocketAddr, UnixStream};
3 use crate::sys::unix::net::new_socket;
4 use std::os::unix::io::{AsRawFd, FromRawFd};
5 use std::os::unix::net;
6 use std::path::Path;
7 use std::{io, mem};
8 
bind(path: &Path) -> io::Result<net::UnixListener>9 pub(crate) fn bind(path: &Path) -> io::Result<net::UnixListener> {
10     let socket = new_socket(libc::AF_UNIX, libc::SOCK_STREAM)?;
11     let (sockaddr, socklen) = socket_addr(path)?;
12     let sockaddr = &sockaddr as *const libc::sockaddr_un as *const libc::sockaddr;
13 
14     syscall!(bind(socket, sockaddr, socklen))
15         .and_then(|_| syscall!(listen(socket, 1024)))
16         .map_err(|err| {
17             // Close the socket if we hit an error, ignoring the error from
18             // closing since we can't pass back two errors.
19             let _ = unsafe { libc::close(socket) };
20             err
21         })
22         .map(|_| unsafe { net::UnixListener::from_raw_fd(socket) })
23 }
24 
accept(listener: &net::UnixListener) -> io::Result<(UnixStream, SocketAddr)>25 pub(crate) fn accept(listener: &net::UnixListener) -> io::Result<(UnixStream, SocketAddr)> {
26     let sockaddr = mem::MaybeUninit::<libc::sockaddr_un>::zeroed();
27 
28     // This is safe to assume because a `libc::sockaddr_un` filled with `0`
29     // bytes is properly initialized.
30     //
31     // `0` is a valid value for `sockaddr_un::sun_family`; it is
32     // `libc::AF_UNSPEC`.
33     //
34     // `[0; 108]` is a valid value for `sockaddr_un::sun_path`; it begins an
35     // abstract path.
36     let mut sockaddr = unsafe { sockaddr.assume_init() };
37 
38     sockaddr.sun_family = libc::AF_UNIX as libc::sa_family_t;
39     let mut socklen = mem::size_of_val(&sockaddr) as libc::socklen_t;
40 
41     #[cfg(not(any(
42         target_os = "ios",
43         target_os = "macos",
44         target_os = "netbsd",
45         target_os = "solaris",
46         // Android x86's seccomp profile forbids calls to `accept4(2)`
47         // See https://github.com/tokio-rs/mio/issues/1445 for details
48         all(
49             target_arch = "x86",
50             target_os = "android"
51         )
52     )))]
53     let socket = {
54         let flags = libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC;
55         syscall!(accept4(
56             listener.as_raw_fd(),
57             &mut sockaddr as *mut libc::sockaddr_un as *mut libc::sockaddr,
58             &mut socklen,
59             flags
60         ))
61         .map(|socket| unsafe { net::UnixStream::from_raw_fd(socket) })
62     };
63 
64     #[cfg(any(
65         target_os = "ios",
66         target_os = "macos",
67         target_os = "netbsd",
68         target_os = "solaris",
69         all(
70             target_arch = "x86",
71             target_os = "android"
72         )
73     ))]
74     let socket = syscall!(accept(
75         listener.as_raw_fd(),
76         &mut sockaddr as *mut libc::sockaddr_un as *mut libc::sockaddr,
77         &mut socklen,
78     ))
79     .and_then(|socket| {
80         // Ensure the socket is closed if either of the `fcntl` calls
81         // error below.
82         let s = unsafe { net::UnixStream::from_raw_fd(socket) };
83         syscall!(fcntl(socket, libc::F_SETFD, libc::FD_CLOEXEC))?;
84 
85         // See https://github.com/tokio-rs/mio/issues/1450
86         #[cfg(all(target_arch = "x86",target_os = "android"))]
87         syscall!(fcntl(socket, libc::F_SETFL, libc::O_NONBLOCK))?;
88 
89         Ok(s)
90     });
91 
92     socket
93         .map(UnixStream::from_std)
94         .map(|stream| (stream, SocketAddr::from_parts(sockaddr, socklen)))
95 }
96 
local_addr(listener: &net::UnixListener) -> io::Result<SocketAddr>97 pub(crate) fn local_addr(listener: &net::UnixListener) -> io::Result<SocketAddr> {
98     super::local_addr(listener.as_raw_fd())
99 }
100