mirror of
https://github.com/tailscale/tailscale.git
synced 2025-10-10 09:45:08 +00:00
wgengine/{monitor,router}: restore Linux ip rules when systemd deletes them
Thanks. Fixes #1591 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:

committed by
Brad Fitzpatrick

parent
0aa77ba80f
commit
e4fecfe31d
@@ -62,6 +62,7 @@ type Mon struct {
|
||||
|
||||
mu sync.Mutex // guards all following fields
|
||||
cbs map[*callbackHandle]ChangeFunc
|
||||
ruleDelCB map[*callbackHandle]RuleDeleteCallback
|
||||
ifState *interfaces.State
|
||||
gwValid bool // whether gw and gwSelfIP are valid
|
||||
gw netaddr.IP // our gateway's IP
|
||||
@@ -148,6 +149,30 @@ func (m *Mon) RegisterChangeCallback(callback ChangeFunc) (unregister func()) {
|
||||
}
|
||||
}
|
||||
|
||||
// RuleDeleteCallback is a callback when a Linux IP policy routing
|
||||
// rule is deleted. The table is the table number (52, 253, 354) and
|
||||
// priority is the priority order number (for Tailscale rules
|
||||
// currently: 5210, 5230, 5250, 5270)
|
||||
type RuleDeleteCallback func(table uint8, priority uint32)
|
||||
|
||||
// RegisterRuleDeleteCallback adds callback to the set of parties to be
|
||||
// notified (in their own goroutine) when a Linux ip rule is deleted.
|
||||
// To remove this callback, call unregister (or close the monitor).
|
||||
func (m *Mon) RegisterRuleDeleteCallback(callback RuleDeleteCallback) (unregister func()) {
|
||||
handle := new(callbackHandle)
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if m.ruleDelCB == nil {
|
||||
m.ruleDelCB = map[*callbackHandle]RuleDeleteCallback{}
|
||||
}
|
||||
m.ruleDelCB[handle] = callback
|
||||
return func() {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
delete(m.ruleDelCB, handle)
|
||||
}
|
||||
}
|
||||
|
||||
// Start starts the monitor.
|
||||
// A monitor can only be started & closed once.
|
||||
func (m *Mon) Start() {
|
||||
@@ -242,6 +267,10 @@ func (m *Mon) pump() {
|
||||
time.Sleep(time.Second)
|
||||
continue
|
||||
}
|
||||
if rdm, ok := msg.(ipRuleDeletedMessage); ok {
|
||||
m.notifyRuleDeleted(rdm)
|
||||
continue
|
||||
}
|
||||
if msg.ignore() {
|
||||
continue
|
||||
}
|
||||
@@ -249,6 +278,14 @@ func (m *Mon) pump() {
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Mon) notifyRuleDeleted(rdm ipRuleDeletedMessage) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
for _, cb := range m.ruleDelCB {
|
||||
go cb(rdm.table, rdm.priority)
|
||||
}
|
||||
}
|
||||
|
||||
// debounce calls the callback function with a delay between events
|
||||
// and exits when a stop is issued.
|
||||
func (m *Mon) debounce() {
|
||||
@@ -338,3 +375,10 @@ func (m *Mon) checkWallTimeAdvanceLocked() {
|
||||
}
|
||||
m.lastWall = now
|
||||
}
|
||||
|
||||
type ipRuleDeletedMessage struct {
|
||||
table uint8
|
||||
priority uint32
|
||||
}
|
||||
|
||||
func (ipRuleDeletedMessage) ignore() bool { return true }
|
||||
|
@@ -134,7 +134,10 @@ func (c *nlConn) Receive() (message, error) {
|
||||
// On `ip -4 rule del pref 5210 table main`, logs:
|
||||
// monitor: ip rule deleted: {Family:2 DstLength:0 SrcLength:0 Tos:0 Table:254 Protocol:0 Scope:0 Type:1 Flags:0 Attributes:{Dst:<nil> Src:<nil> Gateway:<nil> OutIface:0 Priority:5210 Table:254 Mark:4294967295 Expires:<nil> Metrics:<nil> Multipath:[]}}
|
||||
}
|
||||
return ipRuleDeletedMessage{}, nil
|
||||
return ipRuleDeletedMessage{
|
||||
table: rmsg.Table,
|
||||
priority: rmsg.Attributes.Priority,
|
||||
}, nil
|
||||
default:
|
||||
c.logf("unhandled netlink msg type %+v, %q", msg.Header, msg.Data)
|
||||
return unspecifiedMessage{}, nil
|
||||
@@ -192,7 +195,3 @@ func (m *newAddrMessage) ignore() bool {
|
||||
type ignoreMessage struct{}
|
||||
|
||||
func (ignoreMessage) ignore() bool { return true }
|
||||
|
||||
type ipRuleDeletedMessage struct{}
|
||||
|
||||
func (ipRuleDeletedMessage) ignore() bool { return false }
|
||||
|
Reference in New Issue
Block a user