@ -143,8 +143,9 @@ type userspaceEngine struct {
trimmedNodes map [ key . NodePublic ] bool // set of node keys of peers currently excluded from wireguard config
sentActivityAt map [ netip . Addr ] * mono . Time // value is accessed atomically
destIPActivityFuncs map [ netip . Addr ] func ( )
lastStatusPollTime mono . Time // last time we polled the engine status
reconfigureVPN func ( ) error // or nil
lastStatusPollTime mono . Time // last time we polled the engine status
reconfigureVPN func ( ) error // or nil
conn25PacketHooks Conn25PacketHooks // or nil
mu sync . Mutex // guards following; see lock order comment below
netMap * netmap . NetworkMap // or nil
@ -175,6 +176,19 @@ type BIRDClient interface {
Close ( ) error
}
// Conn25PacketHooks are hooks for Connectors 2025 app connectors.
// They are meant to be wired into to corresponding hooks in the
// [tstun.Wrapper]. They may modify the packet (e.g., NAT), or drop
// invalid app connector traffic.
type Conn25PacketHooks interface {
// HandlePacketsFromTunDevice sends packets originating from the tun device
// for further Connectors 2025 app connectors processing.
HandlePacketsFromTunDevice ( * packet . Parsed ) filter . Response
// HandlePacketsFromWireguard sends packets originating from WireGuard
// for further Connectors 2025 app connectors processing.
HandlePacketsFromWireGuard ( * packet . Parsed ) filter . Response
}
// Config is the engine configuration.
type Config struct {
// Tun is the device used by the Engine to exchange packets with
@ -247,6 +261,10 @@ type Config struct {
// TODO(creachadair): As of 2025-03-19 this is optional, but is intended to
// become required non-nil.
EventBus * eventbus . Bus
// Conn25PacketHooks, if non-nil, is used to hook packets for Connectors 2025
// app connector handling logic.
Conn25PacketHooks Conn25PacketHooks
}
// NewFakeUserspaceEngine returns a new userspace engine for testing.
@ -348,19 +366,20 @@ func NewUserspaceEngine(logf logger.Logf, conf Config) (_ Engine, reterr error)
}
e := & userspaceEngine {
eventBus : conf . EventBus ,
timeNow : mono . Now ,
logf : logf ,
reqCh : make ( chan struct { } , 1 ) ,
waitCh : make ( chan struct { } ) ,
tundev : tsTUNDev ,
router : rtr ,
dialer : conf . Dialer ,
confListenPort : conf . ListenPort ,
birdClient : conf . BIRDClient ,
controlKnobs : conf . ControlKnobs ,
reconfigureVPN : conf . ReconfigureVPN ,
health : conf . HealthTracker ,
eventBus : conf . EventBus ,
timeNow : mono . Now ,
logf : logf ,
reqCh : make ( chan struct { } , 1 ) ,
waitCh : make ( chan struct { } ) ,
tundev : tsTUNDev ,
router : rtr ,
dialer : conf . Dialer ,
confListenPort : conf . ListenPort ,
birdClient : conf . BIRDClient ,
controlKnobs : conf . ControlKnobs ,
reconfigureVPN : conf . ReconfigureVPN ,
health : conf . HealthTracker ,
conn25PacketHooks : conf . Conn25PacketHooks ,
}
if e . birdClient != nil {
@ -434,6 +453,16 @@ func NewUserspaceEngine(logf logger.Logf, conf Config) (_ Engine, reterr error)
}
e . tundev . PreFilterPacketOutboundToWireGuardEngineIntercept = e . handleLocalPackets
if e . conn25PacketHooks != nil {
e . tundev . PreFilterPacketOutboundToWireGuardAppConnectorIntercept = func ( p * packet . Parsed , _ * tstun . Wrapper ) filter . Response {
return e . conn25PacketHooks . HandlePacketsFromTunDevice ( p )
}
e . tundev . PostFilterPacketInboundFromWireGuardAppConnector = func ( p * packet . Parsed , _ * tstun . Wrapper ) filter . Response {
return e . conn25PacketHooks . HandlePacketsFromWireGuard ( p )
}
}
if buildfeatures . HasDebug && envknob . BoolDefaultTrue ( "TS_DEBUG_CONNECT_FAILURES" ) {
if e . tundev . PreFilterPacketInboundFromWireGuard != nil {
return nil , errors . New ( "unexpected PreFilterIn already set" )