diff --git a/client/tailscale/tailscale.go b/client/tailscale/tailscale.go index 508a89cfb..b3cdb3dbb 100644 --- a/client/tailscale/tailscale.go +++ b/client/tailscale/tailscale.go @@ -36,7 +36,6 @@ import ( "tailscale.com/paths" "tailscale.com/safesocket" "tailscale.com/tailcfg" - "tailscale.com/version" ) var ( @@ -106,8 +105,8 @@ func DoLocalRequest(req *http.Request) (*http.Response, error) { func doLocalRequestNiceError(req *http.Request) (*http.Response, error) { res, err := DoLocalRequest(req) if err == nil { - if server := res.Header.Get("Tailscale-Version"); server != "" && server != version.Long && onVersionMismatch != nil { - onVersionMismatch(version.Long, server) + if server := res.Header.Get("Tailscale-Version"); server != "" && server != ipn.IPCVersion() && onVersionMismatch != nil { + onVersionMismatch(ipn.IPCVersion(), server) } if res.StatusCode == 403 { all, _ := ioutil.ReadAll(res.Body) diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index 28a72351e..b88eda4d8 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -274,7 +274,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/util/uniq from tailscale.com/wgengine/magicsock tailscale.com/util/winutil from tailscale.com/cmd/tailscaled+ W 💣 tailscale.com/util/winutil/vss from tailscale.com/util/winutil - tailscale.com/version from tailscale.com/client/tailscale+ + tailscale.com/version from tailscale.com/cmd/tailscaled+ tailscale.com/version/distro from tailscale.com/cmd/tailscaled+ W tailscale.com/wf from tailscale.com/cmd/tailscaled tailscale.com/wgengine from tailscale.com/cmd/tailscaled+ diff --git a/ipn/message.go b/ipn/message.go index 12394e1ba..b9e868da0 100644 --- a/ipn/message.go +++ b/ipn/message.go @@ -15,6 +15,7 @@ import ( "log" "time" + "tailscale.com/envknob" "tailscale.com/tailcfg" "tailscale.com/types/logger" "tailscale.com/types/structs" @@ -116,7 +117,7 @@ func (bs *BackendServer) send(n Notify) { if bs.sendNotifyMsg == nil { return } - n.Version = version.Long + n.Version = ipcVersion bs.sendNotifyMsg(n) } @@ -153,9 +154,9 @@ func (bs *BackendServer) GotCommandMsg(ctx context.Context, b []byte) error { const ErrMsgPermissionDenied = "permission denied" func (bs *BackendServer) GotCommand(ctx context.Context, cmd *Command) error { - if cmd.Version != version.Long && !cmd.AllowVersionSkew { + if cmd.Version != ipcVersion && !cmd.AllowVersionSkew { vs := fmt.Sprintf("GotCommand: Version mismatch! frontend=%#v backend=%#v", - cmd.Version, version.Long) + cmd.Version, ipcVersion) bs.logf("%s", vs) // ignore the command, but send a message back to the // caller so it can realize the version mismatch too. @@ -228,6 +229,19 @@ func NewBackendClient(logf logger.Logf, sendCommandMsg func(jsonb []byte)) *Back } } +// IPCVersion returns version.Long usually, unless TS_DEBUG_FAKE_IPC_VERSION is +// set, in which it contains that value. This is only used for weird development +// cases when testing mismatched versions and you want the client to act like it's +// compatible with the server. +func IPCVersion() string { + if v := envknob.String("TS_DEBUG_FAKE_IPC_VERSION"); v != "" { + return v + } + return version.Long +} + +var ipcVersion = IPCVersion() + func (bc *BackendClient) GotNotifyMsg(b []byte) { if len(b) == 0 { // not interesting @@ -240,9 +254,9 @@ func (bc *BackendClient) GotNotifyMsg(b []byte) { if err := json.Unmarshal(b, &n); err != nil { log.Fatalf("BackendClient.Notify: cannot decode message (length=%d, %#q): %v", len(b), b, err) } - if n.Version != version.Long && !bc.AllowVersionSkew { + if n.Version != ipcVersion && !bc.AllowVersionSkew { vs := fmt.Sprintf("GotNotify: Version mismatch! frontend=%#v backend=%#v", - version.Long, n.Version) + ipcVersion, n.Version) bc.logf("%s", vs) // delete anything in the notification except the version, // to prevent incorrect operation. @@ -257,7 +271,7 @@ func (bc *BackendClient) GotNotifyMsg(b []byte) { } func (bc *BackendClient) send(cmd Command) { - cmd.Version = version.Long + cmd.Version = ipcVersion b, err := json.Marshal(cmd) if err != nil { log.Fatalf("Failed json.Marshal(cmd): %v\n", err)