From 237d5005da0a0082efc6bba259c109fce6e19033 Mon Sep 17 00:00:00 2001 From: Jim Pepin Date: Wed, 28 Apr 2021 17:57:43 -0400 Subject: [PATCH 1/8] add IP_TRANSPARENT option --- src/socket.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/socket.rs b/src/socket.rs index ef8781f5..2b638dfc 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -884,6 +884,31 @@ impl Socket { } } + /// IP_TRANSPARENT (since Linux 2.6.24) + /// 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. + pub fn set_ip_transparent(&self) -> io::Result<()> { + unsafe { + setsockopt( + self.inner, + sys::IPPROTO_IP, + libc::IP_TRANSPARENT, + 1 as c_int, + ) + } + } + /// Get the value of the `SO_SNDBUF` option on this socket. /// /// For more information about this option, see [`set_send_buffer_size`]. From 4ed46916d4753b86aae39de7158d0472a2aecb0e Mon Sep 17 00:00:00 2001 From: Jim Pepin Date: Thu, 29 Apr 2021 09:15:51 -0400 Subject: [PATCH 2/8] add target OS and specify feature only available on linux --- src/socket.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/socket.rs b/src/socket.rs index 2b638dfc..98dee7e1 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -898,6 +898,8 @@ impl Socket { /// /// 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(any(target_os = "linux"))] pub fn set_ip_transparent(&self) -> io::Result<()> { unsafe { setsockopt( From 4427ba71d51a527fd73866d001855719d3db657c Mon Sep 17 00:00:00 2001 From: Jim Pepin Date: Thu, 29 Apr 2021 09:50:23 -0400 Subject: [PATCH 3/8] add test and a get method --- src/socket.rs | 12 ++++++++++-- tests/socket.rs | 6 ++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/socket.rs b/src/socket.rs index 98dee7e1..a7162e5d 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -900,16 +900,24 @@ impl Socket { /// requires that this option be set on the redirected socket. /// this feature is only available on linux #[cfg(any(target_os = "linux"))] - pub fn set_ip_transparent(&self) -> io::Result<()> { + pub fn set_ip_transparent(&self, transparent: bool) -> io::Result<()> { unsafe { setsockopt( self.inner, sys::IPPROTO_IP, libc::IP_TRANSPARENT, - 1 as c_int, + transparent as c_int, ) } } + /// Get whether the IP_TRANSPARENT is set for this socket. + #[cfg(any(target_os = "linux"))] + pub fn ip_transparent(&self) -> io::Result { + unsafe { + getsockopt::(self.inner, sys::IPPROTO_IP, libc::IP_TRANSPARENT) + .map(|transparent| transparent != 0) + } + } /// Get the value of the `SO_SNDBUF` option on this socket. /// diff --git a/tests/socket.rs b/tests/socket.rs index 5f39bd8d..e77ccd03 100644 --- a/tests/socket.rs +++ b/tests/socket.rs @@ -1047,6 +1047,12 @@ test!( mss, set_mss(256) ); +#[cfg(any(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)"] From d6ef53fe4dde83bc5f3599cb19f94324f0207c95 Mon Sep 17 00:00:00 2001 From: Jim Pepin Date: Thu, 29 Apr 2021 10:36:41 -0400 Subject: [PATCH 4/8] adhere to conventions + fix feature check --- src/socket.rs | 75 ++++++++++++++++++++++++++----------------------- tests/socket.rs | 2 +- 2 files changed, 41 insertions(+), 36 deletions(-) diff --git a/src/socket.rs b/src/socket.rs index a7162e5d..87e6ab3f 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -884,41 +884,6 @@ impl Socket { } } - /// IP_TRANSPARENT (since Linux 2.6.24) - /// 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(any(target_os = "linux"))] - pub fn set_ip_transparent(&self, transparent: bool) -> io::Result<()> { - unsafe { - setsockopt( - self.inner, - sys::IPPROTO_IP, - libc::IP_TRANSPARENT, - transparent as c_int, - ) - } - } - /// Get whether the IP_TRANSPARENT is set for this socket. - #[cfg(any(target_os = "linux"))] - pub fn ip_transparent(&self) -> io::Result { - unsafe { - getsockopt::(self.inner, sys::IPPROTO_IP, libc::IP_TRANSPARENT) - .map(|transparent| transparent != 0) - } - } - /// Get the value of the `SO_SNDBUF` option on this socket. /// /// For more information about this option, see [`set_send_buffer_size`]. @@ -990,6 +955,46 @@ fn into_linger(duration: Option) -> sys::linger { /// * Linux: /// * Windows: impl Socket { + /// Get the value of the `IP_TRANSPARENTF` 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.inner, sys::IPPROTO_IP, libc::IP_TRANSPARENT) + .map(|transparent| transparent != 0) + } + } + + /// IP_TRANSPARENT (since Linux 2.6.24) + /// 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.inner, + 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 e77ccd03..113dfb6c 100644 --- a/tests/socket.rs +++ b/tests/socket.rs @@ -1047,7 +1047,7 @@ test!( mss, set_mss(256) ); -#[cfg(any(target_os = "linux"))] +#[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, From d3eed7ba3d568011797363adcbee8909a7151a73 Mon Sep 17 00:00:00 2001 From: Jim Pepin Date: Thu, 29 Apr 2021 10:44:04 -0400 Subject: [PATCH 5/8] fix comment to match other set methods --- src/socket.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/socket.rs b/src/socket.rs index 87e6ab3f..c62e063d 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -968,6 +968,8 @@ impl Socket { } } + /// Set the value of the `IP_TRANSPARENTF` option on this socket. + /// /// IP_TRANSPARENT (since Linux 2.6.24) /// Setting this boolean option enables transparent proxying /// on this socket. This socket option allows the calling From 2c2ad16e6ad3174000c8e4e8bc859657615a1689 Mon Sep 17 00:00:00 2001 From: Jim Pepin Date: Thu, 29 Apr 2021 15:47:25 -0400 Subject: [PATCH 6/8] fix typo, remove extra comment line --- src/socket.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/socket.rs b/src/socket.rs index c62e063d..631c46fc 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -968,9 +968,8 @@ impl Socket { } } - /// Set the value of the `IP_TRANSPARENTF` option on this socket. + /// Set the value of the `IP_TRANSPARENT` option on this socket. /// - /// IP_TRANSPARENT (since Linux 2.6.24) /// 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 From 9dda3c71c71122571b4d144962c9e8f009c584e4 Mon Sep 17 00:00:00 2001 From: Jim Pepin Date: Thu, 29 Apr 2021 16:12:47 -0400 Subject: [PATCH 7/8] fix typo --- src/socket.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/socket.rs b/src/socket.rs index 631c46fc..e4d99a04 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -955,7 +955,7 @@ fn into_linger(duration: Option) -> sys::linger { /// * Linux: /// * Windows: impl Socket { - /// Get the value of the `IP_TRANSPARENTF` option on this socket. + /// Get the value of the `IP_TRANSPARENT` option on this socket. /// /// For more information about this option, see [`set_ip_transparent`]. /// From 8e7d0d87d31842c310aa38a71875cc5eb20a356d Mon Sep 17 00:00:00 2001 From: Jim Pepin Date: Thu, 29 Apr 2021 16:18:33 -0400 Subject: [PATCH 8/8] self.inner --> self.inner.as_raw() --- src/socket.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/socket.rs b/src/socket.rs index e4d99a04..91d7a5e6 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -963,7 +963,7 @@ impl Socket { #[cfg(all(feature = "all", target_os = "linux"))] pub fn ip_transparent(&self) -> io::Result { unsafe { - getsockopt::(self.inner, sys::IPPROTO_IP, libc::IP_TRANSPARENT) + getsockopt::(self.as_raw(), sys::IPPROTO_IP, libc::IP_TRANSPARENT) .map(|transparent| transparent != 0) } } @@ -988,7 +988,7 @@ impl Socket { pub fn set_ip_transparent(&self, transparent: bool) -> io::Result<()> { unsafe { setsockopt( - self.inner, + self.as_raw(), sys::IPPROTO_IP, libc::IP_TRANSPARENT, transparent as c_int,