diff options
Diffstat (limited to 'ipn/ipnlocal/peerapi.go')
| -rw-r--r-- | ipn/ipnlocal/peerapi.go | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/ipn/ipnlocal/peerapi.go b/ipn/ipnlocal/peerapi.go index 176880302..ac41893eb 100644 --- a/ipn/ipnlocal/peerapi.go +++ b/ipn/ipnlocal/peerapi.go @@ -38,12 +38,17 @@ import ( "tailscale.com/net/sockstats" "tailscale.com/tailcfg" "tailscale.com/taildrop" + "tailscale.com/tailfs" "tailscale.com/types/views" "tailscale.com/util/clientmetric" "tailscale.com/util/httphdr" "tailscale.com/wgengine/filter" ) +const ( + tailfsPrefix = "/v0/tailfs" +) + var initListenConfig func(*net.ListenConfig, netip.Addr, *interfaces.State, string) error // addH2C is non-nil on platforms where we want to add H2C @@ -317,6 +322,10 @@ func (h *peerAPIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { h.handleDNSQuery(w, r) return } + if strings.HasPrefix(r.URL.Path, tailfsPrefix) { + h.handleServeTailfs(w, r) + return + } switch r.URL.Path { case "/v0/goroutines": h.handleServeGoroutines(w, r) @@ -626,7 +635,11 @@ func (h *peerAPIHandler) canIngress() bool { } func (h *peerAPIHandler) peerHasCap(wantCap tailcfg.PeerCapability) bool { - return h.ps.b.PeerCaps(h.remoteAddr.Addr()).HasCapability(wantCap) + return h.peerCaps().HasCapability(wantCap) +} + +func (h *peerAPIHandler) peerCaps() tailcfg.PeerCapMap { + return h.ps.b.PeerCaps(h.remoteAddr.Addr()) } func (h *peerAPIHandler) handlePeerPut(w http.ResponseWriter, r *http.Request) { @@ -1090,6 +1103,41 @@ func writePrettyDNSReply(w io.Writer, res []byte) (err error) { return nil } +func (h *peerAPIHandler) handleServeTailfs(w http.ResponseWriter, r *http.Request) { + if !h.ps.b.TailfsSharingEnabled() { + http.Error(w, "tailfs not enabled", http.StatusNotFound) + return + } + + capsMap := h.peerCaps() + tailfsCaps, ok := capsMap[tailcfg.PeerCapabilityTailfs] + if !ok { + http.Error(w, "tailfs not permitted", http.StatusForbidden) + return + } + + rawPerms := make([][]byte, 0, len(tailfsCaps)) + for _, cap := range tailfsCaps { + rawPerms = append(rawPerms, []byte(cap)) + } + + p, err := tailfs.ParsePermissions(rawPerms) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + h.ps.b.mu.Lock() + fs := h.ps.b.tailfsForRemote + h.ps.b.mu.Unlock() + if fs == nil { + http.Error(w, "tailfs not enabled", http.StatusNotFound) + return + } + r.URL.Path = strings.TrimPrefix(r.URL.Path, tailfsPrefix) + fs.ServeHTTP(p, w, r) +} + // newFakePeerAPIListener creates a new net.Listener that acts like // it's listening on the provided IP address and on TCP port 1. // |
