mirror of
https://github.com/tailscale/tailscale.git
synced 2025-04-16 03:31:39 +00:00
cmd/tailscale: make "tailscale ping" also resolve names without DNS
This lets "tailscale ping $NAME" work even if MagicDNS is off, letting you ping a name that shows up in "tailscale status". More user friendly.
This commit is contained in:
parent
9541886856
commit
4306433d1c
@ -64,34 +64,63 @@ func runPing(ctx context.Context, args []string) error {
|
|||||||
c, bc, ctx, cancel := connect(ctx)
|
c, bc, ctx, cancel := connect(ctx)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if len(args) != 1 {
|
if len(args) != 1 || args[0] == "" {
|
||||||
return errors.New("usage: ping <hostname-or-IP>")
|
return errors.New("usage: ping <hostname-or-IP>")
|
||||||
}
|
}
|
||||||
hostOrIP := args[0]
|
|
||||||
var ip string
|
var ip string
|
||||||
var res net.Resolver
|
prc := make(chan *ipnstate.PingResult, 1)
|
||||||
if addrs, err := res.LookupHost(ctx, hostOrIP); err != nil {
|
stc := make(chan *ipnstate.Status, 1)
|
||||||
return 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)
|
|
||||||
} else {
|
|
||||||
ip = addrs[0]
|
|
||||||
}
|
|
||||||
if pingArgs.verbose && ip != hostOrIP {
|
|
||||||
log.Printf("lookup %q => %q", hostOrIP, ip)
|
|
||||||
}
|
|
||||||
|
|
||||||
ch := make(chan *ipnstate.PingResult, 1)
|
|
||||||
bc.SetNotifyCallback(func(n ipn.Notify) {
|
bc.SetNotifyCallback(func(n ipn.Notify) {
|
||||||
if n.ErrMessage != nil {
|
if n.ErrMessage != nil {
|
||||||
log.Fatal(*n.ErrMessage)
|
log.Fatal(*n.ErrMessage)
|
||||||
}
|
}
|
||||||
if pr := n.PingResult; pr != nil && pr.IP == ip {
|
if pr := n.PingResult; pr != nil && pr.IP == ip {
|
||||||
ch <- pr
|
prc <- pr
|
||||||
|
}
|
||||||
|
if n.Status != nil {
|
||||||
|
stc <- n.Status
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
go pump(ctx, bc, c)
|
go pump(ctx, bc, c)
|
||||||
|
|
||||||
|
hostOrIP := args[0]
|
||||||
|
|
||||||
|
// If the argument is an IP address, use it directly without any resolution.
|
||||||
|
if net.ParseIP(hostOrIP) != nil {
|
||||||
|
ip = hostOrIP
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, try to resolve it first from the network peer list.
|
||||||
|
if ip == "" {
|
||||||
|
bc.RequestStatus()
|
||||||
|
select {
|
||||||
|
case st := <-stc:
|
||||||
|
for _, ps := range st.Peer {
|
||||||
|
if hostOrIP == dnsOrQuoteHostname(st, ps) || hostOrIP == ps.DNSName {
|
||||||
|
ip = ps.TailAddr
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, use DNS.
|
||||||
|
if ip == "" {
|
||||||
|
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)
|
||||||
|
} else if len(addrs) == 0 {
|
||||||
|
return fmt.Errorf("no IPs found for %q", hostOrIP)
|
||||||
|
} else {
|
||||||
|
ip = addrs[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if pingArgs.verbose && ip != hostOrIP {
|
||||||
|
log.Printf("lookup %q => %q", hostOrIP, ip)
|
||||||
|
}
|
||||||
|
|
||||||
n := 0
|
n := 0
|
||||||
anyPong := false
|
anyPong := false
|
||||||
for {
|
for {
|
||||||
@ -101,7 +130,7 @@ func runPing(ctx context.Context, args []string) error {
|
|||||||
select {
|
select {
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
fmt.Printf("timeout waiting for ping reply\n")
|
fmt.Printf("timeout waiting for ping reply\n")
|
||||||
case pr := <-ch:
|
case pr := <-prc:
|
||||||
timer.Stop()
|
timer.Stop()
|
||||||
if pr.Err != "" {
|
if pr.Err != "" {
|
||||||
return errors.New(pr.Err)
|
return errors.New(pr.Err)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user