Today I've been writing a netfilter-queue for modifying IP packets. Every time I do something involving Ethernet, IP, TCP and what-not, I'm reminded how crazy the headers are. For example, you can add up to 40 bytes of IP option data to an IP header (allocated in 4 byte chunks) via a 4-bit length field. Each option has a field to specify that particular option's type (8-bit), and length (8-bit). The length field denotes the number of bytes in that option header. A single option could be, at most, 40 bytes including its type and length fields, so we have a couple more bits than we need there in the length. Bit of an imbalance between the 4-bit IP header length and 8-bit option field length, and a couple of wasted bits that might have been better spent on a more expressive type field.
Oh well, at least IPv6 is a fair bit nicer!