Files
alpine-router/handlers/clients.go
2026-04-13 12:40:49 +03:00

144 lines
3.1 KiB
Go

package handlers
import (
"encoding/json"
"log"
"net/http"
"strings"
"alpine-router/clients"
"alpine-router/config"
"alpine-router/dhcp"
)
func HandleClients(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
fail(w, http.StatusMethodNotAllowed, "method not allowed")
return
}
list, err := clients.GetAll()
if err != nil {
fail(w, http.StatusInternalServerError, err.Error())
return
}
ok(w, list)
}
func HandleClientUpdate(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
fail(w, http.StatusMethodNotAllowed, "method not allowed")
return
}
mac := strings.TrimPrefix(r.URL.Path, "/api/clients/update/")
if mac == "" {
fail(w, http.StatusBadRequest, "mac address required")
return
}
var req struct {
Hostname string `json:"hostname"`
Blocked bool `json:"blocked"`
StaticIP string `json:"static_ip"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
fail(w, http.StatusBadRequest, "invalid json: "+err.Error())
return
}
if err := updateClient(mac, req.Hostname, req.Blocked, req.StaticIP); err != nil {
fail(w, http.StatusInternalServerError, err.Error())
return
}
go applyBlockedFirewall()
go applyDHCPStaticBindings()
ok(w, map[string]string{"message": "updated"})
}
func updateClient(mac, hostname string, blocked bool, staticIP string) error {
cfg, err := config.Load()
if err != nil {
return err
}
found := false
for i := range cfg.KnownDevices {
if cfg.KnownDevices[i].MAC == mac {
cfg.KnownDevices[i].Blocked = blocked
cfg.KnownDevices[i].Hostname = hostname
cfg.KnownDevices[i].StaticIP = staticIP
found = true
break
}
}
if !found {
cfg.KnownDevices = append(cfg.KnownDevices, config.KnownDevice{
MAC: mac,
Hostname: hostname,
Blocked: blocked,
StaticIP: staticIP,
})
}
return config.Save(cfg)
}
func applyDHCPStaticBindings() {
if !dhcp.IsInstalled() {
return
}
cfg, err := config.Load()
if err != nil {
log.Printf("Warning: load config for DHCP static bindings: %v", err)
return
}
var bindings []dhcp.StaticBinding
for _, kd := range cfg.KnownDevices {
if kd.StaticIP != "" && kd.MAC != "" {
bindings = append(bindings, dhcp.StaticBinding{
MAC: kd.MAC,
Host: kd.Hostname,
IP: kd.StaticIP,
})
}
}
dhcpCfg := &dhcp.Config{
Enabled: cfg.DHCP.Enabled,
Pools: make([]dhcp.Pool, len(cfg.DHCP.Pools)),
}
for i, p := range cfg.DHCP.Pools {
dhcpCfg.Pools[i] = dhcp.Pool{
Interface: p.Interface,
Enabled: p.Enabled,
Subnet: p.Subnet,
Netmask: p.Netmask,
RangeStart: p.RangeStart,
RangeEnd: p.RangeEnd,
Router: p.Router,
DNS: p.DNS,
LeaseTime: p.LeaseTime,
}
}
if err := dhcp.WriteConfigsWithBindings(dhcpCfg, bindings); err != nil {
log.Printf("Warning: write dnsmasq config with static bindings: %v", err)
return
}
if dhcpCfg.Enabled {
if err := dhcp.ServiceRestart(); err != nil {
log.Printf("Warning: restart dnsmasq after static binding update: %v", err)
} else {
log.Printf("dnsmasq restarted with %d static bindings", len(bindings))
}
}
}