From 1e837b8e817c870b980190f17f95f8995c0fa083 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Sun, 31 May 2020 14:01:20 -0700 Subject: [PATCH] net/netns: refactor the sync.Once usage a bit --- net/netns/netns_linux.go | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/net/netns/netns_linux.go b/net/netns/netns_linux.go index d8022c62a..98dc13344 100644 --- a/net/netns/netns_linux.go +++ b/net/netns/netns_linux.go @@ -28,12 +28,20 @@ import ( // wgengine/router/router_linux.go. const tailscaleBypassMark = 0x20000 -// checkIPRule runs the ipRuleAvailable check exactly once. -var checkIPRule sync.Once +// ipRuleOnce is the sync.Once & cached value for ipRuleAvailable. +var ipRuleOnce struct { + sync.Once + v bool +} -// ipRuleAvailable is true if and only if the 'ip rule' command works. +// ipRuleAvailable reports whether the 'ip rule' command works. // If it doesn't, we have to use SO_BINDTODEVICE on our sockets instead. -var ipRuleAvailable bool +func ipRuleAvailable() bool { + ipRuleOnce.Do(func() { + ipRuleOnce.v = exec.Command("ip", "rule").Run() == nil + }) + return ipRuleOnce.v +} // defaultRouteInterface returns the name of the network interface that owns // the default route, not including any tailscale interfaces. We only use @@ -98,18 +106,13 @@ func ignoreErrors() bool { // It's intentionally the same signature as net.Dialer.Control // and net.ListenConfig.Control. func control(network, address string, c syscall.RawConn) error { - checkIPRule.Do(func() { - _, err := exec.Command("ip", "rule").Output() - ipRuleAvailable = (err == nil) - }) - if skipPrivileged.Get() { // We can't set socket marks without CAP_NET_ADMIN on linux, // skip as requested. return nil } - if ipRuleAvailable { + if ipRuleAvailable() { var controlErr error err := c.Control(func(fd uintptr) { controlErr = unix.SetsockoptInt(int(fd),