Skip to content

Commit

Permalink
dhcpd: hide behind iface
Browse files Browse the repository at this point in the history
  • Loading branch information
EugeneOne1 committed Sep 12, 2022
1 parent a95c274 commit 5f801c9
Show file tree
Hide file tree
Showing 14 changed files with 112 additions and 109 deletions.
9 changes: 4 additions & 5 deletions internal/dhcpd/broadcast_bsd.go
Expand Up @@ -10,11 +10,10 @@ import (
// broadcast sends resp to the broadcast address specific for network interface.
func (c *dhcpConn) broadcast(respData []byte, peer *net.UDPAddr) (n int, err error) {
// Despite the fact that server4.NewIPv4UDPConn explicitly sets socket
// options to allow broadcasting, it also binds the connection to a
// specific interface. On FreeBSD and OpenBSD net.UDPConn.WriteTo
// causes errors while writing to the addresses that belong to another
// interface. So, use the broadcast address specific for the interface
// bound.
// options to allow broadcasting, it also binds the connection to a specific
// interface. On FreeBSD and OpenBSD net.UDPConn.WriteTo causes errors
// while writing to the addresses that belong to another interface. So, use
// the broadcast address specific for the interface bound.
peer.IP = c.bcastIP

return c.udpConn.WriteTo(respData, peer)
Expand Down
26 changes: 26 additions & 0 deletions internal/dhcpd/server.go → internal/dhcpd/config.go
Expand Up @@ -3,8 +3,34 @@ package dhcpd
import (
"net"
"time"

"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
)

// ServerConfig is the configuration for the DHCP server. The order of YAML
// fields is important, since the YAML configuration file follows it.
type ServerConfig struct {
// Called when the configuration is changed by HTTP request
ConfigModified func() `yaml:"-"`

// Register an HTTP handler
HTTPRegister aghhttp.RegisterFunc `yaml:"-"`

Enabled bool `yaml:"enabled"`
InterfaceName string `yaml:"interface_name"`

// LocalDomainName is the domain name used for DHCP hosts. For example,
// a DHCP client with the hostname "myhost" can be addressed as "myhost.lan"
// when LocalDomainName is "lan".
LocalDomainName string `yaml:"local_domain_name"`

Conf4 V4ServerConf `yaml:"dhcpv4"`
Conf6 V6ServerConf `yaml:"dhcpv6"`

WorkDir string `yaml:"-"`
DBFilePath string `yaml:"-"`
}

// DHCPServer - DHCP server interface
type DHCPServer interface {
// ResetLeases resets leases.
Expand Down
4 changes: 2 additions & 2 deletions internal/dhcpd/db.go
Expand Up @@ -32,7 +32,7 @@ func normalizeIP(ip net.IP) net.IP {
}

// Load lease table from DB
func (s *Server) dbLoad() (err error) {
func (s *server) dbLoad() (err error) {
dynLeases := []*Lease{}
staticLeases := []*Lease{}
v6StaticLeases := []*Lease{}
Expand Down Expand Up @@ -132,7 +132,7 @@ func normalizeLeases(staticLeases, dynLeases []*Lease) []*Lease {
}

// Store lease table in DB
func (s *Server) dbStore() (err error) {
func (s *server) dbStore() (err error) {
// Use an empty slice here as opposed to nil so that it doesn't write
// "null" into the database file if leases are empty.
leases := []leaseJSON{}
Expand Down
85 changes: 35 additions & 50 deletions internal/dhcpd/dhcpd.go
Expand Up @@ -8,7 +8,6 @@ import (
"path/filepath"
"time"

"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
"github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/netutil"
"github.com/AdguardTeam/golibs/timeutil"
Expand All @@ -24,11 +23,16 @@ const (

// DefaultDHCPLeaseTTL is the default time-to-live for leases.
DefaultDHCPLeaseTTL = uint32(timeutil.Day / time.Second)

// DefaultDHCPTimeoutICMP is the default timeout for waiting ICMP responses.
DefaultDHCPTimeoutICMP = 1000
)

var webHandlersRegistered = false
// Currently used defaults for ifaceDNSAddrs.
const (
defaultMaxAttempts int = 10
defaultBackoff time.Duration = 500 * time.Millisecond
)

// Lease contains the necessary information about a DHCP lease
type Lease struct {
Expand Down Expand Up @@ -124,30 +128,6 @@ func (l *Lease) UnmarshalJSON(data []byte) (err error) {
return nil
}

// ServerConfig is the configuration for the DHCP server. The order of YAML
// fields is important, since the YAML configuration file follows it.
type ServerConfig struct {
// Called when the configuration is changed by HTTP request
ConfigModified func() `yaml:"-"`

// Register an HTTP handler
HTTPRegister aghhttp.RegisterFunc `yaml:"-"`

Enabled bool `yaml:"enabled"`
InterfaceName string `yaml:"interface_name"`

// LocalDomainName is the domain name used for DHCP hosts. For example,
// a DHCP client with the hostname "myhost" can be addressed as "myhost.lan"
// when LocalDomainName is "lan".
LocalDomainName string `yaml:"local_domain_name"`

Conf4 V4ServerConf `yaml:"dhcpv4"`
Conf6 V6ServerConf `yaml:"dhcpv6"`

WorkDir string `yaml:"-"`
DBFilePath string `yaml:"-"`
}

// OnLeaseChangedT is a callback for lease changes.
type OnLeaseChangedT func(flags int)

Expand All @@ -161,8 +141,8 @@ const (
LeaseChangedDBStore
)

// Server - the current state of the DHCP server
type Server struct {
// server - the current state of the DHCP server
type server struct {
srv4 DHCPServer
srv6 DHCPServer

Expand All @@ -174,27 +154,36 @@ type Server struct {
onLeaseChanged []OnLeaseChangedT
}

// type check
var _ Interface = (*server)(nil)

// GetLeasesFlags are the flags for GetLeases.
type GetLeasesFlags uint8

// GetLeasesFlags values
const (
LeasesDynamic GetLeasesFlags = 0b0001
LeasesStatic GetLeasesFlags = 0b0010
LeasesDynamic GetLeasesFlags = 0b01
LeasesStatic GetLeasesFlags = 0b10

LeasesAll = LeasesDynamic | LeasesStatic
)

// ServerInterface is an interface for servers.
type ServerInterface interface {
// Interface is an interface for servers.
type Interface interface {
Start() (err error)
Stop() (err error)

Enabled() (ok bool)
Leases(flags GetLeasesFlags) (leases []*Lease)
SetOnLeaseChanged(onLeaseChanged OnLeaseChangedT)
FindMACbyIP(ip net.IP) (mac net.HardwareAddr)

WriteDiskConfig(c *ServerConfig)
}

// Create - create object
func Create(conf *ServerConfig) (s *Server, err error) {
s = &Server{
func Create(conf *ServerConfig) (s *server, err error) {
s = &server{
conf: &ServerConfig{
ConfigModified: conf.ConfigModified,

Expand All @@ -209,11 +198,7 @@ func Create(conf *ServerConfig) (s *Server, err error) {
},
}

if !webHandlersRegistered && s.conf.HTTPRegister != nil {
s.registerHandlers()

webHandlersRegistered = true
}
s.registerHandlers()

v4conf := conf.Conf4
v4conf.Enabled = s.conf.Enabled
Expand Down Expand Up @@ -258,12 +243,12 @@ func Create(conf *ServerConfig) (s *Server, err error) {
}

// Enabled returns true when the server is enabled.
func (s *Server) Enabled() (ok bool) {
func (s *server) Enabled() (ok bool) {
return s.conf.Enabled
}

// resetLeases resets all leases in the lease database.
func (s *Server) resetLeases() (err error) {
func (s *server) resetLeases() (err error) {
err = s.srv4.ResetLeases(nil)
if err != nil {
return err
Expand All @@ -280,7 +265,7 @@ func (s *Server) resetLeases() (err error) {
}

// server calls this function after DB is updated
func (s *Server) onNotify(flags uint32) {
func (s *server) onNotify(flags uint32) {
if flags == LeaseChangedDBStore {
err := s.dbStore()
if err != nil {
Expand All @@ -294,11 +279,11 @@ func (s *Server) onNotify(flags uint32) {
}

// SetOnLeaseChanged - set callback
func (s *Server) SetOnLeaseChanged(onLeaseChanged OnLeaseChangedT) {
func (s *server) SetOnLeaseChanged(onLeaseChanged OnLeaseChangedT) {
s.onLeaseChanged = append(s.onLeaseChanged, onLeaseChanged)
}

func (s *Server) notify(flags int) {
func (s *server) notify(flags int) {
if len(s.onLeaseChanged) == 0 {
return
}
Expand All @@ -309,7 +294,7 @@ func (s *Server) notify(flags int) {
}

// WriteDiskConfig - write configuration
func (s *Server) WriteDiskConfig(c *ServerConfig) {
func (s *server) WriteDiskConfig(c *ServerConfig) {
c.Enabled = s.conf.Enabled
c.InterfaceName = s.conf.InterfaceName
c.LocalDomainName = s.conf.LocalDomainName
Expand All @@ -318,7 +303,7 @@ func (s *Server) WriteDiskConfig(c *ServerConfig) {
}

// Start will listen on port 67 and serve DHCP requests.
func (s *Server) Start() (err error) {
func (s *server) Start() (err error) {
err = s.srv4.Start()
if err != nil {
return err
Expand All @@ -333,7 +318,7 @@ func (s *Server) Start() (err error) {
}

// Stop closes the listening UDP socket
func (s *Server) Stop() (err error) {
func (s *server) Stop() (err error) {
err = s.srv4.Stop()
if err != nil {
return err
Expand All @@ -349,19 +334,19 @@ func (s *Server) Stop() (err error) {

// Leases returns the list of active IPv4 and IPv6 DHCP leases. It's safe for
// concurrent use.
func (s *Server) Leases(flags GetLeasesFlags) (leases []*Lease) {
func (s *server) Leases(flags GetLeasesFlags) (leases []*Lease) {
return append(s.srv4.GetLeases(flags), s.srv6.GetLeases(flags)...)
}

// FindMACbyIP - find a MAC address by IP address in the currently active DHCP leases
func (s *Server) FindMACbyIP(ip net.IP) net.HardwareAddr {
func (s *server) FindMACbyIP(ip net.IP) net.HardwareAddr {
if ip.To4() != nil {
return s.srv4.FindMACbyIP(ip)
}
return s.srv6.FindMACbyIP(ip)
}

// AddStaticLease - add static v4 lease
func (s *Server) AddStaticLease(l *Lease) error {
func (s *server) AddStaticLease(l *Lease) error {
return s.srv4.AddStaticLease(l)
}
2 changes: 1 addition & 1 deletion internal/dhcpd/dhcpd_test.go
Expand Up @@ -26,7 +26,7 @@ func testNotify(flags uint32) {
// Leases database store/load.
func TestDB(t *testing.T) {
var err error
s := Server{
s := server{
conf: &ServerConfig{
DBFilePath: dbFilename,
},
Expand Down

0 comments on commit 5f801c9

Please sign in to comment.