diff --git a/ipn/ipnlocal/peerapi.go b/ipn/ipnlocal/peerapi.go
index e0f78ec85..1a85775ff 100644
--- a/ipn/ipnlocal/peerapi.go
+++ b/ipn/ipnlocal/peerapi.go
@@ -670,7 +670,7 @@ func (h *peerAPIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}
if peerAPIRequestShouldGetSecurityHeaders(r) {
- w.Header().Set("Content-Security-Policy", `default-src 'none'; frame-ancestors 'none'; script-src 'none'; script-src-elem 'none'; script-src-attr 'none'`)
+ w.Header().Set("Content-Security-Policy", `default-src 'none'; frame-ancestors 'none'; script-src 'none'; script-src-elem 'none'; script-src-attr 'none'; style-src 'unsafe-inline'`)
w.Header().Set("X-Frame-Options", "DENY")
w.Header().Set("X-Content-Type-Options", "nosniff")
}
@@ -799,15 +799,21 @@ func (h *peerAPIHandler) handleServeInterfaces(w http.ResponseWriter, r *http.Re
fmt.Fprintf(w, "
Could not get the default route: %s
\n", html.EscapeString(err.Error()))
}
+ if hasCGNATInterface, err := interfaces.HasCGNATInterface(); hasCGNATInterface {
+ fmt.Fprintln(w, "There is another interface using the CGNAT range.
")
+ } else if err != nil {
+ fmt.Fprintf(w, "Could not check for CGNAT interfaces: %s
\n", html.EscapeString(err.Error()))
+ }
+
i, err := interfaces.GetList()
if err != nil {
fmt.Fprintf(w, "Could not get interfaces: %s\n", html.EscapeString(err.Error()))
return
}
- fmt.Fprintln(w, "")
+ fmt.Fprintln(w, "")
fmt.Fprint(w, "")
- for _, v := range []any{"Index", "Name", "MTU", "Flags", "Addrs"} {
+ for _, v := range []any{"Index", "Name", "MTU", "Flags", "Addrs", "Extra"} {
fmt.Fprintf(w, "%v | ", v)
}
fmt.Fprint(w, "
\n")
@@ -816,6 +822,11 @@ func (h *peerAPIHandler) handleServeInterfaces(w http.ResponseWriter, r *http.Re
for _, v := range []any{iface.Index, iface.Name, iface.MTU, iface.Flags, ipps} {
fmt.Fprintf(w, "%s | ", html.EscapeString(fmt.Sprintf("%v", v)))
}
+ if extras, err := interfaces.InterfaceDebugExtras(iface.Index); err == nil && extras != "" {
+ fmt.Fprintf(w, "%s | ", html.EscapeString(extras))
+ } else if err != nil {
+ fmt.Fprintf(w, "%s | ", html.EscapeString(err.Error()))
+ }
fmt.Fprint(w, "\n")
})
fmt.Fprintln(w, "
")
diff --git a/net/interfaces/interfaces.go b/net/interfaces/interfaces.go
index c9d92dfcb..d5a76c511 100644
--- a/net/interfaces/interfaces.go
+++ b/net/interfaces/interfaces.go
@@ -756,3 +756,15 @@ func HasCGNATInterface() (bool, error) {
}
return hasCGNATInterface, nil
}
+
+var interfaceDebugExtras func(ifIndex int) (string, error)
+
+// InterfaceDebugExtras returns extra debugging information about an interface
+// if any (an empty string will be returned if there are no additional details).
+// Formatting is platform-dependent and should not be parsed.
+func InterfaceDebugExtras(ifIndex int) (string, error) {
+ if interfaceDebugExtras != nil {
+ return interfaceDebugExtras(ifIndex)
+ }
+ return "", nil
+}
diff --git a/net/interfaces/interfaces_darwin.go b/net/interfaces/interfaces_darwin.go
index d16f1a5e7..6c68844fe 100644
--- a/net/interfaces/interfaces_darwin.go
+++ b/net/interfaces/interfaces_darwin.go
@@ -4,6 +4,7 @@
package interfaces
import (
+ "fmt"
"net"
"strings"
"sync"
@@ -29,6 +30,10 @@ var ifNames struct {
m map[int]string // ifindex => name
}
+func init() {
+ interfaceDebugExtras = interfaceDebugExtrasDarwin
+}
+
// getDelegatedInterface returns the interface index of the underlying interface
// for the given interface index. 0 is returned if the interface does not
// delegate.
@@ -93,3 +98,14 @@ func getDelegatedInterface(ifIndex int) (int, error) {
}
return int(ifr.ifr_delegated), nil
}
+
+func interfaceDebugExtrasDarwin(ifIndex int) (string, error) {
+ delegated, err := getDelegatedInterface(ifIndex)
+ if err != nil {
+ return "", err
+ }
+ if delegated == 0 {
+ return "", nil
+ }
+ return fmt.Sprintf("delegated=%d", delegated), nil
+}