Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 17 additions & 27 deletions libtailscale/net.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,36 +80,27 @@ func (b *backend) updateTUN(rcfg *router.Config, dcfg *dns.OSConfig) (err error)
b.logger.Logf("updateTUN: changed")
defer b.logger.Logf("updateTUN: finished")

// Close previous tunnel(s).
// This is necessary for ChromeOS, native Android devices
// seem to handle seamless handover between tunnels correctly.
//
// TODO(eliasnaur): If seamless handover becomes a desirable feature, skip
// the closing on ChromeOS.
b.logger.Logf("updateTUN: closing old TUNs")
b.CloseTUNs()
b.logger.Logf("updateTUN: closed old TUNs")

// Since the previous tunnel(s) are closed, the [multiTUN] device is
// not operational until a new underlying tunnel is created and added,
// which may never happen in case of an error or an empty [router.Config].
//
// Therefore, to prevent deadlocks where a [multiTUN.Write] would
// block waiting for a new tunnel to be added, we bring the multiTUN
// device down on exit unless a new [tun.Device] is created and added
// successfully. See tailscale/tailscale#18679.
//
// TODO(nickkhyl): revisit and simplify the [multiTUN] implementation?
hasTunnel := false
defer func() {
if !hasTunnel && b.devices.Down() {
if disableTUN := len(rcfg.LocalAddrs) == 0; disableTUN {
b.logger.Logf("updateTUN: closing old TUNs")
b.CloseTUNs()
b.logger.Logf("updateTUN: closed old TUNs")

// Since the previous tunnel(s) are closed, the [multiTUN] device is
// not operational until a new underlying tunnel is created and added,
// which may never happen in case of an error or an empty [router.Config].
//
// Therefore, to prevent deadlocks where a [multiTUN.Write] would
// block waiting for a new tunnel to be added, we bring the multiTUN
// device down on exit unless a new [tun.Device] is created and added
// successfully. See tailscale/tailscale#18679.
//
// TODO(nickkhyl): revisit and simplify the [multiTUN] implementation?
if b.devices.Down() {
b.logger.Logf("updateTUN: tunnel brought down: %v", err)
}
}()

if len(rcfg.LocalAddrs) == 0 {
return nil
}

builder := vpnService.service.NewBuilder()
b.logger.Logf("updateTUN: got new builder")

Expand Down Expand Up @@ -244,7 +235,6 @@ func (b *backend) updateTUN(rcfg *router.Config, dcfg *dns.OSConfig) (err error)
b.logger.Logf("updateTUN: created TUN device")

b.devices.add(tunDev)
hasTunnel = true
b.logger.Logf("updateTUN: added TUN device")

if b.devices.Up() {
Expand Down
Loading