Reverse zone suggestions: yours and public, dismiss, per-view switch; child zones take their records

Suggestions split into networks that are yours (private IPv4 /24, ULA /48, an IPv6 /48 this server has an address in), which Create all creates, and public addresses (/32 or /128) to create only if they are yours or dismiss. A view can turn suggestions off, which also keeps it out of choosing a reverse zone's view (database version 13). A zone created inside another in the same view takes the parent's records under it; a delegation and its glue stay, a linked parent keeps them with a warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adamandClaude Opus 5.5 committed 2026-10-12 22:01:18 +01:00
1 parent aa4b004a14
commit b24c730b97
21 files changed
+543 -107

No files matched your search

+18 -1
View File
@@ -29,7 +29,7 @@ func (s *Server) reverseSuggestions(w http.ResponseWriter, r *http.Request, p *a
return err
}
out := []engine.ReverseSuggestion{}
for _, sg := range engine.ReverseSuggestions(st, s.eng.Exposures(st)) {
for _, sg := range s.eng.ReverseSuggestions(st) {
if p.CanSeeZone(sg.Zone+".", sg.View) {
out = append(out, sg)
}
@@ -37,3 +37,20 @@ func (s *Server) reverseSuggestions(w http.ResponseWriter, r *http.Request, p *a
writeJSON(w, http.StatusOK, out)
return nil
}
// reverseDismiss: POST /reverse-zones/dismiss {"view": "internal",
// "prefix": "185.199.108.153/32"} hides a suggestion; /undismiss shows it
// again.
func (s *Server) reverseDismiss(dismiss bool) handler {
return func(w http.ResponseWriter, r *http.Request, p *auth.Principal) error {
var in engine.DismissInput
if err := decodeJSON(r, &in); err != nil {
return err
}
op := engine.OpReverseUndismiss
if dismiss {
op = engine.OpReverseDismiss
}
return s.mutate(w, r, p, "", []engine.Request{engine.NewRequest(op, 0, in)}, nil)
}
}
+2
View File
@@ -116,6 +116,8 @@ func (s *Server) routes() {
m.HandleFunc("POST "+p+"/zones/{zone}/unlink", s.authed(s.zoneLink(false)))
m.HandleFunc("POST "+p+"/zones/{zone}/fill-ptr", s.authed(s.zoneFillPTR))
m.HandleFunc("GET "+p+"/reverse-zones/suggestions", s.authed(s.reverseSuggestions))
m.HandleFunc("POST "+p+"/reverse-zones/dismiss", s.authed(s.reverseDismiss(true)))
m.HandleFunc("POST "+p+"/reverse-zones/undismiss", s.authed(s.reverseDismiss(false)))
m.HandleFunc("POST "+p+"/zones/{zone}/import", s.authed(s.importZoneFile))
m.HandleFunc("GET "+p+"/zones/{zone}/records", s.authed(s.listRecords))
m.HandleFunc("POST "+p+"/zones/{zone}/records", s.authed(s.createRecord))