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         // Android x86's seccomp profile forbids calls to `accept4(2)`
46         // See https://github.com/tokio-rs/mio/issues/1445 for details
47         all(
48             target_arch = "x86",
49             target_os = "android"
50         )
51     )))]
52     let socket = {
53         let flags = libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC;
54         syscall!(accept4(
55             listener.as_raw_fd(),
56             &mut sockaddr as *mut libc::sockaddr_un as *mut libc::sockaddr,
57             &mut socklen,
58             flags
59         ))
60         .map(|socket| unsafe { net::UnixStream::from_raw_fd(socket) })
61     };
62 
63     #[cfg(any(
64         target_os = "ios",
65         target_os = "macos",
66         target_os = "netbsd",
67         all(target_arch = "x86", target_os = "android")
68     ))]
69     let socket = syscall!(accept(
70         listener.as_raw_fd(),
71         &mut sockaddr as *mut libc::sockaddr_un as *mut libc::sockaddr,
72         &mut socklen,
73     ))
74     .and_then(|socket| {
75         // Ensure the socket is closed if either of the `fcntl` calls
76         // error below.
77         let s = unsafe { net::UnixStream::from_raw_fd(socket) };
78         syscall!(fcntl(socket, libc::F_SETFD, libc::FD_CLOEXEC))?;
79 
80         // See https://github.com/tokio-rs/mio/issues/1450
81         #[cfg(all(target_arch = "x86", target_os = "android"))]
82         syscall!(fcntl(socket, libc::F_SETFL, libc::O_NONBLOCK))?;
83 
84         Ok(s)
85     });
86 
87     socket
88         .map(UnixStream::from_std)
89         .map(|stream| (stream, SocketAddr::from_parts(sockaddr, socklen)))
90 }
91 
local_addr(listener: &net::UnixListener) -> io::Result<SocketAddr>92 pub(crate) fn local_addr(listener: &net::UnixListener) -> io::Result<SocketAddr> {
93     super::local_addr(listener.as_raw_fd())
94 }
95