Skip to content

go-net-dhcp documentation

A small, dependency-free DHCPv4 server library in pure Go — the RFC 2131 / 2132 wire codec, a stateless decision core, and a real Linux UDP/67 server, built with zero cgo. The module path is github.com/go-net-dhcp/dhcp.

go-net-dhcp/dhcp targets the "one subnet, hand out a lease per known MAC" case — a host that owns a bridge / VLAN and needs to answer DHCP for the guests it spawns on it, without running an external dnsmasq. You supply a Source that resolves a client MAC into a Lease; the library never persists anything itself.

Status: server library complete

RFC 2131 / 2132 parse + build (OFFER / ACK / NAK), the Decide state machine (DISCOVER→OFFER, REQUEST→ACK, mismatched requested-IP→NAK, unknown MAC / other message types→drop), a real Linux SO_BINDTODEVICE UDP/67 server, a cross-platform StubServer, and an optional Prometheus metrics adapter. 100% coverage — socket error branches included, via injectable syscall seams so nothing needs root — gofmt + go vet clean, CI green across the six 64-bit Go targets.

Design in one paragraph

The DHCPv4 wire format is a fixed BOOTP header + a 4-byte magic cookie + a block of TLV options terminated by code 255 — small enough to hand-roll, so the core module has zero third-party dependencies. Everything that does not touch a socket (Parse, BuildReply, Decide) is build-tag-free and portable, and is therefore unit-tested on every platform. Only the UDP/67 bind lives behind //go:build linux. Metrics are an optional hook: pass any Metrics implementation in Options; a Prometheus adapter lives in a separate sub-package so the core stays lean.

Quick taste

opts := dhcp.Options{
    Interface: "br0",
    ServerIP:  netip.MustParseAddr("10.0.0.1"),
    Source: dhcp.SourceFn(func(mac string) (dhcp.Lease, bool) {
        return dhcp.Lease{
            Yiaddr:         netip.MustParseAddr("10.0.0.42"),
            SubnetMaskBits: 24,
            Router:         netip.MustParseAddr("10.0.0.1"),
        }, true
    }),
}
srv, _ := dhcp.NewLinuxServer(opts)
_ = srv.Run(ctx) // blocks until ctx is cancelled

Repositories

Repo What it is
dhcp the library — wire codec, Decide, the Linux server, and the prom metrics adapter
docs this documentation site (MkDocs Material, versioned with mike)
go-net-dhcp.github.io the organization landing page (Hugo)
brand logo and brand assets

Principles

  • Pure Go, CGO_ENABLED=0 — trivial cross-compilation, a single static binary, no C toolchain.
  • Dependency-free core. The wire codec is hand-rolled; the Prometheus adapter is quarantined in its own sub-package.
  • Stateless & caller-driven. You own the address plan via a Source.
  • Testable to the socket. The Linux socket path is covered without root via injectable syscall seams.
  • 100% test coverage is the target, enforced as a CI gate.

Where to go next

Source lives at github.com/go-net-dhcp/dhcp.