]> git.ipfire.org Git - thirdparty/wireguard-go.git/commitdiff
device: defer state machine transitions until configuration is complete
authorJason A. Donenfeld <Jason@zx2c4.com>
Thu, 11 Nov 2021 02:12:37 +0000 (03:12 +0100)
committerJason A. Donenfeld <Jason@zx2c4.com>
Mon, 15 Nov 2021 22:40:47 +0000 (23:40 +0100)
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
device/device.go
device/peer.go
device/uapi.go

index 5644c8a5049ddde1005e4c2d24302de47f35a02b..7717494cf2844d6a952cd64ee2ede98a4bf79587 100644 (file)
@@ -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()
index c8b825d62b782037f21f35848be1d91560729470..5bd52df794388ff71d0fbdd0646aaaec99995bfe 100644 (file)
@@ -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
 }
 
index 66ecd484fcce073138fc4bd72aee9b7719d32db0..019249df394eeea1f6b08cefbf837550d7ae8338 100644 (file)
@@ -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)