summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPaul Groke <paul.groke@dynatrace.com>2020-12-10 17:38:14 +0100
committerDaniel Stenberg <daniel@haxx.se>2020-12-29 17:49:36 +0100
commit8324dc8b1a730445e7aa91f62d7f88b8376e4aee (patch)
treef4ef26e256e8887a5cc6adb34a3c504dcd5d449d /lib
parent68dde8e330a2580c1af3f34cc1971716948c307b (diff)
downloadcurl-8324dc8b1a730445e7aa91f62d7f88b8376e4aee.tar.gz
dns: extend CURLOPT_RESOLVE syntax for adding non-permanent entries
Extend the syntax of CURLOPT_RESOLVE strings: allow using a '+' prefix (similar to the existing '-' prefix for removing entries) to add DNS cache entries that will time out just like entries that are added by libcurl itself. Append " (non-permanent)" to info log message in case a non-permanent entry is added. Adjust relevant comments to reflect the new behavior. Adjust documentation. Extend unit1607 to test the new functionality. Closes #6294
Diffstat (limited to 'lib')
-rw-r--r--lib/hostip.c36
-rw-r--r--lib/hostip.h2
-rw-r--r--lib/setopt.c13
3 files changed, 33 insertions, 18 deletions
diff --git a/lib/hostip.c b/lib/hostip.c
index ab1f6df05..50fb42f21 100644
--- a/lib/hostip.c
+++ b/lib/hostip.c
@@ -444,7 +444,7 @@ Curl_cache_addr(struct Curl_easy *data,
dns->addr = addr; /* this is the address(es) */
time(&dns->timestamp);
if(dns->timestamp == 0)
- dns->timestamp = 1; /* zero indicates CURLOPT_RESOLVE entry */
+ dns->timestamp = 1; /* zero indicates permanent CURLOPT_RESOLVE entry */
/* Store the resolved data in our DNS cache. */
dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len + 1,
@@ -916,17 +916,24 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
char *addr_end;
char *port_ptr;
char *end_ptr;
+ bool permanent = TRUE;
+ char *host_begin;
char *host_end;
unsigned long tmp_port;
bool error = true;
- host_end = strchr(hostp->data, ':');
+ host_begin = hostp->data;
+ if(host_begin[0] == '+') {
+ host_begin++;
+ permanent = FALSE;
+ }
+ host_end = strchr(host_begin, ':');
if(!host_end ||
- ((host_end - hostp->data) >= (ptrdiff_t)sizeof(hostname)))
+ ((host_end - host_begin) >= (ptrdiff_t)sizeof(hostname)))
goto err;
- memcpy(hostname, hostp->data, host_end - hostp->data);
- hostname[host_end - hostp->data] = '\0';
+ memcpy(hostname, host_begin, host_end - host_begin);
+ hostname[host_end - host_begin] = '\0';
port_ptr = host_end + 1;
tmp_port = strtoul(port_ptr, &end_ptr, 10);
@@ -1008,18 +1015,22 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
- /* See if its already in our dns cache */
+ /* See if it's already in our dns cache */
dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
if(dns) {
infof(data, "RESOLVE %s:%d is - old addresses discarded!\n",
hostname, port);
- /* delete old entry entry, there are two reasons for this
+ /* delete old entry, there are two reasons for this
1. old entry may have different addresses.
2. even if entry with correct addresses is already in the cache,
but if it is close to expire, then by the time next http
request is made, it can get expired and pruned because old
- entry is not necessarily marked as added by CURLOPT_RESOLVE. */
+ entry is not necessarily marked as permanent.
+ 3. when adding a non-permanent entry, we want it to remove and
+ replace an existing permanent entry.
+ 4. when adding a non-permanent entry, we want it to get a "fresh"
+ timeout that starts _now_. */
Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
}
@@ -1027,10 +1038,11 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
/* put this new host in the cache */
dns = Curl_cache_addr(data, head, hostname, port);
if(dns) {
- dns->timestamp = 0; /* mark as added by CURLOPT_RESOLVE */
+ if(permanent)
+ dns->timestamp = 0; /* mark as permanent */
/* release the returned reference; the cache itself will keep the
* entry alive: */
- dns->inuse--;
+ dns->inuse--;
}
if(data->share)
@@ -1040,8 +1052,8 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
Curl_freeaddrinfo(head);
return CURLE_OUT_OF_MEMORY;
}
- infof(data, "Added %s:%d:%s to DNS cache\n",
- hostname, port, addresses);
+ infof(data, "Added %s:%d:%s to DNS cache%s\n",
+ hostname, port, addresses, permanent ? "" : " (non-permanent)");
/* Wildcard hostname */
if(hostname[0] == '*' && hostname[1] == '\0') {
diff --git a/lib/hostip.h b/lib/hostip.h
index 724a03d7f..18485ec61 100644
--- a/lib/hostip.h
+++ b/lib/hostip.h
@@ -65,7 +65,7 @@ struct Curl_hash *Curl_global_host_cache_init(void);
struct Curl_dns_entry {
struct Curl_addrinfo *addr;
- /* timestamp == 0 -- CURLOPT_RESOLVE entry, doesn't timeout */
+ /* timestamp == 0 -- permanent CURLOPT_RESOLVE entry (doesn't time out) */
time_t timestamp;
/* use-counter, use Curl_resolv_unlock to release reference */
long inuse;
diff --git a/lib/setopt.c b/lib/setopt.c
index a6cc562eb..cd7ec3fa8 100644
--- a/lib/setopt.c
+++ b/lib/setopt.c
@@ -1460,13 +1460,16 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_RESOLVE:
/*
- * List of NAME:[address] names to populate the DNS cache with
- * Prefix the NAME with dash (-) to _remove_ the name from the cache.
- *
- * Names added with this API will remain in the cache until explicitly
+ * List of HOST:PORT:[addresses] strings to populate the DNS cache with
+ * Entries added this way will remain in the cache until explicitly
* removed or the handle is cleaned up.
*
- * This API can remove any name from the DNS cache, but only entries
+ * Prefix the HOST with plus sign (+) to have the entry expire just like
+ * automatically added entries.
+ *
+ * Prefix the HOST with dash (-) to _remove_ the entry from the cache.
+ *
+ * This API can remove any entry from the DNS cache, but only entries
* that aren't actually in use right now will be pruned immediately.
*/
data->set.resolve = va_arg(param, struct curl_slist *);