From f66fbc0f6c1000177c1aa8f4df79b64c1c5e03b6 Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Tue, 9 May 2023 07:28:54 +0000 Subject: [PATCH] dhcp reads done, moving on to offers --- cmd/kdhcpd/BUILD.bazel | 2 +- cmd/kdhcpd/main.go | 2 +- config/BUILD.bazel | 2 +- config/config.go | 2 +- config/path.go | 2 +- deps.bzl | 49 +++++++++++++++++++++++--- dhcp/BUILD.bazel | 2 +- dhcp/options.go | 4 +++ dhcp/packet.go | 3 +- dhcp/read_options.go | 80 +++++++++++++++++++++++++++++++++--------- go.mod | 10 ++++-- go.sum | 10 ++++-- iptools/BUILD.bazel | 5 ++- iptools/lease_info.go | 4 +++ iptools/pool.go | 29 ++++++++------- kdhcpd.yaml | 2 +- server/BUILD.bazel | 3 +- server/lease_state.go | 2 +- server/pools.go | 14 +++++++- server/server.go | 27 ++++++++++---- 20 files changed, 196 insertions(+), 58 deletions(-) diff --git a/cmd/kdhcpd/BUILD.bazel b/cmd/kdhcpd/BUILD.bazel index 73957f8..d0e0c68 100644 --- a/cmd/kdhcpd/BUILD.bazel +++ b/cmd/kdhcpd/BUILD.bazel @@ -9,7 +9,7 @@ go_library( "//config", "//server", "@com_github_peterbourgon_ff_v3//ffcli", - "@dev_wntrmute_git_kyle_goutils//syslog", + "@dev_wntrmute_git_kyle_goutils//log", ], ) diff --git a/cmd/kdhcpd/main.go b/cmd/kdhcpd/main.go index 91014e4..d8acf8f 100644 --- a/cmd/kdhcpd/main.go +++ b/cmd/kdhcpd/main.go @@ -6,7 +6,7 @@ import ( "os" "strings" - log "git.wntrmute.dev/kyle/goutils/syslog" + "git.wntrmute.dev/kyle/goutils/log" "git.wntrmute.dev/kyle/kdhcp/config" "git.wntrmute.dev/kyle/kdhcp/server" "github.com/peterbourgon/ff/v3/ffcli" diff --git a/config/BUILD.bazel b/config/BUILD.bazel index 32df335..c5a66e8 100644 --- a/config/BUILD.bazel +++ b/config/BUILD.bazel @@ -10,7 +10,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//iptools", - "@dev_wntrmute_git_kyle_goutils//syslog", + "@dev_wntrmute_git_kyle_goutils//log", "@in_gopkg_yaml_v2//:yaml_v2", ], ) diff --git a/config/config.go b/config/config.go index 2a3cb1b..d79d132 100644 --- a/config/config.go +++ b/config/config.go @@ -6,7 +6,7 @@ import ( "io/ioutil" "net" - log "git.wntrmute.dev/kyle/goutils/syslog" + log "git.wntrmute.dev/kyle/goutils/log" "git.wntrmute.dev/kyle/kdhcp/iptools" "gopkg.in/yaml.v2" ) diff --git a/config/path.go b/config/path.go index de75701..69139de 100644 --- a/config/path.go +++ b/config/path.go @@ -5,7 +5,7 @@ import ( "os/user" "path/filepath" - log "git.wntrmute.dev/kyle/goutils/syslog" + log "git.wntrmute.dev/kyle/goutils/log" ) func FindConfigPath() string { diff --git a/deps.bzl b/deps.bzl index 01652ac..19959cc 100644 --- a/deps.bzl +++ b/deps.bzl @@ -1,6 +1,13 @@ load("@bazel_gazelle//:deps.bzl", "go_repository") def go_dependencies(): + go_repository( + name = "com_github_benbjohnson_clock", + importpath = "github.com/benbjohnson/clock", + sum = "h1:g+rSsSaAzhHJYcIQE78hJ3AhyjjtQvleKDjlhdBnIhc=", + version = "v1.3.3", + ) + go_repository( name = "com_github_cloudflare_cfssl", importpath = "github.com/cloudflare/cfssl", @@ -14,12 +21,32 @@ def go_dependencies(): sum = "h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=", version = "v1.1.1", ) + go_repository( + name = "com_github_google_certificate_transparency_go", + importpath = "github.com/google/certificate-transparency-go", + sum = "h1:Yf1aXowfZ2nuboBsg7iYGLmwsOARdV86pfH3g95wXmE=", + version = "v1.0.21", + ) + go_repository( name = "com_github_hashicorp_go_syslog", importpath = "github.com/hashicorp/go-syslog", sum = "h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE=", version = "v1.0.0", ) + go_repository( + name = "com_github_kr_fs", + importpath = "github.com/kr/fs", + sum = "h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=", + version = "v0.1.0", + ) + go_repository( + name = "com_github_kr_pretty", + importpath = "github.com/kr/pretty", + sum = "h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=", + version = "v0.1.0", + ) + go_repository( name = "com_github_kr_text", importpath = "github.com/kr/text", @@ -51,6 +78,13 @@ def go_dependencies(): sum = "h1:/f3b24xrDhkhddlaobPe2JgBqfdt+gC/NYl0QY9IOuI=", version = "v1.12.0", ) + go_repository( + name = "com_github_pmezard_go_difflib", + importpath = "github.com/pmezard/go-difflib", + sum = "h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=", + version = "v1.0.0", + ) + go_repository( name = "com_github_stretchr_testify", importpath = "github.com/stretchr/testify", @@ -60,15 +94,15 @@ def go_dependencies(): go_repository( name = "dev_wntrmute_git_kyle_goutils", importpath = "git.wntrmute.dev/kyle/goutils", - sum = "h1:CRCBlmSXOTkShbqC6j9lgxh4lb+khzc2zpIJYGQJtnc=", - version = "v1.6.6", + sum = "h1:+lk6uUMcpJK49sEGEMCOns3WVd2ThH/htMWnsyXEGl8=", + version = "v1.7.0", ) go_repository( name = "in_gopkg_check_v1", importpath = "gopkg.in/check.v1", - sum = "h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=", - version = "v0.0.0-20161208181325-20d25e280405", + sum = "h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=", + version = "v1.0.0-20180628173108-788fd7840127", ) go_repository( name = "in_gopkg_yaml_v2", @@ -76,6 +110,13 @@ def go_dependencies(): sum = "h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=", version = "v2.4.0", ) + go_repository( + name = "in_gopkg_yaml_v3", + importpath = "gopkg.in/yaml.v3", + sum = "h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=", + version = "v3.0.0-20200313102051-9f266ea9e77c", + ) + go_repository( name = "org_golang_x_crypto", importpath = "golang.org/x/crypto", diff --git a/dhcp/BUILD.bazel b/dhcp/BUILD.bazel index 0672ead..bd1c59c 100644 --- a/dhcp/BUILD.bazel +++ b/dhcp/BUILD.bazel @@ -9,5 +9,5 @@ go_library( ], importpath = "git.wntrmute.dev/kyle/kdhcp/dhcp", visibility = ["//visibility:public"], - deps = ["@dev_wntrmute_git_kyle_goutils//syslog"], + deps = ["@dev_wntrmute_git_kyle_goutils//log"], ) diff --git a/dhcp/options.go b/dhcp/options.go index 59f0b36..67b3221 100644 --- a/dhcp/options.go +++ b/dhcp/options.go @@ -33,6 +33,8 @@ const ( OptionTagNBScope OptionTag = 47 OptionTagMessageType OptionTag = 53 OptionTagParameterRequestList OptionTag = 55 + OptionTagDHCPMaxMessageSize OptionTag = 57 + OptionTagClientID OptionTag = 61 OptionTagDomainSearch OptionTag = 119 OptionTagClasslessStaticRoute OptionTag = 121 OptionTagEnd OptionTag = 255 @@ -53,6 +55,8 @@ var optionStrings = map[OptionTag]string{ OptionTagNBScope: "NetBIOS scope", OptionTagMessageType: "message type", OptionTagParameterRequestList: "parameter request list", + OptionTagDHCPMaxMessageSize: "DHCP max message size", + OptionTagClientID: "client ID", OptionTagDomainSearch: "search domain", OptionTagClasslessStaticRoute: "classless static route", OptionTagEnd: "end", diff --git a/dhcp/packet.go b/dhcp/packet.go index 182dfbb..fbb8c45 100644 --- a/dhcp/packet.go +++ b/dhcp/packet.go @@ -8,7 +8,7 @@ import ( "net" "strings" - log "git.wntrmute.dev/kyle/goutils/syslog" + log "git.wntrmute.dev/kyle/goutils/log" ) const ( @@ -46,6 +46,7 @@ type BootRequest struct { DHCPType DHCPMessageType // option 53 HostName string // option 12 + ClientID string // option 61 ParameterRequests []OptionTag endOptions bool } diff --git a/dhcp/read_options.go b/dhcp/read_options.go index 7f7e3cc..44fd552 100644 --- a/dhcp/read_options.go +++ b/dhcp/read_options.go @@ -6,7 +6,7 @@ import ( "fmt" "io" - log "git.wntrmute.dev/kyle/goutils/syslog" + log "git.wntrmute.dev/kyle/goutils/log" ) var optionRegistry = map[OptionTag]Option{ @@ -14,6 +14,7 @@ var optionRegistry = map[OptionTag]Option{ OptionTagHostName: OptionHostName, OptionTagMessageType: OptionMessageType, OptionTagParameterRequestList: OptionParameterRequestList, + OptionTagClientID: OptionClientID, OptionTagEnd: OptionEnd, } @@ -22,6 +23,19 @@ func OptionPad(req *BootRequest, r io.Reader) error { return nil } +func getOptionLength(r io.Reader) (int, error) { + var length uint8 + read := newPacketReaderFunc(r) + + if err := read(&length); err != nil { + return -1, fmt.Errorf("dhcp: reading option length for DHCP Message Type") + } else if length == 0 { + return -1, errors.New("dhcp: read option length 0, but expected option length for DHCP Host Name is >= 1") + } + + return int(length), nil +} + // OptionHostName reads a DHCP host name option. // // 3.14. Host Name Option @@ -33,13 +47,9 @@ func OptionPad(req *BootRequest, r io.Reader) error { // The code for this option is 12, and its minimum length is 1. func OptionHostName(req *BootRequest, r io.Reader) error { - read := newPacketReaderFunc(r) - - var length uint8 - if err := read(&length); err != nil { - return fmt.Errorf("dhcp: reading option length for DHCP Message Type") - } else if length == 0 { - return errors.New("dhcp: read option length 0, but expected option length for DHCP Host Name is >= 1") + length, err := getOptionLength(r) + if err != nil { + return err } hostName := make([]byte, int(length)) @@ -56,9 +66,8 @@ func OptionHostName(req *BootRequest, r io.Reader) error { func OptionMessageType(req *BootRequest, r io.Reader) error { read := newPacketReaderFunc(r) - var length uint8 - if err := read(&length); err != nil { - return fmt.Errorf("dhcp: reading option length for DHCP Message Type") + if length, err := getOptionLength(r); err != nil { + return err } else if length != 1 { return fmt.Errorf("dhcp: read option length %d, but expected option length for DHCP Message Type is 1", length) } @@ -71,11 +80,9 @@ func OptionMessageType(req *BootRequest, r io.Reader) error { } func OptionParameterRequestList(req *BootRequest, r io.Reader) error { - read := newPacketReaderFunc(r) - - var length uint8 - if err := read(&length); err != nil { - return fmt.Errorf("dhcp: reading option length for DHCP Message Type") + length, err := getOptionLength(r) + if err != nil { + return err } else if length == 0 { return fmt.Errorf("dhcp: read option length %d, but expected option length for DHCP Parameter Request is >= 1", length) } @@ -96,6 +103,25 @@ func OptionParameterRequestList(req *BootRequest, r io.Reader) error { return nil } +func OptionClientID(req *BootRequest, r io.Reader) error { + length, err := getOptionLength(r) + if err != nil { + return err + } else if length == 0 { + return fmt.Errorf("dhcp: read option length %d, but expected option length for DHCP Parameter Request is >= 1", length) + } + + var clientID = make([]byte, int(length)) + if n, err := r.Read(clientID); err != nil { + return fmt.Errorf("dhcp: while reading client ID: %w", err) + } else if n != int(length) { + return fmt.Errorf("dhcp: only read %d bytes of client ID, expected %d bytes", n, length) + } + + req.ClientID = string(clientID) + return nil +} + func OptionEnd(req *BootRequest, r io.Reader) error { req.endOptions = true return nil @@ -108,7 +134,27 @@ func ReadOption(req *BootRequest, tag byte, r io.Reader) error { return f(req, r) } - return fmt.Errorf("dhcp: unknown/unhandled option %d", opt) + return readUnknownOption(req, tag, r) +} + +func readUnknownOption(req *BootRequest, tag byte, r io.Reader) error { + length, err := getOptionLength(r) + if err != nil { + return err + } else if length == 0 { + log.Debugf("skipped option %d/%02x with length 0", tag, tag) + return nil + } + + var data = make([]byte, length) + if n, err := r.Read(data); err != nil { + return fmt.Errorf("dhcp: while skipping unknown tag %d/%02x: %w", tag, tag, err) + } else if n != int(length) { + return fmt.Errorf("dhcp: only read %d bytes of unknown tag %d/%02x, expected %d bytes", n, tag, tag, length) + } + + log.Infof("skipped unknown tag %d/%02x with data %0x", tag, tag, data) + return nil } const magicCookieLength = 4 diff --git a/go.mod b/go.mod index 079ef78..1a3b7bc 100644 --- a/go.mod +++ b/go.mod @@ -2,12 +2,16 @@ module git.wntrmute.dev/kyle/kdhcp go 1.20 -require github.com/hashicorp/go-syslog v1.0.0 +require github.com/hashicorp/go-syslog v1.0.0 // indirect require ( - github.com/davecgh/go-spew v1.1.1 github.com/peterbourgon/ff/v3 v3.3.0 gopkg.in/yaml.v2 v2.4.0 ) -require git.wntrmute.dev/kyle/goutils v1.6.6 // indirect +require github.com/davecgh/go-spew v1.1.1 // indirect + +require ( + git.wntrmute.dev/kyle/goutils v1.7.0 + github.com/benbjohnson/clock v1.3.3 +) diff --git a/go.sum b/go.sum index 178e58e..cd26237 100644 --- a/go.sum +++ b/go.sum @@ -1,12 +1,16 @@ -git.wntrmute.dev/kyle/goutils v1.6.6 h1:CRCBlmSXOTkShbqC6j9lgxh4lb+khzc2zpIJYGQJtnc= -git.wntrmute.dev/kyle/goutils v1.6.6/go.mod h1:p0m2YprqMXkqtxTPKCiRcmgYo/D/9DtAIRfNVFE3JBg= +git.wntrmute.dev/kyle/goutils v1.7.0 h1:+lk6uUMcpJK49sEGEMCOns3WVd2ThH/htMWnsyXEGl8= +git.wntrmute.dev/kyle/goutils v1.7.0/go.mod h1:hMcPr+XSYXjQ/IRTziNVYmUmb9BPATZc+cyehSjBs0w= +github.com/benbjohnson/clock v1.3.3 h1:g+rSsSaAzhHJYcIQE78hJ3AhyjjtQvleKDjlhdBnIhc= +github.com/benbjohnson/clock v1.3.3/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/peterbourgon/ff/v3 v3.3.0 h1:PaKe7GW8orVFh8Unb5jNHS+JZBwWUMa2se0HM6/BI24= github.com/peterbourgon/ff/v3 v3.3.0/go.mod h1:zjJVUhx+twciwfDl0zBcFzl4dW8axCRyXE/eKY9RztQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/iptools/BUILD.bazel b/iptools/BUILD.bazel index 65f3799..2640e04 100644 --- a/iptools/BUILD.bazel +++ b/iptools/BUILD.bazel @@ -11,7 +11,10 @@ go_library( ], importpath = "git.wntrmute.dev/kyle/kdhcp/iptools", visibility = ["//visibility:public"], - deps = ["@dev_wntrmute_git_kyle_goutils//assert"], + deps = [ + "@dev_wntrmute_git_kyle_goutils//assert", + "@dev_wntrmute_git_kyle_goutils//log", + ], ) go_test( diff --git a/iptools/lease_info.go b/iptools/lease_info.go index a0c941c..ca97a9c 100644 --- a/iptools/lease_info.go +++ b/iptools/lease_info.go @@ -15,6 +15,10 @@ type LeaseInfo struct { Expires time.Time `yaml:"expires"` } +func (li *LeaseInfo) String() string { + return fmt.Sprintf("lease[hostname=%s addr=%s hw=%x expires=%s]", li.HostName, li.Addr, li.HardwareAddress, li.Expires) +} + type sortableLease []*LeaseInfo func (a sortableLease) Len() int { return len(a) } diff --git a/iptools/pool.go b/iptools/pool.go index 94b2f99..f247ea3 100644 --- a/iptools/pool.go +++ b/iptools/pool.go @@ -7,6 +7,7 @@ import ( "time" "git.wntrmute.dev/kyle/goutils/assert" + "git.wntrmute.dev/kyle/goutils/log" ) const DefaultExpiry = 168 * time.Hour @@ -23,7 +24,7 @@ type Pool struct { } func (p *Pool) lock() { - if p.lock == nil { + if p.mtx == nil { p.mtx = &sync.Mutex{} } @@ -48,6 +49,7 @@ func NewPool(name string, r *Range) (*Pool, error) { Expiry: r.Expiry, NoHostName: r.NoHostName, Available: enumerateRange(name, r, true), + Limbo: map[netip.Addr]*LeaseInfo{}, } return p, nil @@ -114,39 +116,40 @@ func (p *Pool) Accept(addr netip.Addr, t time.Time) error { // Update checks expirations on leases, moving any expired leases back // to the available pool and removing any limbo leases that are expired. -func (p *Pool) Update(t time.Time) { +func (p *Pool) Update(t time.Time) bool { p.lock() defer p.unlock() - p.update(t) + return p.update(t) } -func (p *Pool) update(t time.Time) { - evictedHosts := []netip.Addr{} +func (p *Pool) update(t time.Time) bool { + var updated bool for k, v := range p.Active { if v.IsExpired(t) { - evictedHosts = append(evictedHosts, k) + updated = true + log.Infof("expiring active address %s for %x", v.Addr, v.HardwareAddress) + delete(p.Active, k) v = v.Reset() p.Available = append(p.Available, v) } } - for _, ip := range evictedHosts { - delete(p.Active, ip) - } - for k, v := range p.Limbo { if v.IsExpired(t) { + updated = true + log.Infof("expiring limbo address %s for %x", v.Addr, v.HardwareAddress) delete(p.Limbo, k) v = v.Reset() p.Available = append(p.Available, v) } } - p.Sort() + p.sort() + return updated } -func (p *Pool) Renew(lease LeaseInfo, t time.Time) { - +func (p *Pool) Renew(lease *LeaseInfo, t time.Time) { + p.Active[lease.Addr].ResetExpiry(t, p.Expiry) } diff --git a/kdhcpd.yaml b/kdhcpd.yaml index f04ceb8..857294e 100644 --- a/kdhcpd.yaml +++ b/kdhcpd.yaml @@ -26,4 +26,4 @@ kdhcp: statics: controller: 192.168.4.254 haven: 192.168.4.253 - build01: 192.168.4.252 + build01: 192.168.4.252 diff --git a/server/BUILD.bazel b/server/BUILD.bazel index 65af305..0df45d9 100644 --- a/server/BUILD.bazel +++ b/server/BUILD.bazel @@ -15,7 +15,8 @@ go_library( "//config", "//dhcp", "//iptools", - "@dev_wntrmute_git_kyle_goutils//syslog", + "@com_github_benbjohnson_clock//:clock", + "@dev_wntrmute_git_kyle_goutils//log", "@in_gopkg_yaml_v2//:yaml_v2", ], ) diff --git a/server/lease_state.go b/server/lease_state.go index 501912b..e3339da 100644 --- a/server/lease_state.go +++ b/server/lease_state.go @@ -4,7 +4,7 @@ import ( "fmt" "os" - log "git.wntrmute.dev/kyle/goutils/syslog" + log "git.wntrmute.dev/kyle/goutils/log" "git.wntrmute.dev/kyle/kdhcp/iptools" "gopkg.in/yaml.v2" ) diff --git a/server/pools.go b/server/pools.go index 814adfa..ed4226d 100644 --- a/server/pools.go +++ b/server/pools.go @@ -3,8 +3,9 @@ package server import ( "fmt" "net/netip" + "time" - log "git.wntrmute.dev/kyle/goutils/syslog" + log "git.wntrmute.dev/kyle/goutils/log" "git.wntrmute.dev/kyle/kdhcp/iptools" ) @@ -35,3 +36,14 @@ func (srv *Server) loadPoolsFromConfig() error { return nil } + +func (srv *Server) updatePoolLoop() { + for { + time.Sleep(time.Minute) + for _, p := range srv.Pools { + if p.Update(srv.clock.Now()) { + log.Debugln("pools updated") + } + } + } +} diff --git a/server/server.go b/server/server.go index 831a251..dc5e3b3 100644 --- a/server/server.go +++ b/server/server.go @@ -5,10 +5,11 @@ import ( "net" "time" - log "git.wntrmute.dev/kyle/goutils/syslog" + log "git.wntrmute.dev/kyle/goutils/log" "git.wntrmute.dev/kyle/kdhcp/config" "git.wntrmute.dev/kyle/kdhcp/dhcp" "git.wntrmute.dev/kyle/kdhcp/iptools" + "github.com/benbjohnson/clock" ) const ( @@ -22,6 +23,8 @@ type Server struct { Config *config.Config Pools map[string]*iptools.Pool Static map[string]*iptools.LeaseInfo + + clock clock.Clock } func (s *Server) Close() error { @@ -62,23 +65,34 @@ func (s *Server) WriteTo(b []byte, addr net.Addr) error { return errors.New("server: not implemented") } -func (s *Server) AcceptPacket() error { +func (s *Server) AcceptPacket() (*dhcp.BootRequest, error) { request, err := s.ReadDHCPRequest() if err != nil { - return err + return nil, err } log.Debugf("BOOTP request received from %x", request.HardwareAddress) - return nil + return request, nil } func (s *Server) Listen() { + go s.updatePoolLoop() + for { - if err := s.AcceptPacket(); err != nil { + req, err := s.AcceptPacket() + if err != nil { log.Errf("server: error reading packet: %s", err) continue } - break + + lease := s.SelectLease(req, s.clock.Now()) + if err != nil { + log.Err("server: couldn't find available lease") + continue + } + + log.Infof("available lease: %s", lease) + continue } } @@ -87,6 +101,7 @@ func New(cfg *config.Config) (*Server, error) { Config: cfg, Pools: map[string]*iptools.Pool{}, Static: map[string]*iptools.LeaseInfo{}, + clock: clock.New(), } if err := srv.loadPoolsFromConfig(); err != nil {