1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2018 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker
5*bb4ee6a4SAndroid Build Coastguard Worker use std::io;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::size_of;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::net::SocketAddrV4;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::net::SocketAddrV6;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::ffi::OsStrExt;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::net::UnixDatagram;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::net::UnixListener;
12*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::net::UnixStream;
13*bb4ee6a4SAndroid Build Coastguard Worker use std::path::Path;
14*bb4ee6a4SAndroid Build Coastguard Worker use std::ptr::null_mut;
15*bb4ee6a4SAndroid Build Coastguard Worker
16*bb4ee6a4SAndroid Build Coastguard Worker use libc::c_int;
17*bb4ee6a4SAndroid Build Coastguard Worker use libc::c_void;
18*bb4ee6a4SAndroid Build Coastguard Worker use libc::close;
19*bb4ee6a4SAndroid Build Coastguard Worker use libc::fcntl;
20*bb4ee6a4SAndroid Build Coastguard Worker use libc::in6_addr;
21*bb4ee6a4SAndroid Build Coastguard Worker use libc::in_addr;
22*bb4ee6a4SAndroid Build Coastguard Worker use libc::sa_family_t;
23*bb4ee6a4SAndroid Build Coastguard Worker use libc::setsockopt;
24*bb4ee6a4SAndroid Build Coastguard Worker use libc::sockaddr_in;
25*bb4ee6a4SAndroid Build Coastguard Worker use libc::sockaddr_in6;
26*bb4ee6a4SAndroid Build Coastguard Worker use libc::socklen_t;
27*bb4ee6a4SAndroid Build Coastguard Worker use libc::AF_INET;
28*bb4ee6a4SAndroid Build Coastguard Worker use libc::AF_INET6;
29*bb4ee6a4SAndroid Build Coastguard Worker use libc::FD_CLOEXEC;
30*bb4ee6a4SAndroid Build Coastguard Worker use libc::F_SETFD;
31*bb4ee6a4SAndroid Build Coastguard Worker use libc::SOCK_STREAM;
32*bb4ee6a4SAndroid Build Coastguard Worker use libc::SOL_SOCKET;
33*bb4ee6a4SAndroid Build Coastguard Worker use libc::SO_NOSIGPIPE;
34*bb4ee6a4SAndroid Build Coastguard Worker
35*bb4ee6a4SAndroid Build Coastguard Worker use crate::unix::net::socket;
36*bb4ee6a4SAndroid Build Coastguard Worker use crate::unix::net::socketpair;
37*bb4ee6a4SAndroid Build Coastguard Worker use crate::unix::net::sun_path_offset;
38*bb4ee6a4SAndroid Build Coastguard Worker use crate::unix::net::InetVersion;
39*bb4ee6a4SAndroid Build Coastguard Worker use crate::unix::net::TcpSocket;
40*bb4ee6a4SAndroid Build Coastguard Worker use crate::AsRawDescriptor;
41*bb4ee6a4SAndroid Build Coastguard Worker use crate::FromRawDescriptor;
42*bb4ee6a4SAndroid Build Coastguard Worker use crate::SafeDescriptor;
43*bb4ee6a4SAndroid Build Coastguard Worker use crate::ScmSocket;
44*bb4ee6a4SAndroid Build Coastguard Worker use crate::StreamChannel;
45*bb4ee6a4SAndroid Build Coastguard Worker use crate::UnixSeqpacket;
46*bb4ee6a4SAndroid Build Coastguard Worker use crate::UnixSeqpacketListener;
47*bb4ee6a4SAndroid Build Coastguard Worker
48*bb4ee6a4SAndroid Build Coastguard Worker macro_rules! ScmSocketTryFrom {
49*bb4ee6a4SAndroid Build Coastguard Worker ($name:ident) => {
50*bb4ee6a4SAndroid Build Coastguard Worker impl TryFrom<$name> for ScmSocket<$name> {
51*bb4ee6a4SAndroid Build Coastguard Worker type Error = io::Error;
52*bb4ee6a4SAndroid Build Coastguard Worker
53*bb4ee6a4SAndroid Build Coastguard Worker fn try_from(socket: $name) -> io::Result<Self> {
54*bb4ee6a4SAndroid Build Coastguard Worker let set = 1;
55*bb4ee6a4SAndroid Build Coastguard Worker let set_ptr = &set as *const c_int as *const c_void;
56*bb4ee6a4SAndroid Build Coastguard Worker let size = size_of::<c_int>() as socklen_t;
57*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: because we are taking ownership of the file descriptor, and `set_ptr`
58*bb4ee6a4SAndroid Build Coastguard Worker // has at least `size` data available.
59*bb4ee6a4SAndroid Build Coastguard Worker let res = unsafe {
60*bb4ee6a4SAndroid Build Coastguard Worker setsockopt(
61*bb4ee6a4SAndroid Build Coastguard Worker socket.as_raw_descriptor(),
62*bb4ee6a4SAndroid Build Coastguard Worker SOL_SOCKET,
63*bb4ee6a4SAndroid Build Coastguard Worker SO_NOSIGPIPE,
64*bb4ee6a4SAndroid Build Coastguard Worker set_ptr,
65*bb4ee6a4SAndroid Build Coastguard Worker size,
66*bb4ee6a4SAndroid Build Coastguard Worker )
67*bb4ee6a4SAndroid Build Coastguard Worker };
68*bb4ee6a4SAndroid Build Coastguard Worker if res < 0 {
69*bb4ee6a4SAndroid Build Coastguard Worker Err(io::Error::last_os_error())
70*bb4ee6a4SAndroid Build Coastguard Worker } else {
71*bb4ee6a4SAndroid Build Coastguard Worker Ok(ScmSocket { socket })
72*bb4ee6a4SAndroid Build Coastguard Worker }
73*bb4ee6a4SAndroid Build Coastguard Worker }
74*bb4ee6a4SAndroid Build Coastguard Worker }
75*bb4ee6a4SAndroid Build Coastguard Worker };
76*bb4ee6a4SAndroid Build Coastguard Worker }
77*bb4ee6a4SAndroid Build Coastguard Worker
78*bb4ee6a4SAndroid Build Coastguard Worker ScmSocketTryFrom!(StreamChannel);
79*bb4ee6a4SAndroid Build Coastguard Worker ScmSocketTryFrom!(UnixDatagram);
80*bb4ee6a4SAndroid Build Coastguard Worker ScmSocketTryFrom!(UnixListener);
81*bb4ee6a4SAndroid Build Coastguard Worker ScmSocketTryFrom!(UnixSeqpacket);
82*bb4ee6a4SAndroid Build Coastguard Worker ScmSocketTryFrom!(UnixStream);
83*bb4ee6a4SAndroid Build Coastguard Worker
sockaddrv4_to_lib_c(s: &SocketAddrV4) -> sockaddr_in84*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) fn sockaddrv4_to_lib_c(s: &SocketAddrV4) -> sockaddr_in {
85*bb4ee6a4SAndroid Build Coastguard Worker sockaddr_in {
86*bb4ee6a4SAndroid Build Coastguard Worker sin_family: AF_INET as sa_family_t,
87*bb4ee6a4SAndroid Build Coastguard Worker sin_port: s.port().to_be(),
88*bb4ee6a4SAndroid Build Coastguard Worker sin_addr: in_addr {
89*bb4ee6a4SAndroid Build Coastguard Worker s_addr: u32::from_ne_bytes(s.ip().octets()),
90*bb4ee6a4SAndroid Build Coastguard Worker },
91*bb4ee6a4SAndroid Build Coastguard Worker sin_zero: [0; 8],
92*bb4ee6a4SAndroid Build Coastguard Worker sin_len: size_of::<sockaddr_in>() as u8,
93*bb4ee6a4SAndroid Build Coastguard Worker }
94*bb4ee6a4SAndroid Build Coastguard Worker }
95*bb4ee6a4SAndroid Build Coastguard Worker
sockaddrv6_to_lib_c(s: &SocketAddrV6) -> sockaddr_in696*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) fn sockaddrv6_to_lib_c(s: &SocketAddrV6) -> sockaddr_in6 {
97*bb4ee6a4SAndroid Build Coastguard Worker sockaddr_in6 {
98*bb4ee6a4SAndroid Build Coastguard Worker sin6_family: AF_INET6 as sa_family_t,
99*bb4ee6a4SAndroid Build Coastguard Worker sin6_port: s.port().to_be(),
100*bb4ee6a4SAndroid Build Coastguard Worker sin6_flowinfo: 0,
101*bb4ee6a4SAndroid Build Coastguard Worker sin6_addr: in6_addr {
102*bb4ee6a4SAndroid Build Coastguard Worker s6_addr: s.ip().octets(),
103*bb4ee6a4SAndroid Build Coastguard Worker },
104*bb4ee6a4SAndroid Build Coastguard Worker sin6_scope_id: 0,
105*bb4ee6a4SAndroid Build Coastguard Worker sin6_len: size_of::<sockaddr_in6>() as u8,
106*bb4ee6a4SAndroid Build Coastguard Worker }
107*bb4ee6a4SAndroid Build Coastguard Worker }
108*bb4ee6a4SAndroid Build Coastguard Worker
cloexec_or_close<Raw: AsRawDescriptor>(raw: Raw) -> io::Result<Raw>109*bb4ee6a4SAndroid Build Coastguard Worker fn cloexec_or_close<Raw: AsRawDescriptor>(raw: Raw) -> io::Result<Raw> {
110*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: `raw` owns a file descriptor, there are no actions with memory. This potentially
111*bb4ee6a4SAndroid Build Coastguard Worker // races with `fork()` calls in other threads, but on MacOS it's the best we have.
112*bb4ee6a4SAndroid Build Coastguard Worker let res = unsafe { fcntl(raw.as_raw_descriptor(), F_SETFD, FD_CLOEXEC) };
113*bb4ee6a4SAndroid Build Coastguard Worker if res >= 0 {
114*bb4ee6a4SAndroid Build Coastguard Worker Ok(raw)
115*bb4ee6a4SAndroid Build Coastguard Worker } else {
116*bb4ee6a4SAndroid Build Coastguard Worker let err = io::Error::last_os_error();
117*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: `raw` owns this file descriptor.
118*bb4ee6a4SAndroid Build Coastguard Worker unsafe { close(raw.as_raw_descriptor()) };
119*bb4ee6a4SAndroid Build Coastguard Worker Err(err)
120*bb4ee6a4SAndroid Build Coastguard Worker }
121*bb4ee6a4SAndroid Build Coastguard Worker }
122*bb4ee6a4SAndroid Build Coastguard Worker
123*bb4ee6a4SAndroid Build Coastguard Worker // Return `sockaddr_un` for a given `path`
sockaddr_un<P: AsRef<Path>>( path: P, ) -> io::Result<(libc::sockaddr_un, libc::socklen_t)>124*bb4ee6a4SAndroid Build Coastguard Worker pub(in crate::sys) fn sockaddr_un<P: AsRef<Path>>(
125*bb4ee6a4SAndroid Build Coastguard Worker path: P,
126*bb4ee6a4SAndroid Build Coastguard Worker ) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> {
127*bb4ee6a4SAndroid Build Coastguard Worker let mut addr = libc::sockaddr_un {
128*bb4ee6a4SAndroid Build Coastguard Worker sun_family: libc::AF_UNIX as libc::sa_family_t,
129*bb4ee6a4SAndroid Build Coastguard Worker sun_path: std::array::from_fn(|_| 0),
130*bb4ee6a4SAndroid Build Coastguard Worker sun_len: 0,
131*bb4ee6a4SAndroid Build Coastguard Worker };
132*bb4ee6a4SAndroid Build Coastguard Worker
133*bb4ee6a4SAndroid Build Coastguard Worker // Check if the input path is valid. Since
134*bb4ee6a4SAndroid Build Coastguard Worker // * The pathname in sun_path should be null-terminated.
135*bb4ee6a4SAndroid Build Coastguard Worker // * The length of the pathname, including the terminating null byte, should not exceed the size
136*bb4ee6a4SAndroid Build Coastguard Worker // of sun_path.
137*bb4ee6a4SAndroid Build Coastguard Worker //
138*bb4ee6a4SAndroid Build Coastguard Worker // and our input is a `Path`, we only need to check
139*bb4ee6a4SAndroid Build Coastguard Worker // * If the string size of `Path` should less than sizeof(sun_path)
140*bb4ee6a4SAndroid Build Coastguard Worker // and make sure `sun_path` ends with '\0' by initialized the sun_path with zeros.
141*bb4ee6a4SAndroid Build Coastguard Worker //
142*bb4ee6a4SAndroid Build Coastguard Worker // Empty path name is valid since abstract socket address has sun_paht[0] = '\0'
143*bb4ee6a4SAndroid Build Coastguard Worker let bytes = path.as_ref().as_os_str().as_bytes();
144*bb4ee6a4SAndroid Build Coastguard Worker if bytes.len() >= addr.sun_path.len() {
145*bb4ee6a4SAndroid Build Coastguard Worker return Err(io::Error::new(
146*bb4ee6a4SAndroid Build Coastguard Worker io::ErrorKind::InvalidInput,
147*bb4ee6a4SAndroid Build Coastguard Worker "Input path size should be less than the length of sun_path.",
148*bb4ee6a4SAndroid Build Coastguard Worker ));
149*bb4ee6a4SAndroid Build Coastguard Worker };
150*bb4ee6a4SAndroid Build Coastguard Worker
151*bb4ee6a4SAndroid Build Coastguard Worker // Copy data from `path` to `addr.sun_path`
152*bb4ee6a4SAndroid Build Coastguard Worker for (dst, src) in addr.sun_path.iter_mut().zip(bytes) {
153*bb4ee6a4SAndroid Build Coastguard Worker *dst = *src as libc::c_char;
154*bb4ee6a4SAndroid Build Coastguard Worker }
155*bb4ee6a4SAndroid Build Coastguard Worker
156*bb4ee6a4SAndroid Build Coastguard Worker // The addrlen argument that describes the enclosing sockaddr_un structure
157*bb4ee6a4SAndroid Build Coastguard Worker // should have a value of at least:
158*bb4ee6a4SAndroid Build Coastguard Worker //
159*bb4ee6a4SAndroid Build Coastguard Worker // offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path) + 1
160*bb4ee6a4SAndroid Build Coastguard Worker //
161*bb4ee6a4SAndroid Build Coastguard Worker // or, more simply, addrlen can be specified as sizeof(struct sockaddr_un).
162*bb4ee6a4SAndroid Build Coastguard Worker addr.sun_len = sun_path_offset() as u8 + bytes.len() as u8 + 1;
163*bb4ee6a4SAndroid Build Coastguard Worker Ok((addr, addr.sun_len as libc::socklen_t))
164*bb4ee6a4SAndroid Build Coastguard Worker }
165*bb4ee6a4SAndroid Build Coastguard Worker
166*bb4ee6a4SAndroid Build Coastguard Worker impl TcpSocket {
new(inet_version: InetVersion) -> io::Result<Self>167*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(inet_version: InetVersion) -> io::Result<Self> {
168*bb4ee6a4SAndroid Build Coastguard Worker Ok(TcpSocket {
169*bb4ee6a4SAndroid Build Coastguard Worker inet_version,
170*bb4ee6a4SAndroid Build Coastguard Worker descriptor: cloexec_or_close(socket(
171*bb4ee6a4SAndroid Build Coastguard Worker Into::<sa_family_t>::into(inet_version) as libc::c_int,
172*bb4ee6a4SAndroid Build Coastguard Worker SOCK_STREAM,
173*bb4ee6a4SAndroid Build Coastguard Worker 0,
174*bb4ee6a4SAndroid Build Coastguard Worker )?)?,
175*bb4ee6a4SAndroid Build Coastguard Worker })
176*bb4ee6a4SAndroid Build Coastguard Worker }
177*bb4ee6a4SAndroid Build Coastguard Worker }
178*bb4ee6a4SAndroid Build Coastguard Worker
179*bb4ee6a4SAndroid Build Coastguard Worker impl UnixSeqpacket {
180*bb4ee6a4SAndroid Build Coastguard Worker /// Creates a pair of connected `SOCK_SEQPACKET` sockets.
181*bb4ee6a4SAndroid Build Coastguard Worker ///
182*bb4ee6a4SAndroid Build Coastguard Worker /// Both returned file descriptors have the `CLOEXEC` flag set.
pair() -> io::Result<(UnixSeqpacket, UnixSeqpacket)>183*bb4ee6a4SAndroid Build Coastguard Worker pub fn pair() -> io::Result<(UnixSeqpacket, UnixSeqpacket)> {
184*bb4ee6a4SAndroid Build Coastguard Worker let (fd0, fd1) = socketpair(libc::AF_UNIX, libc::SOCK_SEQPACKET, 0)?;
185*bb4ee6a4SAndroid Build Coastguard Worker let (s0, s1) = (UnixSeqpacket::from(fd0), UnixSeqpacket::from(fd1));
186*bb4ee6a4SAndroid Build Coastguard Worker Ok((cloexec_or_close(s0)?, cloexec_or_close(s1)?))
187*bb4ee6a4SAndroid Build Coastguard Worker }
188*bb4ee6a4SAndroid Build Coastguard Worker }
189*bb4ee6a4SAndroid Build Coastguard Worker
190*bb4ee6a4SAndroid Build Coastguard Worker impl UnixSeqpacketListener {
191*bb4ee6a4SAndroid Build Coastguard Worker /// Blocks for and accepts a new incoming connection and returns the socket associated with that
192*bb4ee6a4SAndroid Build Coastguard Worker /// connection.
193*bb4ee6a4SAndroid Build Coastguard Worker ///
194*bb4ee6a4SAndroid Build Coastguard Worker /// The returned socket has the close-on-exec flag set.
accept(&self) -> io::Result<UnixSeqpacket>195*bb4ee6a4SAndroid Build Coastguard Worker pub fn accept(&self) -> io::Result<UnixSeqpacket> {
196*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: we own this fd and the kernel will not write to null pointers.
197*bb4ee6a4SAndroid Build Coastguard Worker let fd = unsafe { libc::accept(self.as_raw_descriptor(), null_mut(), null_mut()) };
198*bb4ee6a4SAndroid Build Coastguard Worker match fd {
199*bb4ee6a4SAndroid Build Coastguard Worker -1 => Err(io::Error::last_os_error()),
200*bb4ee6a4SAndroid Build Coastguard Worker fd => {
201*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: we checked the return value of accept. Therefore, the return value
202*bb4ee6a4SAndroid Build Coastguard Worker // must be a valid socket.
203*bb4ee6a4SAndroid Build Coastguard Worker let safe_desc = unsafe { SafeDescriptor::from_raw_descriptor(fd) };
204*bb4ee6a4SAndroid Build Coastguard Worker Ok(UnixSeqpacket::from(cloexec_or_close(safe_desc)?))
205*bb4ee6a4SAndroid Build Coastguard Worker }
206*bb4ee6a4SAndroid Build Coastguard Worker }
207*bb4ee6a4SAndroid Build Coastguard Worker }
208*bb4ee6a4SAndroid Build Coastguard Worker }
209