dhcpsvc

package
v0.108.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 16, 2026 License: GPL-3.0 Imports: 30 Imported by: 0

Documentation

Overview

Package dhcpsvc contains the AdGuard Home DHCP service.

TODO(e.burkov): Add tests.

Index

Constants

View Source
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
)
View Source
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.

View Source
const EUI48AddrLen = 6

EUI48AddrLen is the length of a valid EUI-48 hardware address.

View Source
const FlagsBroadcast uint16 = 1 << 15

FlagsBroadcast is the DHCPv4 message flags field with the broadcast bit set.

Variables

This section is empty.

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

func (conf *Config) Validate() (err error)

Validate implements the validate.Interface for *Config.

type DHCPServer

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

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

func (srv *DHCPServer) AddLease(ctx context.Context, l *Lease) (err error)

AddLease implements the Interface interface for *DHCPServer.

func (*DHCPServer) Enabled

func (srv *DHCPServer) Enabled() (ok bool)

Enabled implements the Interface interface for *DHCPServer.

func (*DHCPServer) HostByIP

func (srv *DHCPServer) HostByIP(ip netip.Addr) (host string)

HostByIP implements the Interface interface for *DHCPServer.

func (*DHCPServer) IPByHost

func (srv *DHCPServer) IPByHost(host string) (ip netip.Addr)

IPByHost implements the Interface interface for *DHCPServer.

func (*DHCPServer) Leases

func (srv *DHCPServer) Leases() (leases []*Lease)

Leases implements the Interface interface for *DHCPServer.

func (*DHCPServer) MACByIP

func (srv *DHCPServer) MACByIP(ip netip.Addr) (mac net.HardwareAddr)

MACByIP implements the Interface interface for *DHCPServer.

func (*DHCPServer) RemoveLease

func (srv *DHCPServer) RemoveLease(ctx context.Context, l *Lease) (err error)

RemoveLease implements the Interface interface for *DHCPServer.

func (*DHCPServer) Reset

func (srv *DHCPServer) Reset(ctx context.Context) (err error)

Reset implements the Interface interface for *DHCPServer.

func (*DHCPServer) Shutdown

func (srv *DHCPServer) Shutdown(ctx context.Context) (err error)

Shutdown implements the Interface interface for *DHCPServer.

func (*DHCPServer) Start

func (srv *DHCPServer) Start(ctx context.Context) (err error)

Start implements the Interface interface for *DHCPServer.

func (*DHCPServer) UpdateStaticLease

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) AddLease

func (Empty) AddLease(_ context.Context, _ *Lease) (err error)

AddLease implements the Interface interface for Empty.

func (Empty) Config

func (Empty) Config() (conf *Config)

Config implements the [ServiceWithConfig] interface for Empty.

func (Empty) Enabled

func (Empty) Enabled() (ok bool)

Enabled implements the Interface interface for Empty.

func (Empty) HostByIP

func (Empty) HostByIP(_ netip.Addr) (host string)

HostByIP implements the Interface interface for Empty.

func (Empty) IPByHost

func (Empty) IPByHost(_ string) (ip netip.Addr)

IPByHost implements the Interface interface for Empty.

func (Empty) Leases

func (Empty) Leases() (leases []*Lease)

Leases implements the Interface interface for Empty.

func (Empty) MACByIP

func (Empty) MACByIP(_ netip.Addr) (mac net.HardwareAddr)

MACByIP implements the Interface interface for Empty.

func (Empty) RemoveLease

func (Empty) RemoveLease(_ context.Context, _ *Lease) (err error)

RemoveLease implements the Interface interface for Empty.

func (Empty) Reset

func (Empty) Reset(_ context.Context) (err error)

Reset implements the Interface interface for Empty.

func (Empty) Shutdown

func (Empty) Shutdown(_ context.Context) (err error)

Shutdown implements the [Service] interface for Empty.

func (Empty) Start

func (Empty) Start(_ context.Context) (err error)

Start implements the [Service] interface for Empty.

func (Empty) UpdateStaticLease

func (Empty) UpdateStaticLease(_ context.Context, _ *Lease) (err error)

UpdateStaticLease implements the Interface interface for Empty.

type EmptyNetworkDevice

type EmptyNetworkDevice struct{}

EmptyNetworkDevice is an empty implementation of NetworkDevice.

func (EmptyNetworkDevice) Addresses

func (EmptyNetworkDevice) Addresses() (ips []netip.Addr)

Addresses implements the NetworkDevice interface for EmptyNetworkDevice. It always returns nil.

func (EmptyNetworkDevice) Close

func (EmptyNetworkDevice) Close() (err error)

Close implements the io.Closer interface for EmptyNetworkDevice. It always returns nil.

func (EmptyNetworkDevice) LinkType

func (EmptyNetworkDevice) LinkType() (lt layers.LinkType)

LinkType implements the NetworkDevice interface for EmptyNetworkDevice. It always returns layers.LinkTypeNull.

func (EmptyNetworkDevice) ReadPacketData

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

func (EmptyNetworkDevice) WritePacketData(_ []byte) (err error)

WritePacketData implements the NetworkDevice interface for EmptyNetworkDevice. It always returns nil.

type EmptyNetworkDeviceManager

type EmptyNetworkDeviceManager struct{}

EmptyNetworkDeviceManager is an empty implementation of NetworkDeviceManager.

func (EmptyNetworkDeviceManager) Open

Open implements the NetworkDeviceManager interface for EmptyNetworkDeviceManager. It always returns EmptyNetworkDevice.

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

func (c *IPv4Config) Validate() (err error)

Validate implements the validate.Interface interface for *IPv4Config.

type IPv6Config

type IPv6Config struct {
	// 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.

func (*IPv6Config) Validate

func (c *IPv6Config) Validate() (err error)

Validate implements the validate.Interface interface for *IPv6Config.

type Interface

type Interface interface {
	agh.ServiceWithConfig[*Config]

	// 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

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 not be nil.
	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.

func (*Lease) Clone

func (l *Lease) Clone() (clone *Lease)

Clone returns a deep copy of l.

func (*Lease) IsBlocked

func (l *Lease) IsBlocked() (blocked bool)

IsBlocked returns true if the lease is blocked.

type NetworkDevice

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.
	Addresses() (ips []netip.Addr)

	// LinkType returns the link type of the network interface.
	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

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

func (conf *NetworkDeviceConfig) Validate() (err error)

Validate implements the validate.Interface interface for *NetworkDeviceConfig.

type NetworkDeviceManager

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL