From 5593fdee092de3c1c8afe53ee8ae17e8c54a8641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E3=81=AE=E3=81=8B=E3=81=88=E3=81=A7?= Date: Sat, 8 Oct 2022 09:03:51 +0800 Subject: [PATCH] Feat: add bind to device to Windows and Darwin (#1972) --- transport/internet/sockopt_darwin.go | 28 +++++++++++++++++++++++++++ transport/internet/sockopt_windows.go | 18 ++++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/transport/internet/sockopt_darwin.go b/transport/internet/sockopt_darwin.go index 200b6abf8..18868405e 100644 --- a/transport/internet/sockopt_darwin.go +++ b/transport/internet/sockopt_darwin.go @@ -1,6 +1,8 @@ package internet import ( + "net" + "golang.org/x/sys/unix" ) @@ -42,6 +44,19 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf } } + if config.BindToDevice != "" { + iface, err := net.InterfaceByName(config.BindToDevice) + if err != nil { + return newError("failed to get interface ", config.BindToDevice).Base(err) + } + if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_BOUND_IF, iface.Index); err != nil { + return newError("failed to set IP_BOUND_IF", err) + } + if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_BOUND_IF, iface.Index); err != nil { + return newError("failed to set IPV6_BOUND_IF", err) + } + } + if config.TxBufSize != 0 { if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_SNDBUF, int(config.TxBufSize)); err != nil { return newError("failed to set SO_SNDBUF").Base(err) @@ -86,6 +101,19 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) } } + if config.BindToDevice != "" { + iface, err := net.InterfaceByName(config.BindToDevice) + if err != nil { + return newError("failed to get interface ", config.BindToDevice).Base(err) + } + if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_BOUND_IF, iface.Index); err != nil { + return newError("failed to set IP_BOUND_IF", err) + } + if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_BOUND_IF, iface.Index); err != nil { + return newError("failed to set IPV6_BOUND_IF", err) + } + } + if config.TxBufSize != 0 { if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_SNDBUF, int(config.TxBufSize)); err != nil { return newError("failed to set SO_SNDBUF/SO_SNDBUFFORCE").Base(err) diff --git a/transport/internet/sockopt_windows.go b/transport/internet/sockopt_windows.go index eca97278a..6a4ec03fd 100644 --- a/transport/internet/sockopt_windows.go +++ b/transport/internet/sockopt_windows.go @@ -1,13 +1,16 @@ package internet import ( + "net" "syscall" "golang.org/x/sys/windows" ) const ( - TCP_FASTOPEN = 15 // nolint: revive,stylecheck + TCP_FASTOPEN = 15 // nolint: revive,stylecheck + IP_UNICAST_IF = 31 // nolint: revive,stylecheck + IPV6_UNICAST_IF = 31 // nolint: revive,stylecheck ) func setTFO(fd syscall.Handle, settings SocketConfig_TCPFastOpenState) error { @@ -36,6 +39,19 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf } } + if config.BindToDevice != "" { + iface, err := net.InterfaceByName(config.BindToDevice) + if err != nil { + return newError("failed to get interface ", config.BindToDevice).Base(err) + } + if err := windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IP, IP_UNICAST_IF, iface.Index); err != nil { + return newError("failed to set IP_UNICAST_IF", err) + } + if err := windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IPV6, IPV6_UNICAST_IF, iface.Index); err != nil { + return newError("failed to set IPV6_UNICAST_IF", err) + } + } + if config.TxBufSize != 0 { if err := windows.SetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_SNDBUF, int(config.TxBufSize)); err != nil { return newError("failed to set SO_SNDBUF").Base(err)