From 761163815ca05709bc24bd333195258265677486 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Tue, 30 Aug 2022 12:30:55 -0700 Subject: [PATCH] tailcfg: add Hostinfo.Userspace{,Router} bits Change-Id: Iad47f904872f2df146c1f63945f79cfddeac7fe8 Signed-off-by: Brad Fitzpatrick --- ipn/ipnlocal/local.go | 2 ++ tailcfg/tailcfg.go | 40 ++++++++++++++++++++------------------ tailcfg/tailcfg_clone.go | 40 ++++++++++++++++++++------------------ tailcfg/tailcfg_test.go | 1 + tailcfg/tailcfg_view.go | 42 ++++++++++++++++++++++------------------ 5 files changed, 68 insertions(+), 57 deletions(-) diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 729116b53..4639fce66 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -955,6 +955,8 @@ func (b *LocalBackend) Start(opts ipn.Options) error { hostinfo := hostinfo.New() hostinfo.BackendLogID = b.backendLogID hostinfo.FrontendLogID = opts.FrontendLogID + hostinfo.Userspace.Set(wgengine.IsNetstack(b.e)) + hostinfo.UserspaceRouter.Set(wgengine.IsNetstackRouter(b.e)) if b.cc != nil { // TODO(apenwarr): avoid the need to reinit controlclient. diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index aa66ad66d..9835037da 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -465,25 +465,27 @@ type Service struct { // Because it contains pointers (slices), this type should not be used // as a value type. type Hostinfo struct { - IPNVersion string `json:",omitempty"` // version of this code - FrontendLogID string `json:",omitempty"` // logtail ID of frontend instance - BackendLogID string `json:",omitempty"` // logtail ID of backend instance - OS string `json:",omitempty"` // operating system the client runs on (a version.OS value) - OSVersion string `json:",omitempty"` // operating system version, with optional distro prefix ("Debian 10.4", "Windows 10 Pro 10.0.19041") - Desktop opt.Bool `json:",omitempty"` // if a desktop was detected on Linux - Package string `json:",omitempty"` // Tailscale package to disambiguate ("choco", "appstore", etc; "" for unknown) - DeviceModel string `json:",omitempty"` // mobile phone model ("Pixel 3a", "iPhone12,3") - Hostname string `json:",omitempty"` // name of the host the client runs on - ShieldsUp bool `json:",omitempty"` // indicates whether the host is blocking incoming connections - ShareeNode bool `json:",omitempty"` // indicates this node exists in netmap because it's owned by a shared-to user - GoArch string `json:",omitempty"` // the host's GOARCH value (of the running binary) - GoVersion string `json:",omitempty"` // Go version binary was built with - RoutableIPs []netip.Prefix `json:",omitempty"` // set of IP ranges this client can route - RequestTags []string `json:",omitempty"` // set of ACL tags this node wants to claim - Services []Service `json:",omitempty"` // services advertised by this machine - NetInfo *NetInfo `json:",omitempty"` - SSH_HostKeys []string `json:"sshHostKeys,omitempty"` // if advertised - Cloud string `json:",omitempty"` + IPNVersion string `json:",omitempty"` // version of this code + FrontendLogID string `json:",omitempty"` // logtail ID of frontend instance + BackendLogID string `json:",omitempty"` // logtail ID of backend instance + OS string `json:",omitempty"` // operating system the client runs on (a version.OS value) + OSVersion string `json:",omitempty"` // operating system version, with optional distro prefix ("Debian 10.4", "Windows 10 Pro 10.0.19041") + Desktop opt.Bool `json:",omitempty"` // if a desktop was detected on Linux + Package string `json:",omitempty"` // Tailscale package to disambiguate ("choco", "appstore", etc; "" for unknown) + DeviceModel string `json:",omitempty"` // mobile phone model ("Pixel 3a", "iPhone12,3") + Hostname string `json:",omitempty"` // name of the host the client runs on + ShieldsUp bool `json:",omitempty"` // indicates whether the host is blocking incoming connections + ShareeNode bool `json:",omitempty"` // indicates this node exists in netmap because it's owned by a shared-to user + GoArch string `json:",omitempty"` // the host's GOARCH value (of the running binary) + GoVersion string `json:",omitempty"` // Go version binary was built with + RoutableIPs []netip.Prefix `json:",omitempty"` // set of IP ranges this client can route + RequestTags []string `json:",omitempty"` // set of ACL tags this node wants to claim + Services []Service `json:",omitempty"` // services advertised by this machine + NetInfo *NetInfo `json:",omitempty"` + SSH_HostKeys []string `json:"sshHostKeys,omitempty"` // if advertised + Cloud string `json:",omitempty"` + Userspace opt.Bool `json:",omitempty"` // if the client is running in userspace (netstack) mode + UserspaceRouter opt.Bool `json:",omitempty"` // if the client's subnet router is running in userspace (netstack) mode // NOTE: any new fields containing pointers in this type // require changes to Hostinfo.Equal. diff --git a/tailcfg/tailcfg_clone.go b/tailcfg/tailcfg_clone.go index 6d4082308..977a6105c 100644 --- a/tailcfg/tailcfg_clone.go +++ b/tailcfg/tailcfg_clone.go @@ -115,25 +115,27 @@ func (src *Hostinfo) Clone() *Hostinfo { // A compilation failure here means this code must be regenerated, with the command at the top of this file. var _HostinfoCloneNeedsRegeneration = Hostinfo(struct { - IPNVersion string - FrontendLogID string - BackendLogID string - OS string - OSVersion string - Desktop opt.Bool - Package string - DeviceModel string - Hostname string - ShieldsUp bool - ShareeNode bool - GoArch string - GoVersion string - RoutableIPs []netip.Prefix - RequestTags []string - Services []Service - NetInfo *NetInfo - SSH_HostKeys []string - Cloud string + IPNVersion string + FrontendLogID string + BackendLogID string + OS string + OSVersion string + Desktop opt.Bool + Package string + DeviceModel string + Hostname string + ShieldsUp bool + ShareeNode bool + GoArch string + GoVersion string + RoutableIPs []netip.Prefix + RequestTags []string + Services []Service + NetInfo *NetInfo + SSH_HostKeys []string + Cloud string + Userspace opt.Bool + UserspaceRouter opt.Bool }{}) // Clone makes a deep copy of NetInfo. diff --git a/tailcfg/tailcfg_test.go b/tailcfg/tailcfg_test.go index 13fba958c..27cbb23f0 100644 --- a/tailcfg/tailcfg_test.go +++ b/tailcfg/tailcfg_test.go @@ -37,6 +37,7 @@ func TestHostinfoEqual(t *testing.T) { "GoArch", "GoVersion", "RoutableIPs", "RequestTags", "Services", "NetInfo", "SSH_HostKeys", "Cloud", + "Userspace", "UserspaceRouter", } if have := fieldsOf(reflect.TypeOf(Hostinfo{})); !reflect.DeepEqual(have, hiHandles) { t.Errorf("Hostinfo.Equal check might be out of sync\nfields: %q\nhandled: %q\n", diff --git a/tailcfg/tailcfg_view.go b/tailcfg/tailcfg_view.go index 6218a6462..5dcf69af3 100644 --- a/tailcfg/tailcfg_view.go +++ b/tailcfg/tailcfg_view.go @@ -271,29 +271,33 @@ func (v HostinfoView) Services() views.Slice[Service] { return views.SliceOf( func (v HostinfoView) NetInfo() NetInfoView { return v.ж.NetInfo.View() } func (v HostinfoView) SSH_HostKeys() views.Slice[string] { return views.SliceOf(v.ж.SSH_HostKeys) } func (v HostinfoView) Cloud() string { return v.ж.Cloud } +func (v HostinfoView) Userspace() opt.Bool { return v.ж.Userspace } +func (v HostinfoView) UserspaceRouter() opt.Bool { return v.ж.UserspaceRouter } func (v HostinfoView) Equal(v2 HostinfoView) bool { return v.ж.Equal(v2.ж) } // A compilation failure here means this code must be regenerated, with the command at the top of this file. var _HostinfoViewNeedsRegeneration = Hostinfo(struct { - IPNVersion string - FrontendLogID string - BackendLogID string - OS string - OSVersion string - Desktop opt.Bool - Package string - DeviceModel string - Hostname string - ShieldsUp bool - ShareeNode bool - GoArch string - GoVersion string - RoutableIPs []netip.Prefix - RequestTags []string - Services []Service - NetInfo *NetInfo - SSH_HostKeys []string - Cloud string + IPNVersion string + FrontendLogID string + BackendLogID string + OS string + OSVersion string + Desktop opt.Bool + Package string + DeviceModel string + Hostname string + ShieldsUp bool + ShareeNode bool + GoArch string + GoVersion string + RoutableIPs []netip.Prefix + RequestTags []string + Services []Service + NetInfo *NetInfo + SSH_HostKeys []string + Cloud string + Userspace opt.Bool + UserspaceRouter opt.Bool }{}) // View returns a readonly view of NetInfo.