diff --git a/src/yggdrasil/tcp.go b/src/yggdrasil/tcp.go index 7d5b80b..9cca419 100644 --- a/src/yggdrasil/tcp.go +++ b/src/yggdrasil/tcp.go @@ -299,6 +299,7 @@ func (t *tcp) call(saddr string, options interface{}, sintf string, upgrade *Tcp Timeout: time.Second * 5, } if sintf != "" { + dialer.Control = t.getControl(sintf) ief, err := net.InterfaceByName(sintf) if err != nil { return diff --git a/src/yggdrasil/tcp_darwin.go b/src/yggdrasil/tcp_darwin.go index 9d55a1d..3d0626c 100644 --- a/src/yggdrasil/tcp_darwin.go +++ b/src/yggdrasil/tcp_darwin.go @@ -26,3 +26,7 @@ func (t *tcp) tcpContext(network, address string, c syscall.RawConn) error { return control } } + +func (t *tcp) getControl(sintf string) func(string, string, syscall.RawConn) error { + return t.tcpContext +} diff --git a/src/yggdrasil/tcp_linux.go b/src/yggdrasil/tcp_linux.go index 7eda3b5..9ec3c10 100644 --- a/src/yggdrasil/tcp_linux.go +++ b/src/yggdrasil/tcp_linux.go @@ -29,3 +29,17 @@ func (t *tcp) tcpContext(network, address string, c syscall.RawConn) error { // Return nil because errors here are not considered fatal for the connection, it just means congestion control is suboptimal return nil } + +func (t *tcp) getControl(sintf string) func(string, string, syscall.RawConn) error { + return func(network, address string, c syscall.RawConn) error { + var err error + btd := func(fd uintptr) { + err = unix.BindToDevice(int(fd), sintf) + } + c.Control(btd) + if err != nil { + t.link.core.log.Debugln("Failed to set SO_BINDTODEVICE:", sintf) + } + return t.tcpContext(network, address, c) + } +} diff --git a/src/yggdrasil/tcp_other.go b/src/yggdrasil/tcp_other.go index 44c3d76..7ee4197 100644 --- a/src/yggdrasil/tcp_other.go +++ b/src/yggdrasil/tcp_other.go @@ -11,3 +11,7 @@ import ( func (t *tcp) tcpContext(network, address string, c syscall.RawConn) error { return nil } + +func (t *tcp) getControl(sintf string) func(string, string, syscall.RawConn) error { + return t.tcpContext +}