bind socket to device on macos (#9)

bind socket to device on macos
This commit is contained in:
Sijie.Sun
2024-01-31 21:43:23 +08:00
committed by GitHub
parent a0e59f5c56
commit 95a52a4b5c
3 changed files with 55 additions and 26 deletions

View File

@@ -1,6 +1,6 @@
use std::{
collections::VecDeque,
net::IpAddr,
net::{IpAddr, SocketAddr},
sync::Arc,
task::{ready, Context, Poll},
};
@@ -269,6 +269,39 @@ pub(crate) fn get_interface_name_by_ip(local_ip: &IpAddr) -> Option<String> {
None
}
pub(crate) fn setup_sokcet2(
socket2_socket: &socket2::Socket,
bind_addr: &SocketAddr,
) -> Result<(), TunnelError> {
socket2_socket.set_nonblocking(true)?;
socket2_socket.set_reuse_address(true)?;
socket2_socket.bind(&socket2::SockAddr::from(*bind_addr))?;
#[cfg(all(unix, not(target_os = "solaris"), not(target_os = "illumos")))]
socket2_socket.set_reuse_port(true)?;
// linux/mac does not use interface of bind_addr to send packet, so we need to bind device
// win can handle this with bind correctly
#[cfg(any(target_os = "ios", target_os = "macos"))]
if let Some(dev_name) = super::common::get_interface_name_by_ip(&bind_addr.ip()) {
// use IP_BOUND_IF to bind device
unsafe {
let dev_idx = nix::libc::if_nametoindex(dev_name.as_str().as_ptr() as *const i8);
tracing::warn!(?dev_idx, ?dev_name, "bind device");
socket2_socket.bind_device_by_index_v4(std::num::NonZeroU32::new(dev_idx))?;
tracing::warn!(?dev_idx, ?dev_name, "bind device doen");
}
}
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
if let Some(dev_name) = super::common::get_interface_name_by_ip(&bind_addr.ip()) {
tracing::trace!(dev_name = ?dev_name, "bind device");
socket2_socket.bind_device(Some(dev_name.as_bytes()))?;
}
Ok(())
}
pub mod tests {
use std::time::Instant;