device: add peer session state callback

Add a minimal callback API for observing WireGuard peer session state
changes.

Updates tailscale/corp#42874
This commit is contained in:
Brad Fitzpatrick 2026-06-04 21:19:50 +00:00 committed by 世界
parent 09268b375c
commit 7c3a736cbe
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
3 changed files with 126 additions and 8 deletions

View file

@ -64,6 +64,11 @@ type Device struct {
lookupFunc PeerLookupFunc // or nil if unused
}
sessionState struct {
sync.Mutex // serializes PeerSessionStateFunc calls and protects peer.sessionState
fn PeerSessionStateFunc
}
rate struct {
underLoadUntil atomic.Int64
limiter ratelimiter.Ratelimiter
@ -490,6 +495,34 @@ type PeerLookupFunc func(NoisePublicKey) (_ *NewPeerConfig, ok bool)
// See [Device.SetPeerByIPPacketFunc] and [Device.SetPeerLookupFunc].
type PeerByIPPacketFunc func(src, dst netip.Addr, ipPkt []byte) (_ NoisePublicKey, ok bool)
// PeerSessionState is the current WireGuard session state for a peer.
type PeerSessionState uint8
const (
// PeerSessionNone means there is no handshake in progress and no session key
// material retained for this peer.
PeerSessionNone PeerSessionState = iota
// PeerSessionHandshake means a handshake is in progress for this peer, but
// there is not currently a usable WireGuard session.
PeerSessionHandshake
// PeerSessionEstablished means the peer has a completed WireGuard session
// with usable session key material.
PeerSessionEstablished
// PeerSessionExpired means the peer's session key material is no longer
// considered usable, but final key cleanup or lazy peer removal may not have
// happened yet.
PeerSessionExpired
)
// PeerSessionStateFunc is called when a peer's WireGuard session state changes.
//
// Calls are serialized per Device and delivered in transition order. The
// callback must be cheap and must not call back into Device.
type PeerSessionStateFunc func(peer NoisePublicKey, state PeerSessionState)
// SetPeerLookupFunc sets the function used to look up peers by public key
// when receiving packets for unknown peers.
func (device *Device) SetPeerLookupFunc(f PeerLookupFunc) {
@ -507,6 +540,18 @@ func (device *Device) SetPeerByIPPacketFunc(f PeerByIPPacketFunc) {
device.allowedips.device = device
}
// SetSessionStateFunc sets the function used to observe peer WireGuard session
// state changes.
//
// It does not replay current state. Callers that need a complete view should set
// it before peers are started or lazily created, and maintain any snapshots,
// sequence numbers, and pubsub state outside wireguard-go.
func (device *Device) SetSessionStateFunc(f PeerSessionStateFunc) {
device.sessionState.Lock()
defer device.sessionState.Unlock()
device.sessionState.fn = f
}
func (device *Device) Close() {
device.state.Lock()
defer device.state.Unlock()