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