Every answer is a resource record - a name, a type, a class, a time-to-live, and a length-prefixed data blob. Today you parse that fixed framing and use RDLENGTH to carve out exactly the right RDATA bytes.
Parse a resource record's fixed fields and bound its RDATA by RDLENGTH.
An answer in a DNS response is a resource record (RR), and it opens with a fixed frame you already have most of the pieces for: a NAME (a possibly compressed name, decoded with chapter three’s decoder), a 16-bit TYPE, a 16-bit CLASS, a 32-bit TTL (how many seconds the answer may be cached), and a 16-bit RDLENGTH. After that come exactly RDLENGTH bytes of type-specific RDATA.
The rule that keeps a parser honest is that RDLENGTH bounds the RDATA - you
slice off precisely that many bytes and no more, even if useful-looking bytes
follow (here a stray FF that belongs to the next record). That is why the record
consumes fifteen bytes, not sixteen. TTL is your first 32-bit field, so read it as
four big-endian bytes. It is also worth recording where the RDATA begins (its
offset within the whole message), not just the slice: some record types (NS, CNAME,
MX, SOA) put a compressed name in their RDATA whose pointers are relative to the
start of the message, so a later lesson will need that absolute offset to decode
them. Once the frame is parsed, each record type is just a different way of reading
the RDATA - which is the whole rest of this chapter.
type RR struct {Name stringType, Class uint16TTL uint32RData []byte}// name, then TYPE(2) CLASS(2) TTL(4) RDLENGTH(2), then RDLENGTH data bytesrdlen := int(uint16At(b, i)); i += 2rr.RData = b[i : i+rdlen] // bounded strictly by RDLENGTH