|
|
@ -14,7 +14,6 @@ import (
|
|
|
|
"net/http"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/peterbourgon/ff/v2/ffcli"
|
|
|
|
"github.com/peterbourgon/ff/v2/ffcli"
|
|
|
|
"github.com/toqueteos/webbrowser"
|
|
|
|
"github.com/toqueteos/webbrowser"
|
|
|
@ -23,7 +22,6 @@ import (
|
|
|
|
"tailscale.com/ipn"
|
|
|
|
"tailscale.com/ipn"
|
|
|
|
"tailscale.com/ipn/ipnstate"
|
|
|
|
"tailscale.com/ipn/ipnstate"
|
|
|
|
"tailscale.com/net/interfaces"
|
|
|
|
"tailscale.com/net/interfaces"
|
|
|
|
"tailscale.com/tstime/mono"
|
|
|
|
|
|
|
|
"tailscale.com/util/dnsname"
|
|
|
|
"tailscale.com/util/dnsname"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
@ -63,7 +61,7 @@ func runStatus(ctx context.Context, args []string) error {
|
|
|
|
if statusArgs.json {
|
|
|
|
if statusArgs.json {
|
|
|
|
if statusArgs.active {
|
|
|
|
if statusArgs.active {
|
|
|
|
for peer, ps := range st.Peer {
|
|
|
|
for peer, ps := range st.Peer {
|
|
|
|
if !peerActive(ps) {
|
|
|
|
if !ps.Active {
|
|
|
|
delete(st.Peer, peer)
|
|
|
|
delete(st.Peer, peer)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -131,7 +129,6 @@ func runStatus(ctx context.Context, args []string) error {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
var buf bytes.Buffer
|
|
|
|
f := func(format string, a ...interface{}) { fmt.Fprintf(&buf, format, a...) }
|
|
|
|
f := func(format string, a ...interface{}) { fmt.Fprintf(&buf, format, a...) }
|
|
|
|
printPS := func(ps *ipnstate.PeerStatus) {
|
|
|
|
printPS := func(ps *ipnstate.PeerStatus) {
|
|
|
|
active := peerActive(ps)
|
|
|
|
|
|
|
|
f("%-15s %-20s %-12s %-7s ",
|
|
|
|
f("%-15s %-20s %-12s %-7s ",
|
|
|
|
firstIPString(ps.TailscaleIPs),
|
|
|
|
firstIPString(ps.TailscaleIPs),
|
|
|
|
dnsOrQuoteHostname(st, ps),
|
|
|
|
dnsOrQuoteHostname(st, ps),
|
|
|
@ -140,7 +137,7 @@ func runStatus(ctx context.Context, args []string) error {
|
|
|
|
)
|
|
|
|
)
|
|
|
|
relay := ps.Relay
|
|
|
|
relay := ps.Relay
|
|
|
|
anyTraffic := ps.TxBytes != 0 || ps.RxBytes != 0
|
|
|
|
anyTraffic := ps.TxBytes != 0 || ps.RxBytes != 0
|
|
|
|
if !active {
|
|
|
|
if !ps.Active {
|
|
|
|
if ps.ExitNode {
|
|
|
|
if ps.ExitNode {
|
|
|
|
f("idle; exit node")
|
|
|
|
f("idle; exit node")
|
|
|
|
} else if anyTraffic {
|
|
|
|
} else if anyTraffic {
|
|
|
@ -179,8 +176,7 @@ func runStatus(ctx context.Context, args []string) error {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ipnstate.SortPeers(peers)
|
|
|
|
ipnstate.SortPeers(peers)
|
|
|
|
for _, ps := range peers {
|
|
|
|
for _, ps := range peers {
|
|
|
|
active := peerActive(ps)
|
|
|
|
if statusArgs.active && !ps.Active {
|
|
|
|
if statusArgs.active && !active {
|
|
|
|
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
printPS(ps)
|
|
|
|
printPS(ps)
|
|
|
@ -190,13 +186,6 @@ func runStatus(ctx context.Context, args []string) error {
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// peerActive reports whether ps has recent activity.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// TODO: have the server report this bool instead.
|
|
|
|
|
|
|
|
func peerActive(ps *ipnstate.PeerStatus) bool {
|
|
|
|
|
|
|
|
return !ps.LastWrite.IsZero() && mono.Since(ps.LastWrite) < 2*time.Minute
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func dnsOrQuoteHostname(st *ipnstate.Status, ps *ipnstate.PeerStatus) string {
|
|
|
|
func dnsOrQuoteHostname(st *ipnstate.Status, ps *ipnstate.PeerStatus) string {
|
|
|
|
baseName := dnsname.TrimSuffix(ps.DNSName, st.MagicDNSSuffix)
|
|
|
|
baseName := dnsname.TrimSuffix(ps.DNSName, st.MagicDNSSuffix)
|
|
|
|
if baseName != "" {
|
|
|
|
if baseName != "" {
|
|
|
|