pxe: split subnet into network+netmask for dnsmasq proxy-DHCP
CI / Lint + build + test (push) Successful in 2m0s
Release / release (push) Successful in 3m35s

dnsmasq's proxy-DHCP syntax is `dhcp-range=<network-ip>,proxy[,<mask>]`,
not a CIDR. Passing "192.168.1.0/24,proxy" made dnsmasq refuse to start
with "bad dhcp-range at line 12". Parse the CIDR once in writeConf()
and render Network + Netmask as separate template fields.

The config surface (pxe.subnet) stays CIDR because that's the right
shape for humans; we just unpack it before handing to dnsmasq.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-18 12:17:10 -04:00
parent cf3a75591c
commit 157b70f536
+11 -2
View File
@@ -212,10 +212,17 @@ func (s *Supervisor) writeConf(hosts []model.Host) error {
if err != nil {
return fmt.Errorf("create conf: %w", err)
}
_, ipnet, err := net.ParseCIDR(s.cfg.Subnet)
if err != nil {
_ = f.Close()
return fmt.Errorf("parse subnet %q: %w", s.cfg.Subnet, err)
}
data := struct {
Cfg SupervisorConfig
Hosts []model.Host
}{s.cfg, hosts}
Network string
Netmask string
}{s.cfg, hosts, ipnet.IP.String(), net.IP(ipnet.Mask).String()}
if err := tmpl.Execute(f, data); err != nil {
_ = f.Close()
return fmt.Errorf("render conf: %w", err)
@@ -264,7 +271,9 @@ no-resolv
# Proxy DHCP: coexist with the LAN's real DHCP server. We never hand
# out an IP — we only answer the PXE options (option 66/67 and the
# PXE BINL on port 4011) when a registered MAC boots from the network.
dhcp-range={{ .Cfg.Subnet }},proxy
# dnsmasq's proxy syntax takes a bare network address + netmask, not a
# CIDR — we split Subnet upstream in writeConf().
dhcp-range={{ .Network }},proxy,{{ .Netmask }}
# MAC allowlist: dnsmasq only answers DHCP for MACs with a dhcp-host= below.
dhcp-ignore=tag:!known