libcurl: New options to bind DNS to local interfaces or IP addresses
authorKim Vandry <vandry@TZoNE.ORG>
Sat, 7 Sep 2013 16:45:50 +0000 (12:45 -0400)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 12 Sep 2013 19:11:47 +0000 (21:11 +0200)
docs/libcurl/curl_easy_setopt.3
docs/libcurl/symbols-in-versions
include/curl/curl.h
include/curl/typecheck-gcc.h
lib/asyn-ares.c
lib/asyn-thread.c
lib/hostip.h
lib/hostsyn.c
lib/url.c

index f408482..b370855 100644 (file)
@@ -2298,6 +2298,36 @@ 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)
+.IP CURLOPT_DNS_INTERFACE
+Pass a char * as parameter. Set the name of the network interface that
+the DNS resolver should bind to. This must be an interface name (not an
+address). Set this option to NULL to use the default setting (don't
+bind to a specific interface).
+
+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.33.0)
+.IP CURLOPT_DNS_LOCAL_IP4
+Set the local IPv4 address that the resolver should bind to. The argument
+should be of type char * and contain a single IPv4 address as a string.
+Set this option to NULL to use the default setting (don't
+bind to a specific IP address).
+
+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.33.0)
+.IP CURLOPT_DNS_LOCAL_IP6
+Set the local IPv6 address that the resolver should bind to. The argument
+should be of type char * and contain a single IPv6 address as a string.
+Set this option to NULL to use the default setting (don't
+bind to a specific IP address).
+
+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.33.0)
 .IP CURLOPT_ACCEPTTIMEOUT_MS
 Pass a long telling libcurl the maximum number of milliseconds to wait for a
 server to connect back to libcurl when an active FTP connection is used. If no
index 3e20cd6..7c362cd 100644 (file)
@@ -332,6 +332,9 @@ CURLOPT_DEBUGDATA               7.9.6
 CURLOPT_DEBUGFUNCTION           7.9.6
 CURLOPT_DIRLISTONLY             7.17.0
 CURLOPT_DNS_CACHE_TIMEOUT       7.9.3
+CURLOPT_DNS_INTERFACE           7.33.0
+CURLOPT_DNS_LOCAL_IP4           7.33.0
+CURLOPT_DNS_LOCAL_IP6           7.33.0
 CURLOPT_DNS_SERVERS             7.24.0
 CURLOPT_DNS_USE_GLOBAL_CACHE    7.9.3         7.11.1
 CURLOPT_EGDSOCKET               7.7
index 239cecb..4e09cf7 100644 (file)
@@ -1556,6 +1556,19 @@ typedef enum {
   /* The XOAUTH2 bearer token */
   CINIT(XOAUTH2_BEARER, OBJECTPOINT, 220),
 
+  /* Set the interface string to use as outgoing network
+   * interface for DNS requests.
+   * Only supported by the c-ares DNS backend */
+  CINIT(DNS_INTERFACE, OBJECTPOINT, 221),
+
+  /* Set the local IPv4 address to use for outgoing DNS requests.
+   * Only supported by the c-ares DNS backend */
+  CINIT(DNS_LOCAL_IP4, OBJECTPOINT, 222),
+
+  /* Set the local IPv4 address to use for outgoing DNS requests.
+   * Only supported by the c-ares DNS backend */
+  CINIT(DNS_LOCAL_IP6, OBJECTPOINT, 223),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 
index a9fee0c..e8f1dff 100644 (file)
@@ -265,6 +265,10 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
    (option) == CURLOPT_RTSP_STREAM_URI ||                                     \
    (option) == CURLOPT_RTSP_TRANSPORT ||                                      \
    (option) == CURLOPT_XOAUTH2_BEARER ||                                      \
+   (option) == CURLOPT_DNS_SERVERS ||                                         \
+   (option) == CURLOPT_DNS_INTERFACE ||                                       \
+   (option) == CURLOPT_DNS_LOCAL_IP4 ||                                       \
+   (option) == CURLOPT_DNS_LOCAL_IP6 ||                                       \
    0)
 
 /* evaluates to true if option takes a curl_write_callback argument */
index 081667d..fa12f21 100644 (file)
@@ -623,4 +623,65 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data,
 #endif
   return result;
 }
+
+CURLcode Curl_set_dns_interface(struct SessionHandle *data,
+                                const char *interface)
+{
+#if (ARES_VERSION >= 0x010704)
+  if(!interface) interface = "";
+  ares_set_local_dev((ares_channel)data->state.resolver, interface);
+  return CURLE_OK;
+#else /* c-ares version too old! */
+  (void)data;
+  (void)interface;
+  return CURLE_NOT_BUILT_IN;
+#endif
+}
+
+CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
+                                const char *local_ip4)
+{
+#if (ARES_VERSION >= 0x010704)
+  uint32_t a4;
+
+  if((!local_ip4) || (local_ip4[0] == 0)) {
+    a4 = 0; /* disabled: do not bind to a specific address */
+  }
+  else {
+    if(Curl_inet_pton(AF_INET, local_ip4, &a4) != 1) {
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    }
+  }
+  ares_set_local_ip4((ares_channel)data->state.resolver, ntohl(a4));
+  return CURLE_OK;
+#else /* c-ares version too old! */
+  (void)data;
+  (void)local_ip4;
+  return CURLE_NOT_BUILT_IN;
+#endif
+}
+
+CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
+                                const char *local_ip6)
+{
+#if (ARES_VERSION >= 0x010704)
+  unsigned char a6[INET6_ADDRSTRLEN];
+
+  if((!local_ip6) || (local_ip6[0] == 0)) {
+    /* disabled: do not bind to a specific address */
+    memset(a6, 0, sizeof(a6));
+  }
+  else {
+    if(Curl_inet_pton(AF_INET6, local_ip6, a6) != 1) {
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    }
+  }
+  ares_set_local_ip6((ares_channel)data->state.resolver, a6);
+  return CURLE_OK;
+#else /* c-ares version too old! */
+  (void)data;
+  (void)local_ip6;
+  return CURLE_NOT_BUILT_IN;
+#endif
+}
 #endif /* CURLRES_ARES */
index 81d1d5d..206dcdb 100644 (file)
@@ -635,4 +635,28 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data,
 
 }
 
+CURLcode Curl_set_dns_interface(struct SessionHandle *data,
+                                const char *interface)
+{
+  (void)data;
+  (void)interface;
+  return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
+                                const char *local_ip4)
+{
+  (void)data;
+  (void)local_ip4;
+  return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
+                                const char *local_ip6)
+{
+  (void)data;
+  (void)local_ip6;
+  return CURLE_NOT_BUILT_IN;
+}
+
 #endif /* CURLRES_THREADED */
index a38f732..997800a 100644 (file)
@@ -201,6 +201,27 @@ extern sigjmp_buf curl_jmpenv;
 CURLcode Curl_set_dns_servers(struct SessionHandle *data, char *servers);
 
 /*
+ * Function provided by the resolver backend to set
+ * outgoing interface to use for DNS requests
+ */
+CURLcode Curl_set_dns_interface(struct SessionHandle *data,
+                                const char *interface);
+
+/*
+ * Function provided by the resolver backend to set
+ * local IPv4 address to use as source address for DNS requests
+ */
+CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
+                                const char *local_ip4);
+
+/*
+ * Function provided by the resolver backend to set
+ * local IPv6 address to use as source address for DNS requests
+ */
+CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
+                                const char *local_ip6);
+
+/*
  * Clean off entries from the cache
  */
 void Curl_hostcache_clean(struct SessionHandle *data, struct curl_hash *hash);
index 65a4035..24f8dd8 100644 (file)
@@ -72,4 +72,40 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data,
 
 }
 
+/*
+ * Function provided by the resolver backend to set
+ * outgoing interface to use for DNS requests
+ */
+CURLcode Curl_set_dns_interface(struct SessionHandle *data,
+                                const char *interface)
+{
+  (void)data;
+  (void)interface;
+  return CURLE_NOT_BUILT_IN;
+}
+
+/*
+ * Function provided by the resolver backend to set
+ * local IPv4 address to use as source address for DNS requests
+ */
+CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
+                                const char *local_ip4)
+{
+  (void)data;
+  (void)local_ip4;
+  return CURLE_NOT_BUILT_IN;
+}
+
+/*
+ * Function provided by the resolver backend to set
+ * local IPv6 address to use as source address for DNS requests
+ */
+CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
+                                const char *local_ip6)
+{
+  (void)data;
+  (void)local_ip6;
+  return CURLE_NOT_BUILT_IN;
+}
+
 #endif /* truly sync */
index 50ce80d..c1672d0 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -2455,6 +2455,15 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
   case CURLOPT_DNS_SERVERS:
     result = Curl_set_dns_servers(data, va_arg(param, char *));
     break;
+  case CURLOPT_DNS_INTERFACE:
+    result = Curl_set_dns_interface(data, va_arg(param, char *));
+    break;
+  case CURLOPT_DNS_LOCAL_IP4:
+    result = Curl_set_dns_local_ip4(data, va_arg(param, char *));
+    break;
+  case CURLOPT_DNS_LOCAL_IP6:
+    result = Curl_set_dns_local_ip6(data, va_arg(param, char *));
+    break;
 
   case CURLOPT_TCP_KEEPALIVE:
     data->set.tcp_keepalive = (0 != va_arg(param, long))?TRUE:FALSE;