From 2ef8bf6ea0ad1673f6ba7383e9dc7c5acb2a09ce Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Mon, 4 Jun 2018 08:02:28 +0200 Subject: [PATCH] dnsd/dhcp4d: listen on configured address (not hard-coded) --- cmd/dhcp4d/dhcp4d.go | 5 ++++- cmd/dnsd/dnsd.go | 10 +++++++--- internal/dhcp4d/dhcp4d.go | 19 ++++++++++++++----- internal/dhcp4d/dhcp4d_test.go | 32 +++++++++++++++++++++++++++++++- internal/netconfig/netconfig.go | 22 ++++++++++++++++++++++ 5 files changed, 78 insertions(+), 10 deletions(-) diff --git a/cmd/dhcp4d/dhcp4d.go b/cmd/dhcp4d/dhcp4d.go index 2a1388e..6936196 100644 --- a/cmd/dhcp4d/dhcp4d.go +++ b/cmd/dhcp4d/dhcp4d.go @@ -22,7 +22,10 @@ func logic() error { return err } errs := make(chan error) - handler := dhcp4d.NewHandler() + handler, err := dhcp4d.NewHandler("/perm") + if err != nil { + return err + } handler.Leases = func(leases []*dhcp4d.Lease) { b, err := json.Marshal(leases) if err != nil { diff --git a/cmd/dnsd/dnsd.go b/cmd/dnsd/dnsd.go index 82a44fe..ce0a50a 100644 --- a/cmd/dnsd/dnsd.go +++ b/cmd/dnsd/dnsd.go @@ -12,12 +12,16 @@ import ( "router7/internal/dhcp4d" "router7/internal/dns" + "router7/internal/netconfig" ) func logic() error { - // TODO: serve on correct IP address // TODO: set correct upstream DNS resolver(s) - srv := dns.NewServer("192.168.42.1:53", "lan") + ip, err := netconfig.LinkAddress("/perm", "lan0") + if err != nil { + return err + } + srv := dns.NewServer(ip.String()+":53", "lan") readLeases := func() error { b, err := ioutil.ReadFile("/perm/dhcp4d/leases.json") if err != nil { @@ -31,7 +35,7 @@ func logic() error { return nil } if err := readLeases(); err != nil { - log.Printf("readLeases: %v", err) + log.Printf("cannot resolve DHCP hostnames: %v", err) } ch := make(chan os.Signal, 1) signal.Notify(ch, syscall.SIGUSR1) diff --git a/internal/dhcp4d/dhcp4d.go b/internal/dhcp4d/dhcp4d.go index 6cc4199..0fb8fe9 100644 --- a/internal/dhcp4d/dhcp4d.go +++ b/internal/dhcp4d/dhcp4d.go @@ -7,6 +7,8 @@ import ( "net" "time" + "router7/internal/netconfig" + "github.com/krolaw/dhcp4" ) @@ -31,14 +33,21 @@ type Handler struct { } // TODO: restore leases from permanent storage -func NewHandler() *Handler { - serverIP := net.IP{192, 168, 42, 1} // TODO: customizeable +func NewHandler(dir string) (*Handler, error) { + serverIP, err := netconfig.LinkAddress(dir, "lan0") + if err != nil { + return nil, err + } + serverIP = serverIP.To4() + start := make(net.IP, len(serverIP)) + copy(start, serverIP) + start[len(start)-1] += 1 return &Handler{ leasesHW: make(map[string]*Lease), leasesIP: make(map[int]*Lease), serverIP: serverIP, - start: net.IP{192, 168, 42, 2}, - leaseRange: 50, + start: start, + leaseRange: 200, leasePeriod: 2 * time.Hour, options: dhcp4.Options{ dhcp4.OptionSubnetMask: []byte{255, 255, 255, 0}, @@ -47,7 +56,7 @@ func NewHandler() *Handler { dhcp4.OptionDomainName: []byte("lan"), dhcp4.OptionDomainSearch: []byte{0x03, 'l', 'a', 'n', 0x00}, }, - } + }, nil } func (h *Handler) findLease() int { diff --git a/internal/dhcp4d/dhcp4d_test.go b/internal/dhcp4d/dhcp4d_test.go index bfc935f..3e42a1f 100644 --- a/internal/dhcp4d/dhcp4d_test.go +++ b/internal/dhcp4d/dhcp4d_test.go @@ -2,19 +2,49 @@ package dhcp4d import ( "bytes" + "io/ioutil" "net" + "os" + "path/filepath" "testing" "github.com/krolaw/dhcp4" ) +const goldenInterfaces = ` +{ + "interfaces":[ + { + "hardware_addr": "02:73:53:00:ca:fe", + "name": "uplink0" + }, + { + "hardware_addr": "02:73:53:00:b0:0c", + "name": "lan0", + "addr": "192.168.42.1/24" + } + ] +} +` + func TestLease(t *testing.T) { + tmpdir, err := ioutil.TempDir("", "dhcp4dtest") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpdir) + if err := ioutil.WriteFile(filepath.Join(tmpdir, "interfaces.json"), []byte(goldenInterfaces), 0644); err != nil { + t.Fatal(err) + } var ( addr = net.IP{192, 168, 42, 23} hardwareAddr = net.HardwareAddr{0x11, 0x22, 0x33, 0x44, 0x55, 0x66} hostname = "xps" ) - handler := NewHandler() + handler, err := NewHandler(tmpdir) + if err != nil { + t.Fatal(err) + } leasedCalled := false handler.Leases = func(leases []*Lease) { if got, want := len(leases), 1; got != want { diff --git a/internal/netconfig/netconfig.go b/internal/netconfig/netconfig.go index f6c0109..9fc32c3 100644 --- a/internal/netconfig/netconfig.go +++ b/internal/netconfig/netconfig.go @@ -156,6 +156,28 @@ type InterfaceConfig struct { Interfaces []InterfaceDetails `json:"interfaces"` } +// LinkAddress returns the IP address configured for the interface ifname in +// interfaces.json. +func LinkAddress(dir, ifname string) (net.IP, error) { + fn := filepath.Join(dir, "interfaces.json") + b, err := ioutil.ReadFile(fn) + if err != nil { + return nil, err + } + var cfg InterfaceConfig + if err := json.Unmarshal(b, &cfg); err != nil { + return nil, err + } + for _, details := range cfg.Interfaces { + if details.Name != ifname { + continue + } + ip, _, err := net.ParseCIDR(details.Addr) + return ip, err + } + return nil, fmt.Errorf("%s does not configure interface %q", fn, ifname) +} + func applyInterfaces(dir, root string) error { b, err := ioutil.ReadFile(filepath.Join(dir, "interfaces.json")) if err != nil {