Files
lneto/dhcp/allocator.go
2026-06-20 18:20:18 -03:00

66 lines
3.1 KiB
Go

package dhcp
import "net/netip"
// Request is the decoded, allocation-relevant view of an inbound client message
// passed to an [Allocator]. All slice fields alias the caller's receive buffer
// and are only valid for the duration of the call; an implementation that needs
// to persist them must copy.
type Request struct {
// ClientID identifies the client. For DHCPv4 this is the client identifier
// option when present, otherwise the client hardware address. For DHCPv6 it
// is the client DUID.
ClientID []byte
// Requested is the address the client asked for (DHCPv4 "Requested IP
// Address" option), or the zero value when the client expressed no
// preference.
Requested netip.Addr
// Subnet is the server's configured allocation prefix. It is the zero value
// when the server does not constrain allocation to a prefix.
Subnet netip.Prefix
// Hostname is the client-supplied hostname, or nil.
Hostname []byte
// ParamReqList is the client's parameter request list, or nil.
ParamReqList []byte
}
// Allocator owns a DHCP server's lease database: the address pool, the
// persisted client-to-address bindings, and the lease lifetime / expiration
// policy. A server delegates address assignment to an Allocator so that it only
// has to drive the protocol state machine.
//
// Implementations that expire leases must obtain time from a caller-injected
// clock rather than calling time.Now directly, in keeping with lneto's
// time-independent design.
//
// Offer and Commit model the two phases of acquisition: Offer makes a tentative
// reservation in response to a DHCPv4 DISCOVER (or DHCPv6 SOLICIT), and Commit
// binds it in response to a REQUEST. Implementations may treat Offer
// idempotently so that a repeated DISCOVER for the same client returns the same
// reservation.
type Allocator interface {
// Offer tentatively reserves a binding for the requesting client and
// returns it. It is called when the server receives a DISCOVER/SOLICIT.
Offer(Request) (Binding, error)
// Commit binds a previously offered reservation, finalizing the lease, and
// returns the committed binding. It is called when the server receives a
// REQUEST.
Commit(Request) (Binding, error)
// Release frees the binding held for the given client identity. It is
// called when the server receives a RELEASE. Releasing an unknown client is
// not an error.
Release(clientID []byte) error
// Decline marks the addresses in the request as unusable, typically because
// the client detected an address conflict. It is called when the server
// receives a DECLINE.
Decline(Request) error
// AppendOptions lets the allocator customize the option bytes the server is
// about to send. dst already contains the options the server derived from
// its own configuration (server identifier, router, subnet mask, DNS, lease
// times, ...) for the given client and binding. The implementation may
// append further options, or rewrite the existing ones, and must return the
// resulting slice. The returned slice must not exceed dst's capacity.
AppendOptions(dst []byte, clientID []byte, b Binding) ([]byte, error)
}