mirror of
https://github.com/tailscale/tailscale.git
synced 2026-10-09 11:52:00 -04:00
The resnsend dnsproxyd command this package relays raw DNS messages through was added in Android 10. On Android 9 and older the daemon answers it with FrameworkListener's text "500 Command not recognized", which we read as binary: "500 " passed the negative errno check and "Comm" became the answer length, so every lookup failed with "androiddns: bogus answer length 1131375981". That's what a tailcat user hit on a Fire TV stick, which runs Android 9 under Fire OS 7. Detect that text reply (a binary reply never starts with an ASCII digit) and switch the process over to the daemon's older getaddrinfo command, the one bionic's getaddrinfo proxies through. Parse the single A or AAAA question out of the query, send the command with the matching address family, and synthesize a DNS answer from the addrinfo list that comes back, mapping EAI_NONAME to NXDOMAIN and EAI_NODATA to an empty answer so Go's resolver produces its usual errors. Other query types return an error saying the Android version can't answer them. The reply layout is the field-by-field one netd has used since Android 6.0 (a 64-bit netd may serve a 32-bit client, so it stopped sending the raw struct); Android 5.x's raw struct layout is detected and rejected rather than guessed at. The format was verified against a 32-bit Fire OS 7.7.1.3 device (Android 9, API 28), where a tailcat build with this change resolves names, fetches its DERP map over HTTPS, and accepts a connection from another machine. Updates tailscale/tailcat#126 Change-Id: I7062984c7ec8ce6caf737089e220ef2ca439dcc5 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>