|
|
|
@ -231,20 +231,21 @@ func WhoIs(ctx context.Context, remoteAddr string) (*apitype.WhoIsResponse, erro
|
|
|
|
|
return defaultLocalClient.WhoIs(ctx, remoteAddr)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decodeJSON[T any](b []byte) (ret T, err error) {
|
|
|
|
|
if err := json.Unmarshal(b, &ret); err != nil {
|
|
|
|
|
var zero T
|
|
|
|
|
return zero, fmt.Errorf("failed to unmarshal JSON into %T: %w", ret, err)
|
|
|
|
|
}
|
|
|
|
|
return ret, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WhoIs returns the owner of the remoteAddr, which must be an IP or IP:port.
|
|
|
|
|
func (lc *LocalClient) WhoIs(ctx context.Context, remoteAddr string) (*apitype.WhoIsResponse, error) {
|
|
|
|
|
body, err := lc.get200(ctx, "/localapi/v0/whois?addr="+url.QueryEscape(remoteAddr))
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
r := new(apitype.WhoIsResponse)
|
|
|
|
|
if err := json.Unmarshal(body, r); err != nil {
|
|
|
|
|
if max := 200; len(body) > max {
|
|
|
|
|
body = append(body[:max], "..."...)
|
|
|
|
|
}
|
|
|
|
|
return nil, fmt.Errorf("failed to parse JSON WhoIsResponse from %q", body)
|
|
|
|
|
}
|
|
|
|
|
return r, nil
|
|
|
|
|
return decodeJSON[*apitype.WhoIsResponse](body)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Goroutines returns a dump of the Tailscale daemon's current goroutines.
|
|
|
|
@ -411,11 +412,7 @@ func (lc *LocalClient) status(ctx context.Context, queryString string) (*ipnstat
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
st := new(ipnstate.Status)
|
|
|
|
|
if err := json.Unmarshal(body, st); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return st, nil
|
|
|
|
|
return decodeJSON[*ipnstate.Status](body)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IDToken is a request to get an OIDC ID token for an audience.
|
|
|
|
@ -426,11 +423,7 @@ func (lc *LocalClient) IDToken(ctx context.Context, aud string) (*tailcfg.TokenR
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
tr := new(tailcfg.TokenResponse)
|
|
|
|
|
if err := json.Unmarshal(body, tr); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return tr, nil
|
|
|
|
|
return decodeJSON[*tailcfg.TokenResponse](body)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (lc *LocalClient) WaitingFiles(ctx context.Context) ([]apitype.WaitingFile, error) {
|
|
|
|
@ -438,11 +431,7 @@ func (lc *LocalClient) WaitingFiles(ctx context.Context) ([]apitype.WaitingFile,
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
var wfs []apitype.WaitingFile
|
|
|
|
|
if err := json.Unmarshal(body, &wfs); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return wfs, nil
|
|
|
|
|
return decodeJSON[[]apitype.WaitingFile](body)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (lc *LocalClient) DeleteWaitingFile(ctx context.Context, baseName string) error {
|
|
|
|
@ -476,11 +465,7 @@ func (lc *LocalClient) FileTargets(ctx context.Context) ([]apitype.FileTarget, e
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
var fts []apitype.FileTarget
|
|
|
|
|
if err := json.Unmarshal(body, &fts); err != nil {
|
|
|
|
|
return nil, fmt.Errorf("invalid JSON: %w", err)
|
|
|
|
|
}
|
|
|
|
|
return fts, nil
|
|
|
|
|
return decodeJSON[[]apitype.FileTarget](body)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// PushFile sends Taildrop file r to target.
|
|
|
|
@ -555,11 +540,7 @@ func (lc *LocalClient) EditPrefs(ctx context.Context, mp *ipn.MaskedPrefs) (*ipn
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
var p ipn.Prefs
|
|
|
|
|
if err := json.Unmarshal(body, &p); err != nil {
|
|
|
|
|
return nil, fmt.Errorf("invalid prefs JSON: %w", err)
|
|
|
|
|
}
|
|
|
|
|
return &p, nil
|
|
|
|
|
return decodeJSON[*ipn.Prefs](body)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (lc *LocalClient) Logout(ctx context.Context) error {
|
|
|
|
@ -765,11 +746,7 @@ func (lc *LocalClient) Ping(ctx context.Context, ip netip.Addr, pingtype tailcfg
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("error %w: %s", err, body)
|
|
|
|
|
}
|
|
|
|
|
pr := new(ipnstate.PingResult)
|
|
|
|
|
if err := json.Unmarshal(body, pr); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return pr, nil
|
|
|
|
|
return decodeJSON[*ipnstate.PingResult](body)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NetworkLockStatus fetches information about the tailnet key authority, if one is configured.
|
|
|
|
@ -778,11 +755,7 @@ func (lc *LocalClient) NetworkLockStatus(ctx context.Context) (*ipnstate.Network
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("error: %w", err)
|
|
|
|
|
}
|
|
|
|
|
pr := new(ipnstate.NetworkLockStatus)
|
|
|
|
|
if err := json.Unmarshal(body, pr); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return pr, nil
|
|
|
|
|
return decodeJSON[*ipnstate.NetworkLockStatus](body)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NetworkLockInit initializes the tailnet key authority.
|
|
|
|
@ -803,12 +776,7 @@ func (lc *LocalClient) NetworkLockInit(ctx context.Context, keys []tka.Key, disa
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("error: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pr := new(ipnstate.NetworkLockStatus)
|
|
|
|
|
if err := json.Unmarshal(body, pr); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return pr, nil
|
|
|
|
|
return decodeJSON[*ipnstate.NetworkLockStatus](body)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NetworkLockModify adds and/or removes key(s) to the tailnet key authority.
|
|
|
|
@ -827,12 +795,7 @@ func (lc *LocalClient) NetworkLockModify(ctx context.Context, addKeys, removeKey
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("error: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pr := new(ipnstate.NetworkLockStatus)
|
|
|
|
|
if err := json.Unmarshal(body, pr); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return pr, nil
|
|
|
|
|
return decodeJSON[*ipnstate.NetworkLockStatus](body)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NetworkLockSign signs the specified node-key and transmits that signature to the control plane.
|
|
|
|
|