[tor-commits] [tor/master] Add family argument to get_interface_addresses_raw (and subfunctions).

nickm at torproject.org nickm at torproject.org
Mon Jan 11 13:55:10 UTC 2016


commit 44497e9ebc5231dcdb6a392093f85990fe13542e
Author: rl1987 <rl1987 at sdf.lonestar.org>
Date:   Sun Jan 3 15:35:45 2016 +0100

    Add family argument to get_interface_addresses_raw (and subfunctions).
---
 changes/feature17950    |    5 +++++
 src/common/address.c    |   44 +++++++++++++++++++++++---------------------
 src/common/address.h    |   15 ++++++++++-----
 src/test/test_address.c |   11 ++++++-----
 4 files changed, 44 insertions(+), 31 deletions(-)

diff --git a/changes/feature17950 b/changes/feature17950
new file mode 100644
index 0000000..5ea83ec
--- /dev/null
+++ b/changes/feature17950
@@ -0,0 +1,5 @@
+  o Minor features:
+    - Add a family argument to get_interface_addresses_raw() and
+      subfunctions to make network interface address interogation more
+      efficient. Now Tor can specifically ask for IPv4, IPv6 or both
+      types of interfaces from the operating system. Resolves ticket 17950.
diff --git a/src/common/address.c b/src/common/address.c
index 69a8098..1e6bb26 100644
--- a/src/common/address.c
+++ b/src/common/address.c
@@ -1274,7 +1274,7 @@ typedef ULONG (WINAPI *GetAdaptersAddresses_fn_t)(
  * into smartlist of <b>tor_addr_t</b> structures.
  */
 STATIC smartlist_t *
-ifaddrs_to_smartlist(const struct ifaddrs *ifa)
+ifaddrs_to_smartlist(const struct ifaddrs *ifa, sa_family_t family)
 {
   smartlist_t *result = smartlist_new();
   const struct ifaddrs *i;
@@ -1285,8 +1285,7 @@ ifaddrs_to_smartlist(const struct ifaddrs *ifa)
       continue;
     if (!i->ifa_addr)
       continue;
-    if (i->ifa_addr->sa_family != AF_INET &&
-        i->ifa_addr->sa_family != AF_INET6)
+    if (family != AF_UNSPEC && i->ifa_addr->sa_family != family)
       continue;
     if (tor_addr_from_sockaddr(&tmp, i->ifa_addr, NULL) < 0)
       continue;
@@ -1301,7 +1300,7 @@ ifaddrs_to_smartlist(const struct ifaddrs *ifa)
  * <b>tor_addr_t</b> structures.
  */
 STATIC smartlist_t *
-get_interface_addresses_ifaddrs(int severity)
+get_interface_addresses_ifaddrs(int severity, sa_family_t family)
 {
 
   /* Most free Unixy systems provide getifaddrs, which gives us a linked list
@@ -1314,7 +1313,7 @@ get_interface_addresses_ifaddrs(int severity)
     return NULL;
   }
 
-  result = ifaddrs_to_smartlist(ifa);
+  result = ifaddrs_to_smartlist(ifa, family);
 
   freeifaddrs(ifa);
 
@@ -1356,7 +1355,7 @@ ip_adapter_addresses_to_smartlist(const IP_ADAPTER_ADDRESSES *addresses)
  * <b>tor_addr_t</b>  structures.
  */
 STATIC smartlist_t *
-get_interface_addresses_win32(int severity)
+get_interface_addresses_win32(int severity, sa_family_t family)
 {
 
   /* Windows XP began to provide GetAdaptersAddresses. Windows 2000 had a
@@ -1390,7 +1389,7 @@ get_interface_addresses_win32(int severity)
   /* Guess how much space we need. */
   size = 15*1024;
   addresses = tor_malloc(size);
-  res = fn(AF_UNSPEC, FLAGS, NULL, addresses, &size);
+  res = fn(family, FLAGS, NULL, addresses, &size);
   if (res == ERROR_BUFFER_OVERFLOW) {
     /* we didn't guess that we needed enough space; try again */
     tor_free(addresses);
@@ -1464,7 +1463,7 @@ ifreq_to_smartlist(char *buf, size_t buflen)
  * <b>tor_addr_t</b> structures.
  */
 STATIC smartlist_t *
-get_interface_addresses_ioctl(int severity)
+get_interface_addresses_ioctl(int severity, sa_family_t family)
 {
   /* Some older unixy systems make us use ioctl(SIOCGIFCONF) */
   struct ifconf ifc;
@@ -1473,7 +1472,14 @@ get_interface_addresses_ioctl(int severity)
 
   /* This interface, AFAICT, only supports AF_INET addresses,
    * except on AIX. For Solaris, we could use SIOCGLIFCONF. */
-  fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+  /* FIXME: for now, we bail out if family is not AF_INET since
+   * ioctl() technique supports non-IPv4 interface addresses on
+   * a small number of niche systems only. */
+  if (family != AF_INET)
+    return NULL;
+
+  fd = socket(family, SOCK_DGRAM, 0);
   if (fd < 0) {
     tor_log(severity, LD_NET, "socket failed: %s", strerror(errno));
     goto done;
@@ -1508,21 +1514,23 @@ get_interface_addresses_ioctl(int severity)
 /** Try to ask our network interfaces what addresses they are bound to.
  * Return a new smartlist of tor_addr_t on success, and NULL on failure.
  * (An empty smartlist indicates that we successfully learned that we have no
- * addresses.)  Log failure messages at <b>severity</b>. */
+ * addresses.)  Log failure messages at <b>severity</b>. Only return the
+ * interface addresses of requested <b>family</b> and ignore the addresses
+ * of other address families. */
 MOCK_IMPL(smartlist_t *,
-get_interface_addresses_raw,(int severity))
+get_interface_addresses_raw,(int severity, sa_family_t family))
 {
   smartlist_t *result = NULL;
 #if defined(HAVE_IFADDRS_TO_SMARTLIST)
-  if ((result = get_interface_addresses_ifaddrs(severity)))
+  if ((result = get_interface_addresses_ifaddrs(severity, family)))
     return result;
 #endif
 #if defined(HAVE_IP_ADAPTER_TO_SMARTLIST)
-  if ((result = get_interface_addresses_win32(severity)))
+  if ((result = get_interface_addresses_win32(severity, family)))
     return result;
 #endif
 #if defined(HAVE_IFCONF_TO_SMARTLIST)
-  if ((result = get_interface_addresses_ioctl(severity)))
+  if ((result = get_interface_addresses_ioctl(severity, family)))
     return result;
 #endif
   (void) severity;
@@ -1686,15 +1694,9 @@ MOCK_IMPL(smartlist_t *,get_interface_address6_list,(int severity,
   tor_addr_t addr;
 
   /* Try to do this the smart way if possible. */
-  if ((addrs = get_interface_addresses_raw(severity))) {
+  if ((addrs = get_interface_addresses_raw(severity, family))) {
     SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, a)
     {
-      if (family != AF_UNSPEC && family != tor_addr_family(a)) {
-        SMARTLIST_DEL_CURRENT(addrs, a);
-        tor_free(a);
-        continue;
-      }
-
       if (tor_addr_is_loopback(a) ||
           tor_addr_is_multicast(a)) {
         SMARTLIST_DEL_CURRENT(addrs, a);
diff --git a/src/common/address.h b/src/common/address.h
index 684ba65..7609013 100644
--- a/src/common/address.h
+++ b/src/common/address.h
@@ -311,26 +311,31 @@ get_interface_address_list(int severity, int include_internal)
 tor_addr_port_t *tor_addr_port_new(const tor_addr_t *addr, uint16_t port);
 
 #ifdef ADDRESS_PRIVATE
-MOCK_DECL(smartlist_t *,get_interface_addresses_raw,(int severity));
+MOCK_DECL(smartlist_t *,get_interface_addresses_raw,(int severity,
+                                                     sa_family_t family));
 MOCK_DECL(int,get_interface_address6_via_udp_socket_hack,(int severity,
                                                           sa_family_t family,
                                                           tor_addr_t *addr));
 
 #ifdef HAVE_IFADDRS_TO_SMARTLIST
-STATIC smartlist_t *ifaddrs_to_smartlist(const struct ifaddrs *ifa);
-STATIC smartlist_t *get_interface_addresses_ifaddrs(int severity);
+STATIC smartlist_t *ifaddrs_to_smartlist(const struct ifaddrs *ifa,
+                                         sa_family_t family);
+STATIC smartlist_t *get_interface_addresses_ifaddrs(int severity,
+                                                    sa_family_t family);
 #endif
 
 #ifdef HAVE_IP_ADAPTER_TO_SMARTLIST
 STATIC smartlist_t *ip_adapter_addresses_to_smartlist(
                                         const IP_ADAPTER_ADDRESSES *addresses);
-STATIC smartlist_t *get_interface_addresses_win32(int severity);
+STATIC smartlist_t *get_interface_addresses_win32(int severity,
+                                                  sa_family_t family);
 #endif
 
 #ifdef HAVE_IFCONF_TO_SMARTLIST
 STATIC smartlist_t *ifreq_to_smartlist(char *ifr,
                                        size_t buflen);
-STATIC smartlist_t *get_interface_addresses_ioctl(int severity);
+STATIC smartlist_t *get_interface_addresses_ioctl(int severity,
+                                                  sa_family_t family);
 #endif
 
 #endif // ADDRESS_PRIVATE
diff --git a/src/test/test_address.c b/src/test/test_address.c
index 9f3d81c..3ddf247 100644
--- a/src/test/test_address.c
+++ b/src/test/test_address.c
@@ -220,7 +220,7 @@ test_address_ifaddrs_to_smartlist(void *arg)
    ifa_ipv6->ifa_dstaddr = NULL;
    ifa_ipv6->ifa_data = NULL;
 
-   smartlist = ifaddrs_to_smartlist(ifa);
+   smartlist = ifaddrs_to_smartlist(ifa, AF_UNSPEC);
 
    tt_assert(smartlist);
    tt_assert(smartlist_len(smartlist) == 3);
@@ -281,7 +281,7 @@ test_address_get_if_addrs_ifaddrs(void *arg)
 
   (void)arg;
 
-  results = get_interface_addresses_ifaddrs(LOG_ERR);
+  results = get_interface_addresses_ifaddrs(LOG_ERR, AF_UNSPEC);
 
   tt_assert(results);
   /* Some FreeBSD jails don't have localhost IP address. Instead, they only
@@ -314,7 +314,7 @@ test_address_get_if_addrs_win32(void *arg)
 
   (void)arg;
 
-  results = get_interface_addresses_win32(LOG_ERR);
+  results = get_interface_addresses_win32(LOG_ERR, AF_UNSPEC);
 
   tt_int_op(smartlist_len(results),>=,1);
   tt_assert(smartlist_contains_localhost_tor_addr(results));
@@ -511,7 +511,7 @@ test_address_get_if_addrs_ioctl(void *arg)
 
   (void)arg;
 
-  result = get_interface_addresses_ioctl(LOG_ERR);
+  result = get_interface_addresses_ioctl(LOG_ERR, AF_INET);
 
   /* On an IPv6-only system, this will fail and return NULL
   tt_assert(result);
@@ -845,9 +845,10 @@ test_address_get_if_addrs6_list_no_internal(void *arg)
 static int called_get_interface_addresses_raw = 0;
 
 static smartlist_t *
-mock_get_interface_addresses_raw_fail(int severity)
+mock_get_interface_addresses_raw_fail(int severity, sa_family_t family)
 {
   (void)severity;
+  (void)family;
 
   called_get_interface_addresses_raw++;
   return smartlist_new();





More information about the tor-commits mailing list