mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-11 13:18:53 +00:00
wgengine: avoid holding any locks during HandshakeDone
Because wgLock is held while some wireguard-go methods run, trying to hold wgLock during HandshakeDone potentially creates lock cycles between wgengine and internals of wireguard-go. Arguably wireguard-go should call HandshakeDone in a new goroutine, but until its API promises that, don't make any assumptions here. Maybe for #110. Signed-off-by: David Crawshaw <crawshaw@tailscale.com>
This commit is contained in:
@@ -167,7 +167,7 @@ func newUserspaceEngineAdvanced(logf logger.Logf, tundev tun.Device, routerGen R
|
|||||||
if ones, bits := allowedIPs[0].Mask.Size(); ones == bits && ones != 0 {
|
if ones, bits := allowedIPs[0].Mask.Size(); ones == bits && ones != 0 {
|
||||||
var ip wgcfg.IP
|
var ip wgcfg.IP
|
||||||
copy(ip.Addr[:], allowedIPs[0].IP.To16())
|
copy(ip.Addr[:], allowedIPs[0].IP.To16())
|
||||||
e.startPinger(peerKey, ip)
|
go e.pinger(peerKey, ip)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -226,11 +226,11 @@ func newUserspaceEngineAdvanced(logf logger.Logf, tundev tun.Device, routerGen R
|
|||||||
return e, nil
|
return e, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// startPinger starts a goroutine that sends ping packets for a few seconds.
|
// pinger sends ping packets for a few seconds.
|
||||||
//
|
//
|
||||||
// These generated packets are used to ensure we trigger the spray logic in
|
// These generated packets are used to ensure we trigger the spray logic in
|
||||||
// the magicsock package for NAT traversal.
|
// the magicsock package for NAT traversal.
|
||||||
func (e *userspaceEngine) startPinger(peerKey wgcfg.Key, ip wgcfg.IP) {
|
func (e *userspaceEngine) pinger(peerKey wgcfg.Key, ip wgcfg.IP) {
|
||||||
e.logf("generating initial ping traffic to %s (%v)", peerKey.ShortString(), ip)
|
e.logf("generating initial ping traffic to %s (%v)", peerKey.ShortString(), ip)
|
||||||
var srcIP packet.IP
|
var srcIP packet.IP
|
||||||
|
|
||||||
@@ -264,37 +264,35 @@ func (e *userspaceEngine) startPinger(peerKey wgcfg.Key, ip wgcfg.IP) {
|
|||||||
|
|
||||||
payload := []byte("magicsock_spray") // no meaning
|
payload := []byte("magicsock_spray") // no meaning
|
||||||
|
|
||||||
go func() {
|
defer func() {
|
||||||
defer func() {
|
e.mu.Lock()
|
||||||
e.mu.Lock()
|
defer e.mu.Unlock()
|
||||||
defer e.mu.Unlock()
|
select {
|
||||||
select {
|
case <-ctx.Done():
|
||||||
case <-ctx.Done():
|
return
|
||||||
return
|
default:
|
||||||
default:
|
|
||||||
}
|
|
||||||
// If the pinger context is not done, then the
|
|
||||||
// CancelFunc is still in the pingers map.
|
|
||||||
delete(e.pingers, peerKey)
|
|
||||||
}()
|
|
||||||
|
|
||||||
ipid := uint16(1)
|
|
||||||
t := time.NewTicker(sendFreq)
|
|
||||||
defer t.Stop()
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
case <-t.C:
|
|
||||||
}
|
|
||||||
if time.Since(start) > stopAfter {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
b := packet.GenICMP(srcIP, dstIP, ipid, packet.EchoRequest, 0, payload)
|
|
||||||
ipid++
|
|
||||||
e.wgdev.SendPacket(b)
|
|
||||||
}
|
}
|
||||||
|
// If the pinger context is not done, then the
|
||||||
|
// CancelFunc is still in the pingers map.
|
||||||
|
delete(e.pingers, peerKey)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
ipid := uint16(1)
|
||||||
|
t := time.NewTicker(sendFreq)
|
||||||
|
defer t.Stop()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case <-t.C:
|
||||||
|
}
|
||||||
|
if time.Since(start) > stopAfter {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b := packet.GenICMP(srcIP, dstIP, ipid, packet.EchoRequest, 0, payload)
|
||||||
|
ipid++
|
||||||
|
e.wgdev.SendPacket(b)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(apenwarr): dnsDomains really ought to be in wgcfg.Config.
|
// TODO(apenwarr): dnsDomains really ought to be in wgcfg.Config.
|
||||||
|
Reference in New Issue
Block a user