From 5a32f8e181a5ff10ccc4ae13e7a519c117c6e240 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 3 Jun 2020 19:36:40 +0000 Subject: [PATCH] wgengine/router: also accept exit code 254 from `ip rule del`. iproute2 3.16.0-2 from Debian Jessie (oldoldstable) doesn't return exit code 2 when deleting a non-existent IP rule. Fixes #434 Signed-off-by: David Anderson --- wgengine/router/router_linux.go | 7 +++++-- wgengine/router/runner.go | 18 ++++++++++++++---- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/wgengine/router/router_linux.go b/wgengine/router/router_linux.go index ddc01cc14..5287e7fcc 100644 --- a/wgengine/router/router_linux.go +++ b/wgengine/router/router_linux.go @@ -519,7 +519,7 @@ func (r *linuxRouter) addIPRules() error { return err } - rg := newRunGroup(0, r.cmd) + rg := newRunGroup(nil, r.cmd) // NOTE(apenwarr): We leave spaces between each pref number. // This is so the sysadmin can override by inserting rules in @@ -588,7 +588,10 @@ func (r *linuxRouter) delIPRules() error { // Error codes: 'ip rule' returns error code 2 if the rule is a // duplicate (add) or not found (del). It returns a different code // for syntax errors. This is also true of busybox. - rg := newRunGroup(2, r.cmd) + // + // Some older versions of iproute2 also return error code 254 for + // unknown rules during deletion. + rg := newRunGroup([]int{2, 254}, r.cmd) // When deleting rules, we want to be a bit specific (mention which // table we were routing to) but not *too* specific (fwmarks, etc). diff --git a/wgengine/router/runner.go b/wgengine/router/runner.go index 46332129f..5e6bee0bb 100644 --- a/wgengine/router/runner.go +++ b/wgengine/router/runner.go @@ -61,21 +61,31 @@ func (o osCommandRunner) output(args ...string) ([]byte, error) { } type runGroup struct { - OkCode int // an error code that is acceptable, other than 0, if any + OkCode []int // error codes that are acceptable, other than 0, if any Runner commandRunner // the runner that actually runs our commands ErrAcc error // first error encountered, if any } -func newRunGroup(okCode int, runner commandRunner) *runGroup { +func newRunGroup(okCode []int, runner commandRunner) *runGroup { return &runGroup{ OkCode: okCode, Runner: runner, } } +func (rg *runGroup) okCode(err error) bool { + got := errCode(err) + for _, want := range rg.OkCode { + if got == want { + return true + } + } + return false +} + func (rg *runGroup) Output(args ...string) []byte { b, err := rg.Runner.output(args...) - if rg.ErrAcc == nil && err != nil && errCode(err) != rg.OkCode { + if rg.ErrAcc == nil && err != nil && !rg.okCode(err) { rg.ErrAcc = err } return b @@ -83,7 +93,7 @@ func (rg *runGroup) Output(args ...string) []byte { func (rg *runGroup) Run(args ...string) { err := rg.Runner.run(args...) - if rg.ErrAcc == nil && err != nil && errCode(err) != rg.OkCode { + if rg.ErrAcc == nil && err != nil && !rg.okCode(err) { rg.ErrAcc = err } }