@@ -77,7 +77,7 @@ pub(crate) use windows_sys::Win32::Networking::WinSock::{
77
77
IP_MREQ_SOURCE as IpMreqSource , IP_MULTICAST_IF , IP_MULTICAST_LOOP , IP_MULTICAST_TTL ,
78
78
IP_RECVTOS , IP_TOS , IP_TTL , LINGER as linger, MSG_OOB , MSG_PEEK , SO_BROADCAST , SO_ERROR ,
79
79
SO_KEEPALIVE , SO_LINGER , SO_OOBINLINE , SO_RCVBUF , SO_RCVTIMEO , SO_REUSEADDR , SO_SNDBUF ,
80
- SO_SNDTIMEO , SO_TYPE , TCP_NODELAY ,
80
+ SO_SNDTIMEO , SO_TYPE , TCP_NODELAY , SO_ORIGINAL_DST , IP6T_SO_ORIGINAL_DST , SOL_IP
81
81
} ;
82
82
pub ( crate ) const IPPROTO_IP : c_int = windows_sys:: Win32 :: Networking :: WinSock :: IPPROTO_IP as c_int ;
83
83
pub ( crate ) const SOL_SOCKET : c_int = windows_sys:: Win32 :: Networking :: WinSock :: SOL_SOCKET as c_int ;
@@ -927,6 +927,38 @@ impl crate::Socket {
927
927
}
928
928
}
929
929
930
+ /// Get the value for the `SO_ORIGINAL_DST` option on this socket.
931
+ ///
932
+ pub fn original_dst ( & self ) -> io:: Result < SockAddr > {
933
+ // Safety: `getsockopt` initialises the `SockAddr` for us.
934
+ unsafe {
935
+ SockAddr :: try_init ( |storage, len| {
936
+ getsockopt :: < > ( self . as_raw ( ) , SOL_IP , SO_ORIGINAL_DST )
937
+ } )
938
+ }
939
+ . map ( |( _, addr) | addr)
940
+ }
941
+
942
+ /// Get the value for the `IP6T_SO_ORIGINAL_DST` option on this socket.
943
+ ///
944
+ #[ cfg( feature = "all" ) ]
945
+ #[ cfg_attr( docsrs, doc( cfg( all( windows, feature = "all" ) ) ) ) ]
946
+ pub fn original_dst_ipv6 ( & self ) -> io:: Result < SockAddr > {
947
+ // Safety: `getsockopt` initialises the `SockAddr` for us.
948
+ unsafe {
949
+ SockAddr :: try_init ( |storage, len| {
950
+ syscall ! ( getsockopt(
951
+ self . as_raw( ) ,
952
+ libc:: SOL_IPV6 ,
953
+ IP6T_SO_ORIGINAL_DST ,
954
+ storage. cast( ) ,
955
+ len
956
+ ) )
957
+ } )
958
+ }
959
+ . map ( |( _, addr) | addr)
960
+ }
961
+
930
962
/// Returns the [`Protocol`] of this socket by checking the `SO_PROTOCOL_INFOW`
931
963
/// option on this socket.
932
964
///
0 commit comments