1
1
use std:: io;
2
+ use std:: mem:: { self , MaybeUninit } ;
2
3
use std:: net:: { self , SocketAddr } ;
3
- use std:: os:: windows:: io:: FromRawSocket ;
4
+ use std:: os:: windows:: io:: { AsRawSocket , FromRawSocket } ;
4
5
use std:: os:: windows:: raw:: SOCKET as StdSocket ; // winapi uses usize, stdlib uses u32/u64.
5
6
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 } ;
7
11
8
12
use crate :: sys:: windows:: net:: { init, new_ip_socket, socket_addr} ;
9
13
@@ -25,3 +29,25 @@ pub fn bind(addr: SocketAddr) -> io::Result<net::UdpSocket> {
25
29
. map ( |_| unsafe { net:: UdpSocket :: from_raw_socket ( socket as StdSocket ) } )
26
30
} )
27
31
}
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