Skip to content

Commit 0101e05

Browse files
djcThomasdezeeuw
authored andcommitted
Bring back UdpSocket::only_v6 (fixes #1424)
1 parent ec28a8d commit 0101e05

File tree

4 files changed

+55
-3
lines changed

4 files changed

+55
-3
lines changed

src/net/udp.rs

+6
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,12 @@ impl UdpSocket {
511511
self.inner.leave_multicast_v6(multiaddr, interface)
512512
}
513513

514+
/// Get the value of the `IPV6_V6ONLY` option on this socket.
515+
#[allow(clippy::trivially_copy_pass_by_ref)]
516+
pub fn only_v6(&self) -> io::Result<bool> {
517+
sys::udp::only_v6(&self.inner)
518+
}
519+
514520
/// Get the value of the `SO_ERROR` option on this socket.
515521
///
516522
/// This will retrieve the stored error in the underlying socket, clearing

src/sys/shell/udp.rs

+4
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@ use std::net::{self, SocketAddr};
44
pub fn bind(_: SocketAddr) -> io::Result<net::UdpSocket> {
55
os_required!()
66
}
7+
8+
pub(crate) fn only_v6(_: &net::UdpSocket) -> io::Result<bool> {
9+
os_required!()
10+
}

src/sys/unix/udp.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use crate::sys::unix::net::{new_ip_socket, socket_addr};
22

33
use std::io;
4+
use std::mem;
45
use std::net::{self, SocketAddr};
5-
use std::os::unix::io::FromRawFd;
6+
use std::os::unix::io::{AsRawFd, FromRawFd};
67

78
pub fn bind(addr: SocketAddr) -> io::Result<net::UdpSocket> {
89
// Gives a warning for non Apple platforms.
@@ -21,3 +22,18 @@ pub fn bind(addr: SocketAddr) -> io::Result<net::UdpSocket> {
2122
.map(|_| unsafe { net::UdpSocket::from_raw_fd(socket) })
2223
})
2324
}
25+
26+
pub(crate) fn only_v6(socket: &net::UdpSocket) -> io::Result<bool> {
27+
let mut optval: libc::c_int = 0;
28+
let mut optlen = mem::size_of::<libc::c_int>() as libc::socklen_t;
29+
30+
syscall!(getsockopt(
31+
socket.as_raw_fd(),
32+
libc::IPPROTO_IPV6,
33+
libc::IPV6_V6ONLY,
34+
&mut optval as *mut _ as *mut _,
35+
&mut optlen,
36+
))?;
37+
38+
Ok(optval != 0)
39+
}

src/sys/windows/udp.rs

+28-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
use std::io;
2+
use std::mem::{self, MaybeUninit};
23
use std::net::{self, SocketAddr};
3-
use std::os::windows::io::FromRawSocket;
4+
use std::os::windows::io::{AsRawSocket, FromRawSocket};
45
use std::os::windows::raw::SOCKET as StdSocket; // winapi uses usize, stdlib uses u32/u64.
56

6-
use winapi::um::winsock2::{bind as win_bind, closesocket, SOCKET_ERROR, SOCK_DGRAM};
7+
use winapi::ctypes::c_int;
8+
use winapi::shared::ws2def::IPPROTO_IPV6;
9+
use winapi::shared::ws2ipdef::IPV6_V6ONLY;
10+
use winapi::um::winsock2::{bind as win_bind, closesocket, getsockopt, SOCKET_ERROR, SOCK_DGRAM};
711

812
use crate::sys::windows::net::{init, new_ip_socket, socket_addr};
913

@@ -25,3 +29,25 @@ pub fn bind(addr: SocketAddr) -> io::Result<net::UdpSocket> {
2529
.map(|_| unsafe { net::UdpSocket::from_raw_socket(socket as StdSocket) })
2630
})
2731
}
32+
33+
pub(crate) fn only_v6(socket: &net::UdpSocket) -> io::Result<bool> {
34+
let mut optval: MaybeUninit<c_int> = MaybeUninit::uninit();
35+
let mut optlen = mem::size_of::<c_int>() as c_int;
36+
37+
syscall!(
38+
getsockopt(
39+
socket.as_raw_socket() as usize,
40+
IPPROTO_IPV6 as c_int,
41+
IPV6_V6ONLY as c_int,
42+
optval.as_mut_ptr().cast(),
43+
&mut optlen,
44+
),
45+
PartialEq::eq,
46+
SOCKET_ERROR
47+
)?;
48+
49+
debug_assert_eq!(optlen as usize, mem::size_of::<c_int>());
50+
// Safety: `getsockopt` initialised `optval` for us.
51+
let optval = unsafe { optval.assume_init() };
52+
Ok(optval != 0)
53+
}

0 commit comments

Comments
 (0)