AdGuardHome/internal/dhcpsvc/interface.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

94 lines
2.3 KiB
Go

package dhcpsvc
import (
"fmt"
"log/slog"
"net"
"time"
)
// macKey contains hardware address as byte array of 6, 8, or 20 bytes.
//
// TODO(e.burkov): Move to aghnet or even to netutil.
type macKey any
// macToKey converts mac into macKey, which is used as the key for the lease
// maps. mac must be a valid hardware address of length 6, 8, or 20 bytes, see
// [netutil.ValidateMAC].
func macToKey(mac net.HardwareAddr) (key macKey) {
switch len(mac) {
case 6:
return [6]byte(mac)
case 8:
return [8]byte(mac)
case 20:
return [20]byte(mac)
default:
panic(fmt.Errorf("invalid mac address %#v", mac))
}
}
// netInterface is a common part of any interface within the DHCP server.
//
// TODO(e.burkov): Add other methods as [DHCPServer] evolves.
type netInterface struct {
// logger logs the events related to the network interface.
logger *slog.Logger
// leases is the set of DHCP leases assigned to this interface.
leases map[macKey]*Lease
// name is the name of the network interface.
name string
// leaseTTL is the default Time-To-Live value for leases.
leaseTTL time.Duration
}
// reset clears all the slices in iface for reuse.
func (iface *netInterface) reset() {
clear(iface.leases)
}
// addLease inserts the given lease into iface. It returns an error if the
// lease can't be inserted.
func (iface *netInterface) addLease(l *Lease) (err error) {
mk := macToKey(l.HWAddr)
_, found := iface.leases[mk]
if found {
return fmt.Errorf("lease for mac %s already exists", l.HWAddr)
}
iface.leases[mk] = l
return nil
}
// updateLease replaces an existing lease within iface with the given one. It
// returns an error if there is no lease with such hardware address.
func (iface *netInterface) updateLease(l *Lease) (prev *Lease, err error) {
mk := macToKey(l.HWAddr)
prev, found := iface.leases[mk]
if !found {
return nil, fmt.Errorf("no lease for mac %s", l.HWAddr)
}
iface.leases[mk] = l
return prev, nil
}
// removeLease removes an existing lease from iface. It returns an error if
// there is no lease equal to l.
func (iface *netInterface) removeLease(l *Lease) (err error) {
mk := macToKey(l.HWAddr)
_, found := iface.leases[mk]
if !found {
return fmt.Errorf("no lease for mac %s", l.HWAddr)
}
delete(iface.leases, mk)
return nil
}