From d68600c5d03b73d94f380f5442c22ddc8f755d9a Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Mon, 11 Mar 2019 15:11:48 +0300 Subject: [PATCH] + dhcp: handle lease expiration --- dhcpd/dhcpd.go | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/dhcpd/dhcpd.go b/dhcpd/dhcpd.go index 57e0c513..b54195a8 100644 --- a/dhcpd/dhcpd.go +++ b/dhcpd/dhcpd.go @@ -215,14 +215,30 @@ func (s *Server) reserveLease(p dhcp4.Packet) (*Lease, error) { hwaddr := make(net.HardwareAddr, len(hwaddrCOW)) copy(hwaddr, hwaddrCOW) // not assigned a lease, create new one, find IP from LRU + hostname := p.ParseOptions()[dhcp4.OptionHostName] + lease := &Lease{HWAddr: hwaddr, Hostname: string(hostname)} + log.Tracef("Lease not found for %s: creating new one", hwaddr) ip, err := s.findFreeIP(hwaddr) if err != nil { - return nil, wrapErrPrint(err, "Couldn't find free IP for the lease %s", hwaddr.String()) + i := s.findExpiredLease() + if i < 0 { + return nil, wrapErrPrint(err, "Couldn't find free IP for the lease %s", hwaddr.String()) + } + + log.Tracef("Assigning IP address %s to %s (lease for %s expired at %s)", + s.leases[i].IP, hwaddr, s.leases[i].HWAddr, s.leases[i].Expiry) + lease.IP = s.leases[i].IP + s.Lock() + s.leases[i] = lease + s.Unlock() + + s.reserveIP(lease.IP, hwaddr) + return lease, nil } + log.Tracef("Assigning to %s IP address %s", hwaddr, ip.String()) - hostname := p.ParseOptions()[dhcp4.OptionHostName] - lease := &Lease{HWAddr: hwaddr, IP: ip, Hostname: string(hostname)} + lease.IP = ip s.Lock() s.leases = append(s.leases, lease) s.Unlock() @@ -241,6 +257,17 @@ func (s *Server) findLease(p dhcp4.Packet) *Lease { return nil } +// Find an expired lease and return its index or -1 +func (s *Server) findExpiredLease() int { + now := time.Now().Unix() + for i, lease := range s.leases { + if lease.Expiry.Unix() <= now { + return i + } + } + return -1 +} + func (s *Server) findFreeIP(hwaddr net.HardwareAddr) (net.IP, error) { // if IP pool is nil, lazy initialize it if s.IPpool == nil {