AdGuardHome/internal/dhcpd/dhcpd.go

307 lines
7.6 KiB
Go
Raw Permalink Normal View History

Pull request: return 501 when we don't support features Merge in DNS/adguard-home from 2295-dhcp-windows to master Updates #2295. Squashed commit of the following: commit 3b00a90c3d9bc33e9af478e4062c0f938d4f327d Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Nov 16 16:45:43 2020 +0300 all: use the 501 handlers instead of the real ones, revert other changes commit 0a3b37736a21abd6181e0d28c32069e8d7a576d0 Merge: 45feba755 6358240e9 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Nov 16 15:59:15 2020 +0300 Merge branch 'master' into 2295-dhcp-windows and update commit 45feba755dde37e43cc8075b896e1576157341e6 Merge: cd987d8bc a19523b25 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Nov 16 15:51:16 2020 +0300 Merge branch 'master' into 2295-dhcp-windows commit cd987d8bc2cd524b7454d9037b595069714645f9 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Fri Nov 13 15:55:23 2020 +0300 all: improve tests and refactor dhcp checking code even more commit 3aad675443f325b5909523bcc1c987aa04ac61d9 Merge: 70c477e61 09196118e Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Fri Nov 13 14:44:43 2020 +0300 Merge branch 'master' into 2295-dhcp-windows commit 70c477e61cdc1237603918f1c44470c1549f1136 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Fri Nov 13 14:34:06 2020 +0300 home: fix dhcpd test on windows commit e59597d783fb9304e63f94eee2b5a5d67a5b2169 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Fri Nov 13 13:38:25 2020 +0300 all: mention the feature in the changelog commit 5555c8d881b1c20b5b0a0cb096a17cf56e209c06 Merge: c3b6a5a93 e802e6645 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Fri Nov 13 13:35:35 2020 +0300 Merge branch 'master' into 2295-dhcp-windows commit c3b6a5a930693090838eb1ef9f75a09b5b223ba6 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Thu Nov 12 20:37:09 2020 +0300 util: fix comment commit ed92dfdb5d3a6c4ba5d032cbe781e7fd87882813 Author: ArtemBaskal <asbaskal@miem.hse.ru> Date: Thu Nov 12 20:24:14 2020 +0300 Adapt client commit e6f0494c20a4ad5388492af9091568eea5c6e2d6 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Thu Nov 12 13:35:25 2020 +0300 return 501 when we don't support features
2020-11-16 16:01:12 +00:00
// Package dhcpd provides a DHCP server.
package dhcpd
import (
"fmt"
"net"
2023-03-09 12:39:35 +00:00
"net/netip"
"path/filepath"
"time"
2023-09-07 15:13:48 +01:00
"github.com/AdguardTeam/AdGuardHome/internal/dhcpsvc"
"github.com/AdguardTeam/golibs/log"
2022-09-14 14:36:29 +01:00
"github.com/AdguardTeam/golibs/timeutil"
)
Pull request: return 501 when we don't support features Merge in DNS/adguard-home from 2295-dhcp-windows to master Updates #2295. Squashed commit of the following: commit 3b00a90c3d9bc33e9af478e4062c0f938d4f327d Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Nov 16 16:45:43 2020 +0300 all: use the 501 handlers instead of the real ones, revert other changes commit 0a3b37736a21abd6181e0d28c32069e8d7a576d0 Merge: 45feba755 6358240e9 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Nov 16 15:59:15 2020 +0300 Merge branch 'master' into 2295-dhcp-windows and update commit 45feba755dde37e43cc8075b896e1576157341e6 Merge: cd987d8bc a19523b25 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Nov 16 15:51:16 2020 +0300 Merge branch 'master' into 2295-dhcp-windows commit cd987d8bc2cd524b7454d9037b595069714645f9 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Fri Nov 13 15:55:23 2020 +0300 all: improve tests and refactor dhcp checking code even more commit 3aad675443f325b5909523bcc1c987aa04ac61d9 Merge: 70c477e61 09196118e Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Fri Nov 13 14:44:43 2020 +0300 Merge branch 'master' into 2295-dhcp-windows commit 70c477e61cdc1237603918f1c44470c1549f1136 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Fri Nov 13 14:34:06 2020 +0300 home: fix dhcpd test on windows commit e59597d783fb9304e63f94eee2b5a5d67a5b2169 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Fri Nov 13 13:38:25 2020 +0300 all: mention the feature in the changelog commit 5555c8d881b1c20b5b0a0cb096a17cf56e209c06 Merge: c3b6a5a93 e802e6645 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Fri Nov 13 13:35:35 2020 +0300 Merge branch 'master' into 2295-dhcp-windows commit c3b6a5a930693090838eb1ef9f75a09b5b223ba6 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Thu Nov 12 20:37:09 2020 +0300 util: fix comment commit ed92dfdb5d3a6c4ba5d032cbe781e7fd87882813 Author: ArtemBaskal <asbaskal@miem.hse.ru> Date: Thu Nov 12 20:24:14 2020 +0300 Adapt client commit e6f0494c20a4ad5388492af9091568eea5c6e2d6 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Thu Nov 12 13:35:25 2020 +0300 return 501 when we don't support features
2020-11-16 16:01:12 +00:00
const (
2022-09-14 14:36:29 +01:00
// 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
Pull request: return 501 when we don't support features Merge in DNS/adguard-home from 2295-dhcp-windows to master Updates #2295. Squashed commit of the following: commit 3b00a90c3d9bc33e9af478e4062c0f938d4f327d Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Nov 16 16:45:43 2020 +0300 all: use the 501 handlers instead of the real ones, revert other changes commit 0a3b37736a21abd6181e0d28c32069e8d7a576d0 Merge: 45feba755 6358240e9 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Nov 16 15:59:15 2020 +0300 Merge branch 'master' into 2295-dhcp-windows and update commit 45feba755dde37e43cc8075b896e1576157341e6 Merge: cd987d8bc a19523b25 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Nov 16 15:51:16 2020 +0300 Merge branch 'master' into 2295-dhcp-windows commit cd987d8bc2cd524b7454d9037b595069714645f9 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Fri Nov 13 15:55:23 2020 +0300 all: improve tests and refactor dhcp checking code even more commit 3aad675443f325b5909523bcc1c987aa04ac61d9 Merge: 70c477e61 09196118e Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Fri Nov 13 14:44:43 2020 +0300 Merge branch 'master' into 2295-dhcp-windows commit 70c477e61cdc1237603918f1c44470c1549f1136 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Fri Nov 13 14:34:06 2020 +0300 home: fix dhcpd test on windows commit e59597d783fb9304e63f94eee2b5a5d67a5b2169 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Fri Nov 13 13:38:25 2020 +0300 all: mention the feature in the changelog commit 5555c8d881b1c20b5b0a0cb096a17cf56e209c06 Merge: c3b6a5a93 e802e6645 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Fri Nov 13 13:35:35 2020 +0300 Merge branch 'master' into 2295-dhcp-windows commit c3b6a5a930693090838eb1ef9f75a09b5b223ba6 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Thu Nov 12 20:37:09 2020 +0300 util: fix comment commit ed92dfdb5d3a6c4ba5d032cbe781e7fd87882813 Author: ArtemBaskal <asbaskal@miem.hse.ru> Date: Thu Nov 12 20:24:14 2020 +0300 Adapt client commit e6f0494c20a4ad5388492af9091568eea5c6e2d6 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Thu Nov 12 13:35:25 2020 +0300 return 501 when we don't support features
2020-11-16 16:01:12 +00:00
)
2022-09-14 14:36:29 +01:00
// Currently used defaults for ifaceDNSAddrs.
const (
defaultMaxAttempts int = 10
defaultBackoff time.Duration = 500 * time.Millisecond
)
// OnLeaseChangedT is a callback for lease changes.
type OnLeaseChangedT func(flags int)
// flags for onLeaseChanged()
const (
LeaseChangedAdded = iota
LeaseChangedAddedStatic
LeaseChangedRemovedStatic
LeaseChangedRemovedAll
LeaseChangedDBStore
)
// GetLeasesFlags are the flags for GetLeases.
type GetLeasesFlags uint8
// GetLeasesFlags values
const (
2022-09-14 14:36:29 +01:00
LeasesDynamic GetLeasesFlags = 0b01
LeasesStatic GetLeasesFlags = 0b10
LeasesAll = LeasesDynamic | LeasesStatic
)
2022-09-14 14:36:29 +01:00
// Interface is the DHCP server that deals with both IP address families.
type Interface interface {
Start() (err error)
Stop() (err error)
2023-09-07 15:13:48 +01:00
// Enabled returns true if the DHCP server is running.
//
// TODO(e.burkov): Currently, we need this method to determine whether the
// local domain suffix should be considered while resolving A/AAAA requests.
// This is because other parts of the code aren't aware of the DNS suffixes
// in DHCP clients names and caller is responsible for trimming it. This
// behavior should be changed in the future.
Enabled() (ok bool)
2022-09-14 14:36:29 +01:00
2023-09-07 15:13:48 +01:00
// Leases returns all the leases in the database.
Leases() (leases []*dhcpsvc.Lease)
2022-09-14 14:36:29 +01:00
2023-09-07 15:13:48 +01:00
// MacByIP returns the MAC address of a client with ip. It returns nil if
// there is no such client, due to an assumption that a DHCP client must
// always have a HardwareAddr.
MACByIP(ip netip.Addr) (mac net.HardwareAddr)
2022-09-14 14:36:29 +01:00
2023-09-07 15:13:48 +01:00
// HostByIP returns the hostname of the DHCP client with the given IP
// address. The address will be netip.Addr{} if there is no such client,
// due to an assumption that a DHCP client must always have an IP address.
HostByIP(ip netip.Addr) (host string)
2022-09-14 14:36:29 +01:00
2023-09-07 15:13:48 +01:00
// IPByHost returns the IP address of the DHCP client with the given
// hostname. The address will be netip.Addr{} if there is no such client,
// due to an assumption that a DHCP client must always have an IP address.
IPByHost(host string) (ip netip.Addr)
2022-09-14 14:36:29 +01:00
2023-09-07 15:13:48 +01:00
WriteDiskConfig(c *ServerConfig)
2023-03-09 12:39:35 +00:00
}
2022-09-14 14:36:29 +01:00
// server is the DHCP service that handles DHCPv4, DHCPv6, and HTTP API.
type server struct {
srv4 DHCPServer
srv6 DHCPServer
// TODO(a.garipov): Either create a separate type for the internal config or
// just put the config values into Server.
conf *ServerConfig
// Called when the leases DB is modified
onLeaseChanged []OnLeaseChangedT
2019-03-06 12:13:27 +00:00
}
2022-09-14 14:36:29 +01:00
// type check
var _ Interface = (*server)(nil)
// Create initializes and returns the DHCP server handling both address
// families. It also registers the corresponding HTTP API endpoints.
func Create(conf *ServerConfig) (s *server, err error) {
s = &server{
2022-06-02 15:55:48 +01:00
conf: &ServerConfig{
ConfigModified: conf.ConfigModified,
Pull request: return 501 when we don't support features Merge in DNS/adguard-home from 2295-dhcp-windows to master Updates #2295. Squashed commit of the following: commit 3b00a90c3d9bc33e9af478e4062c0f938d4f327d Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Nov 16 16:45:43 2020 +0300 all: use the 501 handlers instead of the real ones, revert other changes commit 0a3b37736a21abd6181e0d28c32069e8d7a576d0 Merge: 45feba755 6358240e9 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Nov 16 15:59:15 2020 +0300 Merge branch 'master' into 2295-dhcp-windows and update commit 45feba755dde37e43cc8075b896e1576157341e6 Merge: cd987d8bc a19523b25 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Nov 16 15:51:16 2020 +0300 Merge branch 'master' into 2295-dhcp-windows commit cd987d8bc2cd524b7454d9037b595069714645f9 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Fri Nov 13 15:55:23 2020 +0300 all: improve tests and refactor dhcp checking code even more commit 3aad675443f325b5909523bcc1c987aa04ac61d9 Merge: 70c477e61 09196118e Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Fri Nov 13 14:44:43 2020 +0300 Merge branch 'master' into 2295-dhcp-windows commit 70c477e61cdc1237603918f1c44470c1549f1136 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Fri Nov 13 14:34:06 2020 +0300 home: fix dhcpd test on windows commit e59597d783fb9304e63f94eee2b5a5d67a5b2169 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Fri Nov 13 13:38:25 2020 +0300 all: mention the feature in the changelog commit 5555c8d881b1c20b5b0a0cb096a17cf56e209c06 Merge: c3b6a5a93 e802e6645 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Fri Nov 13 13:35:35 2020 +0300 Merge branch 'master' into 2295-dhcp-windows commit c3b6a5a930693090838eb1ef9f75a09b5b223ba6 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Thu Nov 12 20:37:09 2020 +0300 util: fix comment commit ed92dfdb5d3a6c4ba5d032cbe781e7fd87882813 Author: ArtemBaskal <asbaskal@miem.hse.ru> Date: Thu Nov 12 20:24:14 2020 +0300 Adapt client commit e6f0494c20a4ad5388492af9091568eea5c6e2d6 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Thu Nov 12 13:35:25 2020 +0300 return 501 when we don't support features
2020-11-16 16:01:12 +00:00
2022-06-02 15:55:48 +01:00
HTTPRegister: conf.HTTPRegister,
Enabled: conf.Enabled,
InterfaceName: conf.InterfaceName,
LocalDomainName: conf.LocalDomainName,
2023-04-18 14:07:11 +01:00
dbFilePath: filepath.Join(conf.DataDir, dataFilename),
2022-06-02 15:55:48 +01:00
},
}
2022-12-07 13:46:59 +00:00
// TODO(e.burkov): Don't register handlers, see TODO on
// [aghhttp.RegisterFunc].
2022-09-14 14:36:29 +01:00
s.registerHandlers()
2023-06-07 18:04:01 +01:00
v4Enabled, v6Enabled, err := s.setServers(conf)
if err != nil {
2023-06-07 18:04:01 +01:00
// Don't wrap the error, because it's informative enough as is.
return nil, err
}
s.conf.Conf4 = conf.Conf4
s.conf.Conf6 = conf.Conf6
2023-06-07 18:04:01 +01:00
if s.conf.Enabled && !v4Enabled && !v6Enabled {
return nil, fmt.Errorf("neither dhcpv4 nor dhcpv6 srv is configured")
}
2023-04-18 14:07:11 +01:00
// Migrate leases db if needed.
err = migrateDB(conf)
if err != nil {
// Don't wrap the error since it's informative enough as is.
return nil, err
}
// Don't delay database loading until the DHCP server is started,
// because we need static leases functionality available beforehand.
err = s.dbLoad()
if err != nil {
return nil, fmt.Errorf("loading db: %w", err)
}
return s, nil
}
2023-06-07 18:04:01 +01:00
// setServers updates DHCPv4 and DHCPv6 servers created from the provided
2023-09-07 15:13:48 +01:00
// configuration conf. It returns the status of both the DHCPv4 and the DHCPv6
// servers, which is always false for corresponding server on any error.
2023-06-07 18:04:01 +01:00
func (s *server) setServers(conf *ServerConfig) (v4Enabled, v6Enabled bool, err error) {
v4conf := conf.Conf4
v4conf.InterfaceName = s.conf.InterfaceName
v4conf.notify = s.onNotify
v4conf.Enabled = s.conf.Enabled && v4conf.RangeStart.IsValid()
s.srv4, err = v4Create(&v4conf)
if err != nil {
if v4conf.Enabled {
2023-09-07 15:13:48 +01:00
return false, false, fmt.Errorf("creating dhcpv4 srv: %w", err)
2023-06-07 18:04:01 +01:00
}
log.Debug("dhcpd: warning: creating dhcpv4 srv: %s", err)
}
v6conf := conf.Conf6
v6conf.InterfaceName = s.conf.InterfaceName
v6conf.notify = s.onNotify
2023-09-07 15:13:48 +01:00
v6conf.Enabled = s.conf.Enabled && len(v6conf.RangeStart) != 0
2023-06-07 18:04:01 +01:00
s.srv6, err = v6Create(v6conf)
if err != nil {
2023-09-07 15:13:48 +01:00
return v4conf.Enabled, false, fmt.Errorf("creating dhcpv6 srv: %w", err)
2023-06-07 18:04:01 +01:00
}
return v4conf.Enabled, v6conf.Enabled, nil
}
// Enabled returns true when the server is enabled.
2022-09-14 14:36:29 +01:00
func (s *server) Enabled() (ok bool) {
return s.conf.Enabled
}
// resetLeases resets all leases in the lease database.
2022-09-14 14:36:29 +01:00
func (s *server) resetLeases() (err error) {
err = s.srv4.ResetLeases(nil)
if err != nil {
return err
}
if s.srv6 != nil {
err = s.srv6.ResetLeases(nil)
if err != nil {
return err
}
}
return s.dbStore()
}
// server calls this function after DB is updated
2022-09-14 14:36:29 +01:00
func (s *server) onNotify(flags uint32) {
if flags == LeaseChangedDBStore {
err := s.dbStore()
if err != nil {
log.Error("updating db: %s", err)
}
return
}
s.notify(int(flags))
}
2022-09-14 14:36:29 +01:00
func (s *server) notify(flags int) {
for _, f := range s.onLeaseChanged {
f(flags)
}
}
// WriteDiskConfig - write configuration
2022-09-14 14:36:29 +01:00
func (s *server) WriteDiskConfig(c *ServerConfig) {
c.Enabled = s.conf.Enabled
c.InterfaceName = s.conf.InterfaceName
2022-06-02 15:55:48 +01:00
c.LocalDomainName = s.conf.LocalDomainName
2022-09-14 14:36:29 +01:00
s.srv4.WriteDiskConfig4(&c.Conf4)
s.srv6.WriteDiskConfig6(&c.Conf6)
}
// Start will listen on port 67 and serve DHCP requests.
2022-09-14 14:36:29 +01:00
func (s *server) Start() (err error) {
err = s.srv4.Start()
if err != nil {
return err
}
err = s.srv6.Start()
if err != nil {
return err
}
return nil
}
2019-01-24 17:11:01 +00:00
// Stop closes the listening UDP socket
2022-09-14 14:36:29 +01:00
func (s *server) Stop() (err error) {
err = s.srv4.Stop()
if err != nil {
return err
}
err = s.srv6.Stop()
if err != nil {
return err
}
return nil
}
2023-09-07 15:13:48 +01:00
// Leases returns the list of active DHCP leases.
func (s *server) Leases() (leases []*dhcpsvc.Lease) {
return append(s.srv4.GetLeases(LeasesAll), s.srv6.GetLeases(LeasesAll)...)
2019-05-28 12:11:47 +01:00
}
2023-09-07 15:13:48 +01:00
// MACByIP returns a MAC address by the IP address of its lease, if there is
2023-03-09 12:39:35 +00:00
// one.
2023-09-07 15:13:48 +01:00
func (s *server) MACByIP(ip netip.Addr) (mac net.HardwareAddr) {
2023-03-09 12:39:35 +00:00
if ip.Is4() {
return s.srv4.FindMACbyIP(ip)
}
2023-03-09 12:39:35 +00:00
return s.srv6.FindMACbyIP(ip)
}
2023-09-07 15:13:48 +01:00
// HostByIP implements the [Interface] interface for *server.
//
// TODO(e.burkov): Implement this method for DHCPv6.
func (s *server) HostByIP(ip netip.Addr) (host string) {
if ip.Is4() {
return s.srv4.HostByIP(ip)
}
return ""
}
// IPByHost implements the [Interface] interface for *server.
//
// TODO(e.burkov): Implement this method for DHCPv6.
func (s *server) IPByHost(host string) (ip netip.Addr) {
return s.srv4.IPByHost(host)
}
// AddStaticLease - add static v4 lease
func (s *server) AddStaticLease(l *dhcpsvc.Lease) error {
return s.srv4.AddStaticLease(l)
2019-03-01 17:03:22 +00:00
}