package api import ( "encoding/json" "net/http" "os" "os/exec" "strings" "proxmox-router/internal/dns" ) // handleGetDNSSettings returns the current router DNS configuration. func (s *Server) handleGetDNSSettings(w http.ResponseWriter, r *http.Request) { if s.dnsMgr == nil { writeError(w, http.StatusServiceUnavailable, "DNS manager not initialized") return } settings := s.dnsMgr.GetSettings() writeJSON(w, http.StatusOK, settings) } // handleSaveDNSSettings updates the router DNS configuration. func (s *Server) handleSaveDNSSettings(w http.ResponseWriter, r *http.Request) { if s.dnsMgr == nil { writeError(w, http.StatusServiceUnavailable, "DNS manager not initialized") return } var req dns.DNSSettings if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, "invalid request body") return } if err := s.dnsMgr.SaveSettings(req); err != nil { writeError(w, http.StatusBadRequest, err.Error()) return } writeJSON(w, http.StatusOK, map[string]any{ "success": true, "settings": s.dnsMgr.GetSettings(), }) } // handleListDNSStatic returns all static DNS host mappings. func (s *Server) handleListDNSStatic(w http.ResponseWriter, r *http.Request) { if s.dnsMgr == nil { writeError(w, http.StatusServiceUnavailable, "DNS manager not initialized") return } records := s.dnsMgr.ListStaticRecords() writeJSON(w, http.StatusOK, records) } // handleSaveDNSStatic adds or updates a static DNS record. func (s *Server) handleSaveDNSStatic(w http.ResponseWriter, r *http.Request) { if s.dnsMgr == nil { writeError(w, http.StatusServiceUnavailable, "DNS manager not initialized") return } var rec dns.StaticRecord if err := json.NewDecoder(r.Body).Decode(&rec); err != nil { writeError(w, http.StatusBadRequest, "invalid request body") return } if err := s.dnsMgr.SaveStaticRecord(rec); err != nil { writeError(w, http.StatusBadRequest, err.Error()) return } writeJSON(w, http.StatusOK, map[string]any{ "success": true, "record": rec, }) } // handleDeleteDNSStatic deletes a static DNS record by ID. func (s *Server) handleDeleteDNSStatic(w http.ResponseWriter, r *http.Request) { if s.dnsMgr == nil { writeError(w, http.StatusServiceUnavailable, "DNS manager not initialized") return } id := r.PathValue("id") if id == "" { writeError(w, http.StatusBadRequest, "record ID is required") return } if err := s.dnsMgr.DeleteStaticRecord(id); err != nil { writeError(w, http.StatusNotFound, err.Error()) return } writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": id}) } // handleSetDNSStaticState toggles enabled/disabled state of a static DNS record. func (s *Server) handleSetDNSStaticState(w http.ResponseWriter, r *http.Request) { if s.dnsMgr == nil { writeError(w, http.StatusServiceUnavailable, "DNS manager not initialized") return } id := r.PathValue("id") var req struct { Disabled bool `json:"disabled"` } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, "invalid request body") return } if err := s.dnsMgr.ToggleStaticRecord(id, req.Disabled); err != nil { writeError(w, http.StatusInternalServerError, err.Error()) return } writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": id, "disabled": req.Disabled}) } // handleFlushDNSCache flushes the local DNS cache. func (s *Server) handleFlushDNSCache(w http.ResponseWriter, r *http.Request) { if s.dnsMgr == nil { writeError(w, http.StatusServiceUnavailable, "DNS manager not initialized") return } if err := s.dnsMgr.FlushCache(); err != nil { writeError(w, http.StatusInternalServerError, err.Error()) return } writeJSON(w, http.StatusOK, map[string]any{"success": true, "message": "DNS cache flushed successfully"}) } // handleGetDNSStatus returns live DNS forwarder and resolv.conf status. func (s *Server) handleGetDNSStatus(w http.ResponseWriter, r *http.Request) { if s.dnsMgr == nil { writeError(w, http.StatusServiceUnavailable, "DNS manager not initialized") return } status := s.dnsMgr.GetStatus() writeJSON(w, http.StatusOK, status) } // handleGetSystemSettings returns hostname, timezone, and appliance info. func (s *Server) handleGetSystemSettings(w http.ResponseWriter, r *http.Request) { hostname, _ := os.Hostname() tz := "UTC" if out, err := exec.Command("timedatectl", "show", "--property=Timezone", "--value").Output(); err == nil { tz = strings.TrimSpace(string(out)) } else if data, err := os.ReadFile("/etc/timezone"); err == nil { tz = strings.TrimSpace(string(data)) } writeJSON(w, http.StatusOK, map[string]any{ "hostname": hostname, "timezone": tz, }) } // handleSaveSystemSettings updates hostname and/or timezone. func (s *Server) handleSaveSystemSettings(w http.ResponseWriter, r *http.Request) { var req struct { Hostname string `json:"hostname"` Timezone string `json:"timezone"` } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, "invalid request body") return } if req.Hostname != "" { h := strings.TrimSpace(req.Hostname) if err := exec.Command("hostnamectl", "set-hostname", h).Run(); err != nil { _ = os.WriteFile("/etc/hostname", []byte(h+"\n"), 0644) } } if req.Timezone != "" { tz := strings.TrimSpace(req.Timezone) _ = exec.Command("timedatectl", "set-timezone", tz).Run() } curH, _ := os.Hostname() writeJSON(w, http.StatusOK, map[string]any{ "success": true, "hostname": curH, "timezone": req.Timezone, }) }