Documentation
¶
Overview ¶
Package dhcpsvc contains the AdGuard Home DHCP service.
TODO(e.burkov): Add tests.
Index ¶
- Constants
- Variables
- type Config
- type DHCPServer
- func (srv *DHCPServer) AddLease(ctx context.Context, l *Lease) (err error)
- func (srv *DHCPServer) Enabled() (ok bool)
- func (srv *DHCPServer) HostByIP(ip netip.Addr) (host string)
- func (srv *DHCPServer) IPByHost(host string) (ip netip.Addr)
- func (srv *DHCPServer) Leases() (leases []*Lease)
- func (srv *DHCPServer) MACByIP(ip netip.Addr) (mac net.HardwareAddr)
- func (srv *DHCPServer) RemoveLease(ctx context.Context, l *Lease) (err error)
- func (srv *DHCPServer) Reset(ctx context.Context) (err error)
- func (srv *DHCPServer) Shutdown(ctx context.Context) (err error)
- func (srv *DHCPServer) Start(ctx context.Context) (err error)
- func (srv *DHCPServer) UpdateStaticLease(ctx context.Context, l *Lease) (err error)
- type Empty
- func (Empty) AddLease(_ context.Context, _ *Lease) (err error)
- func (Empty) Enabled() (ok bool)
- func (Empty) HostByIP(_ netip.Addr) (host string)
- func (Empty) IPByHost(_ string) (ip netip.Addr)
- func (Empty) Leases() (leases []*Lease)
- func (Empty) MACByIP(_ netip.Addr) (mac net.HardwareAddr)
- func (Empty) RemoveLease(_ context.Context, _ *Lease) (err error)
- func (Empty) Reset(_ context.Context) (err error)
- func (Empty) Shutdown(_ context.Context) (err error)
- func (Empty) Start(_ context.Context) (err error)
- func (Empty) UpdateStaticLease(_ context.Context, _ *Lease) (err error)
- type EmptyNetworkDevice
- func (EmptyNetworkDevice) Addresses() (ips []netip.Addr)
- func (EmptyNetworkDevice) Close() (err error)
- func (EmptyNetworkDevice) HardwareAddr() (hw net.HardwareAddr)
- func (EmptyNetworkDevice) LinkType() (lt layers.LinkType)
- func (EmptyNetworkDevice) ReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error)
- func (EmptyNetworkDevice) WritePacketData(_ []byte) (err error)
- type EmptyNetworkDeviceManager
- type IAAddrOption
- type IANAOption
- type IPv4Config
- type IPv6Config
- type Interface
- type InterfaceConfig
- type Lease
- type NetworkDevice
- type NetworkDeviceConfig
- type NetworkDeviceManager
- Bugs
Constants ¶
const ( // ServerPortV4 is the standard DHCPv4 server port. ServerPortV4 layers.UDPPort = 67 // ClientPortV4 is the standard DHCPv4 client port. ClientPortV4 layers.UDPPort = 68 )
Port numbers for DHCPv4.
See RFC 2131 Section 4.1.
const ( // IPv4DefaultTTL is the default Time to Live value in seconds as // recommended by RFC 1700. IPv4DefaultTTL = 64 // IPProtoVersion is the IP internetwork general protocol version number as // defined by RFC 1700. IPProtoVersion = 4 )
const ( // ServerPortV6 is the standard DHCPv6 server port. ServerPortV6 layers.UDPPort = 547 // ClientPortV6 is the standard DHCPv6 client port. ClientPortV6 layers.UDPPort = 546 )
Port numbers for DHCPv6.
See RFC 9915 Section 7.2.
const DefaultSolMaxRT = 1 * time.Hour
DefaultSolMaxRT is the recommended SOL_MAX_RT value sent to clients. It caps the client's solicit retransmission interval.
const EUI48AddrLen = 6
EUI48AddrLen is the length of a valid EUI-48 hardware address.
const FlagsBroadcast uint16 = 1 << 15
FlagsBroadcast is the DHCPv4 message flags field with the broadcast bit set.
const IPv6DefaultHopLimit = 8
IPv6DefaultHopLimit is the default hop limit for relaying DHCPv6 response packets.
See RFC 9915 Section 7.6.
Variables ¶
var ( // AllDHCPRelayAgentsAndServers is the well-known IPv6 multicast address // All_DHCP_Relay_Agents_and_Servers. Clients send messages to this address // to reach all servers on the local link. AllDHCPRelayAgentsAndServers = netip.MustParseAddr("ff02::1:2") // AllDHCPServers is the well-known IPv6 multicast address All_DHCP_Servers. // Relay agents use this to reach all servers. AllDHCPServers = netip.MustParseAddr("ff05::1:3") )
DHCPv6 multicast addresses.
See RFC 9915 Section 7.1.
var HardwareTypeEthernet = []byte{0x00, 0x01}
HardwareTypeEthernet is the IANA hardware type number for Ethernet, used in DUID-LL and DUID-LLT construction. Its value is 1, encoded as a big-endian uint16.
See https://www.iana.org/assignments/arp-parameters/arp-parameters.xhtml#arp-parameters-2.
TODO(e.burkov): Use.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// Interfaces stores configurations of DHCP server specific for the network
// interface identified by its name. It must not be empty and must only
// contain valid interface names and configurations.
Interfaces map[string]*InterfaceConfig
// NetworkDeviceManager is the manager of network devices. It must not be
// nil.
//
// TODO(e.burkov): Set.
NetworkDeviceManager NetworkDeviceManager
// Logger will be used to log the DHCP events. It must not be nil.
Logger *slog.Logger
// LocalDomainName is the top-level domain name to use for resolving DHCP
// clients' hostnames. It must be a valid domain name.
LocalDomainName string
// DBFilePath is the path to the database file containing the DHCP leases.
// It must not be empty.
DBFilePath string
// ICMPTimeout is the timeout for checking another DHCP server's presence.
// It must be non-negative. If it is zero, the check will be skipped.
ICMPTimeout time.Duration
// Enabled is the state of the service, whether it is enabled or not.
Enabled bool
}
Config is the configuration for the DHCP service.
func (*Config) Validate ¶ added in v0.107.42
Validate implements the validate.Interface for *Config.
type DHCPServer ¶ added in v0.107.42
type DHCPServer struct {
// contains filtered or unexported fields
}
DHCPServer is a DHCP server for both IPv4 and IPv6 address families.
TODO(e.burkov): Rename to Default.
func New ¶ added in v0.107.42
func New(ctx context.Context, conf *Config) (srv *DHCPServer, err error)
New creates a new DHCP server with the given configuration. conf must be valid.
TODO(e.burkov): Use.
func (*DHCPServer) AddLease ¶ added in v0.107.46
func (srv *DHCPServer) AddLease(ctx context.Context, l *Lease) (err error)
AddLease implements the Interface interface for *DHCPServer.
func (*DHCPServer) Enabled ¶ added in v0.107.42
func (srv *DHCPServer) Enabled() (ok bool)
Enabled implements the Interface interface for *DHCPServer.
func (*DHCPServer) HostByIP ¶ added in v0.107.46
func (srv *DHCPServer) HostByIP(ip netip.Addr) (host string)
HostByIP implements the Interface interface for *DHCPServer.
func (*DHCPServer) IPByHost ¶ added in v0.107.46
func (srv *DHCPServer) IPByHost(host string) (ip netip.Addr)
IPByHost implements the Interface interface for *DHCPServer.
func (*DHCPServer) Leases ¶ added in v0.107.42
func (srv *DHCPServer) Leases() (leases []*Lease)
Leases implements the Interface interface for *DHCPServer.
func (*DHCPServer) MACByIP ¶ added in v0.107.46
func (srv *DHCPServer) MACByIP(ip netip.Addr) (mac net.HardwareAddr)
MACByIP implements the Interface interface for *DHCPServer.
func (*DHCPServer) RemoveLease ¶ added in v0.107.46
func (srv *DHCPServer) RemoveLease(ctx context.Context, l *Lease) (err error)
RemoveLease implements the Interface interface for *DHCPServer.
func (*DHCPServer) Reset ¶ added in v0.107.46
func (srv *DHCPServer) Reset(ctx context.Context) (err error)
Reset implements the Interface interface for *DHCPServer.
func (*DHCPServer) Shutdown ¶ added in v0.107.63
func (srv *DHCPServer) Shutdown(ctx context.Context) (err error)
Shutdown implements the Interface interface for *DHCPServer.
func (*DHCPServer) Start ¶ added in v0.107.63
func (srv *DHCPServer) Start(ctx context.Context) (err error)
Start implements the Interface interface for *DHCPServer.
func (*DHCPServer) UpdateStaticLease ¶ added in v0.107.46
func (srv *DHCPServer) UpdateStaticLease(ctx context.Context, l *Lease) (err error)
UpdateStaticLease implements the Interface interface for *DHCPServer.
TODO(e.burkov): Support moving leases between interfaces.
type Empty ¶
type Empty struct{}
Empty is an Interface implementation that does nothing.
func (Empty) MACByIP ¶
func (Empty) MACByIP(_ netip.Addr) (mac net.HardwareAddr)
MACByIP implements the Interface interface for Empty.
func (Empty) RemoveLease ¶
RemoveLease implements the Interface interface for Empty.
type EmptyNetworkDevice ¶ added in v0.107.72
type EmptyNetworkDevice struct{}
EmptyNetworkDevice is an empty implementation of NetworkDevice.
func (EmptyNetworkDevice) Addresses ¶ added in v0.107.72
func (EmptyNetworkDevice) Addresses() (ips []netip.Addr)
Addresses implements the NetworkDevice interface for EmptyNetworkDevice. It always returns nil.
func (EmptyNetworkDevice) Close ¶ added in v0.107.74
func (EmptyNetworkDevice) Close() (err error)
Close implements the io.Closer interface for EmptyNetworkDevice. It always returns nil.
func (EmptyNetworkDevice) HardwareAddr ¶ added in v0.107.75
func (EmptyNetworkDevice) HardwareAddr() (hw net.HardwareAddr)
HardwareAddr implements the NetworkDevice interface for EmptyNetworkDevice. It always returns nil.
func (EmptyNetworkDevice) LinkType ¶ added in v0.107.72
func (EmptyNetworkDevice) LinkType() (lt layers.LinkType)
LinkType implements the NetworkDevice interface for EmptyNetworkDevice. It always returns layers.LinkTypeNull.
func (EmptyNetworkDevice) ReadPacketData ¶ added in v0.107.72
func (EmptyNetworkDevice) ReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error)
ReadPacketData implements the gopacket.PacketDataSource interface for EmptyNetworkDevice. It always returns no data, empty capture info and a nil error.
func (EmptyNetworkDevice) WritePacketData ¶ added in v0.107.72
func (EmptyNetworkDevice) WritePacketData(_ []byte) (err error)
WritePacketData implements the NetworkDevice interface for EmptyNetworkDevice. It always returns nil.
type EmptyNetworkDeviceManager ¶ added in v0.107.72
type EmptyNetworkDeviceManager struct{}
EmptyNetworkDeviceManager is an empty implementation of NetworkDeviceManager.
func (EmptyNetworkDeviceManager) Open ¶ added in v0.107.72
func (EmptyNetworkDeviceManager) Open( _ context.Context, _ *NetworkDeviceConfig, ) (nd NetworkDevice, err error)
Open implements the NetworkDeviceManager interface for EmptyNetworkDeviceManager. It always returns EmptyNetworkDevice.
type IAAddrOption ¶ added in v0.107.78
type IAAddrOption struct {
// Addr is the IPv6 address.
Addr netip.Addr
// PreferredLifetime is the preferred lifetime of the address. When it is
// zero, the address is deprecated.
PreferredLifetime time.Duration
// ValidLifetime is the valid lifetime of the address. When it is zero, the
// address is no longer valid.
ValidLifetime time.Duration
}
IAAddrOption represents a parsed IA Address option.
func (*IAAddrOption) UnmarshalBinary ¶ added in v0.107.78
func (ia *IAAddrOption) UnmarshalBinary(data []byte) (err error)
UnmarshalBinary implements the encoding.BinaryUnmarshaler interface for *IAAddrOption. Nested options within IA Address, if any, are ignored. data should have the following format:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | IPv6-address | | | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | preferred-lifetime | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | valid-lifetime | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ . . . IAaddr-options . . . +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
type IANAOption ¶ added in v0.107.78
type IANAOption struct {
// Nested are the IA Address options Nested within this IA_NA.
Nested []IAAddrOption
// ID is the Identity Association Identifier, a 4-octet value uniquely
// identifying this IA within the client.
//
// TODO(e.burkov): Add new type.
ID uint32
// T1 is the time after which the client must contact the same server to
// extend the lifetimes of the addresses in this IA.
T1 time.Duration
// T2 is the time after which the client may contact any available server to
// extend the lifetimes.
T2 time.Duration
}
IANAOption represents a parsed IA_NA (Identity Association for Non-temporary Addresses) option.
func (IANAOption) Encode ¶ added in v0.107.78
func (opt IANAOption) Encode() (iaOpt layers.DHCPv6Option)
Encode serializes opt into a DHCPv6 IA_NA option. Each contained IAAddrOption is encoded as a nested IA Address option.
TODO(e.burkov): Use.
func (*IANAOption) UnmarshalBinary ¶ added in v0.107.78
func (opt *IANAOption) UnmarshalBinary(data []byte) (err error)
UnmarshalBinary implements the encoding.BinaryUnmarshaler interface for *IANAOption. data should have the following format:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | IAID (4 octets) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | T1 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | T2 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | . IA_NA-options . . . +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
type IPv4Config ¶
type IPv4Config struct {
// Clock is used to get current time. It should not be nil.
Clock timeutil.Clock
// GatewayIP is the IPv4 address of the network's gateway. It is used as
// the default gateway for DHCP clients and also used for calculating the
// network-specific broadcast address. It should be a valid IPv4 address,
// should be within the subnet, and should be outside the address range.
GatewayIP netip.Addr
// SubnetMask is the IPv4 subnet mask of the network. It should be a valid
// IPv4 CIDR (i.e. all 1s followed by all 0s).
SubnetMask netip.Addr
// RangeStart is the first address in the range to assign to DHCP clients.
// It should be a valid IPv4 address, should be within the subnet, and
// should be less or equal to RangeEnd.
RangeStart netip.Addr
// RangeEnd is the last address in the range to assign to DHCP clients. It
// should be a valid IPv4 address, should be within the subnet, and should
// be greater or equal to RangeStart.
RangeEnd netip.Addr
// Options is the list of explicitly configured DHCP options to send to
// clients. Options with nil Data field are removed from responses.
//
// TODO(e.burkov): Validate.
Options layers.DHCPOptions
// LeaseDuration is the TTL of a DHCP lease. It should be positive.
LeaseDuration time.Duration
// Enabled is the state of the DHCPv4 service, whether it is enabled or not
// on the specific interface.
Enabled bool
}
IPv4Config is the interface-specific configuration for DHCPv4.
func (*IPv4Config) Validate ¶ added in v0.107.63
func (c *IPv4Config) Validate() (err error)
Validate implements the validate.Interface interface for *IPv4Config.
type IPv6Config ¶
type IPv6Config struct {
// Clock is used to get the current time. It should not be nil.
Clock timeutil.Clock
// RangeStart is the first address in the range to assign to DHCP clients.
// It should be a valid IPv6 address.
RangeStart netip.Addr
// Options is the list of explicit DHCP options to send to clients. The
// options with zero length are treated as deletions of the corresponding
// options, either implicit or explicit.
Options layers.DHCPv6Options
// LeaseDuration is the TTL of a DHCP lease. It should be positive.
LeaseDuration time.Duration
// RASlaacOnly defines whether the DHCP clients should only use SLAAC for
// address assignment.
RASLAACOnly bool
// RAAllowSlaac defines whether the DHCP clients may use SLAAC for address
// assignment.
RAAllowSLAAC bool
// Enabled is the state of the DHCPv6 service, whether it is enabled or not
// on the specific interface.
Enabled bool
}
IPv6Config is the interface-specific configuration for DHCPv6.
TODO(e.burkov): Add RangeEnd and SubnetPrefix fields, and validate them.
func (*IPv6Config) Validate ¶ added in v0.107.63
func (c *IPv6Config) Validate() (err error)
Validate implements the validate.Interface interface for *IPv6Config.
type Interface ¶
type Interface interface {
service.Interface
// Enabled returns true if DHCP provides information about clients.
Enabled() (ok bool)
// 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)
// MACByIP returns the MAC address for the given IP address leased. It
// returns nil if there is no such client, due to an assumption that a DHCP
// client must always have a MAC address.
//
// TODO(e.burkov): Think of a contract for the returned value.
MACByIP(ip netip.Addr) (mac net.HardwareAddr)
// IPByHost returns the IP address of the DHCP client with the given
// hostname. The hostname will be an empty string if there is no such
// client, due to an assumption that a DHCP client must always have a
// hostname, either set or generated.
IPByHost(host string) (ip netip.Addr)
// Leases returns all the active DHCP leases. The returned slice should be
// a clone. The order of leases is undefined.
//
// TODO(e.burkov): Consider implementing iterating methods with appropriate
// signatures instead of cloning the whole list.
Leases() (ls []*Lease)
// AddLease adds a new DHCP lease. l must be valid. It returns an error if
// l already exists.
AddLease(ctx context.Context, l *Lease) (err error)
// UpdateStaticLease replaces an existing static DHCP lease. l must be
// valid. It returns an error if the lease with the given hardware address
// doesn't exist or if other values match another existing lease.
UpdateStaticLease(ctx context.Context, l *Lease) (err error)
// RemoveLease removes an existing DHCP lease. l must be valid. It returns
// an error if there is no lease equal to l.
RemoveLease(ctx context.Context, l *Lease) (err error)
// Reset removes all the DHCP leases.
//
// TODO(e.burkov): If it's really needed?
Reset(ctx context.Context) (err error)
}
Interface is a DHCP service.
TODO(e.burkov): Separate HostByIP, MACByIP, IPByHost into a separate interface. This is also applicable to Enabled method.
TODO(e.burkov): Reconsider the requirements for the leases validity.
type InterfaceConfig ¶
type InterfaceConfig struct {
// IPv4 is the configuration of DHCP protocol for IPv4.
IPv4 *IPv4Config
// IPv6 is the configuration of DHCP protocol for IPv6.
IPv6 *IPv6Config
}
InterfaceConfig is the configuration of a single DHCP interface.
func (*InterfaceConfig) Validate ¶ added in v0.107.63
func (ic *InterfaceConfig) Validate() (err error)
Validate implements the validate.Interface interface for *InterfaceConfig.
type Lease ¶
type Lease struct {
// IP is the IP address leased to the client. It must not be empty.
IP netip.Addr
// Expiry is the expiration time of the lease or its blocking expiration
// time.
Expiry time.Time
// Hostname of the client. It may be empty if the lease is blocked.
Hostname string
// HWAddr is the physical hardware (MAC) address. It must be a valid
// hardware address of length 6, 8, or 20 bytes, see [netutil.ValidateMAC].
HWAddr net.HardwareAddr
// IsStatic defines if the lease is static.
IsStatic bool
}
Lease is a DHCP lease.
TODO(e.burkov): Consider moving it to [agh], since it also may be needed in [websvc].
TODO(e.burkov): Add validation method.
BUG(e.burkov): The implementation currently relies on the client's hardware address for client identification. This approach is not recommended by RFC 9915, so the database should be migrated to use the client's DUID and IAID for lease identification.
type NetworkDevice ¶ added in v0.107.71
type NetworkDevice interface {
gopacket.PacketDataSource
// No methods of a device should be called after Close.
io.Closer
// Addresses returns all IP addresses assigned to the device. It must
// return at least one valid address, unless the implementation documents
// the opposite.
Addresses() (ips []netip.Addr)
// HardwareAddr returns the hardware (MAC) address of the device. It must
// return a valid hardware address, unless the implementation documents the
// opposite.
HardwareAddr() (hw net.HardwareAddr)
// LinkType returns the link type of the network interface. It must return
// a valid link type, unless the implementation documents the opposite.
LinkType() (lt layers.LinkType)
// WritePacketData writes a serialized packet to the network interface.
WritePacketData(data []byte) (err error)
}
NetworkDevice provides an ability of reading and writing packets to a network interface. It used to generalize implementations for different platforms and to simplify testing.
It's based on [pcap.Handle].
type NetworkDeviceConfig ¶ added in v0.107.71
type NetworkDeviceConfig struct {
// Name is the name of the network device. It must be a valid interface
// name on the system.
Name string
}
NetworkDeviceConfig is the configuration for a network device.
func (*NetworkDeviceConfig) Validate ¶ added in v0.107.71
func (conf *NetworkDeviceConfig) Validate() (err error)
Validate implements the validate.Interface interface for *NetworkDeviceConfig.
type NetworkDeviceManager ¶ added in v0.107.71
type NetworkDeviceManager interface {
// Open opens a network device. conf must be valid.
//
// An attempt to open the same device multiple times may return an error.
Open(ctx context.Context, conf *NetworkDeviceConfig) (dev NetworkDevice, err error)
}
NetworkDeviceManager creates and manages network devices.