11use std:: io;
2+ use std:: mem:: { self , MaybeUninit } ;
23use std:: net:: { self , SocketAddr } ;
3- use std:: os:: windows:: io:: FromRawSocket ;
4+ use std:: os:: windows:: io:: { AsRawSocket , FromRawSocket } ;
45use 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
812use 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