dhcp4d: implement loading leases files from persistent storage
This commit is contained in:
parent
f9c3c23b16
commit
d21822f531
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user