From 9df2516f96f88617f6ef57dedae2b135ce5533cd Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Thu, 14 Oct 2021 13:17:06 -0700 Subject: [PATCH] wgengine/router: ignore Linux ip route error adding dup route Updates #3060 Updates #391 Signed-off-by: Brad Fitzpatrick (cherry picked from commit 14f9c7529338c046706d16fa560ea356d98bbcb7) --- wgengine/router/router_linux.go | 16 +++++++++++++++- wgengine/router/runner.go | 2 ++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/wgengine/router/router_linux.go b/wgengine/router/router_linux.go index 279d8c93b..c43433f7b 100644 --- a/wgengine/router/router_linux.go +++ b/wgengine/router/router_linux.go @@ -533,7 +533,21 @@ func (r *linuxRouter) addRouteDef(routeDef []string, cidr netaddr.IPPrefix) erro if r.ipRuleAvailable { args = append(args, "table", tailscaleRouteTable) } - return r.cmd.run(args...) + err := r.cmd.run(args...) + if err == nil { + return nil + } + + // TODO(bradfitz): remove this ugly hack to detect failure to + // add a route that already exists (as happens in when we're + // racing to add kernel-maintained routes when enabling exit + // nodes w/o Local LAN access, Issue 3060) and use netlink + // directly instead (Issue 391). + if errCode(err) == 2 && strings.Contains(err.Error(), "RTNETLINK answers: File exists") { + r.logf("ignoring route add of %v; already exists", cidr) + return nil + } + return err } // delRoute removes the route for cidr pointing to the tunnel diff --git a/wgengine/router/runner.go b/wgengine/router/runner.go index 1d1f44af3..736b54b6c 100644 --- a/wgengine/router/runner.go +++ b/wgengine/router/runner.go @@ -10,6 +10,7 @@ import ( "errors" "fmt" + "os" "os/exec" "strconv" "strings" @@ -68,6 +69,7 @@ func (o osCommandRunner) output(args ...string) ([]byte, error) { } cmd := exec.Command(args[0], args[1:]...) + cmd.Env = append(os.Environ(), "LC_ALL=C") if o.ambientCapNetAdmin { cmd.SysProcAttr = &syscall.SysProcAttr{ AmbientCaps: []uintptr{unix.CAP_NET_ADMIN},