ttl returned by DNSServiceQueryRecord() has value 4502 and it never changes.

My application caches reverse lookups of IP addresses. I use DNSServiceQueryRecord() in order to obtain the ttl of the returned record.

Many of the lookups return the same ttl of 4502 which seems erroneous. Requesting the same address repeatedly returns that value when I would expect it to be decreasing.

I submitted a Feedback with sample project attached.

Feedback: FB23574201

Answered by DTS Engineer in 896469022
I would expect it to be decreasing.

That’s not how this API works. Quoting the doc comments in <dns_sd.h>:

The ttl value is not updated when the daemon answers from the cache

What are you trying to do with this value? There may be a better option.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I would expect it to be decreasing.

That’s not how this API works. Quoting the doc comments in <dns_sd.h>:

The ttl value is not updated when the daemon answers from the cache

What are you trying to do with this value? There may be a better option.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I am caching the results of the query until the ttl expires. The application is monitoring network traffic and may see several thousand IP addresses in a short time period.

I did read the documentation in the header and it seemed to me that the portion quoted only applies when the async operation is left running. If it applies to all queries then maybe it should be the first line in the documentation, but that's quibbling.

This strategy worked well when using libresolv. My workaround for now is to cache the result for 300 seconds if I see the specific value of 4502.

Thanks for your input.

Accepted Answer

Oh, one last thing. A response tells you whether it came from the cache or not via the kDNSServiceFlagAnsweredFromCache. If that’s set, you don’t need to cache the response yourself because mDNSResponder has done so. And if it’s not set, you know the response just came from the network and thus the TTL makes sense.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks Quinn. Much appreciated.

That didn't work as expected/hoped for. After flushing the DNS cache (dscacheutil etc..) I checked the kDNSServiceFlagAnsweredFromCache and it does toggle on the second query for the same IP address, indicating a network result for the first query and from the cache in the second case.

However in both cases it returns this value of 4502 as the TTL. I was expecting a more reasonable value for the first case where the resolver was clean.

I was expecting a more reasonable value

I’m confused. What makes you think that a TTL of 4502 is unreasonable?

In your bug report you mentioned google.com, so let’s explore that:

% dig @8.8.8.8 -t A google.com.
…
;; ANSWER SECTION:
google.com.		93	IN	A	142.250.140.113
…
% dig @8.8.8.8 -t PTR +ttl 113.140.250.142.in-addr.arpa.
…
113.140.250.142.in-addr.arpa. 3121 IN	PTR	wj-in-f113.1e100.net.
…

IMPORTANT This is going directly to Google’s DNS server, meaning it skips mDNSResponder entirely.

The TTL here is 3121, which is pretty similar to the 4502 value you’re getting. And given the scope of their network, it doesn’t surprise me that I’d see somewhat different values in different contexts. And thus my confusion as to why you think this is a problem.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I think it's a problem because 4502 is the most frequent ttl returned by mDNSResponder and there is no explanation in the documentation as to why this should be. It looks to me like a hard-coded default response. Maybe it is a maximum allowable ttl or indication of some other network error.

When I used libresolv (as I presume is used by dig and host) I did not have this issue.

I have attached a debug log from my application to FB23574201 which may help.

Consider this:

% dig @1.1.1.1 +ttl -t PTR 110.42.251.142.in-addr.arpa.    
…
110.42.251.142.in-addr.arpa. 86400 IN	PTR	tzsyda-af-in-f14.1e100.net.
110.42.251.142.in-addr.arpa. 86400 IN	PTR	bom07s45-in-f14.1e100.net.
…
% dig @8.8.8.8 +ttl -t PTR 110.42.251.142.in-addr.arpa.    
…
110.42.251.142.in-addr.arpa. 21600 IN	PTR	bom07s45-in-f14.1e100.net.
110.42.251.142.in-addr.arpa. 21600 IN	PTR	tzsyda-af-in-f14.1e100.net.
…
% dig @192.168.1.1 +ttl -t PTR 110.42.251.142.in-addr.arpa.
…
110.42.251.142.in-addr.arpa. 86176 IN	PTR	tzsyda-af-in-f14.1e100.net.
…

So:

  • Cloudflare gives you a day.
  • Google gives you 6 hours.
  • My home gateway gives me just under a day.

So it’s reasonable for a specific DNS client to artificially limit the TTL of these records.

As to where mDNSResponder is getting 4502, that’s a little over 75 minutes and a quick search in Darwin turned up that value. I don’t fully understand all the implications of that code, but it almost certainly explains what you’re seeing.

Coming back to your big picture issue, I don’t see any way to tell mDNSResponder to cache for longer, or to return the original TTL value so you can cache for longer.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thank you Quinn - that fully explains the results I'm seeing. Trust in the source.

ttl returned by DNSServiceQueryRecord() has value 4502 and it never changes.
 
 
Q