net/netns: thread logf into control functions
So that darwin can log there without panicking during tests. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
This commit is contained in:

committed by
Josh Bleecher Snyder

parent
85184a58ed
commit
758c37b83d
@ -21,6 +21,7 @@ import (
|
||||
"inet.af/netaddr"
|
||||
"tailscale.com/net/netknob"
|
||||
"tailscale.com/syncs"
|
||||
"tailscale.com/types/logger"
|
||||
)
|
||||
|
||||
var disabled syncs.AtomicBool
|
||||
@ -34,19 +35,19 @@ func SetEnabled(on bool) {
|
||||
// Listener returns a new net.Listener with its Control hook func
|
||||
// initialized as necessary to run in logical network namespace that
|
||||
// doesn't route back into Tailscale.
|
||||
func Listener() *net.ListenConfig {
|
||||
func Listener(logf logger.Logf) *net.ListenConfig {
|
||||
if disabled.Get() {
|
||||
return new(net.ListenConfig)
|
||||
}
|
||||
return &net.ListenConfig{Control: control}
|
||||
return &net.ListenConfig{Control: control(logf)}
|
||||
}
|
||||
|
||||
// NewDialer returns a new Dialer using a net.Dialer with its Control
|
||||
// hook func initialized as necessary to run in a logical network
|
||||
// namespace that doesn't route back into Tailscale. It also handles
|
||||
// using a SOCKS if configured in the environment with ALL_PROXY.
|
||||
func NewDialer() Dialer {
|
||||
return FromDialer(&net.Dialer{
|
||||
func NewDialer(logf logger.Logf) Dialer {
|
||||
return FromDialer(logf, &net.Dialer{
|
||||
KeepAlive: netknob.PlatformTCPKeepAlive(),
|
||||
})
|
||||
}
|
||||
@ -55,11 +56,11 @@ func NewDialer() Dialer {
|
||||
// network namespace that doesn't route back into Tailscale. It also
|
||||
// handles using a SOCKS if configured in the environment with
|
||||
// ALL_PROXY.
|
||||
func FromDialer(d *net.Dialer) Dialer {
|
||||
func FromDialer(logf logger.Logf, d *net.Dialer) Dialer {
|
||||
if disabled.Get() {
|
||||
return d
|
||||
}
|
||||
d.Control = control
|
||||
d.Control = control(logf)
|
||||
if wrapDialer != nil {
|
||||
return wrapDialer(d)
|
||||
}
|
||||
|
@ -11,6 +11,8 @@ import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"tailscale.com/types/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -44,11 +46,15 @@ func SetAndroidProtectFunc(f func(fd int) error) {
|
||||
androidProtectFunc = f
|
||||
}
|
||||
|
||||
// control marks c as necessary to dial in a separate network namespace.
|
||||
func control(logger.Logf) func(network, address string, c syscall.RawConn) error {
|
||||
return controlC
|
||||
}
|
||||
|
||||
// controlC marks c as necessary to dial in a separate network namespace.
|
||||
//
|
||||
// It's intentionally the same signature as net.Dialer.Control
|
||||
// and net.ListenConfig.Control.
|
||||
func control(network, address string, c syscall.RawConn) error {
|
||||
func controlC(network, address string, c syscall.RawConn) error {
|
||||
var sockErr error
|
||||
err := c.Control(func(fd uintptr) {
|
||||
androidProtectFuncMu.Lock()
|
||||
|
@ -9,26 +9,32 @@ package netns
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"tailscale.com/net/interfaces"
|
||||
"tailscale.com/types/logger"
|
||||
)
|
||||
|
||||
// control marks c as necessary to dial in a separate network namespace.
|
||||
func control(logf logger.Logf) func(network, address string, c syscall.RawConn) error {
|
||||
return func(network, address string, c syscall.RawConn) error {
|
||||
return controlLogf(logf, network, address, c)
|
||||
}
|
||||
}
|
||||
|
||||
// controlLogf marks c as necessary to dial in a separate network namespace.
|
||||
//
|
||||
// It's intentionally the same signature as net.Dialer.Control
|
||||
// and net.ListenConfig.Control.
|
||||
func control(network, address string, c syscall.RawConn) error {
|
||||
func controlLogf(logf logger.Logf, network, address string, c syscall.RawConn) error {
|
||||
if strings.HasPrefix(address, "127.") || address == "::1" {
|
||||
// Don't bind to an interface for localhost connections.
|
||||
return nil
|
||||
}
|
||||
idx, err := interfaces.DefaultRouteInterfaceIndex()
|
||||
if err != nil {
|
||||
log.Printf("netns: DefaultRouteInterfaceIndex: %v", err)
|
||||
logf("[unexpected] netns: DefaultRouteInterfaceIndex: %v", err)
|
||||
return nil
|
||||
}
|
||||
v6 := strings.Contains(address, "]:") || strings.HasSuffix(network, "6") // hacky test for v6
|
||||
@ -47,7 +53,7 @@ func control(network, address string, c syscall.RawConn) error {
|
||||
return fmt.Errorf("RawConn.Control on %T: %w", c, err)
|
||||
}
|
||||
if sockErr != nil {
|
||||
log.Printf("netns: control(%q, %q), v6=%v, index=%v: %v", network, address, v6, idx, sockErr)
|
||||
logf("[unexpected] netns: control(%q, %q), v6=%v, index=%v: %v", network, address, v6, idx, sockErr)
|
||||
}
|
||||
return sockErr
|
||||
}
|
||||
|
@ -7,9 +7,17 @@
|
||||
|
||||
package netns
|
||||
|
||||
import "syscall"
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
// control does nothing to c.
|
||||
func control(network, address string, c syscall.RawConn) error {
|
||||
"tailscale.com/types/logger"
|
||||
)
|
||||
|
||||
func control(logger.Logf) func(network, address string, c syscall.RawConn) error {
|
||||
return controlC
|
||||
}
|
||||
|
||||
// controlC does nothing to c.
|
||||
func controlC(network, address string, c syscall.RawConn) error {
|
||||
return nil
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"tailscale.com/net/interfaces"
|
||||
"tailscale.com/types/logger"
|
||||
)
|
||||
|
||||
// tailscaleBypassMark is the mark indicating that packets originating
|
||||
@ -82,11 +83,15 @@ func ignoreErrors() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// control marks c as necessary to dial in a separate network namespace.
|
||||
func control(logger.Logf) func(network, address string, c syscall.RawConn) error {
|
||||
return controlC
|
||||
}
|
||||
|
||||
// controlC marks c as necessary to dial in a separate network namespace.
|
||||
//
|
||||
// It's intentionally the same signature as net.Dialer.Control
|
||||
// and net.ListenConfig.Control.
|
||||
func control(network, address string, c syscall.RawConn) error {
|
||||
func controlC(network, address string, c syscall.RawConn) error {
|
||||
if isLocalhost(address) {
|
||||
// Don't bind to an interface for localhost connections.
|
||||
return nil
|
||||
|
@ -25,7 +25,7 @@ func TestDial(t *testing.T) {
|
||||
if !*extNetwork {
|
||||
t.Skip("skipping test without --use-external-network")
|
||||
}
|
||||
d := NewDialer()
|
||||
d := NewDialer(t.Logf)
|
||||
c, err := d.Dial("tcp", "google.com:80")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"golang.org/x/sys/windows"
|
||||
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
|
||||
"tailscale.com/net/interfaces"
|
||||
"tailscale.com/types/logger"
|
||||
"tailscale.com/util/endian"
|
||||
)
|
||||
|
||||
@ -26,9 +27,13 @@ func interfaceIndex(iface *winipcfg.IPAdapterAddresses) uint32 {
|
||||
return iface.IfIndex
|
||||
}
|
||||
|
||||
// control binds c to the Windows interface that holds a default
|
||||
func control(logger.Logf) func(network, address string, c syscall.RawConn) error {
|
||||
return controlC
|
||||
}
|
||||
|
||||
// controlC binds c to the Windows interface that holds a default
|
||||
// route, and is not the Tailscale WinTun interface.
|
||||
func control(network, address string, c syscall.RawConn) error {
|
||||
func controlC(network, address string, c syscall.RawConn) error {
|
||||
if strings.HasPrefix(address, "127.") {
|
||||
// Don't bind to an interface for localhost connections,
|
||||
// otherwise we get:
|
||||
|
Reference in New Issue
Block a user