device: defer state machine transitions until configuration is complete

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2021-11-11 03:12:37 +01:00
parent 63abb5537b
commit e3134bf665
3 changed files with 18 additions and 15 deletions

View file

@ -172,6 +172,11 @@ func (device *Device) upLocked() error {
return err 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() device.peers.RLock()
for _, peer := range device.peers.keyMap { for _, peer := range device.peers.keyMap {
peer.Start() peer.Start()

View file

@ -107,15 +107,12 @@ func (device *Device) NewPeer(pk NoisePublicKey) (*Peer, error) {
// reset endpoint // reset endpoint
peer.endpoint = nil peer.endpoint = nil
// init timers
peer.timersInit()
// add // add
device.peers.keyMap[pk] = peer device.peers.keyMap[pk] = peer
// start peer
peer.timersInit()
if peer.device.isUp() {
peer.Start()
}
return peer, nil return peer, nil
} }

View file

@ -254,10 +254,18 @@ type ipcSetPeer struct {
*Peer // Peer is the current peer being operated on *Peer // Peer is the current peer being operated on
dummy bool // dummy reports whether this peer is a temporary, placeholder peer dummy bool // dummy reports whether this peer is a temporary, placeholder peer
created bool // new reports whether this is a newly created 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() { 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() peer.SendStagedPackets()
} }
} }
@ -349,14 +357,7 @@ func (device *Device) handlePeerLine(peer *ipcSetPeer, key, value string) error
old := atomic.SwapUint32(&peer.persistentKeepaliveInterval, uint32(secs)) old := atomic.SwapUint32(&peer.persistentKeepaliveInterval, uint32(secs))
// Send immediate keepalive if we're turning it on and before it wasn't on. // Send immediate keepalive if we're turning it on and before it wasn't on.
if old == 0 && secs != 0 { peer.pkaOn = 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()
}
}
case "replace_allowed_ips": case "replace_allowed_ips":
device.log.Verbosef("%v - UAPI: Removing all allowedips", peer.Peer) device.log.Verbosef("%v - UAPI: Removing all allowedips", peer.Peer)