xref: /aosp_15_r20/external/crosvm/base/src/sys/linux/net.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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::net::SocketAddrV4;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::net::SocketAddrV6;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::os::fd::RawFd;
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::in6_addr;
18*bb4ee6a4SAndroid Build Coastguard Worker use libc::in_addr;
19*bb4ee6a4SAndroid Build Coastguard Worker use libc::msghdr;
20*bb4ee6a4SAndroid Build Coastguard Worker use libc::sa_family_t;
21*bb4ee6a4SAndroid Build Coastguard Worker use libc::sendmsg;
22*bb4ee6a4SAndroid Build Coastguard Worker use libc::sockaddr_in;
23*bb4ee6a4SAndroid Build Coastguard Worker use libc::sockaddr_in6;
24*bb4ee6a4SAndroid Build Coastguard Worker use libc::ssize_t;
25*bb4ee6a4SAndroid Build Coastguard Worker use libc::AF_INET;
26*bb4ee6a4SAndroid Build Coastguard Worker use libc::AF_INET6;
27*bb4ee6a4SAndroid Build Coastguard Worker use libc::MSG_NOSIGNAL;
28*bb4ee6a4SAndroid Build Coastguard Worker use libc::SOCK_CLOEXEC;
29*bb4ee6a4SAndroid Build Coastguard Worker use libc::SOCK_STREAM;
30*bb4ee6a4SAndroid Build Coastguard Worker 
31*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::AsRawDescriptor;
32*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::FromRawDescriptor;
33*bb4ee6a4SAndroid Build Coastguard Worker use crate::unix::net::socket;
34*bb4ee6a4SAndroid Build Coastguard Worker use crate::unix::net::socketpair;
35*bb4ee6a4SAndroid Build Coastguard Worker use crate::unix::net::sun_path_offset;
36*bb4ee6a4SAndroid Build Coastguard Worker use crate::unix::net::InetVersion;
37*bb4ee6a4SAndroid Build Coastguard Worker use crate::unix::net::TcpSocket;
38*bb4ee6a4SAndroid Build Coastguard Worker use crate::SafeDescriptor;
39*bb4ee6a4SAndroid Build Coastguard Worker use crate::ScmSocket;
40*bb4ee6a4SAndroid Build Coastguard Worker use crate::StreamChannel;
41*bb4ee6a4SAndroid Build Coastguard Worker use crate::UnixSeqpacket;
42*bb4ee6a4SAndroid Build Coastguard Worker use crate::UnixSeqpacketListener;
43*bb4ee6a4SAndroid Build Coastguard Worker 
sendmsg_nosignal( fd: RawFd, msg: *const msghdr, flags: c_int, ) -> ssize_t44*bb4ee6a4SAndroid Build Coastguard Worker pub(in crate::sys) unsafe fn sendmsg_nosignal(
45*bb4ee6a4SAndroid Build Coastguard Worker     fd: RawFd,
46*bb4ee6a4SAndroid Build Coastguard Worker     msg: *const msghdr,
47*bb4ee6a4SAndroid Build Coastguard Worker     flags: c_int,
48*bb4ee6a4SAndroid Build Coastguard Worker ) -> ssize_t {
49*bb4ee6a4SAndroid Build Coastguard Worker     sendmsg(fd, msg, flags | MSG_NOSIGNAL)
50*bb4ee6a4SAndroid Build Coastguard Worker }
51*bb4ee6a4SAndroid Build Coastguard Worker 
sockaddrv4_to_lib_c(s: &SocketAddrV4) -> sockaddr_in52*bb4ee6a4SAndroid Build Coastguard Worker pub(in crate::sys) fn sockaddrv4_to_lib_c(s: &SocketAddrV4) -> sockaddr_in {
53*bb4ee6a4SAndroid Build Coastguard Worker     sockaddr_in {
54*bb4ee6a4SAndroid Build Coastguard Worker         sin_family: AF_INET as sa_family_t,
55*bb4ee6a4SAndroid Build Coastguard Worker         sin_port: s.port().to_be(),
56*bb4ee6a4SAndroid Build Coastguard Worker         sin_addr: in_addr {
57*bb4ee6a4SAndroid Build Coastguard Worker             s_addr: u32::from_ne_bytes(s.ip().octets()),
58*bb4ee6a4SAndroid Build Coastguard Worker         },
59*bb4ee6a4SAndroid Build Coastguard Worker         sin_zero: [0; 8],
60*bb4ee6a4SAndroid Build Coastguard Worker     }
61*bb4ee6a4SAndroid Build Coastguard Worker }
62*bb4ee6a4SAndroid Build Coastguard Worker 
sockaddrv6_to_lib_c(s: &SocketAddrV6) -> sockaddr_in663*bb4ee6a4SAndroid Build Coastguard Worker pub(in crate::sys) fn sockaddrv6_to_lib_c(s: &SocketAddrV6) -> sockaddr_in6 {
64*bb4ee6a4SAndroid Build Coastguard Worker     sockaddr_in6 {
65*bb4ee6a4SAndroid Build Coastguard Worker         sin6_family: AF_INET6 as sa_family_t,
66*bb4ee6a4SAndroid Build Coastguard Worker         sin6_port: s.port().to_be(),
67*bb4ee6a4SAndroid Build Coastguard Worker         sin6_flowinfo: 0,
68*bb4ee6a4SAndroid Build Coastguard Worker         sin6_addr: in6_addr {
69*bb4ee6a4SAndroid Build Coastguard Worker             s6_addr: s.ip().octets(),
70*bb4ee6a4SAndroid Build Coastguard Worker         },
71*bb4ee6a4SAndroid Build Coastguard Worker         sin6_scope_id: 0,
72*bb4ee6a4SAndroid Build Coastguard Worker     }
73*bb4ee6a4SAndroid Build Coastguard Worker }
74*bb4ee6a4SAndroid Build Coastguard Worker 
75*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)>76*bb4ee6a4SAndroid Build Coastguard Worker pub(in crate::sys) fn sockaddr_un<P: AsRef<Path>>(
77*bb4ee6a4SAndroid Build Coastguard Worker     path: P,
78*bb4ee6a4SAndroid Build Coastguard Worker ) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> {
79*bb4ee6a4SAndroid Build Coastguard Worker     let mut addr = libc::sockaddr_un {
80*bb4ee6a4SAndroid Build Coastguard Worker         sun_family: libc::AF_UNIX as libc::sa_family_t,
81*bb4ee6a4SAndroid Build Coastguard Worker         sun_path: std::array::from_fn(|_| 0),
82*bb4ee6a4SAndroid Build Coastguard Worker     };
83*bb4ee6a4SAndroid Build Coastguard Worker 
84*bb4ee6a4SAndroid Build Coastguard Worker     // Check if the input path is valid. Since
85*bb4ee6a4SAndroid Build Coastguard Worker     // * The pathname in sun_path should be null-terminated.
86*bb4ee6a4SAndroid Build Coastguard Worker     // * The length of the pathname, including the terminating null byte, should not exceed the size
87*bb4ee6a4SAndroid Build Coastguard Worker     //   of sun_path.
88*bb4ee6a4SAndroid Build Coastguard Worker     //
89*bb4ee6a4SAndroid Build Coastguard Worker     // and our input is a `Path`, we only need to check
90*bb4ee6a4SAndroid Build Coastguard Worker     // * If the string size of `Path` should less than sizeof(sun_path)
91*bb4ee6a4SAndroid Build Coastguard Worker     // and make sure `sun_path` ends with '\0' by initialized the sun_path with zeros.
92*bb4ee6a4SAndroid Build Coastguard Worker     //
93*bb4ee6a4SAndroid Build Coastguard Worker     // Empty path name is valid since abstract socket address has sun_paht[0] = '\0'
94*bb4ee6a4SAndroid Build Coastguard Worker     let bytes = path.as_ref().as_os_str().as_bytes();
95*bb4ee6a4SAndroid Build Coastguard Worker     if bytes.len() >= addr.sun_path.len() {
96*bb4ee6a4SAndroid Build Coastguard Worker         return Err(io::Error::new(
97*bb4ee6a4SAndroid Build Coastguard Worker             io::ErrorKind::InvalidInput,
98*bb4ee6a4SAndroid Build Coastguard Worker             "Input path size should be less than the length of sun_path.",
99*bb4ee6a4SAndroid Build Coastguard Worker         ));
100*bb4ee6a4SAndroid Build Coastguard Worker     };
101*bb4ee6a4SAndroid Build Coastguard Worker 
102*bb4ee6a4SAndroid Build Coastguard Worker     // Copy data from `path` to `addr.sun_path`
103*bb4ee6a4SAndroid Build Coastguard Worker     for (dst, src) in addr.sun_path.iter_mut().zip(bytes) {
104*bb4ee6a4SAndroid Build Coastguard Worker         *dst = *src as libc::c_char;
105*bb4ee6a4SAndroid Build Coastguard Worker     }
106*bb4ee6a4SAndroid Build Coastguard Worker 
107*bb4ee6a4SAndroid Build Coastguard Worker     // The addrlen argument that describes the enclosing sockaddr_un structure
108*bb4ee6a4SAndroid Build Coastguard Worker     // should have a value of at least:
109*bb4ee6a4SAndroid Build Coastguard Worker     //
110*bb4ee6a4SAndroid Build Coastguard Worker     //     offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path) + 1
111*bb4ee6a4SAndroid Build Coastguard Worker     //
112*bb4ee6a4SAndroid Build Coastguard Worker     // or, more simply, addrlen can be specified as sizeof(struct sockaddr_un).
113*bb4ee6a4SAndroid Build Coastguard Worker     let len = sun_path_offset() + bytes.len() + 1;
114*bb4ee6a4SAndroid Build Coastguard Worker     Ok((addr, len as libc::socklen_t))
115*bb4ee6a4SAndroid Build Coastguard Worker }
116*bb4ee6a4SAndroid Build Coastguard Worker 
117*bb4ee6a4SAndroid Build Coastguard Worker impl TcpSocket {
new(inet_version: InetVersion) -> io::Result<Self>118*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(inet_version: InetVersion) -> io::Result<Self> {
119*bb4ee6a4SAndroid Build Coastguard Worker         Ok(TcpSocket {
120*bb4ee6a4SAndroid Build Coastguard Worker             inet_version,
121*bb4ee6a4SAndroid Build Coastguard Worker             descriptor: socket(
122*bb4ee6a4SAndroid Build Coastguard Worker                 Into::<sa_family_t>::into(inet_version) as libc::c_int,
123*bb4ee6a4SAndroid Build Coastguard Worker                 SOCK_STREAM | SOCK_CLOEXEC,
124*bb4ee6a4SAndroid Build Coastguard Worker                 0,
125*bb4ee6a4SAndroid Build Coastguard Worker             )?,
126*bb4ee6a4SAndroid Build Coastguard Worker         })
127*bb4ee6a4SAndroid Build Coastguard Worker     }
128*bb4ee6a4SAndroid Build Coastguard Worker }
129*bb4ee6a4SAndroid Build Coastguard Worker 
130*bb4ee6a4SAndroid Build Coastguard Worker impl UnixSeqpacket {
131*bb4ee6a4SAndroid Build Coastguard Worker     /// Creates a pair of connected `SOCK_SEQPACKET` sockets.
132*bb4ee6a4SAndroid Build Coastguard Worker     ///
133*bb4ee6a4SAndroid Build Coastguard Worker     /// Both returned file descriptors have the `CLOEXEC` flag set.
pair() -> io::Result<(UnixSeqpacket, UnixSeqpacket)>134*bb4ee6a4SAndroid Build Coastguard Worker     pub fn pair() -> io::Result<(UnixSeqpacket, UnixSeqpacket)> {
135*bb4ee6a4SAndroid Build Coastguard Worker         socketpair(libc::AF_UNIX, libc::SOCK_SEQPACKET | libc::SOCK_CLOEXEC, 0)
136*bb4ee6a4SAndroid Build Coastguard Worker             .map(|(s0, s1)| (UnixSeqpacket::from(s0), UnixSeqpacket::from(s1)))
137*bb4ee6a4SAndroid Build Coastguard Worker     }
138*bb4ee6a4SAndroid Build Coastguard Worker }
139*bb4ee6a4SAndroid Build Coastguard Worker 
140*bb4ee6a4SAndroid Build Coastguard Worker impl UnixSeqpacketListener {
141*bb4ee6a4SAndroid Build Coastguard Worker     /// Blocks for and accepts a new incoming connection and returns the socket associated with that
142*bb4ee6a4SAndroid Build Coastguard Worker     /// connection.
143*bb4ee6a4SAndroid Build Coastguard Worker     ///
144*bb4ee6a4SAndroid Build Coastguard Worker     /// The returned socket has the close-on-exec flag set.
accept(&self) -> io::Result<UnixSeqpacket>145*bb4ee6a4SAndroid Build Coastguard Worker     pub fn accept(&self) -> io::Result<UnixSeqpacket> {
146*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
147*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because we own this fd and the kernel will not write to null pointers.
148*bb4ee6a4SAndroid Build Coastguard Worker         match unsafe {
149*bb4ee6a4SAndroid Build Coastguard Worker             libc::accept4(
150*bb4ee6a4SAndroid Build Coastguard Worker                 self.as_raw_descriptor(),
151*bb4ee6a4SAndroid Build Coastguard Worker                 null_mut(),
152*bb4ee6a4SAndroid Build Coastguard Worker                 null_mut(),
153*bb4ee6a4SAndroid Build Coastguard Worker                 SOCK_CLOEXEC,
154*bb4ee6a4SAndroid Build Coastguard Worker             )
155*bb4ee6a4SAndroid Build Coastguard Worker         } {
156*bb4ee6a4SAndroid Build Coastguard Worker             -1 => Err(io::Error::last_os_error()),
157*bb4ee6a4SAndroid Build Coastguard Worker             fd => {
158*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(UnixSeqpacket::from(
159*bb4ee6a4SAndroid Build Coastguard Worker                     // SAFETY: Safe because we checked the return value of accept. Therefore, the
160*bb4ee6a4SAndroid Build Coastguard Worker                     // return value must be a valid socket.
161*bb4ee6a4SAndroid Build Coastguard Worker                     unsafe { SafeDescriptor::from_raw_descriptor(fd) },
162*bb4ee6a4SAndroid Build Coastguard Worker                 ))
163*bb4ee6a4SAndroid Build Coastguard Worker             }
164*bb4ee6a4SAndroid Build Coastguard Worker         }
165*bb4ee6a4SAndroid Build Coastguard Worker     }
166*bb4ee6a4SAndroid Build Coastguard Worker }
167*bb4ee6a4SAndroid Build Coastguard Worker 
168*bb4ee6a4SAndroid Build Coastguard Worker macro_rules! ScmSocketTryFrom {
169*bb4ee6a4SAndroid Build Coastguard Worker     ($name:ident) => {
170*bb4ee6a4SAndroid Build Coastguard Worker         impl TryFrom<$name> for ScmSocket<$name> {
171*bb4ee6a4SAndroid Build Coastguard Worker             type Error = io::Error;
172*bb4ee6a4SAndroid Build Coastguard Worker 
173*bb4ee6a4SAndroid Build Coastguard Worker             fn try_from(socket: $name) -> io::Result<Self> {
174*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(ScmSocket { socket })
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 
180*bb4ee6a4SAndroid Build Coastguard Worker ScmSocketTryFrom!(StreamChannel);
181*bb4ee6a4SAndroid Build Coastguard Worker ScmSocketTryFrom!(UnixDatagram);
182*bb4ee6a4SAndroid Build Coastguard Worker ScmSocketTryFrom!(UnixListener);
183*bb4ee6a4SAndroid Build Coastguard Worker ScmSocketTryFrom!(UnixSeqpacket);
184*bb4ee6a4SAndroid Build Coastguard Worker ScmSocketTryFrom!(UnixStream);
185