From 0122045b492f2bd41a74769b8e6a9cefc73f988b Mon Sep 17 00:00:00 2001 From: srdusr <99972264+srdusr@users.noreply.github.com> Date: Wed, 27 May 2026 01:04:00 +0200 Subject: Decode DNS answer records (A/AAAA/CNAME) - resolved addresses, not just ancount Probably the single most-wanted thing a packet analyzer shows that this one didn't yet: responses showed ancount=N but never what a query actually resolved to. A, AAAA, and CNAME rdata now render into readable text; every other type is still walked correctly (name/type/ttl/rdlength read and bounds-checked) but not rendered. Needed a second name reader alongside the existing question-only read_dns_name(): real answer records almost always compress their NAME field as a 2-byte pointer back to the question, which the original reader deliberately rejects. read_dns_name_following_pointers() actually follows them, bounded by a maximum jump count rather than a backward-only check - a cycle across pointers pointing at each other would still loop forever under "must point backward", but can't survive a hard cap on jumps followed. Fuzzed the new pointer-chasing logic specifically before trusting it (fuzz_dns, fuzz_summarize, ~5.1M combined runs) - exactly the kind of attacker-influenced-offset code this project's fuzzing exists for. Clean, no crashes or timeouts. Live-verified extensively on wlp1s0: a direct query to 8.8.8.8 for example.com resolved two real A records; a query for www.github.com showed a real CNAME chain; and organic background DNS traffic from this machine's own browser sessions showed AAAA records (including an 8-address response, all correctly listed) and DNS RR type 65 (HTTPS records) correctly producing no answers suffix. --- PLAN.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'PLAN.md') diff --git a/PLAN.md b/PLAN.md index 9837ebb..65130fe 100644 --- a/PLAN.md +++ b/PLAN.md @@ -627,3 +627,40 @@ None currently open. handshake afterward, and a repeat of the earlier real HTTP/3 capture against google.com confirmed genuine QUIC traffic still decodes correctly on UDP. +- DNS answer records: probably the single most-wanted thing a packet + analyzer shows that this one didn't yet - responses showed + ancount=N but never what a query actually resolved to. A, AAAA, and + CNAME rdata are rendered into readable text; every other type is + still walked correctly (name/type/ttl/rdlength all read and + bounds-checked, so parsing the rest of the message doesn't break) + but not rendered, the same "decode the common cases precisely rather + than guess at everything" pattern as TLS's cipher suite names. + Needed a second name reader alongside the existing question-only + read_dns_name(): real answer records almost always compress their + NAME field as a 2-byte pointer back to the question (RFC 1035 + 4.1.4), which the original reader deliberately rejects (a design + decision from when only the question was parsed, preserved as-is). + read_dns_name_following_pointers() actually follows them, bounded by + a maximum jump count rather than a backward-only check - a cycle + across several pointers pointing at each other would still loop + forever under "must point backward", but can't survive a hard cap on + jumps followed. AAAA is rendered with a plain, uncompressed + hex-group formatter local to dns.hpp rather than summarize.hpp's + RFC-5952-canonical ipv6_to_string, for the same circular-include + reason arp_summary/dhcp's yiaddr formatter are where they are: + correct, just not maximally compact. + Fuzzed the new pointer-chasing logic specifically before trusting it + (fuzz_dns, fuzz_summarize, ~2.4M and ~2.7M runs) - exactly the kind + of attacker-influenced-offset code this project's fuzzing exists + for, and the jump-bound is exactly the sort of thing worth confirming + can't be made to hang, not just reasoned about. Clean, no crashes or + timeouts either target. + Live-verified extensively against real DNS traffic on wlp1s0: a + direct query to 8.8.8.8 for example.com correctly resolved two real + A records; a query for www.github.com correctly showed a real CNAME + chain (-> github.com -> 20.87.245.0); and organic background DNS + traffic from this machine's own browser sessions incidentally + captured alongside it showed AAAA records (including one response + with 8 real IPv6 addresses, all correctly listed), and DNS RR type + 65 (HTTPS records, ancount=0 in these captures) correctly producing + no answers suffix since there was nothing to list. -- cgit v1.2.3