dhcp4d: implement loading leases files from persistent storage

This commit is contained in:
Michael Stapelberg 2018-06-09 15:10:11 +02:00
parent f9c3c23b16
commit d21822f531
3 changed files with 62 additions and 10 deletions

View File

@ -4,19 +4,36 @@ package main
import (
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"syscall"
"router7/internal/dhcp4d"
"router7/internal/notify"
"router7/internal/teelogger"
"github.com/krolaw/dhcp4"
"github.com/krolaw/dhcp4/conn"
)
var log = teelogger.NewConsole()
func loadLeases(h *dhcp4d.Handler, fn string) error {
b, err := ioutil.ReadFile(fn)
if err != nil {
if os.IsNotExist(err) {
return nil
}
return err
}
var leases []*dhcp4d.Lease
if err := json.Unmarshal(b, leases); err != nil {
return err
}
h.SetLeases(leases)
return nil
}
func logic() error {
if err := os.MkdirAll("/perm/dhcp4d", 0755); err != nil {
return err
@ -26,6 +43,9 @@ func logic() error {
if err != nil {
return err
}
if err := loadLeases(handler, "/perm/dhcp4d/leases.json"); err != nil {
return err
}
handler.Leases = func(leases []*dhcp4d.Lease) {
b, err := json.Marshal(leases)
if err != nil {
@ -38,7 +58,6 @@ func logic() error {
}
if err := notify.Process("/user/dnsd", syscall.SIGUSR1); err != nil {
log.Printf("notifying dnsd: %v", err)
ioutil.WriteFile("/dev/console", []byte(fmt.Sprintf("notifying dnsd: %+v\n", err)), 0600)
}
}
conn, err := conn.NewUDP4BoundListener("lan0", ":67") // TODO: customizeable

View File

@ -14,11 +14,11 @@ import (
)
type Lease struct {
Num int
Addr net.IP
HardwareAddr string
Hostname string
Expiry time.Time
Num int `json:"num"` // relative to Handler.start
Addr net.IP `json:"addr"`
HardwareAddr string `json:"hardware_addr"`
Hostname string `json:"hostname"`
Expiry time.Time `json:"expiry"`
}
type Handler struct {
@ -36,7 +36,6 @@ type Handler struct {
Leases func([]*Lease)
}
// TODO: restore leases from permanent storage
func NewHandler(dir string) (*Handler, error) {
serverIP, err := netconfig.LinkAddress(dir, "lan0")
if err != nil {
@ -64,6 +63,18 @@ func NewHandler(dir string) (*Handler, error) {
}, nil
}
// SetLeases overwrites the leases database with the specified leases, typically
// loaded from persistent storage. There is no locking, so SetLeases must be
// called before Serve.
func (h *Handler) SetLeases(leases []*Lease) {
h.leasesHW = make(map[string]*Lease)
h.leasesIP = make(map[int]*Lease)
for _, l := range leases {
h.leasesHW[l.HardwareAddr] = l
h.leasesIP[l.Num] = l
}
}
func (h *Handler) findLease() int {
now := h.timeNow()
if len(h.leasesIP) < h.leaseRange {

View File

@ -316,4 +316,26 @@ func TestServerID(t *testing.T) {
}
}
// TODO: test persistent storage
func TestPersistentStorage(t *testing.T) {
handler, cleanup := testHandler(t)
defer cleanup()
var (
addr = net.IP{192, 168, 42, 4}
hardwareAddr = net.HardwareAddr{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}
)
handler.SetLeases([]*Lease{
{
Num: 2,
Addr: addr,
HardwareAddr: hardwareAddr.String(),
},
})
p := request(net.IPv4zero, hardwareAddr)
resp := handler.ServeDHCP(p, dhcp4.Discover, p.ParseOptions())
if got, want := resp.YIAddr().To4(), addr.To4(); !bytes.Equal(got, want) {
t.Errorf("DHCPOFFER for wrong IP: got %v, want %v", got, want)
}
}