diff --git a/ipn/ipnlocal/peerapi.go b/ipn/ipnlocal/peerapi.go index 3337a8b6c..64017c365 100644 --- a/ipn/ipnlocal/peerapi.go +++ b/ipn/ipnlocal/peerapi.go @@ -567,6 +567,9 @@ func (h *peerAPIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { case "/v0/wol": h.handleWakeOnLAN(w, r) return + case "/v0/interfaces": + h.handleServeInterfaces(w, r) + return } who := h.peerUser.DisplayName fmt.Fprintf(w, ` @@ -581,6 +584,40 @@ This is my Tailscale device. Your device is %v. } } +func (h *peerAPIHandler) handleServeInterfaces(w http.ResponseWriter, r *http.Request) { + if !h.canDebug() { + http.Error(w, "denied; no debug access", http.StatusForbidden) + return + } + i, err := interfaces.GetList() + if err != nil { + http.Error(w, err.Error(), 500) + } + + dr, err := interfaces.DefaultRoute() + if err != nil { + http.Error(w, err.Error(), 500) + } + w.Header().Set("Content-Type", "text/html; charset=utf-8") + fmt.Fprintln(w, "

Interfaces

") + fmt.Fprintf(w, "

Default route is %q(%d)

\n", dr.InterfaceName, dr.InterfaceIndex) + + fmt.Fprintln(w, "") + fmt.Fprint(w, "") + for _, v := range []any{"Index", "Name", "MTU", "Flags", "Addrs"} { + fmt.Fprintf(w, " ", v) + } + fmt.Fprint(w, "\n") + i.ForeachInterface(func(iface interfaces.Interface, ipps []netaddr.IPPrefix) { + fmt.Fprint(w, "") + for _, v := range []any{iface.Index, iface.Name, iface.MTU, iface.Flags, ipps} { + fmt.Fprintf(w, " ", v) + } + fmt.Fprint(w, "\n") + }) + fmt.Fprintln(w, "
%v
%v
") +} + type incomingFile struct { name string // "foo.jpg" started time.Time