diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/curl_addrinfo.c | 21 | ||||
-rw-r--r-- | lib/curl_addrinfo.h | 2 | ||||
-rw-r--r-- | lib/hostip.c | 6 | ||||
-rw-r--r-- | lib/transfer.c | 47 | ||||
-rw-r--r-- | lib/url.c | 14 | ||||
-rw-r--r-- | lib/urldata.h | 4 |
6 files changed, 89 insertions, 5 deletions
diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c index 5098fa431..cfb858c6b 100644 --- a/lib/curl_addrinfo.c +++ b/lib/curl_addrinfo.c @@ -49,6 +49,7 @@ #endif #include "curl_addrinfo.h" +#include "inet_pton.h" #define _MPRINTF_REPLACE /* use our functions only */ #include <curl/mprintf.h> @@ -434,6 +435,26 @@ Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port) return ai; } +/* + * Given an IPv4 or IPv6 dotted string address, this converts it to a proper + * allocated Curl_addrinfo struct and returns it. + */ +Curl_addrinfo *Curl_str2addr(char *address, int port) +{ + struct in_addr in; + if(Curl_inet_pton(AF_INET, address, &in) > 0) + /* This is a dotted IP address 123.123.123.123-style */ + return Curl_ip2addr(AF_INET, &in, address, port); +#ifdef ENABLE_IPV6 + else { + struct in6_addr in6; + if(Curl_inet_pton(AF_INET6, address, &in6) > 0) + /* This is a dotted IPv6 address ::1-style */ + return Curl_ip2addr(AF_INET6, &in6, address, port); + } +#endif + return NULL; /* bad input format */ +} #if defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) /* diff --git a/lib/curl_addrinfo.h b/lib/curl_addrinfo.h index 63159cc4a..11c339474 100644 --- a/lib/curl_addrinfo.h +++ b/lib/curl_addrinfo.h @@ -80,6 +80,8 @@ Curl_he2ai(const struct hostent *he, int port); Curl_addrinfo * Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port); +Curl_addrinfo *Curl_str2addr(char *dotted, int port); + #if defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) void curl_dofreeaddrinfo(struct addrinfo *freethis, diff --git a/lib/hostip.c b/lib/hostip.c index 8f6a52e4f..8e1494e3f 100644 --- a/lib/hostip.c +++ b/lib/hostip.c @@ -421,6 +421,9 @@ int Curl_resolv(struct connectdata *conn, /* See if its already in our dns cache */ dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len+1); + /* free the allocated entry_id again */ + free(entry_id); + /* See whether the returned entry is stale. Done before we release lock */ if( remove_entry_if_stale(data, dns) ) dns = NULL; /* the memory deallocation is being handled by the hash */ @@ -433,9 +436,6 @@ int Curl_resolv(struct connectdata *conn, if(data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); - /* free the allocated entry_id again */ - free(entry_id); - if(!dns) { /* The entry was not in the cache. Resolve it to IP address */ diff --git a/lib/transfer.c b/lib/transfer.c index 754f6e621..ead3a4deb 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -1382,6 +1382,46 @@ Transfer(struct connectdata *conn) return CURLE_OK; } +static void loadhostpairs(struct SessionHandle *data) +{ + struct curl_slist *hostp; + char hostname[256]; + char address[256]; + int port; + + for(hostp = data->change.resolve; hostp; hostp = hostp->next ) { + if(!hostp->data) + continue; + if(hostp->data[0] == '-') { + /* mark an entry for removal */ + } + else if(3 == sscanf(hostp->data, "%255[^:]:%d:%255s", hostname, &port, + address)) { + struct Curl_dns_entry *dns; + Curl_addrinfo *addr; + + addr = Curl_str2addr(address, port); + if(!addr) { + infof(data, "Resolve %s found illegal!\n", hostp->data); + continue; + } + infof(data, "Added %s:%d:%s to DNS cache\n", + hostname, port, address); + + if(data->share) + Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); + + /* put this host in the cache */ + dns = Curl_cache_addr(data, addr, hostname, port); + + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + } + } + data->change.resolve = NULL; /* dealt with now */ +} + + /* * Curl_pretransfer() is called immediately before a transfer starts. */ @@ -1415,9 +1455,12 @@ CURLcode Curl_pretransfer(struct SessionHandle *data) data->info.wouldredirect = NULL; /* If there is a list of cookie files to read, do it now! */ - if(data->change.cookielist) { + if(data->change.cookielist) Curl_cookie_loadfiles(data); - } + + /* If there is a list of host pairs to deal with */ + if(data->change.resolve) + loadhostpairs(data); /* Allow data->set.use_port to set which port to use. This needs to be * disabled for example when we follow Location: headers to URLs using @@ -1750,6 +1750,20 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, */ data->set.quote = va_arg(param, struct curl_slist *); 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 + * removed or the handle is cleaned up. + * + * This API can remove any name 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 *); + data->change.resolve = data->set.resolve; + break; case CURLOPT_PROGRESSFUNCTION: /* * Progress callback function diff --git a/lib/urldata.h b/lib/urldata.h index 4d6059152..489ab16aa 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1186,6 +1186,8 @@ struct DynamicStatic { bool referer_alloc; /* referer sting is malloc()ed */ struct curl_slist *cookielist; /* list of cookie files set by curl_easy_setopt(COOKIEFILE) calls */ + struct curl_slist *resolve; /* set to point to the set.resolve list when + this should be dealt with in pretransfer */ }; /* @@ -1332,6 +1334,8 @@ struct UserDefined { struct curl_slist *source_postquote; /* in 3rd party transfer mode - after the transfer on source host */ struct curl_slist *telnet_options; /* linked list of telnet options */ + struct curl_slist *resolve; /* list of names to add/remove from + DNS cache */ curl_TimeCond timecondition; /* kind of time/date comparison */ time_t timevalue; /* what time to compare with */ Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */ |