As it turns out, it's fairly difficult to do anything useful with DHCP
without this information, and the Conn implementations I can think of
all provide the information, so we might as well make it a requirement.
Also introduces a "Trace" member to the API, for the future addition of
extremely verbose and complete tracing, to be used for bug reports. But
for now, only Log is used.
This version is still *extremely* barebones, and the unstable tag
in the README applies triple for it, but the code in its current
state is capable of booting x86 and UEFI clients correctly, and
that was hard enough to merit a snapshot checkpoint.
It turns out many PXE firmwares request tsize to size the download
buffer, and will refuse to download at all if the server cannot
provide a tsize.
This unfortunately breaks API compatibility to add a size parameter,
but I think it's an unfortunate necessity to make this work.
Conn is supposed to accept "" to mean "listen for DHCP on all interfaces",
but portableConn didn't correctly handle that.
And I got the comparison wrong on ifidx in the portable send function, so
packets got sent out entirely the wrong interface :(.
This implementation uses a raw IP socket combined with a BPF packet
filter to receive traffic for one UDP port, without having to bind()
to that port. This enables this Conn to coexist on a machine alongside
a DHCP server.
AF_PACKET is poorly suited to be the main receiving socket of this
implementation, for a variety of reasons: it bypasses netfilter, you
receive duplicate packets when bridges and aggregated links are involved,
and more generally it's a lot of pain just to get a MAC address out of
the link layer.
Next up, I'm going to try using an AF_INET/SOCK_RAW socket as the main
listening socket, which loses a bit of precision in acquiring packets, but
puts more of the kernel and its desirable semantics between us and the wire.
We'll still have to use an AF_PACKET socket to transmit to unconfigured
clients (although the spec gives us an option to sidestep that as well
if we want).
We only really use it to pretty-print pcap.Packet, and it was making
`go vet` angry. So we replaced it with a specialized pretty printer
instead. As a nice side-effect, it shows nicer timestamps now.
This is a fairly advanced, linux-specific implementation that lets you run a DHCP
listener on a machine that's already running some other DHCP service.