-
Notifications
You must be signed in to change notification settings - Fork 1
DNS Overview
This example builds a complete structural validator for DNS packets (RFC 1035) using Hammer. By the end, you'll have a working parser that accepts or rejects raw DNS messages based purely on grammar correctness and protocol constraints.
Unlike many DNS implementations, this example focuses strictly on validation, not semantic extraction. If the packet is structurally correct, it passes. If any invariant is violated, parsing fails.
Prerequisites: Make sure you've completed Getting Started and have either built Hammer in the checkout with
scons examplesor installed Hammer system-wide.
DNS maps human-readable domain names (like example.com) to machine-readable records (like IPv4 or IPv6 addresses).
A DNS message consists of:
- A 12-byte header
- A variable-length body containing:
- Questions
- Answers
- Authority records
- Additional records
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ID |QR|Opcode| DNS Flags | RCode |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Total Questions | Total Answers |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Total Auth Resource Record | Total Add'l Resource Record |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Note: The flags section consists of:
- AA (Authoritative Answer) - 1 bit: Indicates the responding server is authoritative for the queried domain
- TC (Truncated) - 1 bit: Indicates message was truncated
- RD (Recursion Desired) - 1 bit: Client requests recursive resolution
- RA (Recursion Available) - 1 bit: Server indicates it supports recursion
- Z (Reserved) - 3 bits: Always set to 0
DNS names are encoded as:
- One or more labels
- Each label is length-prefixed
- Terminated with
0x00
Example:
03 'w' 'w' 'w'
07 'e' 'x' 'a' 'm' 'p' 'l' 'e'
03 'c' 'o' 'm'
00
DNS also supports compression pointers:
11xxxxxx xxxxxxxx
- The top two bits must be
11 - The remaining 14 bits are an offset from the start of the DNS message
Example:
C0 0C
This means “jump to byte offset 12”.
DNS exercises a wide range of Hammer features:
-
Sub-byte fields - QR, Opcode, and flag bits require
h_bits -
Reserved bit validation - Z bits must be zero (
h_attr_bool) -
Length-prefixed data - Labels and RDATA use
h_length_value -
Pointer validation - Compression requires contextual checks (
h_tell) -
Repetition controlled by header counts -
h_repeat_n -
Alternatives in grammar - Names may be label-based or pointer-based (
h_choice) -
Context storage - Section counts are saved using
h_action
DNS provides real-world complexity without requiring external state.
examples/dns/
├── Makefile # Build system (library + CLI)
├── main.c # Entry point: reads input and runs the parser
├── dns.c # DNS protocol grammar defined with Hammer
├── dns.h # DNSContext and parser prototypes
├── tests/
│ ├── good_packets/ # Structurally valid test packets
│ ├── bad_packets/ # Structurally invalid test packets
│ └── runtests.py # Automated test runner
| File | Role |
|---|---|
main.c |
Entry point. Reads input (stdin or file), runs the header and body parsers, prints result. |
dns.c |
Defines the DNS protocol grammar using Hammer combinators. |
dns.h |
Defines DNSContext and parser declarations (headerParser, bodyParser). |
tests/runtests.py |
Runs all good and bad packet fixtures and checks results. |
From the Hammer repository root, build the checkout-local library first:
scons examplesThen build the DNS example:
cd examples/dns
makeThis produces the dns_parser executable. The Makefile first looks for a checkout-local Hammer library at ../../build/opt/src. If that library is not present, it falls back to pkg-config libhammer.
Run the parser against a known-good packet:
./dns_parser tests/good_packets/1q_pass.binExpected output:
Packet Passed
Run against a malformed packet:
./dns_parser tests/bad_packets/truncated_header.binExpected output:
Packet Failed
Follow these pages in order for the full tutorial:
| # | Page | Hammer Concepts |
|---|---|---|
| 1 | Parsing the Header |
h_bits, h_attr_bool, h_sequence
|
| 2 | Parsing the Body |
h_length_value, h_choice, h_repeat_n, h_tell, h_action
|
| 3 | Assembling the Parser | Combining header and body parsers |
| 4 | Running and Testing | Testing with good and bad packets |
Next: Parsing the Header
Back to: Examples Index · Hammer Fundamentals
Learn Hammer
Protocol Examples
NTP
- NTP Overview
- Parsing the Header
- Parsing Data Fields
- Extension Fields and MAC
- Assembling the Parser
- Hex Input Preprocessing
- Running and Testing
DNS
TFTP
- TFTP Overview
- RRQ/WRQ Packets
- DATA Packets
- ACK Packets
- ERROR Packets
- Assembling the Parser
- Running and Testing
References
- Hammer Quick Reference
- Parsing Backends
- Unit Testing
- Using RTEMS
- Extending Hammer
- Adding a New Example
- Adding a New Binding
Further Reading