diff options
author | Nick Mathewson <nickm@torproject.org> | 2016-01-11 08:54:51 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2016-01-11 08:54:51 -0500 |
commit | d10ea49588701b29148a27c87701961227d63ba9 (patch) | |
tree | 7114f84e4ced028fb5ab0ef8798a892d8bfdd509 /src | |
parent | 8fc27ac0420c71205c61edb1c8e02ffce516a906 (diff) | |
parent | fd26c1d994e88fbfc8546551e59633679cae5c78 (diff) | |
download | tor-d10ea49588701b29148a27c87701961227d63ba9.tar.gz tor-d10ea49588701b29148a27c87701961227d63ba9.zip |
Merge remote-tracking branch 'rl1987/feature17950'
Diffstat (limited to 'src')
-rw-r--r-- | src/common/address.c | 46 | ||||
-rw-r--r-- | src/common/address.h | 15 | ||||
-rw-r--r-- | src/test/test_address.c | 11 |
3 files changed, 43 insertions, 29 deletions
diff --git a/src/common/address.c b/src/common/address.c index 53be7027d5..86c32efdd9 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; @@ -1288,6 +1288,8 @@ ifaddrs_to_smartlist(const struct ifaddrs *ifa) if (i->ifa_addr->sa_family != AF_INET && i->ifa_addr->sa_family != AF_INET6) continue; + if (family != AF_UNSPEC && i->ifa_addr->sa_family != family) + continue; if (tor_addr_from_sockaddr(&tmp, i->ifa_addr, NULL) < 0) continue; smartlist_add(result, tor_memdup(&tmp, sizeof(tmp))); @@ -1301,7 +1303,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 +1316,7 @@ get_interface_addresses_ifaddrs(int severity) return NULL; } - result = ifaddrs_to_smartlist(ifa); + result = ifaddrs_to_smartlist(ifa, family); freeifaddrs(ifa); @@ -1356,7 +1358,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 +1392,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 +1466,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 +1475,17 @@ 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); + + /* Bail out if family is neither AF_INET nor AF_UNSPEC since + * ioctl() technique supports non-IPv4 interface addresses on + * a small number of niche systems only. If family is AF_UNSPEC, + * fall back to getting AF_INET addresses only. */ + if (family == AF_UNSPEC) + family = AF_INET; + else 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 +1520,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; @@ -1687,15 +1701,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 684ba65c4f..76090136d8 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 9f3d81c92c..3ddf2476e3 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(); |