cmd/tailscale: fix "tailscale ip $self-host-hostname"

And in the process, fix the related confusing error messages from
pinging your own IP or hostname.

Fixes #2803

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2021-09-07 11:57:23 -07:00
parent 4917a96aec
commit 7bfd4f521d
6 changed files with 59 additions and 22 deletions

View File

@@ -1244,7 +1244,7 @@ func (e *userspaceEngine) UpdateStatus(sb *ipnstate.StatusBuilder) {
func (e *userspaceEngine) Ping(ip netaddr.IP, useTSMP bool, cb func(*ipnstate.PingResult)) {
res := &ipnstate.PingResult{IP: ip.String()}
peer, err := e.peerForIP(ip)
peer, self, err := e.peerForIP(ip)
if err != nil {
e.logf("ping(%v): %v", ip, err)
res.Err = err.Error()
@@ -1257,6 +1257,13 @@ func (e *userspaceEngine) Ping(ip netaddr.IP, useTSMP bool, cb func(*ipnstate.Pi
cb(res)
return
}
if self {
res.Err = fmt.Sprintf("%v is local Tailscale IP", ip)
res.IsLocalIP = true
cb(res)
return
}
pingType := "disco"
if useTSMP {
pingType = "TSMP"
@@ -1400,12 +1407,12 @@ func (e *userspaceEngine) WhoIsIPPort(ipport netaddr.IPPort) (tsIP netaddr.IP, o
//
// peerForIP acquires both e.mu and e.wgLock, but neither at the same
// time.
func (e *userspaceEngine) peerForIP(ip netaddr.IP) (n *tailcfg.Node, err error) {
func (e *userspaceEngine) peerForIP(ip netaddr.IP) (n *tailcfg.Node, isSelf bool, err error) {
e.mu.Lock()
nm := e.netMap
e.mu.Unlock()
if nm == nil {
return nil, errors.New("no network map")
return nil, false, errors.New("no network map")
}
// Check for exact matches before looking for subnet matches.
@@ -1414,7 +1421,7 @@ func (e *userspaceEngine) peerForIP(ip netaddr.IP) (n *tailcfg.Node, err error)
for _, p := range nm.Peers {
for _, a := range p.Addresses {
if a.IP() == ip && a.IsSingleIP() && tsaddr.IsTailscaleIP(ip) {
return p, nil
return p, false, nil
}
}
for _, cidr := range p.AllowedIPs {
@@ -1427,6 +1434,11 @@ func (e *userspaceEngine) peerForIP(ip netaddr.IP) (n *tailcfg.Node, err error)
}
}
}
for _, a := range nm.Addresses {
if a.IP() == ip && a.IsSingleIP() && tsaddr.IsTailscaleIP(ip) {
return nm.SelfNode, true, nil
}
}
e.wgLock.Lock()
defer e.wgLock.Unlock()
@@ -1450,17 +1462,17 @@ func (e *userspaceEngine) peerForIP(ip netaddr.IP) (n *tailcfg.Node, err error)
if !bestKey.IsZero() {
for _, p := range nm.Peers {
if p.Key == bestKey {
return p, nil
return p, false, nil
}
}
}
if bestInNM == nil {
return nil, nil
return nil, false, nil
}
if bestInNMPrefix.Bits() == 0 {
return nil, errors.New("exit node found but not enabled")
return nil, false, errors.New("exit node found but not enabled")
}
return nil, fmt.Errorf("node %q found, but not using its %v route", bestInNM.ComputedNameWithHost, bestInNMPrefix)
return nil, false, fmt.Errorf("node %q found, but not using its %v route", bestInNM.ComputedNameWithHost, bestInNMPrefix)
}
type closeOnErrorPool []func()