Skip to content

Commit 7a46f91

Browse files
committed
Migrate original_dst to socket.rs out of os specific files
Signed-off-by: Keith Mattix II <[email protected]>
1 parent e29f621 commit 7a46f91

File tree

4 files changed

+153
-120
lines changed

4 files changed

+153
-120
lines changed

src/socket.rs

Lines changed: 150 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
8-
98
use std::fmt;
109
use std::io::{self, Read, Write};
1110
#[cfg(not(target_os = "redox"))]
@@ -19,6 +18,10 @@ use std::os::unix::io::{FromRawFd, IntoRawFd};
1918
#[cfg(windows)]
2019
use std::os::windows::io::{FromRawSocket, IntoRawSocket};
2120
use std::time::Duration;
21+
#[cfg(all(windows, feature = "all"))]
22+
use windows_sys::Win32::Networking::WinSock::{
23+
IP6T_SO_ORIGINAL_DST, SOCKET_ERROR, SOL_IP, SO_ORIGINAL_DST,
24+
};
2225

2326
use crate::sys::{self, c_int, getsockopt, setsockopt, Bool};
2427
#[cfg(all(unix, not(target_os = "redox")))]
@@ -27,6 +30,38 @@ use crate::{Domain, Protocol, SockAddr, TcpKeepalive, Type};
2730
#[cfg(not(target_os = "redox"))]
2831
use crate::{MaybeUninitSlice, MsgHdr, RecvFlags};
2932

33+
#[cfg(all(windows, feature = "all"))]
34+
#[cfg_attr(docsrs, doc(cfg(all(windows, feature = "all"))))]
35+
/// Helper macro to execute a system call that returns an `io::Result`.
36+
macro_rules! syscall {
37+
($fn: ident ( $($arg: expr),* $(,)* ), $err_test: path, $err_value: expr) => {{
38+
#[allow(unused_unsafe)]
39+
let res = unsafe { windows_sys::Win32::Networking::WinSock::$fn($($arg, )*) };
40+
if $err_test(&res, &$err_value) {
41+
Err(io::Error::last_os_error())
42+
} else {
43+
Ok(res)
44+
}
45+
}};
46+
}
47+
48+
#[cfg(all(
49+
feature = "all",
50+
any(target_os = "android", target_os = "fuchsia", target_os = "linux",)
51+
))]
52+
/// Helper macro to execute a system call that returns an `io::Result`.
53+
macro_rules! syscall {
54+
($fn: ident ( $($arg: expr),* $(,)* ) ) => {{
55+
#[allow(unused_unsafe)]
56+
let res = unsafe { libc::$fn($($arg, )*) };
57+
if res == -1 {
58+
Err(std::io::Error::last_os_error())
59+
} else {
60+
Ok(res)
61+
}
62+
}};
63+
}
64+
3065
/// Owned wrapper around a system socket.
3166
///
3267
/// This type simply wraps an instance of a file descriptor (`c_int`) on Unix
@@ -2205,6 +2240,120 @@ impl Socket {
22052240
)
22062241
}
22072242
}
2243+
2244+
/// Get the value for the `SO_ORIGINAL_DST` option on this socket.
2245+
///
2246+
/// This value contains the original destination IPv4 address of the connection
2247+
/// redirected using `iptables` `REDIRECT` or `TPROXY`.
2248+
#[cfg(all(
2249+
feature = "all",
2250+
any(target_os = "android", target_os = "fuchsia", target_os = "linux",)
2251+
))]
2252+
#[cfg_attr(
2253+
docsrs,
2254+
doc(cfg(all(
2255+
feature = "all",
2256+
any(target_os = "android", target_os = "fuchsia", target_os = "linux",)
2257+
)))
2258+
)]
2259+
pub fn original_dst(&self) -> io::Result<SockAddr> {
2260+
// Safety: `getsockopt` initialises the `SockAddr` for us.
2261+
unsafe {
2262+
SockAddr::try_init(|storage, len| {
2263+
syscall!(getsockopt(
2264+
self.as_raw(),
2265+
libc::SOL_IP,
2266+
libc::SO_ORIGINAL_DST,
2267+
storage.cast(),
2268+
len
2269+
))
2270+
})
2271+
}
2272+
.map(|(_, addr)| addr)
2273+
}
2274+
2275+
/// Get the value for the `IP6T_SO_ORIGINAL_DST` option on this socket.
2276+
///
2277+
/// This value contains the original destination IPv6 address of the connection
2278+
/// redirected using `ip6tables` `REDIRECT` or `TPROXY`.
2279+
#[cfg(all(feature = "all", any(target_os = "android", target_os = "linux",)))]
2280+
#[cfg_attr(
2281+
docsrs,
2282+
doc(cfg(all(feature = "all", any(target_os = "android", target_os = "linux",))))
2283+
)]
2284+
pub fn original_dst_ipv6(&self) -> io::Result<SockAddr> {
2285+
// Safety: `getsockopt` initialises the `SockAddr` for us.
2286+
unsafe {
2287+
SockAddr::try_init(|storage, len| {
2288+
syscall!(getsockopt(
2289+
self.as_raw(),
2290+
libc::SOL_IPV6,
2291+
libc::IP6T_SO_ORIGINAL_DST,
2292+
storage.cast(),
2293+
len
2294+
))
2295+
})
2296+
}
2297+
.map(|(_, addr)| addr)
2298+
}
2299+
2300+
/// Get the value for the `SO_ORIGINAL_DST` option on this socket.
2301+
/// Only valid for sockets in accepting mode.
2302+
///
2303+
/// Note: if using this function in a proxy context, you must query the
2304+
/// redirect records for this socket and set them on the outbound socket
2305+
/// created by your proxy in order for any OS level firewall rules to be
2306+
/// applied. Read more in the Windows bind and connect redirection
2307+
/// [documentation](https://learn.microsoft.com/en-us/windows-hardware/drivers/network/using-bind-or-connect-redirection).
2308+
#[cfg(all(windows, feature = "all"))]
2309+
#[cfg_attr(docsrs, doc(cfg(all(windows, feature = "all"))))]
2310+
pub fn original_dst(&self) -> io::Result<SockAddr> {
2311+
unsafe {
2312+
SockAddr::try_init(|storage, len| {
2313+
syscall!(
2314+
getsockopt(
2315+
self.as_raw(),
2316+
SOL_IP as i32,
2317+
SO_ORIGINAL_DST as i32,
2318+
storage.cast(),
2319+
len,
2320+
),
2321+
PartialEq::eq,
2322+
SOCKET_ERROR
2323+
)
2324+
})
2325+
}
2326+
.map(|(_, addr)| addr)
2327+
}
2328+
2329+
/// Get the value for the `IP6T_SO_ORIGINAL_DST` option on this socket.
2330+
/// Only valid for sockets in accepting mode.
2331+
///
2332+
/// Note: if using this function in a proxy context, you must query the
2333+
/// redirect records for this socket and set them on the outbound socket
2334+
/// created by your proxy in order for any OS level firewall rules to be
2335+
/// applied. Read more in the Windows bind and connect redirection
2336+
/// [documentation](https://learn.microsoft.com/en-us/windows-hardware/drivers/network/using-bind-or-connect-redirection).
2337+
#[cfg(all(windows, feature = "all"))]
2338+
#[cfg_attr(docsrs, doc(cfg(all(windows, feature = "all"))))]
2339+
pub fn original_dst_ipv6(&self) -> io::Result<SockAddr> {
2340+
unsafe {
2341+
SockAddr::try_init(|storage, len| {
2342+
syscall!(
2343+
getsockopt(
2344+
self.as_raw(),
2345+
SOL_IP as i32,
2346+
IP6T_SO_ORIGINAL_DST as i32,
2347+
storage.cast(),
2348+
len,
2349+
),
2350+
PartialEq::eq,
2351+
SOCKET_ERROR
2352+
)
2353+
})
2354+
}
2355+
.map(|(_, addr)| addr)
2356+
}
22082357
}
22092358

22102359
impl Read for Socket {

src/sys/unix.rs

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2402,62 +2402,6 @@ impl crate::Socket {
24022402
}
24032403
}
24042404

2405-
/// Get the value for the `SO_ORIGINAL_DST` option on this socket.
2406-
///
2407-
/// This value contains the original destination IPv4 address of the connection
2408-
/// redirected using `iptables` `REDIRECT` or `TPROXY`.
2409-
#[cfg(all(
2410-
feature = "all",
2411-
any(target_os = "android", target_os = "fuchsia", target_os = "linux")
2412-
))]
2413-
#[cfg_attr(
2414-
docsrs,
2415-
doc(cfg(all(
2416-
feature = "all",
2417-
any(target_os = "android", target_os = "fuchsia", target_os = "linux")
2418-
)))
2419-
)]
2420-
pub fn original_dst(&self) -> io::Result<SockAddr> {
2421-
// Safety: `getsockopt` initialises the `SockAddr` for us.
2422-
unsafe {
2423-
SockAddr::try_init(|storage, len| {
2424-
syscall!(getsockopt(
2425-
self.as_raw(),
2426-
libc::SOL_IP,
2427-
libc::SO_ORIGINAL_DST,
2428-
storage.cast(),
2429-
len
2430-
))
2431-
})
2432-
}
2433-
.map(|(_, addr)| addr)
2434-
}
2435-
2436-
/// Get the value for the `IP6T_SO_ORIGINAL_DST` option on this socket.
2437-
///
2438-
/// This value contains the original destination IPv6 address of the connection
2439-
/// redirected using `ip6tables` `REDIRECT` or `TPROXY`.
2440-
#[cfg(all(feature = "all", any(target_os = "android", target_os = "linux")))]
2441-
#[cfg_attr(
2442-
docsrs,
2443-
doc(cfg(all(feature = "all", any(target_os = "android", target_os = "linux"))))
2444-
)]
2445-
pub fn original_dst_ipv6(&self) -> io::Result<SockAddr> {
2446-
// Safety: `getsockopt` initialises the `SockAddr` for us.
2447-
unsafe {
2448-
SockAddr::try_init(|storage, len| {
2449-
syscall!(getsockopt(
2450-
self.as_raw(),
2451-
libc::SOL_IPV6,
2452-
libc::IP6T_SO_ORIGINAL_DST,
2453-
storage.cast(),
2454-
len
2455-
))
2456-
})
2457-
}
2458-
.map(|(_, addr)| addr)
2459-
}
2460-
24612405
/// Copies data between a `file` and this socket using the `sendfile(2)`
24622406
/// system call. Because this copying is done within the kernel,
24632407
/// `sendfile()` is more efficient than the combination of `read(2)` and

src/sys/windows.rs

Lines changed: 2 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,14 @@ use std::time::{Duration, Instant};
2020
use std::{process, ptr, slice};
2121

2222
use windows_sys::Win32::Foundation::{SetHandleInformation, HANDLE, HANDLE_FLAG_INHERIT};
23+
#[cfg(feature = "all")]
24+
use windows_sys::Win32::Networking::WinSock::SO_PROTOCOL_INFOW;
2325
use windows_sys::Win32::Networking::WinSock::{
2426
self, tcp_keepalive, FIONBIO, IN6_ADDR, IN6_ADDR_0, INVALID_SOCKET, IN_ADDR, IN_ADDR_0,
2527
POLLERR, POLLHUP, POLLRDNORM, POLLWRNORM, SD_BOTH, SD_RECEIVE, SD_SEND, SIO_KEEPALIVE_VALS,
2628
SOCKET_ERROR, WSABUF, WSAEMSGSIZE, WSAESHUTDOWN, WSAPOLLFD, WSAPROTOCOL_INFOW,
2729
WSA_FLAG_NO_HANDLE_INHERIT, WSA_FLAG_OVERLAPPED,
2830
};
29-
#[cfg(feature = "all")]
30-
use windows_sys::Win32::Networking::WinSock::{
31-
IP6T_SO_ORIGINAL_DST, SOL_IP, SO_ORIGINAL_DST, SO_PROTOCOL_INFOW,
32-
};
3331
use windows_sys::Win32::System::Threading::INFINITE;
3432

3533
use crate::{MsgHdr, RecvFlags, SockAddr, TcpKeepalive, Type};
@@ -929,64 +927,6 @@ impl crate::Socket {
929927
}
930928
}
931929

932-
/// Get the value for the `SO_ORIGINAL_DST` option on this socket.
933-
/// Only valid for sockets in accepting mode.
934-
///
935-
/// Note: if using this function in a proxy context, you must query the
936-
/// redirect records for this socket and set them on the outbound socket
937-
/// created by your proxy in order for any OS level firewall rules to be
938-
/// applied. Read more in the Windows bind and connect redirection
939-
/// [documentation](https://learn.microsoft.com/en-us/windows-hardware/drivers/network/using-bind-or-connect-redirection).
940-
#[cfg(feature = "all")]
941-
#[cfg_attr(docsrs, doc(cfg(all(windows, feature = "all"))))]
942-
pub fn original_dst(&self) -> io::Result<SockAddr> {
943-
unsafe {
944-
SockAddr::try_init(|storage, len| {
945-
syscall!(
946-
getsockopt(
947-
self.as_raw(),
948-
SOL_IP as i32,
949-
SO_ORIGINAL_DST as i32,
950-
storage.cast(),
951-
len,
952-
),
953-
PartialEq::eq,
954-
SOCKET_ERROR
955-
)
956-
})
957-
}
958-
.map(|(_, addr)| addr)
959-
}
960-
961-
/// Get the value for the `IP6T_SO_ORIGINAL_DST` option on this socket.
962-
/// Only valid for sockets in accepting mode.
963-
///
964-
/// Note: if using this function in a proxy context, you must query the
965-
/// redirect records for this socket and set them on the outbound socket
966-
/// created by your proxy in order for any OS level firewall rules to be
967-
/// applied. Read more in the Windows bind and connect redirection
968-
/// [documentation](https://learn.microsoft.com/en-us/windows-hardware/drivers/network/using-bind-or-connect-redirection).
969-
#[cfg(feature = "all")]
970-
#[cfg_attr(docsrs, doc(cfg(all(windows, feature = "all"))))]
971-
pub fn original_dst_ipv6(&self) -> io::Result<SockAddr> {
972-
unsafe {
973-
SockAddr::try_init(|storage, len| {
974-
syscall!(
975-
getsockopt(
976-
self.as_raw(),
977-
SOL_IP as i32,
978-
IP6T_SO_ORIGINAL_DST as i32,
979-
storage.cast(),
980-
len,
981-
),
982-
PartialEq::eq,
983-
SOCKET_ERROR
984-
)
985-
})
986-
}
987-
.map(|(_, addr)| addr)
988-
}
989-
990930
/// Returns the [`Protocol`] of this socket by checking the `SO_PROTOCOL_INFOW`
991931
/// option on this socket.
992932
///

tests/socket.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ fn unix_sockets_supported() -> bool {
542542
Ok(_) => {}
543543
Err(err)
544544
if err.raw_os_error()
545-
== Some(windows_sys::Win32::Networking::WinSock::WSAEAFNOSUPPORT as i32) =>
545+
== Some(windows_sys::Win32::Networking::WinSock::WSAEAFNOSUPPORT) =>
546546
{
547547
return false;
548548
}

0 commit comments

Comments
 (0)