Files
AdGuardHome/internal/dhcpsvc/config.go
Eugene Burkov d4ee146f6b Pull request #2422: 4923 gopacket dhcp vol.10
Merge in DNS/adguard-home from 4923-gopacket-dhcp-vol.10 to master

Squashed commit of the following:

commit ef2106a35aadecf8340314535ec232f91ff44b50
Merge: f14e68781 f69da062e
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Jun 9 16:13:52 2025 +0300

    Merge branch 'master' into 4923-gopacket-dhcp-vol.10

commit f14e687815eb66a7c161dfaa3655c41fded643a8
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Fri Jun 6 18:36:32 2025 +0300

    dhcpsvc: imp code, docs

commit c94b428d6fd277a840476f02820bd065cde17d6c
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Jun 5 13:21:37 2025 +0300

    dhcpsvc: imp code

commit 57eaea08e572fea41295d373b547f614a0c099ac
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Jun 4 19:48:03 2025 +0300

    dhcpsvc: add methods

commit b32218848cf2a90ecfc9cc6cf12c2579bcb1a2df
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Apr 30 15:57:53 2025 +0300

    dhcpsvc: add handlers

commit 615f1248160351f3bcdb040fb867d32630979d40
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Jan 14 16:10:01 2025 +0300

    dhcpsvc: multiplex dhcpv4
2025-06-10 12:28:51 +03:00

107 lines
2.8 KiB
Go

package dhcpsvc
import (
"fmt"
"log/slog"
"maps"
"os"
"slices"
"time"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/netutil"
"github.com/AdguardTeam/golibs/validate"
)
// Config is the configuration for the DHCP service.
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
// 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
}
// type check
var _ validate.Interface = (*Config)(nil)
// Validate implements the [validate.Interface] for *Config.
func (conf *Config) Validate() (err error) {
switch {
case conf == nil:
return errors.ErrNoValue
case !conf.Enabled:
return nil
}
errs := []error{
validate.NotNegative("ICMPTimeout", conf.ICMPTimeout),
}
err = netutil.ValidateDomainName(conf.LocalDomainName)
if err != nil {
errs = append(errs, fmt.Errorf("LocalDomainName: %w", err))
}
// This is a best-effort check for the file accessibility. The file will be
// checked again when it is opened later.
if _, err = os.Stat(conf.DBFilePath); err != nil && !errors.Is(err, os.ErrNotExist) {
errs = append(errs, fmt.Errorf("DBFilePath %q: %w", conf.DBFilePath, err))
}
if len(conf.Interfaces) == 0 {
err = fmt.Errorf("interfaces: %w", errors.ErrEmptyValue)
errs = append(errs, err)
return errors.Join(errs...)
}
for _, iface := range slices.Sorted(maps.Keys(conf.Interfaces)) {
ifaceConf := conf.Interfaces[iface]
errs = validate.Append(errs, iface, ifaceConf)
}
return errors.Join(errs...)
}
// InterfaceConfig is the configuration of a single DHCP interface.
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
}
// type check
var _ validate.Interface = (*InterfaceConfig)(nil)
// Validate implements the [validate.Interface] interface for *InterfaceConfig.
func (ic *InterfaceConfig) Validate() (err error) {
if ic == nil {
return errors.ErrNoValue
}
return errors.Join(
errors.Annotate(ic.IPv4.Validate(), "ipv4: %w"),
errors.Annotate(ic.IPv6.Validate(), "ipv6: %w"),
)
}