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 - 2023 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"
2021-10-28 13:47:50 +02:00
_ "unsafe"
2018-02-11 19:02:50 +01:00
)
2021-10-28 13:47:50 +02:00
//go:linkname fastrandn runtime.fastrandn
func fastrandn ( n uint32 ) uint32
2021-10-28 13:34:21 +02:00
2021-02-08 19:01:35 +01:00
// 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 {
2019-01-03 19:04:00 +01:00
* 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 { }
2019-01-03 19:04:00 +01:00
timer . Timer = time . AfterFunc ( time . Hour , func ( ) {
2018-05-15 18:38:18 +02:00
timer . runningLock . Lock ( )
2020-12-15 00:30:10 +01: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 )
} )
2019-01-03 19:04:00 +01:00
timer . Stop ( )
2018-05-07 22:27:03 +02:00
return timer
2018-02-11 19:02:50 +01:00
}
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
2019-01-03 19:04:00 +01:00
timer . Reset ( d )
2018-05-15 18:38:18 +02:00
timer . modifyingLock . Unlock ( )
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
2019-01-03 19:04:00 +01:00
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-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 16:43:11 +02:00
return peer . isRunning . Load ( ) && peer . device != nil && peer . device . isUp ( )
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 expiredRetransmitHandshake ( peer * Peer ) {
2022-08-30 16:43:11 +02:00
if peer . timers . handshakeAttempts . Load ( ) > MaxTimerHandshakes {
2021-01-26 23:05:48 +01:00
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-02-11 19:02:50 +01:00
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 16:43:11 +02: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. */
2023-11-21 01:49:06 +01:00
peer . markEndpointSrcForClearing ( )
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
func expiredSendKeepalive ( peer * Peer ) {
peer . SendKeepalive ( )
2022-08-30 16:43:11 +02: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-05-05 02:20:52 +02:00
}
2018-05-07 22:27:03 +02:00
func expiredNewHandshake ( peer * Peer ) {
2021-01-26 23:05:48 +01:00
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. */
2023-11-21 01:49:06 +01:00
peer . markEndpointSrcForClearing ( )
2018-05-07 22:27:03 +02:00
peer . SendHandshakeInitiation ( false )
}
2018-05-05 04:15:07 +02:00
2018-05-07 22:27:03 +02:00
func expiredZeroKeyMaterial ( peer * Peer ) {
2021-01-26 23:05:48 +01:00
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
}
2018-02-11 19:02:50 +01:00
2018-05-07 22:27:03 +02:00
func expiredPersistentKeepalive ( peer * Peer ) {
2022-08-30 16:43:11 +02:00
if peer . persistentKeepaliveInterval . Load ( ) > 0 {
2018-05-07 22:27:03 +02:00
peer . SendKeepalive ( )
}
}
2018-05-05 02:20:52 +02:00
2018-05-07 22:27:03 +02:00
/* 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 ( ) {
2021-10-28 13:47:50 +02:00
peer . timers . newHandshake . Mod ( KeepaliveTimeout + RekeyTimeout + time . Millisecond * time . Duration ( fastrandn ( RekeyTimeoutJitterMaxMs ) ) )
2018-05-07 22:27:03 +02:00
}
}
2018-02-11 19:02:50 +01:00
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 16:43:11 +02:00
peer . timers . needAnotherKeepalive . Store ( true )
2018-05-07 22:27:03 +02:00
}
}
}
2018-05-05 04:15:07 +02:00
2018-05-19 01:19:53 +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 ( )
}
}
2018-05-05 04:15:07 +02:00
2018-05-07 22:27:03 +02:00
/* Should be called after a handshake initiation message is sent. */
func ( peer * Peer ) timersHandshakeInitiated ( ) {
if peer . timersActive ( ) {
2021-10-28 13:47:50 +02:00
peer . timers . retransmitHandshake . Mod ( RekeyTimeout + time . Millisecond * time . Duration ( fastrandn ( RekeyTimeoutJitterMaxMs ) ) )
2018-05-07 22:27:03 +02:00
}
}
2018-02-11 19:02:50 +01:00
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 16:43:11 +02: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
}
2018-02-11 19:02:50 +01:00
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 )
}
}
2018-02-11 19:02:50 +01:00
2018-05-19 01:19:53 +02:00
/* 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 16:43:11 +02:00
keepalive := peer . persistentKeepaliveInterval . Load ( )
2020-12-15 00:28:52 +01:00
if keepalive > 0 && peer . timersActive ( ) {
peer . timers . persistentKeepalive . Mod ( time . Duration ( keepalive ) * time . Second )
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 ( 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 )
2021-02-08 19:01:35 +01:00
}
func ( peer * Peer ) timersStart ( ) {
2022-08-30 16:43:11 +02:00
peer . timers . handshakeAttempts . Store ( 0 )
peer . timers . sentLastMinuteHandshake . Store ( false )
peer . timers . needAnotherKeepalive . Store ( false )
2018-05-07 22:27:03 +02:00
}
2018-05-05 04:15:07 +02:00
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-02-11 19:02:50 +01:00
}