hostinfo, ipnlocal: add optional os-specific callback for querying the hostname (#15647)

updates tailscale/tailscale#13476

On darwin, os.Hostname is no longer reliable when called
from a sandboxed process.  To fix this, we will allow clients
to set an optional callback to query the hostname via an
alternative native API.

We will leave the default implementation as os.Hostname since
this works perfectly well for almost everything besides sandboxed
darwin clients.

Signed-off-by: Jonathan Nobels <jonathan@tailscale.com>
pull/15681/head
Jonathan Nobels 8 months ago committed by GitHub
parent 62182fc37d
commit d6fd865d41
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -43,7 +43,7 @@ func RegisterHostinfoNewHook(f func(*tailcfg.Hostinfo)) {
// New returns a partially populated Hostinfo for the current host.
func New() *tailcfg.Hostinfo {
hostname, _ := os.Hostname()
hostname, _ := Hostname()
hostname = dnsname.FirstLabel(hostname)
hi := &tailcfg.Hostinfo{
IPNVersion: version.Long(),
@ -509,3 +509,21 @@ func IsInVM86() bool {
return New().DeviceModel == copyV86DeviceModel
})
}
type hostnameQuery func() (string, error)
var hostnameFn atomic.Value // of func() (string, error)
// SetHostNameFn sets a custom function for querying the system hostname.
func SetHostnameFn(fn hostnameQuery) {
hostnameFn.Store(fn)
}
// Hostname returns the system hostname using the function
// set by SetHostNameFn. We will fallback to os.Hostname.
func Hostname() (string, error) {
if fn, ok := hostnameFn.Load().(hostnameQuery); ok && fn != nil {
return fn()
}
return os.Hostname()
}

@ -5,6 +5,7 @@ package hostinfo
import (
"encoding/json"
"os"
"strings"
"testing"
)
@ -49,3 +50,31 @@ func TestEtcAptSourceFileIsDisabled(t *testing.T) {
})
}
}
func TestCustomHostnameFunc(t *testing.T) {
want := "custom-hostname"
SetHostnameFn(func() (string, error) {
return want, nil
})
got, err := Hostname()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got != want {
t.Errorf("got %q, want %q", got, want)
}
SetHostnameFn(os.Hostname)
got, err = Hostname()
want, _ = os.Hostname()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got != want {
t.Errorf("got %q, want %q", got, want)
}
}

@ -1245,7 +1245,7 @@ func (b *LocalBackend) UpdateStatus(sb *ipnstate.StatusBuilder) {
}
} else {
ss.HostName, _ = os.Hostname()
ss.HostName, _ = hostinfo.Hostname()
}
for _, pln := range b.peerAPIListeners {
ss.PeerAPIURL = append(ss.PeerAPIURL, pln.urlStr)

Loading…
Cancel
Save