curl plugin: add AddressFamily
authorJakub Jankowski <shasta@toxcorp.com>
Sat, 3 Nov 2018 01:51:29 +0000 (02:51 +0100)
committerJakub Jankowski <shasta@toxcorp.com>
Sat, 3 Nov 2018 01:51:29 +0000 (02:51 +0100)
In situations when hostnames in URLs resolve to both IPv4 and IPv6
addresses, sometimes it's useful to have separate statistics for both
of these separately.

With this commit, within <Page> block you can set
  AddressFamily "ipv6"
or
  AddressFamily "ipv4"
to specifically use one or the other.

Signed-off-by: Jakub Jankowski <shasta@toxcorp.com>
src/collectd.conf.in
src/collectd.conf.pod
src/curl.c

index b7c1b27..335ec8c 100644 (file)
 #<Plugin curl>
 #  <Page "stock_quotes">
 #    URL "http://finance.google.com/finance?q=NYSE%3AAMD"
+#    AddressFamily "any"
 #    User "foo"
 #    Password "bar"
 #    Digest false
index 03b163e..f62417b 100644 (file)
@@ -1795,6 +1795,7 @@ finance page and dispatch the value to collectd.
     <Page "stock_quotes">
       Plugin "quotes"
       URL "http://finance.google.com/finance?q=NYSE%3AAMD"
+      AddressFamily "any"
       User "foo"
       Password "bar"
       Digest false
@@ -1835,6 +1836,16 @@ Defaults to C<curl>.
 URL of the web site to retrieve. Since a regular expression will be used to
 extract information from this data, non-binary data is a big plus here ;)
 
+=item B<AddressFamily> I<Type>
+
+IP version to resolve URL to. Useful in cases when hostname in URL resolves
+to both IPv4 and IPv6 addresses, and you are interested in using one of them
+specifically.
+Use C<ipv4> to enforce IPv4, C<ipv6> to enforce IPv6. If C<libcurl> is compiled
+without IPv6 support, the latter will result in a warning, and fallback to C<any>.
+If C<Type> cannot be parsed, C<any> will be used as well (all IP versions that
+your system allows).
+
 =item B<User> I<Name>
 
 Username to use if authorization is required to read the page.
index 4925ad0..5c30ab7 100644 (file)
@@ -57,6 +57,7 @@ struct web_page_s /* {{{ */
   char *instance;
 
   char *url;
+  int address_family;
   char *user;
   char *pass;
   char *credentials;
@@ -345,6 +346,7 @@ static int cc_page_init_curl(web_page_t *wp) /* {{{ */
   curl_easy_setopt(wp->curl, CURLOPT_ERRORBUFFER, wp->curl_errbuf);
   curl_easy_setopt(wp->curl, CURLOPT_FOLLOWLOCATION, 1L);
   curl_easy_setopt(wp->curl, CURLOPT_MAXREDIRS, 50L);
+  curl_easy_setopt(wp->curl, CURLOPT_IPRESOLVE, wp->address_family);
 
   if (wp->user != NULL) {
 #ifdef HAVE_CURLOPT_USERNAME
@@ -398,6 +400,8 @@ static int cc_config_add_page(oconfig_item_t *ci) /* {{{ */
   cdtime_t interval = 0;
   web_page_t *page;
   int status;
+  char *af = NULL;
+  curl_version_info_data *curl_info = curl_version_info(CURLVERSION_NOW);
 
   if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
     WARNING("curl plugin: `Page' blocks need exactly one string argument.");
@@ -411,6 +415,7 @@ static int cc_config_add_page(oconfig_item_t *ci) /* {{{ */
   }
   page->plugin_name = NULL;
   page->url = NULL;
+  page->address_family = CURL_IPRESOLVE_WHATEVER;
   page->user = NULL;
   page->pass = NULL;
   page->digest = false;
@@ -437,7 +442,19 @@ static int cc_config_add_page(oconfig_item_t *ci) /* {{{ */
       status = cf_util_get_string(child, &page->plugin_name);
     else if (strcasecmp("URL", child->key) == 0)
       status = cf_util_get_string(child, &page->url);
-    else if (strcasecmp("User", child->key) == 0)
+    else if (strcasecmp("AddressFamily", child->key) == 0) {
+      status = cf_util_get_string(child, &af);
+      if (status != 0 || af == NULL) {
+        page->address_family = CURL_IPRESOLVE_WHATEVER;
+      } else if (strcasecmp("inet4", af) == 0 || strcasecmp("ipv4", af) == 0) {
+        page->address_family = CURL_IPRESOLVE_V4;
+      } else if (strcasecmp("inet6", af) == 0 || strcasecmp("ipv6", af) == 0) {
+        if (curl_info->features & CURL_VERSION_IPV6)
+          page->address_family = CURL_IPRESOLVE_V6;
+        else
+          WARNING("curl plugin: IPv6 not supported by this libCURL.");
+      }
+    } else if (strcasecmp("User", child->key) == 0)
       status = cf_util_get_string(child, &page->user);
     else if (strcasecmp("Password", child->key) == 0)
       status = cf_util_get_string(child, &page->pass);