From e3134bf6659b13bbc4713fe2b9147463cc9ff374 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Thu, 11 Nov 2021 03:12:37 +0100 Subject: [PATCH] device: defer state machine transitions until configuration is complete Signed-off-by: Jason A. Donenfeld --- device/device.go | 5 +++++ device/peer.go | 9 +++------ device/uapi.go | 19 ++++++++++--------- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/device/device.go b/device/device.go index 5644c8a..7717494 100644 --- a/device/device.go +++ b/device/device.go @@ -172,6 +172,11 @@ func (device *Device) upLocked() error { return err } + // The IPC set operation waits for peers to be created before calling Start() on them, + // so if there's a concurrent IPC set request happening, we should wait for it to complete. + device.ipcMutex.Lock() + defer device.ipcMutex.Unlock() + device.peers.RLock() for _, peer := range device.peers.keyMap { peer.Start() diff --git a/device/peer.go b/device/peer.go index c8b825d..5bd52df 100644 --- a/device/peer.go +++ b/device/peer.go @@ -107,15 +107,12 @@ func (device *Device) NewPeer(pk NoisePublicKey) (*Peer, error) { // reset endpoint peer.endpoint = nil + // init timers + peer.timersInit() + // add device.peers.keyMap[pk] = peer - // start peer - peer.timersInit() - if peer.device.isUp() { - peer.Start() - } - return peer, nil } diff --git a/device/uapi.go b/device/uapi.go index 66ecd48..019249d 100644 --- a/device/uapi.go +++ b/device/uapi.go @@ -254,10 +254,18 @@ type ipcSetPeer struct { *Peer // Peer is the current peer being operated on dummy bool // dummy reports whether this peer is a temporary, placeholder peer created bool // new reports whether this is a newly created peer + pkaOn bool // pkaOn reports whether the peer had the persistent keepalive turn on } func (peer *ipcSetPeer) handlePostConfig() { - if peer.Peer != nil && !peer.dummy && peer.Peer.device.isUp() { + if peer.Peer == nil { + return + } + if !peer.dummy && peer.device.isUp() { + peer.Start() + if peer.pkaOn { + peer.SendKeepalive() + } peer.SendStagedPackets() } } @@ -349,14 +357,7 @@ func (device *Device) handlePeerLine(peer *ipcSetPeer, key, value string) error old := atomic.SwapUint32(&peer.persistentKeepaliveInterval, uint32(secs)) // Send immediate keepalive if we're turning it on and before it wasn't on. - if old == 0 && secs != 0 { - if err != nil { - return ipcErrorf(ipc.IpcErrorIO, "failed to get tun device status: %w", err) - } - if device.isUp() && !peer.dummy { - peer.SendKeepalive() - } - } + peer.pkaOn = old == 0 && secs != 0 case "replace_allowed_ips": device.log.Verbosef("%v - UAPI: Removing all allowedips", peer.Peer)