internal/dhcp4d: handle DHCPDECLINE and fix bug regarding MacBook declining leases (#48)

Fixes #40

Signed-off-by: Matt Layher <mdlayher@gmail.com>
This commit is contained in:
Matt Layher 2020-05-23 14:53:13 -04:00 committed by GitHub
parent fe68c2dd52
commit 7aeb51e9ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 86 additions and 0 deletions

View File

@ -353,6 +353,35 @@ func (h *Handler) serveDHCP(p dhcp4.Packet, msgType dhcp4.MessageType, options d
reqIP,
h.leasePeriodForDevice(hwAddr),
h.options.SelectOrderOrAll(options[dhcp4.OptionParameterRequestList]))
case dhcp4.Decline:
if h.expireLease(hwAddr) {
log.Printf("Expired leases for %v upon DHCPDECLINE", hwAddr)
}
// Decline does not expect an ACK response.
return nil
}
return nil
}
// expireLease expires the lease for hwAddr and reports whether or not the
// lease was actually expired by this call.
func (h *Handler) expireLease(hwAddr string) bool {
h.leasesMu.Lock()
defer h.leasesMu.Unlock()
// TODO: deduplicate with h.leaseHW which also acquires h.leasesMu.
num, ok := h.leasesHW[hwAddr]
if !ok {
return false
}
l, ok := h.leasesIP[num]
if !ok {
return false
}
if l.HardwareAddr != hwAddr {
return false
}
l.Expiry = time.Now()
return true
}

View File

@ -50,6 +50,10 @@ func discover(addr net.IP, hwaddr net.HardwareAddr, opts ...dhcp4.Option) dhcp4.
return packet(dhcp4.Discover, addr, hwaddr, opts)
}
func decline(addr net.IP, hwaddr net.HardwareAddr, opts ...dhcp4.Option) dhcp4.Packet {
return packet(dhcp4.Decline, addr, hwaddr, opts)
}
const goldenInterfaces = `
{
"interfaces":[
@ -500,3 +504,56 @@ func TestMinimumLeaseTime(t *testing.T) {
}
}
}
func TestClientDecline(t *testing.T) {
handler, cleanup := testHandler(t)
defer cleanup()
now := time.Now()
handler.timeNow = func() time.Time { return now }
addr := net.IP{192, 168, 42, 23}
hardwareAddr := net.HardwareAddr{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}
// macbook requests a new lease
t.Run("mbp grabs an address", func(t *testing.T) {
p := request(addr, hardwareAddr)
resp := handler.serveDHCP(p, dhcp4.Request, p.ParseOptions())
if got, want := messageType(resp), dhcp4.ACK; got != want {
t.Errorf("DHCPREQUEST resulted in unexpected message type: got %v, want %v", got, want)
}
})
// macbook lease expires
now = now.Add(3 * time.Hour)
t.Run("mbp requests previous address", func(t *testing.T) {
p := request(addr, hardwareAddr)
resp := handler.serveDHCP(p, dhcp4.Discover, p.ParseOptions())
if got, want := resp.YIAddr().To4(), addr.To4(); !got.Equal(want) {
t.Errorf("DHCPOFFER for wrong IP: got %v, want %v", got, want)
}
p = request(addr, hardwareAddr)
resp = handler.serveDHCP(p, dhcp4.Request, p.ParseOptions())
if got, want := messageType(resp), dhcp4.ACK; got != want {
t.Errorf("DHCPREQUEST resulted in unexpected message type: got %v, want %v", got, want)
}
})
t.Run("mbp declines address", func(t *testing.T) {
p := decline(addr, hardwareAddr)
resp := handler.serveDHCP(p, dhcp4.Decline, p.ParseOptions())
if resp != nil {
t.Fatalf("DHCPDECLINE was unexpectedly answered: %v", messageType(resp))
}
})
t.Run("mbp requests any address", func(t *testing.T) {
p := request(net.IPv4zero, hardwareAddr)
resp := handler.serveDHCP(p, dhcp4.Discover, p.ParseOptions())
if got, want := resp.YIAddr().To4(), addr.To4(); got.Equal(want) {
t.Errorf("DHCPOFFER returned unexpected address: %v", got)
}
})
}