Networking in C · intermediate · ~12 min
Decode a DNS question name from its label encoding, safely.
Walk length-prefixed labels to the 0x00 terminator; insert dots; refuse 0xC0 pointer bytes to stay loop-proof.
Label decoding is step one of every DNS tool, and the pointer-refusal is the difference between a safe parser and a DoS.
Every DNS tool — dig, a resolver, a passive-DNS monitor — starts by decoding the QNAME. DNS doesn't store names as dotted strings; it stores them as a chain of length-prefixed labels ending in a zero byte.
03 'w' 'w' 'w' 07 'e' 'x' 'a' 'm' 'p' 'l' 'e' 03 'c' 'o' 'm' 00
└len┘ └label┘ └len┘ └────label────┘ └len┘└label┘ └end
Read a length, copy that many bytes, insert a dot, repeat until the 0x00.
A length byte with its top two bits set (& 0xC0) is a compression pointer
into an earlier part of the packet. Following pointers naively can loop forever
— a classic parser DoS. A defensive decoder that only reads one name refuses
pointer bytes outright.
Implement int parse_dns_qname(const uint8_t *pkt, size_t n, char *out, size_t cap)
that decodes the dotted name, bounds-checking every label against n and every
write against cap, and returns -1 on a pointer byte or any overrun.
Length, bytes, dot, repeat — until 0x00. Bounds-check everything; refuse 0xC0.