diff --git a/src/socket.rs b/src/socket.rs index ef8781f5..91d7a5e6 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -955,6 +955,47 @@ fn into_linger(duration: Option) -> sys::linger { /// * Linux: /// * Windows: impl Socket { + /// Get the value of the `IP_TRANSPARENT` option on this socket. + /// + /// For more information about this option, see [`set_ip_transparent`]. + /// + /// [`ip_transparent`]: Socket::set_ip_transparent + #[cfg(all(feature = "all", target_os = "linux"))] + pub fn ip_transparent(&self) -> io::Result { + unsafe { + getsockopt::(self.as_raw(), sys::IPPROTO_IP, libc::IP_TRANSPARENT) + .map(|transparent| transparent != 0) + } + } + + /// Set the value of the `IP_TRANSPARENT` option on this socket. + /// + /// Setting this boolean option enables transparent proxying + /// on this socket. This socket option allows the calling + /// application to bind to a nonlocal IP address and operate + /// both as a client and a server with the foreign address as + /// the local endpoint. NOTE: this requires that routing be + /// set up in a way that packets going to the foreign address + /// are routed through the TProxy box (i.e., the system + /// hosting the application that employs the IP_TRANSPARENT + /// socket option). Enabling this socket option requires + /// superuser privileges (the CAP_NET_ADMIN capability). + /// + /// TProxy redirection with the iptables TPROXY target also + /// requires that this option be set on the redirected socket. + /// this feature is only available on linux + #[cfg(all(feature = "all", target_os = "linux"))] + pub fn set_ip_transparent(&self, transparent: bool) -> io::Result<()> { + unsafe { + setsockopt( + self.as_raw(), + sys::IPPROTO_IP, + libc::IP_TRANSPARENT, + transparent as c_int, + ) + } + } + /// Join a multicast group using `IP_ADD_MEMBERSHIP` option on this socket. /// /// This function specifies a new multicast group for this socket to join. diff --git a/tests/socket.rs b/tests/socket.rs index 5f39bd8d..113dfb6c 100644 --- a/tests/socket.rs +++ b/tests/socket.rs @@ -1047,6 +1047,12 @@ test!( mss, set_mss(256) ); +#[cfg(all(feature = "all", target_os = "linux"))] +test!( + #[ignore = "setting `IP_TRANSPARENT` requires the `CAP_NET_ADMIN` capability (works when running as root)"] + ip_transparent, + set_ip_transparent(true) +); #[cfg(all(feature = "all", any(target_os = "fuchsia", target_os = "linux")))] test!( #[ignore = "setting `SO_MARK` requires the `CAP_NET_ADMIN` capability (works when running as root)"]