diff options
author | Pablo Mazzini <pmazzini@gmail.com> | 2022-09-10 17:13:29 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-10 17:13:29 +0100 |
commit | 662dd554284fba5ca82569386c953788aabb6572 (patch) | |
tree | 95ebc09073ce043dc8097f52cf9c2837235a292f /dhcpv4/nclient4 | |
parent | a91ce0db92a593b386863adceaf420b01f5de1a3 (diff) | |
parent | 74d7c5e9788cc201369a044b99dd0b3bb29eac53 (diff) |
Merge branch 'master' into fix_label
Diffstat (limited to 'dhcpv4/nclient4')
-rw-r--r-- | dhcpv4/nclient4/client.go | 1 | ||||
-rw-r--r-- | dhcpv4/nclient4/lease.go | 39 | ||||
-rw-r--r-- | dhcpv4/nclient4/lease_test.go | 10 |
3 files changed, 49 insertions, 1 deletions
diff --git a/dhcpv4/nclient4/client.go b/dhcpv4/nclient4/client.go index 02bd1f6..d40e1a9 100644 --- a/dhcpv4/nclient4/client.go +++ b/dhcpv4/nclient4/client.go @@ -493,6 +493,7 @@ func (e *ErrNak) Error() string { } // RequestFromOffer sends a Request message and waits for an response. +// It assumes the SELECTING state by default, see Section 4.3.2 in RFC 2131 for more details. func (c *Client) RequestFromOffer(ctx context.Context, offer *dhcpv4.DHCPv4, modifiers ...dhcpv4.Modifier) (*Lease, error) { // TODO(chrisko): should this be unicast to the server? request, err := dhcpv4.NewRequestFromOffer(offer, dhcpv4.PrependModifiers(modifiers, diff --git a/dhcpv4/nclient4/lease.go b/dhcpv4/nclient4/lease.go index 184fae2..1895dd0 100644 --- a/dhcpv4/nclient4/lease.go +++ b/dhcpv4/nclient4/lease.go @@ -3,6 +3,7 @@ package nclient4 import ( + "context" "fmt" "net" "time" @@ -36,3 +37,41 @@ func (c *Client) Release(lease *Lease, modifiers ...dhcpv4.Modifier) error { } return err } + +// Renew sends a DHCPv4 request to the server to renew the given lease. The renewal information is +// sourced from the initial offer in the lease, and the ACK of the lease is updated to the ACK of +// the latest renewal. This avoids issues with DHCP servers that omit information needed to build a +// completely new lease from their renewal ACK (such as the Windows DHCP Server). +func (c *Client) Renew(ctx context.Context, lease *Lease, modifiers ...dhcpv4.Modifier) error { + if lease == nil { + return fmt.Errorf("lease is nil") + } + + request, err := dhcpv4.NewRenewFromOffer(lease.Offer, dhcpv4.PrependModifiers(modifiers, + dhcpv4.WithOption(dhcpv4.OptMaxMessageSize(MaxMessageSize)))...) + if err != nil { + return fmt.Errorf("unable to create a request: %w", err) + } + + // Servers are supposed to only respond to Requests containing their server identifier, + // but sometimes non-compliant servers respond anyway. + // Clients are not required to validate this field, but servers are required to + // include the server identifier in their Offer per RFC 2131 Section 4.3.1 Table 3. + response, err := c.SendAndRead(ctx, c.serverAddr, request, IsAll( + IsCorrectServer(lease.Offer.ServerIdentifier()), + IsMessageType(dhcpv4.MessageTypeAck, dhcpv4.MessageTypeNak))) + if err != nil { + return fmt.Errorf("got an error while processing the request: %w", err) + } + if response.MessageType() == dhcpv4.MessageTypeNak { + return &ErrNak{ + Offer: lease.Offer, + Nak: response, + } + } + + // Update the ACK of the lease with the ACK of the latest renewal + lease.ACK = response + + return nil +} diff --git a/dhcpv4/nclient4/lease_test.go b/dhcpv4/nclient4/lease_test.go index 361847f..d27eeca 100644 --- a/dhcpv4/nclient4/lease_test.go +++ b/dhcpv4/nclient4/lease_test.go @@ -1,4 +1,4 @@ -// this tests nclient4 with lease and release +// this tests nclient4 with lease, renew and release package nclient4 @@ -236,6 +236,14 @@ func (sll *testServerLeaseList) runTest(t *testing.T) { sll.lastTestSvrErrLock.RLock() keepgoing := chkerr(err, sll.lastTestSvrErr, l.ShouldFail, t) sll.lastTestSvrErrLock.RUnlock() + + if keepgoing { + err = clnt.Renew(context.Background(), lease) + sll.lastTestSvrErrLock.RLock() + keepgoing = chkerr(err, sll.lastTestSvrErr, l.ShouldFail, t) + sll.lastTestSvrErrLock.RUnlock() + } + if keepgoing { err = clnt.Release(lease) //this sleep is to make sure release is handled by server |