dhcp4d: implement loading leases files from persistent storage
This commit is contained in:
parent
f9c3c23b16
commit
d21822f531
@ -4,19 +4,36 @@ package main
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"router7/internal/dhcp4d"
|
"router7/internal/dhcp4d"
|
||||||
"router7/internal/notify"
|
"router7/internal/notify"
|
||||||
|
"router7/internal/teelogger"
|
||||||
|
|
||||||
"github.com/krolaw/dhcp4"
|
"github.com/krolaw/dhcp4"
|
||||||
"github.com/krolaw/dhcp4/conn"
|
"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 {
|
func logic() error {
|
||||||
if err := os.MkdirAll("/perm/dhcp4d", 0755); err != nil {
|
if err := os.MkdirAll("/perm/dhcp4d", 0755); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -26,6 +43,9 @@ func logic() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := loadLeases(handler, "/perm/dhcp4d/leases.json"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
handler.Leases = func(leases []*dhcp4d.Lease) {
|
handler.Leases = func(leases []*dhcp4d.Lease) {
|
||||||
b, err := json.Marshal(leases)
|
b, err := json.Marshal(leases)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -38,7 +58,6 @@ func logic() error {
|
|||||||
}
|
}
|
||||||
if err := notify.Process("/user/dnsd", syscall.SIGUSR1); err != nil {
|
if err := notify.Process("/user/dnsd", syscall.SIGUSR1); err != nil {
|
||||||
log.Printf("notifying dnsd: %v", err)
|
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
|
conn, err := conn.NewUDP4BoundListener("lan0", ":67") // TODO: customizeable
|
||||||
|
@ -14,11 +14,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Lease struct {
|
type Lease struct {
|
||||||
Num int
|
Num int `json:"num"` // relative to Handler.start
|
||||||
Addr net.IP
|
Addr net.IP `json:"addr"`
|
||||||
HardwareAddr string
|
HardwareAddr string `json:"hardware_addr"`
|
||||||
Hostname string
|
Hostname string `json:"hostname"`
|
||||||
Expiry time.Time
|
Expiry time.Time `json:"expiry"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
@ -36,7 +36,6 @@ type Handler struct {
|
|||||||
Leases func([]*Lease)
|
Leases func([]*Lease)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: restore leases from permanent storage
|
|
||||||
func NewHandler(dir string) (*Handler, error) {
|
func NewHandler(dir string) (*Handler, error) {
|
||||||
serverIP, err := netconfig.LinkAddress(dir, "lan0")
|
serverIP, err := netconfig.LinkAddress(dir, "lan0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -64,6 +63,18 @@ func NewHandler(dir string) (*Handler, error) {
|
|||||||
}, nil
|
}, 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 {
|
func (h *Handler) findLease() int {
|
||||||
now := h.timeNow()
|
now := h.timeNow()
|
||||||
if len(h.leasesIP) < h.leaseRange {
|
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