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