Skip to content

DNS resolver fails on truncated UDP AAAA responses (missing TCP fallback) #81

Description

@MrIron-no

Description

The custom resolver in ircd_res.c appears to mishandle truncated DNS UDP responses (TC=1) for AAAA lookups.

This causes hostname validation failures for valid IPv6-only hosts where the AAAA answer is returned only after TCP retry.

Reproduction

Example IPv6-only hostname:

ipv6-only.example.net

System DNS tools resolve it correctly:

host -t AAAA ipv6-only.example.net

returns:

2001:db8:1234::42

Reverse lookup:

host 2001:db8:1234::42

returns:

ipv6-only.example.net

However ircd fails to resolve/validate the hostname.

Packet capture

Captured traffic from ircd:

PTR? 2.4.0.0....ip6.arpa
reply: PTR ipv6-only.example.net.

A? ipv6-only.example.net.
reply: NOERROR, 0 answers

AAAA? ipv6-only.example.net.
UDP reply: truncated (TC=1)

TCP retry:
AAAA ipv6-only.example.net. -> 2001:db8:1234::42

So:

  • reverse PTR works
  • AAAA exists
  • DNS server behaves correctly
  • TCP fallback succeeds
  • ircd still fails resolution

Root cause

ircd_res.c uses UDP-only DNS transport:

os_socket(... SOCK_DGRAM ...)
os_sendto_nonb(...)
os_recvfrom_nonb(...)

There does not appear to be TCP fallback support for truncated replies.

The resolver currently treats:

TC=1

as equivalent to:

lookup failed / no answer

and for AAAA requests falls back to querying A:

case T_AAAA:
    if (request->state == REQ_AAAA)
        do_query_name(NULL, NULL, request->name, request, T_A);

This is incorrect.

A truncated DNS response means:

retry the same query over TCP

not:

AAAA lookup failed

Expected behavior

For IPv6 hostname verification:

PTR(ipv6) -> hostname
AAAA(hostname) -> same ipv6 address

If a UDP response has TC=1, the resolver should retry the same query over TCP.

Correct flow:

AAAA over UDP
TC=1
retry AAAA over TCP
receive AAAA
success

Current behavior:

AAAA over UDP
TC=1
treat as failure
fallback to A
A has no record
resolution fails

Suggested fix

Handle truncated replies explicitly:

if (header->tc) {
    retry same query over TCP
}

At minimum, do not fall back AAAA -> A when TC=1.

Environment

  • FreeBSD 14.2
  • ircu2 custom resolver (ircd_res.c)
  • upstream recursive resolver (example: Cloudflare / local resolver)

Impact

This affects valid IPv6-only hosts and causes incorrect hostname resolution failures.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions