func (h *Handler) SetLeases(leases []*Lease) {
	h.leasesMu.Lock()
	defer h.leasesMu.Unlock()
	h.leasesHW = make(map[string]int)
	h.leasesIP = make(map[int]*Lease)
	for _, l := range leases {
		h.leasesHW[l.HardwareAddr] = l.Num
		h.leasesIP[l.Num] = l
	}
}
SetLeases overwrites the leases database with the specified leases, typically
loaded from persistent storage. There is no locking, so SetLeases must be
called before Serve.
package dhcp4d
import (
	"bytes"
	"encoding/hex"
	"fmt"
	"log"
	"math/rand"
	"net"
	"sort"
	"strings"
	"sync"
	"syscall"
	"time"
	"github.com/rtr7/router7/internal/netconfig"
	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/krolaw/dhcp4"
	"github.com/mdlayher/raw"
)
type Lease struct {
	Num              int       `json:"num"`  
	Addr             net.IP    `json:"addr"`
	HardwareAddr     string    `json:"hardware_addr"`
	Hostname         string    `json:"hostname"`
	HostnameOverride string    `json:"hostname_override"`
	Expiry           time.Time `json:"expiry"`
}
func (l *Lease) Expired(at time.Time) bool {
	return !l.Expiry.IsZero() && at.After(l.Expiry)
}
type Handler struct {
	serverIP    net.IP
	start       net.IP  
	leaseRange  int     
	LeasePeriod time.Duration
	options     dhcp4.Options
	rawConn     net.PacketConn
	iface       *net.Interface
	timeNow func() time.Time
	Leases func([]*Lease, *Lease)
	leasesMu sync.Mutex
	leasesHW map[string]int  
	leasesIP map[int]*Lease
}
func NewHandler(dir string, iface *net.Interface, ifaceName string, conn net.PacketConn) (*Handler, error) {
	serverIP, err := netconfig.LinkAddress(dir, ifaceName)
	if err != nil {
		return nil, err
	}
	if iface == nil {
		iface, err = net.InterfaceByName(ifaceName)
		if err != nil {
			return nil, err
		}
	}
	if conn == nil {
		conn, err = raw.ListenPacket(iface, syscall.ETH_P_ALL, nil)
		if err != nil {
			return nil, err
		}
	}
	serverIP = serverIP.To4()
	start := make(net.IP, len(serverIP))
	copy(start, serverIP)
	start[len(start)-1] += 1
	return &Handler{
		rawConn:    conn,
		iface:      iface,
		leasesHW:   make(map[string]int),
		leasesIP:   make(map[int]*Lease),
		serverIP:   serverIP,
		start:      start,
		leaseRange: 230,
		LeasePeriod: 20 * time.Minute,
		options: dhcp4.Options{
			dhcp4.OptionSubnetMask:       []byte{255, 255, 255, 0},
			dhcp4.OptionRouter:           []byte(serverIP),
			dhcp4.OptionDomainNameServer: []byte(serverIP),
			dhcp4.OptionDomainName:       []byte("lan"),
			dhcp4.OptionDomainSearch:     []byte{0x03, 'l', 'a', 'n', 0x00},
		},
		timeNow: time.Now,
	}, nil
}