diff --git a/src/sys/unix.rs b/src/sys/unix.rs index 89320b32..0bc70caf 100644 --- a/src/sys/unix.rs +++ b/src/sys/unix.rs @@ -3309,6 +3309,40 @@ impl crate::Socket { ) } } + + /// Set the value of the `SO_BINDANY` option on this socket. + /// + /// SO_BINDANY allows the socket to be bound to addresses which are not + /// local to the machine, so it can be used to make a transparent proxy. + /// Note that this option is limited to the superuser. In order to + /// receive packets for these addresses, SO_BINDANY needs to be combined + /// with matching outgoing pf(4) rules with the divert-reply parameter. + #[cfg(all(feature = "all", target_os = "openbsd"))] + #[cfg_attr(docsrs, doc(cfg(all(feature = "all", target_os = "openbsd"))))] + pub fn set_so_bindany(&self, bindany: bool) -> io::Result<()> { + unsafe { + setsockopt( + self.as_raw(), + libc::IPPROTO_IP, + libc::SO_BINDANY, + bindany as c_int, + ) + } + } + + /// Get the value of the `IP_BINDANY` option on this socket. + /// + /// For more information about this option, see [`set_ip_bindany`]. + /// + /// [`set_ip_bindany`]: crate::Socket::set_ip_bindany + #[cfg(all(feature = "all", target_os = "freebsd"))] + #[cfg_attr(docsrs, doc(cfg(all(feature = "all", target_os = "freebsd"))))] + pub fn ip_bindany(&self) -> io::Result { + unsafe { + getsockopt::(self.as_raw(), libc::IPPROTO_IP, libc::IP_BINDANY) + .map(|bindany| bindany != 0) + } + } } /// See [`Socket::dccp_available_ccids`]. diff --git a/tests/socket.rs b/tests/socket.rs index cd7e868f..3a31318b 100644 --- a/tests/socket.rs +++ b/tests/socket.rs @@ -1390,6 +1390,12 @@ test!( ip_bindany_v6, set_ip_bindany_v6(true) ); +#[cfg(all(feature = "all", target_os = "openbsd"))] +test!( + #[ignore = "setting `SO_BINDANY` is limited to the superuser"] + so_bindany, + set_so_bindany(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)"]