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