Menu

#1303 libcurl not refreshing DNS entries populated with CURLOPT_RESOLVE

closed-fixed
None
5
2015-01-02
2013-11-13
Rômulo C
No

Tested on: Ubuntu/Linux 3.11.0-12-generic, curl 7.34.0-DEV.

This has already been discussed at the curl-library mailing list.

I use the multi interface to cache the connections to some server between requests and CURLOPT_RESOLVE to populate the DNS cache (my scenario is a private GPRS network with no working DNS servers). But even though I initialize the DNS entries with every easy handle libcurl sometimes considers them expired when initiating the connection. As a result libcurl tries to reach one of the default DNS servers, which always results in a CURLE_COULDNT_RESOLVE_HOST in my case.

The documentation states that CURLOPT_RESOLVE just pre-populates the DNS cache, which implies it should follow the same rules about expiration. But since I'm setting the option with every easy handle I would expect the entries to be "refreshed". Moreover, there's a timing issue: depending on how much you wait before the requests libcurl will indeed "refresh" the entries. So, at the very least, the behaviour is not consistent.

I attached a program demonstrating the problem, also available at: https://gist.github.com/romuloceccon/6941606. It outputs the following. Note that you can't reproduce it when omitting the call to sleep():

debug: Added fake.host:80:137.56.161.173 to DNS cache
debug: About to connect() to fake.host port 80 (#0)
debug:   Trying 137.56.161.173...
debug: Adding handle: conn: 0xb81160
debug: Adding handle: send: 0
debug: Adding handle: recv: 0
debug: Curl_addHandleToPipeline: length: 1
debug: - Conn 0 (0xb81160) send_pipe: 1, recv_pipe: 0
debug: Connected to fake.host (137.56.161.173) port 80 (#0)
debug: Server lighttpd/1.4.28 is not blacklisted
debug: Closing connection 0
HTTP transfer completed with status 0
debug: Added fake.host:80:137.56.161.173 to DNS cache
debug: getaddrinfo(3) failed for fake.host:80
debug: Couldn't resolve host 'fake.host'
debug: Closing connection 1
HTTP transfer completed with status 6

I managed to fix it by patching Curl_loadhostpairs() with code copied from Curl_cache_addr(), but because of the timing issue I think it's just covering the real bug somewhere else:

diff --git a/lib/hostip.c b/lib/hostip.c
index f37b492..4157a2a 100644
--- a/lib/hostip.c
+++ b/lib/hostip.c
@@ -807,8 +807,15 @@ CURLcode Curl_loadhostpairs(struct SessionHandle *data)
         /* if not in the cache already, put this host in the cache */
         dns = Curl_cache_addr(data, addr, hostname, port);
       else

+      {
         /* this is a duplicate, free it again */
         Curl_freeaddrinfo(addr);
+        
+        /* reset timestamp */
+        time(&dns->timestamp);
+        if(dns->timestamp == 0)
+          dns->timestamp = 1;   /* zero indicates that entry isn't in hash table */
+      }

       if(data->share)
         Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
1 Attachments

Related

Bugs: #1327

Discussion

  • Rômulo C

    Rômulo C - 2013-11-14

    The documentation changed since I started the discussion on the mailing list. So, please, ignore the paragraph where I talk about it (I don't have permission to edit the ticket).

     
  • Daniel Stenberg

    Daniel Stenberg - 2013-11-17
    • status: open --> open-confirmed
    • assigned_to: Daniel Stenberg
     
  • Daniel Stenberg

    Daniel Stenberg - 2013-11-25

    Thanks for your report. This bug has now been fixed in git, commit 030a2b8cb8c4f1d.

     
  • Daniel Stenberg

    Daniel Stenberg - 2013-11-25
    • status: open-confirmed --> closed-fixed
     
MongoDB Logo MongoDB