How to get full DNS responses from the system resolver? DNSServiceQueryRecord not returning errors..
I would like to get the full DNS responses from the system resolver. I'm using DNSServiceQueryRecord, but I can't get negative responses. How do I get the negative responses?
I need the full response because they have clues about network-level censorship. For instance, mismatched case in the name, bad answer RR type, missing SOA record on no answers response.
On Android I can use android_res_nquery, but I couldn't find anything similar on iOS and macOS. The closest I found was DNSServiceQueryRecord, which at least gives me resource records, so I can inspect TTL and name case.
After some struggle, I was able to make it work. I'm using Go with cgo for that: https://github.com/fortuna/gio-test/blob/fortuna-dns/sysresolver_darwin.go
https://github.com/fortuna/gio-test/blob/fortuna-dns/sysresolver_darwin_export.go
My sequence of calls is:
DNSServiceQueryRecord(sdRef, 0, 0, fullname, rrtype, rrclass, (DNSServiceQueryRecordReply)goCallback, context);
fd := C.DNSServiceRefSockFD(sdRef)
nReady, err := unix.Poll([]unix.PollFd{{Fd: int32(fd), Events: unix.POLLIN | unix.POLLERR | unix.POLLHUP}}, timeout)
serviceErr = C.DNSServiceProcessResult(sdRef)
// Here my callback gets called, multiple times for multiple answers.
C.DNSServiceRefDeallocate(sdRef)
I'm able to get positive answers, even multiple answers. But the Poll doesn't return when there are no answers (like for CNAME www.example.com). I expected the poll to return on negative answers, and my callback to be called with an error when calling DNSServiceProcessResult.
Is that not the expected behavior? How do I get notified that a query has no answers?