@ -2103,7 +2103,7 @@ func (c *Conn) handleDiscoMessage(msg []byte, src epAddr, shouldBeRelayHandshake
c . logf ( "[unexpected] %T packets should not come from a relay server with Geneve control bit set" , dm )
return
}
c . relayManager . handleGeneveEncapDiscoMsg NotBestAddr ( c , challenge , di , src )
c . relayManager . handleGeneveEncapDiscoMsg ( c , challenge , di , src )
return
}
@ -2125,7 +2125,10 @@ func (c *Conn) handleDiscoMessage(msg []byte, src epAddr, shouldBeRelayHandshake
return true
} )
if ! knownTxID && src . vni . isSet ( ) {
c . relayManager . handleGeneveEncapDiscoMsgNotBestAddr ( c , dm , di , src )
// If it's an unknown TxID, and it's Geneve-encapsulated, then
// make [relayManager] aware. It might be in the middle of probing
// src.
c . relayManager . handleGeneveEncapDiscoMsg ( c , dm , di , src )
}
case * disco . CallMeMaybe , * disco . CallMeMaybeVia :
var via * disco . CallMeMaybeVia
@ -2233,6 +2236,35 @@ func (c *Conn) handlePingLocked(dm *disco.Ping, src epAddr, di *discoInfo, derpN
di . lastPingTime = time . Now ( )
isDerp := src . ap . Addr ( ) == tailcfg . DerpMagicIPAddr
if src . vni . isSet ( ) {
if isDerp {
c . logf ( "[unexpected] got Geneve-encapsulated disco ping from %v/%v over DERP" , src , derpNodeSrc )
return
}
// [relayManager] is always responsible for handling (replying) to
// Geneve-encapsulated [disco.Ping] messages in the interest of
// simplicity. It might be in the middle of probing src, so it must be
// made aware.
c . relayManager . handleGeneveEncapDiscoMsg ( c , dm , di , src )
return
}
// This is a naked [disco.Ping] without a VNI.
// If we can figure out with certainty which node key this disco
// message is for, eagerly update our [epAddr]<>node and disco<>node
// mappings to make p2p path discovery faster in simple
// cases. Without this, disco would still work, but would be
// reliant on DERP call-me-maybe to establish the disco<>node
// mapping, and on subsequent disco handlePongConnLocked to establish
// the IP:port<>disco mapping.
if nk , ok := c . unambiguousNodeKeyOfPingLocked ( dm , di . discoKey , derpNodeSrc ) ; ok {
if ! isDerp {
c . peerMap . setNodeKeyForEpAddr ( src , nk )
}
}
// numNodes tracks how many nodes (node keys) are associated with the disco
// key tied to this inbound ping. Multiple nodes may share the same disco
// key in the case of node sharing and users switching accounts.
@ -2244,81 +2276,34 @@ func (c *Conn) handlePingLocked(dm *disco.Ping, src epAddr, di *discoInfo, derpN
// a dstKey if the dst ip:port is DERP.
dstKey := derpNodeSrc
switch {
case src . vni . isSet ( ) :
if isDerp {
c . logf ( "[unexpected] got Geneve-encapsulated disco ping from %v/%v over DERP" , src , derpNodeSrc )
return
}
var bestEpAddr epAddr
var discoKey key . DiscoPublic
ep , ok := c . peerMap . endpointForEpAddr ( src )
if ok {
ep . mu . Lock ( )
bestEpAddr = ep . bestAddr . epAddr
ep . mu . Unlock ( )
disco := ep . disco . Load ( )
if disco != nil {
discoKey = disco . key
// Remember this route if not present.
var dup bool
if isDerp {
if ep , ok := c . peerMap . endpointForNodeKey ( derpNodeSrc ) ; ok {
if ep . addCandidateEndpoint ( src . ap , dm . TxID ) {
return
}
}
if src == bestEpAddr && discoKey == di . discoKey {
// We have an associated endpoint with src as its bestAddr. Set
// numNodes so we TX a pong further down.
numNodes = 1
} else {
// We have no [endpoint] in the [peerMap] for this relay [epAddr]
// using it as a bestAddr. [relayManager] might be in the middle of
// probing it or attempting to set it as best via
// [endpoint.udpRelayEndpointReady()]. Make [relayManager] aware.
c . relayManager . handleGeneveEncapDiscoMsgNotBestAddr ( c , dm , di , src )
return
}
default : // no VNI
// If we can figure out with certainty which node key this disco
// message is for, eagerly update our [epAddr]<>node and disco<>node
// mappings to make p2p path discovery faster in simple
// cases. Without this, disco would still work, but would be
// reliant on DERP call-me-maybe to establish the disco<>node
// mapping, and on subsequent disco handlePongConnLocked to establish
// the IP:port<>disco mapping.
if nk , ok := c . unambiguousNodeKeyOfPingLocked ( dm , di . discoKey , derpNodeSrc ) ; ok {
if ! isDerp {
c . peerMap . setNodeKeyForEpAddr ( src , nk )
}
}
// Remember this route if not present.
var dup bool
if isDerp {
if ep , ok := c . peerMap . endpointForNodeKey ( derpNodeSrc ) ; ok {
if ep . addCandidateEndpoint ( src . ap , dm . TxID ) {
return
}
numNodes = 1
}
} else {
c . peerMap . forEachEndpointWithDiscoKey ( di . discoKey , func ( ep * endpoint ) ( keepGoing bool ) {
if ep . addCandidateEndpoint ( src . ap , dm . TxID ) {
dup = true
return false
}
numNodes ++
if numNodes == 1 && dstKey . IsZero ( ) {
dstKey = ep . publicKey
}
return true
} )
if dup {
return
} else {
c . peerMap . forEachEndpointWithDiscoKey ( di . discoKey , func ( ep * endpoint ) ( keepGoing bool ) {
if ep . addCandidateEndpoint ( src . ap , dm . TxID ) {
dup = true
return false
}
if numNodes > 1 {
// Zero it out if it's ambiguous, so sendDiscoMessage logging
// isn't confusing.
dstKey = key . NodePublic { }
numNodes ++
if numNodes == 1 && dstKey . IsZero ( ) {
dstKey = ep . publicKey
}
return true
} )
if dup {
return
}
if numNodes > 1 {
// Zero it out if it's ambiguous, so sendDiscoMessage logging
// isn't confusing.
dstKey = key . NodePublic { }
}
}