summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2021-11-11 03:12:37 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2021-11-15 23:40:47 +0100
commite3134bf6659b13bbc4713fe2b9147463cc9ff374 (patch)
tree062284c8337b881429e2114f958479c6e301d5e4
parent63abb5537bef592fe65ec94801e10a7406314094 (diff)
device: defer state machine transitions until configuration is complete
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--device/device.go5
-rw-r--r--device/peer.go9
-rw-r--r--device/uapi.go19
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)