Skip to content

Commit 5c59fba

Browse files
committed
fix(shadowsocks): check IPv4-mapped-IPv6 compatiblity with UDP socket
- ref #1543
1 parent 5d965ab commit 5c59fba

File tree

1 file changed

+17
-23
lines changed
  • crates/shadowsocks/src/net/sys

1 file changed

+17
-23
lines changed

crates/shadowsocks/src/net/sys/mod.rs

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::{
22
io::{self, ErrorKind},
33
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
4-
time::Duration,
54
};
65

76
use cfg_if::cfg_if;
@@ -177,39 +176,34 @@ static IP_STACK_CAPABILITIES: Lazy<IpStackCapabilities> = Lazy::new(|| {
177176
});
178177

179178
fn check_ipv4_mapped_ipv6_capability() -> io::Result<()> {
179+
// https://stackoverflow.com/questions/30184377/how-to-detect-if-dual-stack-socket-is-supported
180+
180181
let local_host = SockAddr::from(SocketAddr::new(Ipv4Addr::LOCALHOST.to_ipv6_mapped().into(), 0));
182+
let local_host_53 = SockAddr::from(SocketAddr::new(Ipv4Addr::LOCALHOST.to_ipv6_mapped().into(), 53));
181183

182-
let socket1 = Socket::new(Domain::IPV6, Type::STREAM, Some(Protocol::TCP))?;
183-
socket1.set_only_v6(false)?;
184-
socket1.bind(&local_host)?;
185-
socket1.listen(128)?;
184+
let socket = Socket::new(Domain::IPV6, Type::DGRAM, Some(Protocol::UDP))?;
185+
socket.set_only_v6(false)?;
186+
socket.bind(&local_host)?;
187+
socket.connect(&local_host_53)?;
186188

187-
let socket1_address = socket1.local_addr()?;
188-
match socket1_address.as_socket() {
189+
// getsockname()
190+
let local_addr = socket.local_addr()?;
191+
match local_addr.as_socket() {
189192
None => return Err(io::Error::new(ErrorKind::Other, "invalid local_addr")),
190-
Some(socket_addr) => match socket_addr {
191-
SocketAddr::V4(..) => {
192-
return Err(io::Error::new(
193-
ErrorKind::Other,
194-
"local_addr shouldn't be an IPv4 address",
195-
));
196-
}
197-
SocketAddr::V6(ref v6) => {
198-
if let None = v6.ip().to_ipv4_mapped() {
193+
Some(addr) => match addr {
194+
SocketAddr::V4(..) => return Err(io::Error::new(ErrorKind::Other, "local_addr returned an IPv4 address")),
195+
SocketAddr::V6(v6) => match v6.ip().to_ipv4_mapped() {
196+
Some(_) => {}
197+
None => {
199198
return Err(io::Error::new(
200199
ErrorKind::Other,
201-
"local_addr is not an IPv4-mapped-IPv6 address",
200+
"local_addr returned an non IPv4-mapped-IPv6 address",
202201
));
203202
}
204-
}
203+
},
205204
},
206205
}
207206

208-
let socket2 = Socket::new(Domain::IPV6, Type::STREAM, Some(Protocol::TCP))?;
209-
socket2.set_only_v6(false)?;
210-
socket2.bind(&local_host)?;
211-
socket2.connect_timeout(&socket1_address, Duration::from_secs(1))?;
212-
213207
Ok(())
214208
}
215209

0 commit comments

Comments
 (0)