networking · intermediate · ~15 min
Construct raw binary DNS headers and encode domain names into RFC 1035 wire labels.
DNS queries use a 12-byte binary header followed by labeled domain name questions (e.g. "\x03www\x06google\x03com\x00"). Network tools pack these wire records in big-endian network byte order.
Implement:
int pack_dns_query_header(uint16_t tx_id, uint16_t question_count, uint8_t *wire, size_t wire_cap);
int encode_dns_qname(const char *domain, uint8_t *wire, size_t wire_cap, size_t *qname_len);
pack_dns_query_header:wire == NULL or wire_cap < 12, return -1.tx_id (big endian)0x0100 (standard query with recursion desired)question_count (big endian)12.encode_dns_qname:domain == NULL, wire == NULL, qname_len == NULL, or wire_cap == 0, return -1."abc.com") to label format (\x03abc\x03com\x00).1..63. Empty labels (consecutive dots ..) return -1.wire_cap, return -1.wire, set *qname_len, and return 0.uint8_t wire[64];
pack_dns_query_header(0x1234, 1, wire, sizeof(wire)); // returns 12
size_t qlen = 0;
encode_dns_qname("example.org", wire + 12, sizeof(wire) - 12, &qlen); // wire becomes \x07example\x03org\x00
tx_id, question_count: uint16_t; domain: string; wire buffers and capacities.
Returns 12 on header pack, 0 on qname encode, or -1 on error.
Big-endian network byte order. Bounded label format validation.
#include <stddef.h>
#include <stdint.h>
int pack_dns_query_header(uint16_t tx_id, uint16_t question_count, uint8_t *wire, size_t wire_cap) {
(void)tx_id; (void)question_count; (void)wire; (void)wire_cap;
return -1;
}
int encode_dns_qname(const char *domain, uint8_t *wire, size_t wire_cap, size_t *qname_len) {
(void)domain; (void)wire; (void)wire_cap; (void)qname_len;
return -1;
}
Forgetting terminating 0x00 byte on QNAME; wrong byte order for transaction ID.
Labels longer than 63 bytes rejected; consecutive dots rejected; trailing dot handled gracefully.
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.