Skip to content

Commit

Permalink
Generalize original_dst funcs
Browse files Browse the repository at this point in the history
Signed-off-by: Keith Mattix II <[email protected]>
  • Loading branch information
keithmattix committed Oct 7, 2024
1 parent e29f621 commit d75c86d
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 114 deletions.
12 changes: 12 additions & 0 deletions src/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2205,6 +2205,18 @@ impl Socket {
)
}
}

/// Get the value for the `SO_ORIGINAL_DST` option on this socket.
#[cfg(feature = "all")]
pub fn original_dst(&self) -> io::Result<SockAddr> {
sys::original_dst(self.as_raw())
}

/// Get the value for the `IP6T_SO_ORIGINAL_DST` option on this socket.
#[cfg(feature = "all")]
pub fn original_dst_ipv6(&self) -> io::Result<SockAddr> {
sys::original_dst_ipv6(self.as_raw())
}
}

impl Read for Socket {
Expand Down
112 changes: 56 additions & 56 deletions src/sys/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1406,6 +1406,62 @@ pub(crate) const fn to_mreqn(
}
}

/// Get the value for the `SO_ORIGINAL_DST` option on this socket.
///
/// This value contains the original destination IPv4 address of the connection
/// redirected using `iptables` `REDIRECT` or `TPROXY`.
#[cfg(all(
feature = "all",
any(target_os = "android", target_os = "fuchsia", target_os = "linux")
))]
#[cfg_attr(
docsrs,
doc(cfg(all(
feature = "all",
any(target_os = "android", target_os = "fuchsia", target_os = "linux")
)))
)]
pub(crate) fn original_dst(fd: Socket) -> io::Result<SockAddr> {
// Safety: `getsockopt` initialises the `SockAddr` for us.
unsafe {
SockAddr::try_init(|storage, len| {
syscall!(getsockopt(
fd,
libc::SOL_IP,
libc::SO_ORIGINAL_DST,
storage.cast(),
len
))
})
}
.map(|(_, addr)| addr)
}

/// Get the value for the `IP6T_SO_ORIGINAL_DST` option on this socket.
///
/// This value contains the original destination IPv6 address of the connection
/// redirected using `ip6tables` `REDIRECT` or `TPROXY`.
#[cfg(all(feature = "all", any(target_os = "android", target_os = "linux")))]
#[cfg_attr(
docsrs,
doc(cfg(all(feature = "all", any(target_os = "android", target_os = "linux"))))
)]
pub(crate) fn original_dst_ipv6(fd: Socket) -> io::Result<SockAddr> {
// Safety: `getsockopt` initialises the `SockAddr` for us.
unsafe {
SockAddr::try_init(|storage, len| {
syscall!(getsockopt(
fd,
libc::SOL_IPV6,
libc::IP6T_SO_ORIGINAL_DST,
storage.cast(),
len
))
})
}
.map(|(_, addr)| addr)
}

/// Unix only API.
impl crate::Socket {
/// Accept a new incoming connection from this listener.
Expand Down Expand Up @@ -2402,62 +2458,6 @@ impl crate::Socket {
}
}

/// Get the value for the `SO_ORIGINAL_DST` option on this socket.
///
/// This value contains the original destination IPv4 address of the connection
/// redirected using `iptables` `REDIRECT` or `TPROXY`.
#[cfg(all(
feature = "all",
any(target_os = "android", target_os = "fuchsia", target_os = "linux")
))]
#[cfg_attr(
docsrs,
doc(cfg(all(
feature = "all",
any(target_os = "android", target_os = "fuchsia", target_os = "linux")
)))
)]
pub fn original_dst(&self) -> io::Result<SockAddr> {
// Safety: `getsockopt` initialises the `SockAddr` for us.
unsafe {
SockAddr::try_init(|storage, len| {
syscall!(getsockopt(
self.as_raw(),
libc::SOL_IP,
libc::SO_ORIGINAL_DST,
storage.cast(),
len
))
})
}
.map(|(_, addr)| addr)
}

/// Get the value for the `IP6T_SO_ORIGINAL_DST` option on this socket.
///
/// This value contains the original destination IPv6 address of the connection
/// redirected using `ip6tables` `REDIRECT` or `TPROXY`.
#[cfg(all(feature = "all", any(target_os = "android", target_os = "linux")))]
#[cfg_attr(
docsrs,
doc(cfg(all(feature = "all", any(target_os = "android", target_os = "linux"))))
)]
pub fn original_dst_ipv6(&self) -> io::Result<SockAddr> {
// Safety: `getsockopt` initialises the `SockAddr` for us.
unsafe {
SockAddr::try_init(|storage, len| {
syscall!(getsockopt(
self.as_raw(),
libc::SOL_IPV6,
libc::IP6T_SO_ORIGINAL_DST,
storage.cast(),
len
))
})
}
.map(|(_, addr)| addr)
}

/// Copies data between a `file` and this socket using the `sendfile(2)`
/// system call. Because this copying is done within the kernel,
/// `sendfile()` is more efficient than the combination of `read(2)` and
Expand Down
116 changes: 58 additions & 58 deletions src/sys/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,64 @@ pub(crate) fn to_mreqn(
}
}

/// Get the value for the `SO_ORIGINAL_DST` option on this socket.
/// Only valid for sockets in accepting mode.
///
/// Note: if using this function in a proxy context, you must query the
/// redirect records for this socket and set them on the outbound socket
/// created by your proxy in order for any OS level firewall rules to be
/// applied. Read more in the Windows bind and connect redirection
/// [documentation](https://learn.microsoft.com/en-us/windows-hardware/drivers/network/using-bind-or-connect-redirection).
#[cfg(feature = "all")]
#[cfg_attr(docsrs, doc(cfg(all(windows, feature = "all"))))]
pub(crate) fn original_dst(socket: Socket) -> io::Result<SockAddr> {
unsafe {
SockAddr::try_init(|storage, len| {
syscall!(
getsockopt(
socket,
SOL_IP as i32,
SO_ORIGINAL_DST as i32,
storage.cast(),
len,
),
PartialEq::eq,
SOCKET_ERROR
)
})
}
.map(|(_, addr)| addr)
}

/// Get the value for the `IP6T_SO_ORIGINAL_DST` option on this socket.
/// Only valid for sockets in accepting mode.
///
/// Note: if using this function in a proxy context, you must query the
/// redirect records for this socket and set them on the outbound socket
/// created by your proxy in order for any OS level firewall rules to be
/// applied. Read more in the Windows bind and connect redirection
/// [documentation](https://learn.microsoft.com/en-us/windows-hardware/drivers/network/using-bind-or-connect-redirection).
#[cfg(feature = "all")]
#[cfg_attr(docsrs, doc(cfg(all(windows, feature = "all"))))]
pub(crate) fn original_dst_ipv6(socket: Socket) -> io::Result<SockAddr> {
unsafe {
SockAddr::try_init(|storage, len| {
syscall!(
getsockopt(
socket,
SOL_IP as i32,
IP6T_SO_ORIGINAL_DST as i32,
storage.cast(),
len,
),
PartialEq::eq,
SOCKET_ERROR
)
})
}
.map(|(_, addr)| addr)
}

#[allow(unsafe_op_in_unsafe_fn)]
pub(crate) fn unix_sockaddr(path: &Path) -> io::Result<SockAddr> {
// SAFETY: a `sockaddr_storage` of all zeros is valid.
Expand Down Expand Up @@ -929,64 +987,6 @@ impl crate::Socket {
}
}

/// Get the value for the `SO_ORIGINAL_DST` option on this socket.
/// Only valid for sockets in accepting mode.
///
/// Note: if using this function in a proxy context, you must query the
/// redirect records for this socket and set them on the outbound socket
/// created by your proxy in order for any OS level firewall rules to be
/// applied. Read more in the Windows bind and connect redirection
/// [documentation](https://learn.microsoft.com/en-us/windows-hardware/drivers/network/using-bind-or-connect-redirection).
#[cfg(feature = "all")]
#[cfg_attr(docsrs, doc(cfg(all(windows, feature = "all"))))]
pub fn original_dst(&self) -> io::Result<SockAddr> {
unsafe {
SockAddr::try_init(|storage, len| {
syscall!(
getsockopt(
self.as_raw(),
SOL_IP as i32,
SO_ORIGINAL_DST as i32,
storage.cast(),
len,
),
PartialEq::eq,
SOCKET_ERROR
)
})
}
.map(|(_, addr)| addr)
}

/// Get the value for the `IP6T_SO_ORIGINAL_DST` option on this socket.
/// Only valid for sockets in accepting mode.
///
/// Note: if using this function in a proxy context, you must query the
/// redirect records for this socket and set them on the outbound socket
/// created by your proxy in order for any OS level firewall rules to be
/// applied. Read more in the Windows bind and connect redirection
/// [documentation](https://learn.microsoft.com/en-us/windows-hardware/drivers/network/using-bind-or-connect-redirection).
#[cfg(feature = "all")]
#[cfg_attr(docsrs, doc(cfg(all(windows, feature = "all"))))]
pub fn original_dst_ipv6(&self) -> io::Result<SockAddr> {
unsafe {
SockAddr::try_init(|storage, len| {
syscall!(
getsockopt(
self.as_raw(),
SOL_IP as i32,
IP6T_SO_ORIGINAL_DST as i32,
storage.cast(),
len,
),
PartialEq::eq,
SOCKET_ERROR
)
})
}
.map(|(_, addr)| addr)
}

/// Returns the [`Protocol`] of this socket by checking the `SO_PROTOCOL_INFOW`
/// option on this socket.
///
Expand Down

0 comments on commit d75c86d

Please sign in to comment.