@ -84,10 +84,14 @@ func runPing(ctx context.Context, args []string) error {
go func ( ) { pumpErr <- pump ( ctx , bc , c ) } ( )
hostOrIP := args [ 0 ]
ip , err := tailscaleIPFromArg ( ctx , hostOrIP )
ip , self, err := tailscaleIPFromArg ( ctx , hostOrIP )
if err != nil {
return err
}
if self {
fmt . Printf ( "%v is local Tailscale IP\n" , ip )
return nil
}
if pingArgs . verbose && ip != hostOrIP {
log . Printf ( "lookup %q => %q" , hostOrIP , ip )
@ -107,6 +111,10 @@ func runPing(ctx context.Context, args []string) error {
case pr := <- prc :
timer . Stop ( )
if pr . Err != "" {
if pr . IsLocalIP {
fmt . Println ( pr . Err )
return nil
}
return errors . New ( pr . Err )
}
latency := time . Duration ( pr . LatencySeconds * float64 ( time . Second ) ) . Round ( time . Millisecond )
@ -147,33 +155,39 @@ func runPing(ctx context.Context, args []string) error {
}
}
func tailscaleIPFromArg ( ctx context . Context , hostOrIP string ) ( ip string , err error ) {
func tailscaleIPFromArg ( ctx context . Context , hostOrIP string ) ( ip string , self bool , err error ) {
// If the argument is an IP address, use it directly without any resolution.
if net . ParseIP ( hostOrIP ) != nil {
return hostOrIP , nil
return hostOrIP , false, nil
}
// Otherwise, try to resolve it first from the network peer list.
st , err := tailscale . Status ( ctx )
if err != nil {
return "" , err
return "" , false , err
}
match := func ( ps * ipnstate . PeerStatus ) bool {
return strings . EqualFold ( hostOrIP , dnsOrQuoteHostname ( st , ps ) ) || hostOrIP == ps . DNSName
}
for _ , ps := range st . Peer {
if hostOrIP == dnsOrQuoteHostname ( st , ps ) || hostOrIP == ps . DNSName {
if match ( ps ) {
if len ( ps . TailscaleIPs ) == 0 {
return "" , errors . New ( "node found but lacks an IP" )
return "" , false , errors . New ( "node found but lacks an IP" )
}
return ps . TailscaleIPs [ 0 ] . String ( ) , nil
return ps . TailscaleIPs [ 0 ] . String ( ) , false, nil
}
}
if match ( st . Self ) && len ( st . Self . TailscaleIPs ) > 0 {
return st . Self . TailscaleIPs [ 0 ] . String ( ) , true , nil
}
// Finally, use DNS.
var res net . Resolver
if addrs , err := res . LookupHost ( ctx , hostOrIP ) ; err != nil {
return "" , fmt . Errorf ( "error looking up IP of %q: %v" , hostOrIP , err )
return "" , false , fmt . Errorf ( "error looking up IP of %q: %v" , hostOrIP , err )
} else if len ( addrs ) == 0 {
return "" , fmt . Errorf ( "no IPs found for %q" , hostOrIP )
return "" , false , fmt . Errorf ( "no IPs found for %q" , hostOrIP )
} else {
return addrs [ 0 ] , nil
return addrs [ 0 ] , false, nil
}
}