Master the fundamental concepts of protocol implementation through this focused micro-challenge.
DNS translates names like example.com into IP addresses like 93.184.216.34. A query fits in a single UDP datagram to port 53 on a resolver such as 8.8.8.8.
The 12-byte header contains:
0x1234)A type-A query (type 1, class 1) asks for an IPv4 address. The name is encoded in length-prefixed labels: 7example3com0 for example.com.
The answer section returns the resolved name, type, TTL, and the 4-byte IPv4 address. Other record types include AAAA for IPv6, MX for mail routing, and NS for delegating authority to another nameserver. Recursive resolvers set the RD (recursion desired) bit and rely on upstream servers to chase referrals through the authority section.
This task requires you to build a DNS query packet and parse the response. glibc's getaddrinfo() does this internally against resolvers like 8.8.8.8 or 1.1.1.1, encoding names into DNS's length-prefixed label format before parsing the answer section. Dan Kaminsky's 2008 cache-poisoning attack exploited weak randomization in the very transaction ID field you set here, which is why modern resolvers randomize both the ID and the source port.
Write a C program that builds a DNS query packet, sends it via UDP to 8.8.8.8 (Google Public DNS), and parses the response.
Requirements:
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
All starter code and reference implementations are available for your local setup.
View on Github