Documentation ¶
Overview ¶
Package dhcp4c implements a DHCPv4 Client as specified in RFC2131 (with some notable deviations). It implements only the DHCP state machine itself, any configuration other than the interface IP address (which is always assigned in DHCP and necessary for the protocol to work) is exposed as [informers/observables/watchable variables/???] to consumers who then deal with it.
Package dhcp4c provides a client implementation of the DHCPv4 protocol (RFC2131) and a few extensions for Linux-based systems. The code is split into three main parts:
- The core DHCP state machine, which lives in dhcpc.go
- Mechanisms to send and receive DHCP messages, which live in transport/
- Standard callbacks which implement necessary kernel configuration steps in a simple and standalone way living in callback/
Since the DHCP protocol is ugly and underspecified (see https://tools.ietf.org/html/draft-ietf-dhc-implementation-02 for a subset of known issues), this client slightly bends the specification in the following cases:
- IP fragmentation for DHCP messages is not supported for both sending and receiving messages This is because the major servers (ISC, dnsmasq, ...) do not implement it and just drop fragmented packets, so it would be counterproductive to try to send them. The client just attempts to send the full message and hopes it passes through to the server.
- The suggested timeouts and wait periods have been tightened significantly. When the standard was written 10Mbps Ethernet with hubs was a common interconnect. Using these would make the client extremely slow on today's 1Gbps+ networks.
- Wrong data in DHCP responses is fixed up if possible. This fixing includes dropping prohibited options, clamping semantically invalid data and defaulting not set options as far as it's possible. Non-recoverable responses (for example because a non-Unicast IP is handed out or lease time is not set or zero) are still ignored. All data which can be stored in both DHCP fields and options is also normalized to the corresponding option.
- Duplicate Address Detection is not implemented by default. It's slow, hard to implement correctly and generally not necessary on modern networks as the servers already waste time checking for duplicate addresses. It's possible to hook it in via a LeaseCallback if necessary in a given application.
Operationally, there's one known caveat to using this client: If the lease offered during the select phase (in a DHCPOFFER) is not the same as the one sent in the following DHCPACK the first one might be acceptable, but the second one might not be. This can cause pathological behavior where the client constantly switches between discovering and requesting states. Depending on the reuse policies on the DHCP server this can cause the client to consume all available IP addresses. Sadly there's no good way of fixing this within the boundaries of the protocol. A DHCPRELEASE for the adresse would need to be unicasted so the unaccepable address would need to be configured which can be either impossible if it's not valid or not acceptable from a security standpoint (for example because it overlaps with a prefix used internally) and a DHCPDECLINE would cause the server to blacklist the IP thus also depleting the IP pool. This could be potentially avoided by originating DHCPRELEASE packages from a userspace transport, but said transport would need to be routing- and PMTU-aware which would make it even more complicated than the existing BroadcastTransport.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrInvalidMsg = errors.New("invalid message")
Functions ¶
This section is empty.
Types ¶
type BroadcastTransport ¶
type BroadcastTransport interface { Transport // Open connects the transport. Can only be called after calling Close() or // after creating a new transport. Open() error }
BroadcastTransport represents a mechanism over which DHCP messages can be exchanged with all servers on a Layer 2 broadcast domain. Implementers need to support sending and receiving messages without any IP being configured on the interface.
type Client ¶
type Client struct { // RequestedOptions contains a list of extra options this client is // interested in RequestedOptions dhcpv4.OptionCodeList // ClientIdentifier is used by the DHCP server to identify this client. // If empty, on Ethernet the MAC address is used instead. ClientIdentifier []byte // VendorClassIdentifier is used by the DHCP server to identify options // specific to this type of clients and to populate the vendor-specific // option (43). VendorClassIdentifier string // ExtraRequestOptions are extra options sent to the server. ExtraRequestOptions dhcpv4.Options // Backoff strategies for each state. These all have sane defaults, // override them only if necessary. DiscoverBackoff backoff.BackOff AcceptOfferBackoff backoff.BackOff RenewBackoff backoff.BackOff RebindBackoff backoff.BackOff // LeaseCallback is called every time a lease is aquired, renewed or lost LeaseCallback LeaseCallback // contains filtered or unexported fields }
Client implements a DHCPv4 client.
Note that the size of all data sent to the server (RequestedOptions, ClientIdentifier, VendorClassIdentifier and ExtraRequestOptions) should be kept reasonably small (<500 bytes) in order to maximize the chance that requests can be properly transmitted.
func NewClient ¶
NewClient instantiates (but doesn't start) a new DHCPv4 client. To have a working client it's required to set LeaseCallback to something that is capable of configuring the IP address on the given interface. Unless managed through external means like a routing protocol, setting the default route is also required. A simple example with the callback package thus looks like this:
c := dhcp4c.NewClient(yourInterface) c.LeaseCallback = callback.Compose(callback.ManageIP(yourInterface), callback.ManageDefaultRoute(yourInterface)) c.Run(ctx)
type DNSServers ¶
DNSServers represents an ordered collection of DNS servers
func (DNSServers) Equal ¶
func (a DNSServers) Equal(b DNSServers) bool
type Lease ¶
Lease represents a DHCPv4 lease. It only consists of an IP, an expiration timestamp and options as all other relevant parts of the message have been normalized into their respective options. It also contains some smart getters for commonly-used options which extract only valid information from options.
func (*Lease) DNSServers ¶
func (l *Lease) DNSServers() DNSServers
DNSServers returns all unique valid DNS servers from the DHCP DomainNameServers options. It returns nil if the lease is nil.
func (*Lease) IPNet ¶
IPNet returns an IPNet from the assigned IP and subnet mask. It returns nil if the lease is nil.
func (*Lease) Routes ¶
Routes returns all routes assigned by a DHCP answer. It combines and normalizes data from the Router, StaticRoutingTable and ClasslessStaticRoute options.
func (*Lease) SubnetMask ¶
SubnetMask returns the SubnetMask option or the default mask if not set or invalid. It returns nil if the lease is nil.
type LeaseCallback ¶
type Transport ¶
type Transport interface { // Send attempts to send the given DHCP payload message to the transport // target once. An empty return value does not indicate that the message // was successfully received. Send(payload *dhcpv4.DHCPv4) error // SetReceiveDeadline sets a deadline for Receive() calls after which they // return with ErrDeadlineExceeded SetReceiveDeadline(time.Time) error // Receive waits for a DHCP message to arrive and returns it. If the // deadline expires without a message arriving it will return // ErrDeadlineExceeded. If the message is completely malformed it will an // instance of InvalidMessageError. Receive() (*dhcpv4.DHCPv4, error) // Close closes the given transport. Calls to any of the above methods will // fail if the transport is closed. Specific transports can be reopened // after being closed. Close() error }
Transport represents a mechanism over which DHCP messages can be exchanged with a server.
type UnicastTransport ¶
type UnicastTransport interface { Transport // Open connects the transport to a new unicast target. Can only be called // after calling Close() or after creating a new transport. Open(serverIP, bindIP net.IP) error }
UnicastTransport represents a mechanism over which DHCP messages can be exchanged with a single server over an arbitrary IPv4-based network. Implementers need to support servers running outside the local network via a router.
Directories ¶
Path | Synopsis |
---|---|
Package callback contains minimal callbacks for configuring the kernel with options received over DHCP.
|
Package callback contains minimal callbacks for configuring the kernel with options received over DHCP. |
Package transport contains Linux-based transports for the DHCP broadcast and unicast specifications.
|
Package transport contains Linux-based transports for the DHCP broadcast and unicast specifications. |