@@ -1221,17 +1221,19 @@ func (c *Client) measureICMPLatency(ctx context.Context, reg *tailcfg.DERPRegion
12211221 // Try pinging the first node in the region
12221222 node := reg .Nodes [0 ]
12231223
1224- // Get the IPAddr by asking for the UDP address that we would use for
1225- // STUN and then using that IP.
1226- //
1227- // TODO(andrew-d): this is a bit ugly
1228- nodeAddr := c .nodeAddr (ctx , node , probeIPv4 )
1229- if ! nodeAddr .IsValid () {
1224+ if node .STUNPort < 0 {
1225+ // If STUN is disabled on a node, interpret that as meaning don't measure latency.
1226+ return 0 , false , nil
1227+ }
1228+ const unusedPort = 0
1229+ stunAddrPort , ok := c .nodeAddrPort (ctx , node , unusedPort , probeIPv4 )
1230+ if ! ok {
12301231 return 0 , false , fmt .Errorf ("no address for node %v (v4-for-icmp)" , node .Name )
12311232 }
1233+ ip := stunAddrPort .Addr ()
12321234 addr := & net.IPAddr {
1233- IP : net .IP (nodeAddr . Addr () .AsSlice ()),
1234- Zone : nodeAddr . Addr () .Zone (),
1235+ IP : net .IP (ip .AsSlice ()),
1236+ Zone : ip .Zone (),
12351237 }
12361238
12371239 // Use the unique node.Name field as the packet data to reduce the
@@ -1478,8 +1480,8 @@ func (rs *reportState) runProbe(ctx context.Context, dm *tailcfg.DERPMap, probe
14781480 return
14791481 }
14801482
1481- addr := c .nodeAddr (ctx , node , probe .proto )
1482- if ! addr . IsValid () {
1483+ addr , ok := c .nodeAddrPort (ctx , node , node . STUNPort , probe .proto )
1484+ if ! ok {
14831485 c .logf ("netcheck.runProbe: named node %q has no %v address" , probe .node , probe .proto )
14841486 return
14851487 }
@@ -1528,12 +1530,17 @@ func (rs *reportState) runProbe(ctx context.Context, dm *tailcfg.DERPMap, probe
15281530 c .vlogf ("sent to %v" , addr )
15291531}
15301532
1531- // proto is 4 or 6
1532- // If it returns nil, the node is skipped.
1533- func (c * Client ) nodeAddr (ctx context.Context , n * tailcfg.DERPNode , proto probeProto ) (ap netip.AddrPort ) {
1534- port := cmp .Or (n .STUNPort , 3478 )
1533+ // nodeAddrPort returns the IP:port to send a STUN queries to for a given node.
1534+ //
1535+ // The provided port should be n.STUNPort, which may be negative to disable STUN.
1536+ // If STUN is disabled for this node, it returns ok=false.
1537+ // The port parameter is separate for the ICMP caller to provide a fake value.
1538+ //
1539+ // proto is [probeIPv4] or [probeIPv6].
1540+ func (c * Client ) nodeAddrPort (ctx context.Context , n * tailcfg.DERPNode , port int , proto probeProto ) (_ netip.AddrPort , ok bool ) {
1541+ var zero netip.AddrPort
15351542 if port < 0 || port > 1 << 16 - 1 {
1536- return
1543+ return zero , false
15371544 }
15381545 if n .STUNTestIP != "" {
15391546 ip , err := netip .ParseAddr (n .STUNTestIP )
@@ -1546,28 +1553,28 @@ func (c *Client) nodeAddr(ctx context.Context, n *tailcfg.DERPNode, proto probeP
15461553 if proto == probeIPv6 && ip .Is4 () {
15471554 return
15481555 }
1549- return netip .AddrPortFrom (ip , uint16 (port ))
1556+ return netip .AddrPortFrom (ip , uint16 (port )), true
15501557 }
15511558
15521559 switch proto {
15531560 case probeIPv4 :
15541561 if n .IPv4 != "" {
15551562 ip , _ := netip .ParseAddr (n .IPv4 )
15561563 if ! ip .Is4 () {
1557- return
1564+ return zero , false
15581565 }
1559- return netip .AddrPortFrom (ip , uint16 (port ))
1566+ return netip .AddrPortFrom (ip , uint16 (port )), true
15601567 }
15611568 case probeIPv6 :
15621569 if n .IPv6 != "" {
15631570 ip , _ := netip .ParseAddr (n .IPv6 )
15641571 if ! ip .Is6 () {
1565- return
1572+ return zero , false
15661573 }
1567- return netip .AddrPortFrom (ip , uint16 (port ))
1574+ return netip .AddrPortFrom (ip , uint16 (port )), true
15681575 }
15691576 default :
1570- return
1577+ return zero , false
15711578 }
15721579
15731580 // The default lookup function if we don't set UseDNSCache is to use net.DefaultResolver.
@@ -1609,13 +1616,13 @@ func (c *Client) nodeAddr(ctx context.Context, n *tailcfg.DERPNode, proto probeP
16091616 addrs , err := lookupIPAddr (ctx , n .HostName )
16101617 for _ , a := range addrs {
16111618 if (a .Is4 () && probeIsV4 ) || (a .Is6 () && ! probeIsV4 ) {
1612- return netip .AddrPortFrom (a , uint16 (port ))
1619+ return netip .AddrPortFrom (a , uint16 (port )), true
16131620 }
16141621 }
16151622 if err != nil {
16161623 c .logf ("netcheck: DNS lookup error for %q (node %q region %v): %v" , n .HostName , n .Name , n .RegionID , err )
16171624 }
1618- return
1625+ return zero , false
16191626}
16201627
16211628func regionHasDERPNode (r * tailcfg.DERPRegion ) bool {
0 commit comments