diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3 index 31464bf2a..3b86476ea 100644 --- a/docs/libcurl/curl_easy_setopt.3 +++ b/docs/libcurl/curl_easy_setopt.3 @@ -2045,6 +2045,20 @@ resolves, by including a string in the linked list that uses the format and port number must exactly match what was already added previously. (Added in 7.21.3) +.IP CURLOPT_DNS_SERVERS +Set the list of DNS servers to be used instead of the system default. +The format of the dns servers option is: + +host[:port][,host[:port]]... + +For example: + +192.168.1.100,192.168.1.101,3.4.5.6 + +This option requires that libcurl was built with a resolver backend that +supports this operation. The c-ares backend is the only such one. + +(Added in 7.24.0) .SH SSL and SECURITY OPTIONS .IP CURLOPT_SSLCERT Pass a pointer to a zero terminated string as parameter. The string should be diff --git a/include/curl/curl.h b/include/curl/curl.h index f4aa17fdd..8f823486a 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -1486,6 +1486,9 @@ typedef enum { /* allow GSSAPI credential delegation */ CINIT(GSSAPI_DELEGATION, LONG, 210), + /* Set the name servers to use for DNS resolution */ + CINIT(DNS_SERVERS, OBJECTPOINT, 211), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c index 7f3bdf8a2..7c2c372c3 100644 --- a/lib/asyn-ares.c +++ b/lib/asyn-ares.c @@ -600,4 +600,30 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, } return NULL; /* no struct yet */ } + +CURLcode Curl_set_dns_servers(struct SessionHandle *data, + char *servers) +{ + CURLcode result = CURLE_NOT_BUILT_IN; +#if (ARES_VERSION >= 0x010704) + int ares_result = ares_set_servers_csv(data->state.resolver, servers); + switch(ares_result) { + case ARES_SUCCESS: + break; + case ARES_ENOMEM: + result = CURLE_OUT_OF_MEMORY; + break; + case ARES_ENOTINITIALIZED: + case ARES_ENODATA: + case ARES_EBADSTR: + default: + result = CURLE_BAD_FUNCTION_ARGUMENT; + break; + } +#else /* too old c-ares version! */ + (void)data; + (void)servers; +#endif + return result; +} #endif /* CURLRES_ARES */ diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c index 38cde5df7..cd035dc2f 100644 --- a/lib/asyn-thread.c +++ b/lib/asyn-thread.c @@ -696,4 +696,13 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, #endif /* !HAVE_GETADDRINFO */ +CURLcode Curl_set_dns_servers(struct SessionHandle *data, + char *servers) +{ + (void)data; + (void)servers; + return CURLE_NOT_BUILT_IN; + +} + #endif /* CURLRES_THREADED */ diff --git a/lib/hostip.h b/lib/hostip.h index 32a37b9dd..dbbb1f7a2 100644 --- a/lib/hostip.h +++ b/lib/hostip.h @@ -195,4 +195,9 @@ Curl_cache_addr(struct SessionHandle *data, Curl_addrinfo *addr, extern sigjmp_buf curl_jmpenv; #endif +/* + * Function provided by the resolver backend to set DNS servers to use. + */ +CURLcode Curl_set_dns_servers(struct SessionHandle *data, char *servers); + #endif /* HEADER_CURL_HOSTIP_H */ diff --git a/lib/hostsyn.c b/lib/hostsyn.c index b60188708..d1a907924 100644 --- a/lib/hostsyn.c +++ b/lib/hostsyn.c @@ -66,5 +66,16 @@ **********************************************************************/ #ifdef CURLRES_SYNCH +/* + * Function provided by the resolver backend to set DNS servers to use. + */ +CURLcode Curl_set_dns_servers(struct SessionHandle *data, + char *servers) +{ + (void)data; + (void)servers; + return CURLE_NOT_BUILT_IN; + +} #endif /* truly sync */ diff --git a/lib/url.c b/lib/url.c index 4bc82a65f..f478e3828 100644 --- a/lib/url.c +++ b/lib/url.c @@ -2531,6 +2531,10 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, data->set.ssl.authtype = CURL_TLSAUTH_NONE; break; #endif + case CURLOPT_DNS_SERVERS: + result = Curl_set_dns_servers(data, va_arg(param, char *)); + break; + default: /* unknown tag and its companion, just ignore: */ result = CURLE_UNKNOWN_OPTION;