feature/conn25: add and register c2n handler for /conn25/state

Gets the active state just like the LocalAPI endpoint does. See #20471.

Updates tailscale/corp#40125

Signed-off-by: Michael Ben-Ami <mzb@tailscale.com>
This commit is contained in:
Michael Ben-Ami
2026-07-22 13:04:41 -04:00
committed by mzbenami
parent 8f89d4fb55
commit 4d846b5501
2 changed files with 26 additions and 0 deletions
+25
View File
@@ -51,6 +51,31 @@ func serveLocalAPIStateGet(h *localapi.Handler, w http.ResponseWriter, r *http.R
}
}
// serveC2NStateGet serves the C2N endpoint /conn25/state.
// See also [*Conn25.GetActiveState].
func serveC2NStateGet(b *ipnlocal.LocalBackend, w http.ResponseWriter, r *http.Request) {
// TODO(tailscale/corp#39033): Remove for alpha release.
if !envknob.UseWIPCode() && !testenv.InTest() {
w.WriteHeader(http.StatusNotImplemented)
return
}
logf := b.Logger()
logf("c2n: GET /conn25/state received")
ext, ok := ipnlocal.GetExt[*extension](b)
if !ok {
http.Error(w, "miswired", http.StatusInternalServerError)
return
}
state := ext.conn25.GetActiveState()
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(state); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
// GetActiveState returns active state for the client and the connector,
// including IP pool usage, address mappings, domains, and active flow counts.
func (c *Conn25) GetActiveState() appctype.Conn25ActiveState {
+1
View File
@@ -86,6 +86,7 @@ func init() {
ipnlocal.RegisterPeerAPIHandler("/v0/connector/transit-ip", handleConnectorTransitIP)
ipnlocal.HookReplyToDNSQueries.Add(handleHookReplyToDNSQueries)
localapi.Register("conn25/state", serveLocalAPIStateGet)
ipnlocal.RegisterC2N("GET /conn25/state", serveC2NStateGet)
}
func handleConnectorTransitIP(h ipnlocal.PeerAPIHandler, w http.ResponseWriter, r *http.Request) {