two/internal/dhcpd/engine.go
GnomeZworc 0938d1e0e0
f-46: dhcpd: add the decision engine and the persisted state #46
Store porte la configuration du subnet et les réservations par MAC, et les
persiste dans un .state écrit de façon atomique (temp + chmod 0600 + rename).
Chaque écriture remplace le fichier, donc un chmod externe est effacé.

Les snapshots sont à la fois la forme sérialisée et la forme d'entrée des
ordres : validation au moment où l'agent pousse, pas quand un guest demande une
adresse. Les hôtes sont triés par MAC, base du digest de L3.

Handle rend (nil, nil) — le silence est un retour normal — pour un type de
message non traité, un subnet non configuré ou une MAC inconnue. La MAC est
normalisée à l'écriture comme au chargement.

58 tests, -race propre, dix mutations toutes détectées.

Signed-off-by: GnomeZworc <nicolas.boufidjeline@g3e.fr>
2026-09-05 23:15:45 +02:00

66 lines
1.1 KiB
Go

package dhcpd
import (
"net"
"github.com/insomniacslk/dhcp/dhcpv4"
)
func answerable(req *dhcpv4.DHCPv4) bool {
switch req.MessageType() {
case dhcpv4.MessageTypeDiscover, dhcpv4.MessageTypeRequest:
return true
default:
return false
}
}
func (s *Store) Handle(req *dhcpv4.DHCPv4) (*dhcpv4.DHCPv4, error) {
if req == nil {
return nil, ErrNoRequest
}
if !answerable(req) {
return nil, nil
}
subnet, configured := s.Subnet()
if !configured {
return nil, nil
}
host, known := s.Lookup(req.ClientHWAddr)
if !known {
return nil, nil
}
return BuildReply(subnet, host, req)
}
func (s *Store) Probe(mac string) (*dhcpv4.DHCPv4, error) {
key, err := normalizeMAC(mac)
if err != nil {
return nil, err
}
subnet, configured := s.Subnet()
if !configured {
return nil, ErrNotConfigured
}
parsed, err := net.ParseMAC(key)
if err != nil {
return nil, err
}
host, known := s.Lookup(parsed)
if !known {
return nil, nil
}
req, err := dhcpv4.New(dhcpv4.WithMessageType(dhcpv4.MessageTypeRequest), dhcpv4.WithHwAddr(parsed))
if err != nil {
return nil, err
}
return BuildReply(subnet, host, req)
}