Skip to content

Commit d75c86d

Browse files
committed
Generalize original_dst funcs
Signed-off-by: Keith Mattix II <[email protected]>
1 parent e29f621 commit d75c86d

File tree

3 files changed

+126
-114
lines changed

3 files changed

+126
-114
lines changed

src/socket.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2205,6 +2205,18 @@ impl Socket {
22052205
)
22062206
}
22072207
}
2208+
2209+
/// Get the value for the `SO_ORIGINAL_DST` option on this socket.
2210+
#[cfg(feature = "all")]
2211+
pub fn original_dst(&self) -> io::Result<SockAddr> {
2212+
sys::original_dst(self.as_raw())
2213+
}
2214+
2215+
/// Get the value for the `IP6T_SO_ORIGINAL_DST` option on this socket.
2216+
#[cfg(feature = "all")]
2217+
pub fn original_dst_ipv6(&self) -> io::Result<SockAddr> {
2218+
sys::original_dst_ipv6(self.as_raw())
2219+
}
22082220
}
22092221

22102222
impl Read for Socket {

src/sys/unix.rs

Lines changed: 56 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,6 +1406,62 @@ pub(crate) const fn to_mreqn(
14061406
}
14071407
}
14081408

1409+
/// Get the value for the `SO_ORIGINAL_DST` option on this socket.
1410+
///
1411+
/// This value contains the original destination IPv4 address of the connection
1412+
/// redirected using `iptables` `REDIRECT` or `TPROXY`.
1413+
#[cfg(all(
1414+
feature = "all",
1415+
any(target_os = "android", target_os = "fuchsia", target_os = "linux")
1416+
))]
1417+
#[cfg_attr(
1418+
docsrs,
1419+
doc(cfg(all(
1420+
feature = "all",
1421+
any(target_os = "android", target_os = "fuchsia", target_os = "linux")
1422+
)))
1423+
)]
1424+
pub(crate) fn original_dst(fd: Socket) -> io::Result<SockAddr> {
1425+
// Safety: `getsockopt` initialises the `SockAddr` for us.
1426+
unsafe {
1427+
SockAddr::try_init(|storage, len| {
1428+
syscall!(getsockopt(
1429+
fd,
1430+
libc::SOL_IP,
1431+
libc::SO_ORIGINAL_DST,
1432+
storage.cast(),
1433+
len
1434+
))
1435+
})
1436+
}
1437+
.map(|(_, addr)| addr)
1438+
}
1439+
1440+
/// Get the value for the `IP6T_SO_ORIGINAL_DST` option on this socket.
1441+
///
1442+
/// This value contains the original destination IPv6 address of the connection
1443+
/// redirected using `ip6tables` `REDIRECT` or `TPROXY`.
1444+
#[cfg(all(feature = "all", any(target_os = "android", target_os = "linux")))]
1445+
#[cfg_attr(
1446+
docsrs,
1447+
doc(cfg(all(feature = "all", any(target_os = "android", target_os = "linux"))))
1448+
)]
1449+
pub(crate) fn original_dst_ipv6(fd: Socket) -> io::Result<SockAddr> {
1450+
// Safety: `getsockopt` initialises the `SockAddr` for us.
1451+
unsafe {
1452+
SockAddr::try_init(|storage, len| {
1453+
syscall!(getsockopt(
1454+
fd,
1455+
libc::SOL_IPV6,
1456+
libc::IP6T_SO_ORIGINAL_DST,
1457+
storage.cast(),
1458+
len
1459+
))
1460+
})
1461+
}
1462+
.map(|(_, addr)| addr)
1463+
}
1464+
14091465
/// Unix only API.
14101466
impl crate::Socket {
14111467
/// Accept a new incoming connection from this listener.
@@ -2402,62 +2458,6 @@ impl crate::Socket {
24022458
}
24032459
}
24042460

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-
24612461
/// Copies data between a `file` and this socket using the `sendfile(2)`
24622462
/// system call. Because this copying is done within the kernel,
24632463
/// `sendfile()` is more efficient than the combination of `read(2)` and

src/sys/windows.rs

Lines changed: 58 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,64 @@ pub(crate) fn to_mreqn(
859859
}
860860
}
861861

862+
/// Get the value for the `SO_ORIGINAL_DST` option on this socket.
863+
/// Only valid for sockets in accepting mode.
864+
///
865+
/// Note: if using this function in a proxy context, you must query the
866+
/// redirect records for this socket and set them on the outbound socket
867+
/// created by your proxy in order for any OS level firewall rules to be
868+
/// applied. Read more in the Windows bind and connect redirection
869+
/// [documentation](https://learn.microsoft.com/en-us/windows-hardware/drivers/network/using-bind-or-connect-redirection).
870+
#[cfg(feature = "all")]
871+
#[cfg_attr(docsrs, doc(cfg(all(windows, feature = "all"))))]
872+
pub(crate) fn original_dst(socket: Socket) -> io::Result<SockAddr> {
873+
unsafe {
874+
SockAddr::try_init(|storage, len| {
875+
syscall!(
876+
getsockopt(
877+
socket,
878+
SOL_IP as i32,
879+
SO_ORIGINAL_DST as i32,
880+
storage.cast(),
881+
len,
882+
),
883+
PartialEq::eq,
884+
SOCKET_ERROR
885+
)
886+
})
887+
}
888+
.map(|(_, addr)| addr)
889+
}
890+
891+
/// Get the value for the `IP6T_SO_ORIGINAL_DST` option on this socket.
892+
/// Only valid for sockets in accepting mode.
893+
///
894+
/// Note: if using this function in a proxy context, you must query the
895+
/// redirect records for this socket and set them on the outbound socket
896+
/// created by your proxy in order for any OS level firewall rules to be
897+
/// applied. Read more in the Windows bind and connect redirection
898+
/// [documentation](https://learn.microsoft.com/en-us/windows-hardware/drivers/network/using-bind-or-connect-redirection).
899+
#[cfg(feature = "all")]
900+
#[cfg_attr(docsrs, doc(cfg(all(windows, feature = "all"))))]
901+
pub(crate) fn original_dst_ipv6(socket: Socket) -> io::Result<SockAddr> {
902+
unsafe {
903+
SockAddr::try_init(|storage, len| {
904+
syscall!(
905+
getsockopt(
906+
socket,
907+
SOL_IP as i32,
908+
IP6T_SO_ORIGINAL_DST as i32,
909+
storage.cast(),
910+
len,
911+
),
912+
PartialEq::eq,
913+
SOCKET_ERROR
914+
)
915+
})
916+
}
917+
.map(|(_, addr)| addr)
918+
}
919+
862920
#[allow(unsafe_op_in_unsafe_fn)]
863921
pub(crate) fn unix_sockaddr(path: &Path) -> io::Result<SockAddr> {
864922
// SAFETY: a `sockaddr_storage` of all zeros is valid.
@@ -929,64 +987,6 @@ impl crate::Socket {
929987
}
930988
}
931989

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-
990990
/// Returns the [`Protocol`] of this socket by checking the `SO_PROTOCOL_INFOW`
991991
/// option on this socket.
992992
///

0 commit comments

Comments
 (0)