mirror of
https://github.com/AdguardTeam/AdGuardHome.git
synced 2024-11-15 18:08:30 -07:00
dhcpsvc: imp code, names, docs
This commit is contained in:
parent
a92f44c752
commit
120c0472f3
42
internal/dhcpsvc/interface.go
Normal file
42
internal/dhcpsvc/interface.go
Normal file
@ -0,0 +1,42 @@
|
||||
package dhcpsvc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
// netInterface is a common part of any network interface within the DHCP
|
||||
// server.
|
||||
//
|
||||
// TODO(e.burkov): Add other methods as [DHCPServer] evolves.
|
||||
type netInterface struct {
|
||||
// name is the name of the network interface.
|
||||
name string
|
||||
|
||||
// leases is a set of leases sorted by hardware address.
|
||||
leases []*Lease
|
||||
|
||||
// leaseTTL is the default Time-To-Live value for leases.
|
||||
leaseTTL time.Duration
|
||||
}
|
||||
|
||||
// reset clears all the slices in the interface for reuse.
|
||||
func (iface *netInterface) reset() {
|
||||
iface.leases = iface.leases[:0]
|
||||
}
|
||||
|
||||
// insertLease inserts the given lease into the interface. It returns an
|
||||
// error if the lease can't be inserted. The error should be informative
|
||||
// enough to be returned as is.
|
||||
func (iface *netInterface) insertLease(l *Lease) (err error) {
|
||||
i, found := slices.BinarySearchFunc(iface.leases, l, compareLeaseMAC)
|
||||
if found {
|
||||
return fmt.Errorf("lease for mac %s already exists", l.HWAddr)
|
||||
}
|
||||
|
||||
iface.leases = slices.Insert(iface.leases, i, l)
|
||||
|
||||
return nil
|
||||
}
|
@ -2,7 +2,6 @@ package dhcpsvc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"time"
|
||||
@ -48,38 +47,7 @@ func (l *Lease) Clone() (clone *Lease) {
|
||||
}
|
||||
}
|
||||
|
||||
// leaseHandler is an interface for handler of leases. It's used to access
|
||||
// leases in a generic way.
|
||||
//
|
||||
// TODO(e.burkov): Add other methods as [DHCPServer] evolves.
|
||||
type leaseHandler struct {
|
||||
// leases is a set of leases sorted by hardware address.
|
||||
leases []*Lease
|
||||
|
||||
// leaseTTL is the default Time-To-Live value for leases.
|
||||
leaseTTL time.Duration
|
||||
}
|
||||
|
||||
// reset clears all the slices in the interface for reuse.
|
||||
func (lh *leaseHandler) reset() {
|
||||
lh.leases = lh.leases[:0]
|
||||
}
|
||||
|
||||
// compareLeaseMAC compares two [Lease]s by hardware address.
|
||||
func compareLeaseMAC(a, b *Lease) (res int) {
|
||||
return bytes.Compare(a.HWAddr, b.HWAddr)
|
||||
}
|
||||
|
||||
// insertLease inserts the given lease into the interface. It returns an
|
||||
// error if the lease can't be inserted. The error should be informative
|
||||
// enough to be returned as is.
|
||||
func (lh *leaseHandler) insertLease(l *Lease) (err error) {
|
||||
i, found := slices.BinarySearchFunc(lh.leases, l, compareLeaseMAC)
|
||||
if found {
|
||||
return fmt.Errorf("lease for mac %s already exists", l.HWAddr)
|
||||
}
|
||||
|
||||
lh.leases = slices.Insert(lh.leases, i, l)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -179,43 +179,56 @@ func (srv *DHCPServer) Reset() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// leasesHandlerForAddr returns the corresponding leasesHandler for the given IP
|
||||
// address.
|
||||
func (srv *DHCPServer) leasesHandlerForAddr(addr netip.Addr) (iface *leaseHandler, err error) {
|
||||
switch {
|
||||
case addr.Is4():
|
||||
i := slices.IndexFunc(srv.interfaces4, func(i *netInterfaceV4) (ok bool) {
|
||||
return i.Contains(addr)
|
||||
})
|
||||
if i >= 0 {
|
||||
return &srv.interfaces4[i].leaseHandler, nil
|
||||
}
|
||||
case addr.Is6():
|
||||
i := slices.IndexFunc(srv.interfaces6, func(i *netInterfaceV6) (ok bool) {
|
||||
return i.Contains(addr)
|
||||
})
|
||||
if i >= 0 {
|
||||
return &srv.interfaces6[i].leaseHandler, nil
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid IP address %s", addr)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no interface for IP address %s", addr)
|
||||
}
|
||||
|
||||
// AddLease implements the [Interface] interface for *DHCPServer.
|
||||
func (srv *DHCPServer) AddLease(l *Lease) (err error) {
|
||||
leases, err := srv.leasesHandlerForAddr(l.IP)
|
||||
if err != nil {
|
||||
return err
|
||||
if l.IP.Is4() {
|
||||
err = srv.addLease4(l)
|
||||
} else {
|
||||
err = srv.addLease6(l)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// addLease4 adds l to the corresponding network interface of srv. The address
|
||||
// of l must have the IPv4 family.
|
||||
func (srv *DHCPServer) addLease4(l *Lease) (err error) {
|
||||
i := slices.IndexFunc(srv.interfaces4, func(iface *netInterfaceV4) (ok bool) {
|
||||
return iface.Contains(l.IP)
|
||||
})
|
||||
if i < 0 {
|
||||
return fmt.Errorf("no interface for IP address %s", l.IP)
|
||||
}
|
||||
|
||||
srv.leasesMu.Lock()
|
||||
defer srv.leasesMu.Unlock()
|
||||
|
||||
if err = leases.insertLease(l); err != nil {
|
||||
// Don't wrap the error, since it's already informative enough as is.
|
||||
err = srv.interfaces4[i].insertLease(l)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
srv.leaseByIP[l.IP] = l
|
||||
srv.leaseByName[strings.ToLower(l.Hostname)] = l
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// addLease6 adds l to the corresponding network interface of srv. The address
|
||||
// of l must have the IPv6 family.
|
||||
func (srv *DHCPServer) addLease6(l *Lease) (err error) {
|
||||
i := slices.IndexFunc(srv.interfaces6, func(iface *netInterfaceV6) (ok bool) {
|
||||
return iface.Contains(l.IP)
|
||||
})
|
||||
if i < 0 {
|
||||
return fmt.Errorf("no interface for IP address %s", l.IP)
|
||||
}
|
||||
|
||||
srv.leasesMu.Lock()
|
||||
defer srv.leasesMu.Unlock()
|
||||
|
||||
err = srv.interfaces6[i].insertLease(l)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -267,9 +267,6 @@ type netInterfaceV4 struct {
|
||||
// addrSpace is the IPv4 address space allocated for leasing.
|
||||
addrSpace ipRange
|
||||
|
||||
// name is the name of the interface.
|
||||
name string
|
||||
|
||||
// implicitOpts are the options listed in Appendix A of RFC 2131 and
|
||||
// initialized with default values. It must not have intersections with
|
||||
// explicitOpts.
|
||||
@ -279,9 +276,9 @@ type netInterfaceV4 struct {
|
||||
// intersections with implicitOpts.
|
||||
explicitOpts layers.DHCPOptions
|
||||
|
||||
// leaseHandler stores and handles leases. It should only be accessed under
|
||||
// the common lock.
|
||||
leaseHandler
|
||||
// netInterface is embedded here to provide some common network interface
|
||||
// logic.
|
||||
netInterface
|
||||
}
|
||||
|
||||
// newNetInterfaceV4 creates a new DHCP interface for IPv4 address family with
|
||||
@ -310,11 +307,11 @@ func newNetInterfaceV4(name string, conf *IPv4Config) (i *netInterfaceV4, err er
|
||||
}
|
||||
|
||||
i = &netInterfaceV4{
|
||||
name: name,
|
||||
gateway: conf.GatewayIP,
|
||||
subnet: subnet,
|
||||
addrSpace: addrSpace,
|
||||
leaseHandler: leaseHandler{
|
||||
netInterface: netInterface{
|
||||
name: name,
|
||||
leaseTTL: conf.LeaseDuration,
|
||||
},
|
||||
}
|
||||
|
@ -90,9 +90,6 @@ type netInterfaceV6 struct {
|
||||
// rangeStart is the first IP address in the range.
|
||||
rangeStart netip.Addr
|
||||
|
||||
// name is the name of the interface.
|
||||
name string
|
||||
|
||||
// implicitOpts are the DHCPv6 options listed in RFC 8415 (and others) and
|
||||
// initialized with default values. It must not have intersections with
|
||||
// explicitOpts.
|
||||
@ -102,9 +99,9 @@ type netInterfaceV6 struct {
|
||||
// intersections with implicitOpts.
|
||||
explicitOpts layers.DHCPv6Options
|
||||
|
||||
// leaseHandler stores and handles leases. It should only be accessed under
|
||||
// the common lock.
|
||||
leaseHandler
|
||||
// netInterface is embedded here to provide some common network interface
|
||||
// logic.
|
||||
netInterface
|
||||
|
||||
// raSLAACOnly defines if DHCP should send ICMPv6.RA packets without MO
|
||||
// flags.
|
||||
@ -124,9 +121,9 @@ func newNetInterfaceV6(name string, conf *IPv6Config) (i *netInterfaceV6) {
|
||||
}
|
||||
|
||||
i = &netInterfaceV6{
|
||||
name: name,
|
||||
rangeStart: conf.RangeStart,
|
||||
leaseHandler: leaseHandler{
|
||||
netInterface: netInterface{
|
||||
name: name,
|
||||
leaseTTL: conf.LeaseDuration,
|
||||
},
|
||||
raSLAACOnly: conf.RASLAACOnly,
|
||||
|
Loading…
Reference in New Issue
Block a user