Files
wireguard-go/device/timers.go
T

230 lines
6.8 KiB
Go
Raw Normal View History

2019-01-02 01:55:51 +01:00
/* SPDX-License-Identifier: MIT
2018-05-03 15:04:00 +02:00
*
2022-09-20 17:21:32 +02:00
* Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
2018-05-07 22:27:03 +02:00
*
* This is based heavily on timers.c from the kernel implementation.
2018-05-03 15:04:00 +02:00
*/
2019-03-03 04:04:41 +01:00
package device
2018-02-11 19:02:50 +01:00
import (
2018-05-15 18:38:18 +02:00
"sync"
2018-02-11 19:02:50 +01:00
"time"
_ "unsafe"
2018-02-11 19:02:50 +01:00
)
//go:linkname fastrandn runtime.fastrandn
func fastrandn(n uint32) uint32
// A Timer manages time-based aspects of the WireGuard protocol.
// Timer roughly copies the interface of the Linux kernel's struct timer_list.
2018-05-07 22:27:03 +02:00
type Timer struct {
*time.Timer
2018-05-20 03:31:27 +02:00
modifyingLock sync.RWMutex
2018-05-15 18:38:18 +02:00
runningLock sync.Mutex
isPending bool
2018-02-11 19:02:50 +01:00
}
2018-05-07 22:27:03 +02:00
func (peer *Peer) NewTimer(expirationFunction func(*Peer)) *Timer {
timer := &Timer{}
timer.Timer = time.AfterFunc(time.Hour, func() {
2018-05-15 18:38:18 +02:00
timer.runningLock.Lock()
2020-12-14 15:30:10 -08:00
defer timer.runningLock.Unlock()
2018-05-15 18:38:18 +02:00
timer.modifyingLock.Lock()
if !timer.isPending {
timer.modifyingLock.Unlock()
return
}
2018-05-07 22:27:03 +02:00
timer.isPending = false
2018-05-15 18:38:18 +02:00
timer.modifyingLock.Unlock()
2018-05-07 22:27:03 +02:00
expirationFunction(peer)
})
timer.Stop()
return timer
}
2018-05-07 22:27:03 +02:00
func (timer *Timer) Mod(d time.Duration) {
2018-05-15 18:38:18 +02:00
timer.modifyingLock.Lock()
2018-05-07 22:27:03 +02:00
timer.isPending = true
timer.Reset(d)
2018-05-15 18:38:18 +02:00
timer.modifyingLock.Unlock()
2018-05-07 22:27:03 +02:00
}
2018-02-11 19:02:50 +01:00
2018-05-07 22:27:03 +02:00
func (timer *Timer) Del() {
2018-05-15 18:38:18 +02:00
timer.modifyingLock.Lock()
2018-05-07 22:27:03 +02:00
timer.isPending = false
timer.Stop()
2018-05-15 18:38:18 +02:00
timer.modifyingLock.Unlock()
}
func (timer *Timer) DelSync() {
timer.Del()
timer.runningLock.Lock()
timer.Del()
timer.runningLock.Unlock()
2018-05-07 22:27:03 +02:00
}
2018-02-11 19:02:50 +01:00
2018-05-20 03:31:27 +02:00
func (timer *Timer) IsPending() bool {
timer.modifyingLock.RLock()
defer timer.modifyingLock.RUnlock()
return timer.isPending
}
2018-05-07 22:27:03 +02:00
func (peer *Peer) timersActive() bool {
2022-08-30 07:43:11 -07:00
return peer.isRunning.Load() && peer.device != nil && peer.device.isUp()
2018-05-07 22:27:03 +02:00
}
2018-04-18 20:29:48 +02:00
2018-05-07 22:27:03 +02:00
func expiredRetransmitHandshake(peer *Peer) {
2022-08-30 07:43:11 -07:00
if peer.timers.handshakeAttempts.Load() > MaxTimerHandshakes {
peer.device.log.Verbosef("%s - Handshake did not complete after %d attempts, giving up", peer, MaxTimerHandshakes+2)
2018-02-11 19:02:50 +01:00
2018-05-07 22:27:03 +02:00
if peer.timersActive() {
peer.timers.sendKeepalive.Del()
}
2018-05-07 22:27:03 +02:00
/* We drop all packets without a keypair and don't try again,
* if we try unsuccessfully for too long to make a handshake.
*/
2021-01-27 18:13:53 +01:00
peer.FlushStagedPackets()
2018-02-11 19:02:50 +01:00
2018-05-07 22:27:03 +02:00
/* We set a timer for destroying any residue that might be left
* of a partial exchange.
*/
2018-05-20 03:31:27 +02:00
if peer.timersActive() && !peer.timers.zeroKeyMaterial.IsPending() {
2018-05-07 22:27:03 +02:00
peer.timers.zeroKeyMaterial.Mod(RejectAfterTime * 3)
}
} else {
2022-08-30 07:43:11 -07:00
peer.timers.handshakeAttempts.Add(1)
peer.device.log.Verbosef("%s - Handshake did not complete after %d seconds, retrying (try %d)", peer, int(RekeyTimeout.Seconds()), peer.timers.handshakeAttempts.Load()+1)
2018-05-07 22:27:03 +02:00
/* We clear the endpoint address src address, in case this is the cause of trouble. */
peer.Lock()
2018-05-07 22:27:03 +02:00
if peer.endpoint != nil {
peer.endpoint.ClearSrc()
}
peer.Unlock()
2018-02-11 19:02:50 +01:00
2018-05-07 22:27:03 +02:00
peer.SendHandshakeInitiation(true)
2018-02-11 19:02:50 +01:00
}
2018-05-07 22:27:03 +02:00
}
2018-02-11 19:02:50 +01:00
2018-05-07 22:27:03 +02:00
func expiredSendKeepalive(peer *Peer) {
peer.SendKeepalive()
2022-08-30 07:43:11 -07:00
if peer.timers.needAnotherKeepalive.Load() {
peer.timers.needAnotherKeepalive.Store(false)
2018-05-07 22:27:03 +02:00
if peer.timersActive() {
peer.timers.sendKeepalive.Mod(KeepaliveTimeout)
2018-02-11 19:02:50 +01:00
}
}
}
2018-05-07 22:27:03 +02:00
func expiredNewHandshake(peer *Peer) {
peer.device.log.Verbosef("%s - Retrying handshake because we stopped hearing back after %d seconds", peer, int((KeepaliveTimeout + RekeyTimeout).Seconds()))
2018-05-07 22:27:03 +02:00
/* We clear the endpoint address src address, in case this is the cause of trouble. */
peer.Lock()
2018-05-07 22:27:03 +02:00
if peer.endpoint != nil {
peer.endpoint.ClearSrc()
}
peer.Unlock()
2018-05-07 22:27:03 +02:00
peer.SendHandshakeInitiation(false)
}
func expiredZeroKeyMaterial(peer *Peer) {
peer.device.log.Verbosef("%s - Removing all keys, since we haven't received a new one in %d seconds", peer, int((RejectAfterTime * 3).Seconds()))
2018-05-13 23:14:43 +02:00
peer.ZeroAndFlushAll()
2018-05-07 22:27:03 +02:00
}
func expiredPersistentKeepalive(peer *Peer) {
2022-08-30 07:43:11 -07:00
if peer.persistentKeepaliveInterval.Load() > 0 {
2018-05-07 22:27:03 +02:00
peer.SendKeepalive()
}
}
/* Should be called after an authenticated data packet is sent. */
func (peer *Peer) timersDataSent() {
2018-05-20 03:31:27 +02:00
if peer.timersActive() && !peer.timers.newHandshake.IsPending() {
peer.timers.newHandshake.Mod(KeepaliveTimeout + RekeyTimeout + time.Millisecond*time.Duration(fastrandn(RekeyTimeoutJitterMaxMs)))
2018-05-07 22:27:03 +02:00
}
}
/* Should be called after an authenticated data packet is received. */
func (peer *Peer) timersDataReceived() {
if peer.timersActive() {
2018-05-20 03:31:27 +02:00
if !peer.timers.sendKeepalive.IsPending() {
2018-05-07 22:27:03 +02:00
peer.timers.sendKeepalive.Mod(KeepaliveTimeout)
} else {
2022-08-30 07:43:11 -07:00
peer.timers.needAnotherKeepalive.Store(true)
2018-05-07 22:27:03 +02:00
}
}
}
/* Should be called after any type of authenticated packet is sent -- keepalive, data, or handshake. */
func (peer *Peer) timersAnyAuthenticatedPacketSent() {
if peer.timersActive() {
peer.timers.sendKeepalive.Del()
}
}
/* Should be called after any type of authenticated packet is received -- keepalive, data, or handshake. */
2018-05-07 22:27:03 +02:00
func (peer *Peer) timersAnyAuthenticatedPacketReceived() {
if peer.timersActive() {
peer.timers.newHandshake.Del()
}
}
/* Should be called after a handshake initiation message is sent. */
func (peer *Peer) timersHandshakeInitiated() {
if peer.timersActive() {
peer.timers.retransmitHandshake.Mod(RekeyTimeout + time.Millisecond*time.Duration(fastrandn(RekeyTimeoutJitterMaxMs)))
2018-05-07 22:27:03 +02:00
}
}
/* Should be called after a handshake response message is received and processed or when getting key confirmation via the first data message. */
func (peer *Peer) timersHandshakeComplete() {
if peer.timersActive() {
peer.timers.retransmitHandshake.Del()
}
2022-08-30 07:43:11 -07:00
peer.timers.handshakeAttempts.Store(0)
peer.timers.sentLastMinuteHandshake.Store(false)
peer.lastHandshakeNano.Store(time.Now().UnixNano())
2018-05-07 22:27:03 +02:00
}
/* Should be called after an ephemeral key is created, which is before sending a handshake response or after receiving a handshake response. */
func (peer *Peer) timersSessionDerived() {
if peer.timersActive() {
peer.timers.zeroKeyMaterial.Mod(RejectAfterTime * 3)
}
}
/* Should be called before a packet with authentication -- keepalive, data, or handshake -- is sent, or after one is received. */
2018-05-07 22:27:03 +02:00
func (peer *Peer) timersAnyAuthenticatedPacketTraversal() {
2022-08-30 07:43:11 -07:00
keepalive := peer.persistentKeepaliveInterval.Load()
if keepalive > 0 && peer.timersActive() {
peer.timers.persistentKeepalive.Mod(time.Duration(keepalive) * time.Second)
2018-05-07 22:27:03 +02:00
}
}
func (peer *Peer) timersInit() {
peer.timers.retransmitHandshake = peer.NewTimer(expiredRetransmitHandshake)
peer.timers.sendKeepalive = peer.NewTimer(expiredSendKeepalive)
peer.timers.newHandshake = peer.NewTimer(expiredNewHandshake)
peer.timers.zeroKeyMaterial = peer.NewTimer(expiredZeroKeyMaterial)
peer.timers.persistentKeepalive = peer.NewTimer(expiredPersistentKeepalive)
}
func (peer *Peer) timersStart() {
2022-08-30 07:43:11 -07:00
peer.timers.handshakeAttempts.Store(0)
peer.timers.sentLastMinuteHandshake.Store(false)
peer.timers.needAnotherKeepalive.Store(false)
2018-05-07 22:27:03 +02:00
}
func (peer *Peer) timersStop() {
2018-05-15 18:38:18 +02:00
peer.timers.retransmitHandshake.DelSync()
peer.timers.sendKeepalive.DelSync()
peer.timers.newHandshake.DelSync()
peer.timers.zeroKeyMaterial.DelSync()
peer.timers.persistentKeepalive.DelSync()
2018-05-07 22:27:03 +02:00
}