aboutsummaryrefslogtreecommitdiff
path: root/src/common/address.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2016-01-11 08:54:51 -0500
committerNick Mathewson <nickm@torproject.org>2016-01-11 08:54:51 -0500
commitd10ea49588701b29148a27c87701961227d63ba9 (patch)
tree7114f84e4ced028fb5ab0ef8798a892d8bfdd509 /src/common/address.c
parent8fc27ac0420c71205c61edb1c8e02ffce516a906 (diff)
parentfd26c1d994e88fbfc8546551e59633679cae5c78 (diff)
downloadtor-d10ea49588701b29148a27c87701961227d63ba9.tar.gz
tor-d10ea49588701b29148a27c87701961227d63ba9.zip
Merge remote-tracking branch 'rl1987/feature17950'
Diffstat (limited to 'src/common/address.c')
-rw-r--r--src/common/address.c46
1 files changed, 27 insertions, 19 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);