Browse Source

Feat: add bind to device to Windows and Darwin (#1972)

秋のかえで 3 years ago
parent
commit
5593fdee09
2 changed files with 45 additions and 1 deletions
  1. 28 0
      transport/internet/sockopt_darwin.go
  2. 17 1
      transport/internet/sockopt_windows.go

+ 28 - 0
transport/internet/sockopt_darwin.go

@@ -1,6 +1,8 @@
 package internet
 package internet
 
 
 import (
 import (
+	"net"
+
 	"golang.org/x/sys/unix"
 	"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 config.TxBufSize != 0 {
 		if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_SNDBUF, int(config.TxBufSize)); err != nil {
 		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)
 			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 config.TxBufSize != 0 {
 		if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_SNDBUF, int(config.TxBufSize)); err != nil {
 		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)
 			return newError("failed to set SO_SNDBUF/SO_SNDBUFFORCE").Base(err)

+ 17 - 1
transport/internet/sockopt_windows.go

@@ -1,13 +1,16 @@
 package internet
 package internet
 
 
 import (
 import (
+	"net"
 	"syscall"
 	"syscall"
 
 
 	"golang.org/x/sys/windows"
 	"golang.org/x/sys/windows"
 )
 )
 
 
 const (
 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 {
 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 config.TxBufSize != 0 {
 		if err := windows.SetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_SNDBUF, int(config.TxBufSize)); err != nil {
 		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)
 			return newError("failed to set SO_SNDBUF").Base(err)