Skip to content

Commit

Permalink
dhcpd: imp code, names
Browse files Browse the repository at this point in the history
  • Loading branch information
EugeneOne1 committed Aug 30, 2022
1 parent a09540b commit f076cf8
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 77 deletions.
135 changes: 68 additions & 67 deletions internal/dhcpd/v4.go
Original file line number Diff line number Diff line change
Expand Up @@ -542,14 +542,32 @@ func (s *v4Server) reserveLease(mac net.HardwareAddr) (l *Lease, err error) {
return l, nil
}

// commitLease refreshes l's values. A non-empty prevName will be removed from
// the known hostnames registry.
func (s *v4Server) commitLease(l *Lease, prevName string) {
// commitLease refreshes l's values. It takes the desired hostname into account
// when setting it into the lease, but generates a unique one if the provided
// can't be used.
func (s *v4Server) commitLease(l *Lease, hostname string) {
prev := l.Hostname
hostname = s.validHostnameForClient(hostname, l.IP)

if s.leaseHosts.Has(hostname) {
log.Info("dhcpv4: hostname %q already exists", hostname)

if prev == "" {
// The lease is just allocated due to DHCPDISCOVER.
hostname = aghnet.GenerateHostname(l.IP)
} else {
hostname = prev
}
}
if l.Hostname != hostname {
l.Hostname = hostname
}

s.conf.notify(LeaseChangedDBStore)

l.Expiry = time.Now().Add(s.conf.leaseTime)
if prevName != "" && prevName != l.Hostname {
s.leaseHosts.Del(prevName)
if prev != "" && prev != l.Hostname {
s.leaseHosts.Del(prev)
}
if l.Hostname != "" {
s.leaseHosts.Add(l.Hostname)
Expand Down Expand Up @@ -577,8 +595,8 @@ func (s *v4Server) allocateLease(mac net.HardwareAddr) (l *Lease, err error) {
}
}

// processDiscover is the handler for the DHCP Discover request.
func (s *v4Server) processDiscover(req, resp *dhcpv4.DHCPv4) (l *Lease, err error) {
// handleDiscover is the handler for the DHCP Discover request.
func (s *v4Server) handleDiscover(req, resp *dhcpv4.DHCPv4) (l *Lease, err error) {
mac := req.ClientHWAddr

defer s.conf.notify(LeaseChangedDBStore)
Expand Down Expand Up @@ -660,32 +678,8 @@ func (s *v4Server) checkLease(mac net.HardwareAddr, ip net.IP) (lease *Lease, mi
return nil, false
}

// setHostname sets the unique hostname, either requested or generated, to the
// lease and to the DHCP response if the one is requested. It returns the
// previous value of the lease's hostname.
func (s *v4Server) setHostname(lease *Lease, hostname string) (prev string) {
prev = lease.Hostname
hostname = s.validHostnameForClient(hostname, lease.IP)

if s.leaseHosts.Has(hostname) {
log.Info("dhcpv4: hostname %q already exists", hostname)

if prev == "" {
// The lease is just allocated due to DHCPDISCOVER.
hostname = aghnet.GenerateHostname(lease.IP)
} else {
hostname = prev
}
}
if lease.Hostname != hostname {
lease.Hostname = hostname
}

return prev
}

// processSelecting handles the DHCPREQUEST generated during SELECTING state.
func (s *v4Server) processSelecting(
// handleSelecting handles the DHCPREQUEST generated during SELECTING state.
func (s *v4Server) handleSelecting(
req *dhcpv4.DHCPv4,
reqIP net.IP,
sid net.IP,
Expand All @@ -703,7 +697,7 @@ func (s *v4Server) processSelecting(
return nil, false
}

// 'requested IP address' MUST be filled in with the yiaddr value from the
// Requested IP address MUST be filled in with the yiaddr value from the
// chosen DHCPOFFER.
if ip4 := reqIP.To4(); ip4 == nil {
log.Debug("dhcpv4: bad requested address in req msg for %s: %s", mac, reqIP)
Expand All @@ -721,8 +715,8 @@ func (s *v4Server) processSelecting(
return l, true
}

// processInitReboot handles the DHCPREQUEST generated during INIT-REBOOT state.
func (s *v4Server) processInitReboot(req *dhcpv4.DHCPv4, reqIP net.IP) (l *Lease, needsReply bool) {
// handleInitReboot handles the DHCPREQUEST generated during INIT-REBOOT state.
func (s *v4Server) handleInitReboot(req *dhcpv4.DHCPv4, reqIP net.IP) (l *Lease, needsReply bool) {
mac := req.ClientHWAddr

if ip4 := reqIP.To4(); ip4 == nil {
Expand Down Expand Up @@ -761,15 +755,15 @@ func (s *v4Server) processInitReboot(req *dhcpv4.DHCPv4, reqIP net.IP) (l *Lease
return l, true
}

// processRenew handles the DHCPREQUEST generated during RENEWING or REBINDING
// handleRenew handles the DHCPREQUEST generated during RENEWING or REBINDING
// state.
func (s *v4Server) processRenew(req *dhcpv4.DHCPv4) (l *Lease, needsReply bool) {
func (s *v4Server) handleRenew(req *dhcpv4.DHCPv4) (l *Lease, needsReply bool) {
mac := req.ClientHWAddr

// ciaddr MUST be filled in with client's IP address.
ciaddr := req.ClientIPAddr
if ciaddr == nil || ciaddr.IsUnspecified() || ciaddr.To4() == nil {
log.Debug("dhcpv4: bad ciaddr in renew req msg for %s", mac)
log.Debug("dhcpv4: bad ciaddr in renew req msg for %s: %s", mac, ciaddr)

return nil, false
}
Expand All @@ -788,26 +782,34 @@ func (s *v4Server) processRenew(req *dhcpv4.DHCPv4) (l *Lease, needsReply bool)
return l, true
}

// processRequest is the handler for a DHCPREQUEST message.
//
// See https://datatracker.ietf.org/doc/html/rfc2131#section-4.3.2.
func (s *v4Server) processRequest(req, resp *dhcpv4.DHCPv4) (lease *Lease, needsReply bool) {
switch reqIP, sid := req.RequestedIPAddress(), req.ServerIdentifier(); {
case sid != nil && !sid.IsUnspecified():
// handleByRequestType handles the DHCPREQUEST according to the state during
// which it's generated by client.
func (s *v4Server) handleByRequestType(req *dhcpv4.DHCPv4) (lease *Lease, needsReply bool) {
reqIP, sid := req.RequestedIPAddress(), req.ServerIdentifier()

if sid != nil && !sid.IsUnspecified() {
// If the DHCPREQUEST message contains a server identifier option, the
// message is in response to a DHCPOFFER message. Otherwise, the
// message is a request to verify or extend an existing lease.
lease, needsReply = s.processSelecting(req, reqIP, sid)
case reqIP != nil && !reqIP.IsUnspecified():
return s.handleSelecting(req, reqIP, sid)
}

if reqIP != nil && !reqIP.IsUnspecified() {
// Requested IP address option MUST be filled in with client's notion of
// its previously assigned address.
lease, needsReply = s.processInitReboot(req, reqIP)
default:
// Server identifier MUST NOT be filled in, requested IP address option
// MUST NOT be filled in.
lease, needsReply = s.processRenew(req)
return s.handleInitReboot(req, reqIP)
}

// Server identifier MUST NOT be filled in, requested IP address option MUST
// NOT be filled in.
return s.handleRenew(req)
}

// handleRequest is the handler for a DHCPREQUEST message.
//
// See https://datatracker.ietf.org/doc/html/rfc2131#section-4.3.2.
func (s *v4Server) handleRequest(req, resp *dhcpv4.DHCPv4) (lease *Lease, needsReply bool) {
lease, needsReply = s.handleByRequestType(req)
if lease == nil {
return nil, needsReply
}
Expand All @@ -831,8 +833,7 @@ func (s *v4Server) processRequest(req, resp *dhcpv4.DHCPv4) (lease *Lease, needs
return lease, needsReply
}

prev := s.setHostname(lease, hostname)
s.commitLease(lease, prev)
s.commitLease(lease, hostname)

if isRequested {
resp.UpdateOption(dhcpv4.OptHostName(lease.Hostname))
Expand All @@ -841,8 +842,8 @@ func (s *v4Server) processRequest(req, resp *dhcpv4.DHCPv4) (lease *Lease, needs
return lease, needsReply
}

// processDecline is the handler for the DHCP Decline request.
func (s *v4Server) processDecline(req, resp *dhcpv4.DHCPv4) (err error) {
// handleDecline is the handler for the DHCP Decline request.
func (s *v4Server) handleDecline(req, resp *dhcpv4.DHCPv4) (err error) {
s.conf.notify(LeaseChangedDBStore)

s.leasesLock.Lock()
Expand Down Expand Up @@ -904,8 +905,8 @@ func (s *v4Server) processDecline(req, resp *dhcpv4.DHCPv4) (err error) {
return nil
}

// processRelease is the handler for the DHCP Release request.
func (s *v4Server) processRelease(req, resp *dhcpv4.DHCPv4) (err error) {
// handleRelease is the handler for the DHCP Release request.
func (s *v4Server) handleRelease(req, resp *dhcpv4.DHCPv4) (err error) {
mac := req.ClientHWAddr
reqIP := req.RequestedIPAddress()
if reqIP == nil {
Expand Down Expand Up @@ -946,7 +947,7 @@ func (s *v4Server) processRelease(req, resp *dhcpv4.DHCPv4) (err error) {
// Return 1: OK
// Return 0: error; reply with Nak
// Return -1: error; don't reply
func (s *v4Server) process(req, resp *dhcpv4.DHCPv4) int {
func (s *v4Server) handle(req, resp *dhcpv4.DHCPv4) int {
var err error

// Include server's identifier option since any reply should contain it.
Expand All @@ -958,9 +959,9 @@ func (s *v4Server) process(req, resp *dhcpv4.DHCPv4) int {
var l *Lease
switch mt := req.MessageType(); mt {
case dhcpv4.MessageTypeDiscover:
l, err = s.processDiscover(req, resp)
l, err = s.handleDiscover(req, resp)
if err != nil {
log.Error("dhcpv4: processing discover: %s", err)
log.Error("dhcpv4: handling discover: %s", err)

return 0
}
Expand All @@ -970,24 +971,24 @@ func (s *v4Server) process(req, resp *dhcpv4.DHCPv4) int {
}
case dhcpv4.MessageTypeRequest:
var toReply bool
l, toReply = s.processRequest(req, resp)
l, toReply = s.handleRequest(req, resp)
if l == nil {
if toReply {
return 0
}
return -1 // drop packet
}
case dhcpv4.MessageTypeDecline:
err = s.processDecline(req, resp)
err = s.handleDecline(req, resp)
if err != nil {
log.Error("dhcpv4: processing decline: %s", err)
log.Error("dhcpv4: handling decline: %s", err)

return 0
}
case dhcpv4.MessageTypeRelease:
err = s.processRelease(req, resp)
err = s.handleRelease(req, resp)
if err != nil {
log.Error("dhcpv4: processing release: %s", err)
log.Error("dhcpv4: handling release: %s", err)

return 0
}
Expand Down Expand Up @@ -1061,7 +1062,7 @@ func (s *v4Server) packetHandler(conn net.PacketConn, peer net.Addr, req *dhcpv4
return
}

r := s.process(req, resp)
r := s.handle(req, resp)
if r < 0 {
return
} else if r == 0 {
Expand Down
20 changes: 10 additions & 10 deletions internal/dhcpd/v4_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ func TestV4Server_leasing(t *testing.T) {
require.NoError(t, err)

resp = &dhcpv4.DHCPv4{}
res := s4.process(req, resp)
res := s4.handle(req, resp)
require.Positive(t, res)
require.Equal(t, dhcpv4.MessageTypeOffer, resp.MessageType())

Expand All @@ -160,7 +160,7 @@ func TestV4Server_leasing(t *testing.T) {
))
require.NoError(t, err)

res := s4.process(req, resp)
res := s4.handle(req, resp)
require.Positive(t, res)

assert.Equal(t, aghnet.GenerateHostname(resp.YourIPAddr), resp.HostName())
Expand All @@ -174,7 +174,7 @@ func TestV4Server_leasing(t *testing.T) {
))
require.NoError(t, err)

res := s4.process(req, resp)
res := s4.handle(req, resp)
require.Positive(t, res)

fqdnOptData := resp.Options.Get(dhcpv4.OptionFQDN)
Expand All @@ -192,7 +192,7 @@ func TestV4Server_leasing(t *testing.T) {
))
require.NoError(t, err)

res := s4.process(req, resp)
res := s4.handle(req, resp)
require.Positive(t, res)

assert.NotEqual(t, staticIP, resp.YourIPAddr)
Expand Down Expand Up @@ -328,7 +328,7 @@ func TestV4_AddReplace(t *testing.T) {
}
}

func TestV4Server_Process_optionsPriority(t *testing.T) {
func TestV4Server_handle_optionsPriority(t *testing.T) {
defaultIP := net.IP{192, 168, 1, 1}
knownIP := net.IP{1, 2, 3, 4}

Expand Down Expand Up @@ -376,7 +376,7 @@ func TestV4Server_Process_optionsPriority(t *testing.T) {
resp, err = dhcpv4.NewReplyFromRequest(req)
require.NoError(t, err)

res := s.process(req, resp)
res := s.handle(req, resp)
require.Equal(t, 1, res)

o := resp.GetOneOption(dhcpv4.OptionDomainNameServer)
Expand Down Expand Up @@ -431,7 +431,7 @@ func TestV4StaticLease_Get(t *testing.T) {
resp, err = dhcpv4.NewReplyFromRequest(req)
require.NoError(t, err)

assert.Equal(t, 1, s.process(req, resp))
assert.Equal(t, 1, s.handle(req, resp))
})

// Don't continue if we got any errors in the previous subtest.
Expand All @@ -454,7 +454,7 @@ func TestV4StaticLease_Get(t *testing.T) {
resp, err = dhcpv4.NewReplyFromRequest(req)
require.NoError(t, err)

assert.Equal(t, 1, s.process(req, resp))
assert.Equal(t, 1, s.handle(req, resp))
})

require.NoError(t, err)
Expand Down Expand Up @@ -513,7 +513,7 @@ func TestV4DynamicLease_Get(t *testing.T) {
resp, err = dhcpv4.NewReplyFromRequest(req)
require.NoError(t, err)

assert.Equal(t, 1, s.process(req, resp))
assert.Equal(t, 1, s.handle(req, resp))
})

// Don't continue if we got any errors in the previous subtest.
Expand Down Expand Up @@ -547,7 +547,7 @@ func TestV4DynamicLease_Get(t *testing.T) {
resp, err = dhcpv4.NewReplyFromRequest(req)
require.NoError(t, err)

assert.Equal(t, 1, s.process(req, resp))
assert.Equal(t, 1, s.handle(req, resp))
})

require.NoError(t, err)
Expand Down

0 comments on commit f076cf8

Please sign in to comment.