[tor-commits] [tor/master] Refactor code that looks up addresses from interfaces
nickm at torproject.org
nickm at torproject.org
Fri Jan 23 15:13:43 UTC 2015
commit 3966145dff817adb67e5b46020632d55f19e289f
Author: rl1987 <rl1987 at sdf.lonestar.org>
Date: Sat May 24 15:03:14 2014 +0300
Refactor code that looks up addresses from interfaces
Now the code has separate implementation and examination functions,
uses smartlists sanely, and has relatively decent test coverage.
---
changes/ticket12376_part2 | 11 ++
src/common/address.c | 227 +++++++++++++++-------
src/common/address.h | 53 +++++
src/test/include.am | 1 +
src/test/test.c | 2 +
src/test/test_address.c | 467 +++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 697 insertions(+), 64 deletions(-)
diff --git a/changes/ticket12376_part2 b/changes/ticket12376_part2
new file mode 100644
index 0000000..13f9bb5
--- /dev/null
+++ b/changes/ticket12376_part2
@@ -0,0 +1,11 @@
+ o Major refactoring:
+ - Refactor the get_interface_addresses_raw() Doom-function into
+ multiple smaller and easier to understand subfunctions. Cover the
+ resulting subfunctions with unit-tests. Fixes a significant portion
+ of issue 12376.
+
+ o Minor bugfixes:
+ - Fix the ioctl()-based network interface lookup code so that it will
+ work on systems that have variable-length struct ifreq, for example
+ Mac OS X.
+
diff --git a/src/common/address.c b/src/common/address.c
index 2825b12..7b4584f 100644
--- a/src/common/address.c
+++ b/src/common/address.c
@@ -8,24 +8,26 @@
* \brief Functions to use and manipulate the tor_addr_t structure.
**/
-#include "orconfig.h"
-#include "compat.h"
-#include "util.h"
-#include "address.h"
-#include "torlog.h"
-#include "container.h"
-#include "sandbox.h"
+#define ADDRESS_PRIVATE
#ifdef _WIN32
-#include <process.h>
-#include <windows.h>
-#include <winsock2.h>
/* For access to structs needed by GetAdaptersAddresses */
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
+#include <process.h>
+#include <winsock2.h>
+#include <windows.h>
#include <iphlpapi.h>
#endif
+#include "orconfig.h"
+#include "compat.h"
+#include "util.h"
+#include "address.h"
+#include "torlog.h"
+#include "container.h"
+#include "sandbox.h"
+
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
@@ -122,7 +124,7 @@ tor_addr_to_sockaddr(const tor_addr_t *a,
}
/** Set the tor_addr_t in <b>a</b> to contain the socket address contained in
- * <b>sa</b>. */
+ * <b>sa</b>. Return 0 on success and -1 on failure. */
int
tor_addr_from_sockaddr(tor_addr_t *a, const struct sockaddr *sa,
uint16_t *port_out)
@@ -1192,26 +1194,17 @@ typedef ULONG (WINAPI *GetAdaptersAddresses_fn_t)(
ULONG, ULONG, PVOID, PIP_ADAPTER_ADDRESSES, PULONG);
#endif
-/** 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>. */
-static smartlist_t *
-get_interface_addresses_raw(int severity)
+#ifdef HAVE_IFADDRS_TO_SMARTLIST
+/*
+ * Convert a linked list consisting of <b>ifaddrs</b> structures
+ * into smartlist of <b>tor_addr_t</b> structures.
+ */
+STATIC smartlist_t *
+ifaddrs_to_smartlist(const struct ifaddrs *ifa)
{
-#if defined(HAVE_GETIFADDRS)
- /* Most free Unixy systems provide getifaddrs, which gives us a linked list
- * of struct ifaddrs. */
- struct ifaddrs *ifa = NULL;
+ smartlist_t *result = smartlist_new();
const struct ifaddrs *i;
- smartlist_t *result;
- if (getifaddrs(&ifa) < 0) {
- log_fn(severity, LD_NET, "Unable to call getifaddrs(): %s",
- strerror(errno));
- return NULL;
- }
- result = smartlist_new();
for (i = ifa; i; i = i->ifa_next) {
tor_addr_t tmp;
if ((i->ifa_flags & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING))
@@ -1226,9 +1219,72 @@ get_interface_addresses_raw(int severity)
smartlist_add(result, tor_memdup(&tmp, sizeof(tmp)));
}
+ return result;
+}
+
+/** Use getiffaddrs() function to get list of current machine
+ * network interface addresses. Represent the result by smartlist of
+ * <b>tor_addr_t</b> structures.
+ */
+STATIC smartlist_t *
+get_interface_addresses_ifaddrs(int severity)
+{
+
+ /* Most free Unixy systems provide getifaddrs, which gives us a linked list
+ * of struct ifaddrs. */
+ struct ifaddrs *ifa = NULL;
+ smartlist_t *result;
+ if (getifaddrs(&ifa) < 0) {
+ log_fn(severity, LD_NET, "Unable to call getifaddrs(): %s",
+ strerror(errno));
+ return NULL;
+ }
+
+ result = ifaddrs_to_smartlist(ifa);
+
freeifaddrs(ifa);
+
+ return result;
+}
+#endif
+
+#ifdef HAVE_IP_ADAPTER_TO_SMARTLIST
+
+/** Convert a Windows-specific <b>addresses</b> linked list into smartlist
+ * of <b>tor_addr_t</b> structures.
+ */
+
+STATIC smartlist_t *
+ip_adapter_addresses_to_smartlist(const IP_ADAPTER_ADDRESSES *addresses)
+{
+ smartlist_t *result = smartlist_new();
+ const IP_ADAPTER_ADDRESSES *address;
+
+ for (address = addresses; address; address = address->Next) {
+ const IP_ADAPTER_UNICAST_ADDRESS *a;
+ for (a = address->FirstUnicastAddress; a; a = a->Next) {
+ /* Yes, it's a linked list inside a linked list */
+ const struct sockaddr *sa = a->Address.lpSockaddr;
+ tor_addr_t tmp;
+ if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6)
+ continue;
+ if (tor_addr_from_sockaddr(&tmp, sa, NULL) < 0)
+ continue;
+ smartlist_add(result, tor_memdup(&tmp, sizeof(tmp)));
+ }
+ }
+
return result;
-#elif defined(_WIN32)
+}
+
+/** Windows only: use GetAdaptersInfo() function to retrieve network interface
+ * addresses of current machine and return them to caller as smartlist of
+ * <b>tor_addr_t</b> structures.
+ */
+STATIC smartlist_t *
+get_interface_addresses_win32(int severity)
+{
+
/* Windows XP began to provide GetAdaptersAddresses. Windows 2000 had a
"GetAdaptersInfo", but that's deprecated; let's just try
GetAdaptersAddresses and fall back to connect+getsockname.
@@ -1237,7 +1293,7 @@ get_interface_addresses_raw(int severity)
smartlist_t *result = NULL;
GetAdaptersAddresses_fn_t fn;
ULONG size, res;
- IP_ADAPTER_ADDRESSES *addresses = NULL, *address;
+ IP_ADAPTER_ADDRESSES *addresses = NULL;
(void) severity;
@@ -1272,63 +1328,106 @@ get_interface_addresses_raw(int severity)
goto done;
}
- result = smartlist_new();
- for (address = addresses; address; address = address->Next) {
- IP_ADAPTER_UNICAST_ADDRESS *a;
- for (a = address->FirstUnicastAddress; a; a = a->Next) {
- /* Yes, it's a linked list inside a linked list */
- struct sockaddr *sa = a->Address.lpSockaddr;
- tor_addr_t tmp;
- if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6)
- continue;
- if (tor_addr_from_sockaddr(&tmp, sa, NULL) < 0)
- continue;
- smartlist_add(result, tor_memdup(&tmp, sizeof(tmp)));
- }
- }
+ result = ip_adapter_addresses_to_smartlist(addresses);
done:
if (lib)
FreeLibrary(lib);
tor_free(addresses);
return result;
-#elif defined(SIOCGIFCONF) && defined(HAVE_IOCTL)
+}
+
+#endif
+
+#ifdef HAVE_IFCONF_TO_SMARTLIST
+
+/* This is defined on Mac OS X */
+#ifndef _SIZEOF_ADDR_IFREQ
+#define _SIZEOF_ADDR_IFREQ sizeof
+#endif
+
+/** Convert <b>*ifr</b>, an ifreq structure array of size <b>buflen</b>
+ * into smartlist of <b>tor_addr_t</b> structures.
+ */
+STATIC smartlist_t *
+ifreq_to_smartlist(const struct ifreq *ifr, size_t buflen)
+{
+ smartlist_t *result = smartlist_new();
+
+ struct ifreq *r = (struct ifreq *)ifr;
+
+ while ((char *)r < (char *)ifr+buflen) {
+ const struct sockaddr *sa = &r->ifr_addr;
+ tor_addr_t tmp;
+ int valid_sa_family = (sa->sa_family == AF_INET ||
+ sa->sa_family == AF_INET6);
+
+ int conversion_success = (tor_addr_from_sockaddr(&tmp, sa, NULL) == 0);
+
+ if (valid_sa_family && conversion_success)
+ smartlist_add(result, tor_memdup(&tmp, sizeof(tmp)));
+
+ r = (struct ifreq *)((char *)r + _SIZEOF_ADDR_IFREQ(*r));
+ }
+
+ return result;
+}
+
+/** Use ioctl(.,SIOCGIFCONF,.) to get a list of current machine
+ * network interface addresses. Represent the result by smartlist of
+ * <b>tor_addr_t</b> structures.
+ */
+STATIC smartlist_t *
+get_interface_addresses_ioctl(int severity)
+{
/* Some older unixy systems make us use ioctl(SIOCGIFCONF) */
struct ifconf ifc;
- int fd, i, sz, n;
+ int fd, sz;
+ void *databuf = NULL;
smartlist_t *result = NULL;
+
/* This interface, AFAICT, only supports AF_INET addresses */
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
tor_log(severity, LD_NET, "socket failed: %s", strerror(errno));
goto done;
}
+
/* Guess how much space we need. */
- ifc.ifc_len = sz = 15*1024;
- ifc.ifc_ifcu.ifcu_req = tor_malloc(sz);
+ ifc.ifc_len = sz = 4096;
+ databuf = tor_malloc_zero(sz);
+ ifc.ifc_buf = databuf;
+
if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) {
tor_log(severity, LD_NET, "ioctl failed: %s", strerror(errno));
close(fd);
goto done;
}
- close(fd);
- result = smartlist_new();
- if (ifc.ifc_len < sz)
- sz = ifc.ifc_len;
- n = sz / sizeof(struct ifreq);
- for (i = 0; i < n ; ++i) {
- struct ifreq *r = &ifc.ifc_ifcu.ifcu_req[i];
- struct sockaddr *sa = &r->ifr_addr;
- tor_addr_t tmp;
- if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6)
- continue; /* should be impossible */
- if (tor_addr_from_sockaddr(&tmp, sa, NULL) < 0)
- continue;
- smartlist_add(result, tor_memdup(&tmp, sizeof(tmp)));
- }
+
+ result = ifreq_to_smartlist(databuf, ifc.ifc_len);
+
done:
- tor_free(ifc.ifc_ifcu.ifcu_req);
+ close(fd);
+ tor_free(databuf);
return result;
+}
+#endif
+
+/** 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>. */
+STATIC smartlist_t *
+get_interface_addresses_raw(int severity)
+{
+#if defined(HAVE_IFADDRS_TO_SMARTLIST)
+ return get_interface_addresses_ifaddrs(severity);
+#endif
+#if defined(HAVE_IP_ADAPTER_TO_SMARTLIST)
+ return get_interface_addresses_win32(severity);
+#endif
+#if defined(HAVE_IFCONF_TO_SMARTLIST)
+ return get_interface_addresses_ioctl(severity);
#else
(void) severity;
return NULL;
diff --git a/src/common/address.h b/src/common/address.h
index 8dc63b7..934c3f5 100644
--- a/src/common/address.h
+++ b/src/common/address.h
@@ -11,10 +11,41 @@
#ifndef TOR_ADDRESS_H
#define TOR_ADDRESS_H
+//#include <sys/sockio.h>
#include "orconfig.h"
#include "torint.h"
#include "compat.h"
+#ifdef ADDRESS_PRIVATE
+
+#if defined(HAVE_SYS_IOCTL_H)
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_GETIFADDRS
+#define HAVE_IFADDRS_TO_SMARTLIST
+#endif
+
+#ifdef _WIN32
+#define HAVE_IP_ADAPTER_TO_SMARTLIST
+#endif
+
+#if defined(SIOCGIFCONF) && defined(HAVE_IOCTL)
+#define HAVE_IFCONF_TO_SMARTLIST
+#endif
+
+#if defined(HAVE_NET_IF_H)
+#include <net/if.h> // for struct ifconf
+#endif
+
+#if defined(HAVE_IFADDRS_TO_SMARTLIST)
+#include <ifaddrs.h>
+#endif
+
+// TODO win32 specific includes
+#include "container.h"
+#endif // ADDRESS_PRIVATE
+
/** The number of bits from an address to consider while doing a masked
* comparison. */
typedef uint8_t maskbits_t;
@@ -229,5 +260,27 @@ int get_interface_address(int severity, uint32_t *addr);
tor_addr_port_t *tor_addr_port_new(const tor_addr_t *addr, uint16_t port);
+#ifdef ADDRESS_PRIVATE
+STATIC smartlist_t *get_interface_addresses_raw(int severity);
+
+#ifdef HAVE_IFADDRS_TO_SMARTLIST
+STATIC smartlist_t *ifaddrs_to_smartlist(const struct ifaddrs *ifa);
+STATIC smartlist_t *get_interface_addresses_ifaddrs(int severity);
+#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);
+#endif
+
+#ifdef HAVE_IFCONF_TO_SMARTLIST
+STATIC smartlist_t *ifreq_to_smartlist(const struct ifreq *ifr,
+ size_t buflen);
+STATIC smartlist_t *get_interface_addresses_ioctl(int severity);
+#endif
+
+#endif // ADDRESS_PRIVATE
+
#endif
diff --git a/src/test/include.am b/src/test/include.am
index fba439a..371f063 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -45,6 +45,7 @@ src_test_test_SOURCES = \
src/test/test_nodelist.c \
src/test/test_policy.c \
src/test/test_status.c \
+ src/test/test_address.c \
src/ext/tinytest.c
src_test_test_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
diff --git a/src/test/test.c b/src/test/test.c
index c96b396..ed3013c 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -1287,6 +1287,7 @@ static struct testcase_t test_array[] = {
};
extern struct testcase_t addr_tests[];
+extern struct testcase_t address_tests[];
extern struct testcase_t buffer_tests[];
extern struct testcase_t crypto_tests[];
extern struct testcase_t container_tests[];
@@ -1319,6 +1320,7 @@ static struct testgroup_t testgroups[] = {
{ "buffer/", buffer_tests },
{ "socks/", socks_tests },
{ "addr/", addr_tests },
+ { "address/", address_tests },
{ "crypto/", crypto_tests },
{ "container/", container_tests },
{ "util/", util_tests },
diff --git a/src/test/test_address.c b/src/test/test_address.c
new file mode 100644
index 0000000..971618d
--- /dev/null
+++ b/src/test/test_address.c
@@ -0,0 +1,467 @@
+/* Copyright (c) 2014-2015, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define ADDRESS_PRIVATE
+
+#ifdef _WIN32
+#include <winsock2.h>
+/* For access to structs needed by GetAdaptersAddresses */
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#include <iphlpapi.h>
+#endif
+
+#ifdef HAVE_IFADDRS_TO_SMARTLIST
+#include <net/if.h>
+#include <ifaddrs.h>
+#endif
+
+#ifdef HAVE_IFCONF_TO_SMARTLIST
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#include <net/if.h>
+#endif
+
+#include "or.h"
+#include "address.h"
+#include "test.h"
+
+/** Return 1 iff <b>sockaddr1</b> and <b>sockaddr2</b> represent
+ * the same IP address and port combination. Otherwise, return 0.
+ */
+static uint8_t
+sockaddr_in_are_equal(struct sockaddr_in *sockaddr1,
+ struct sockaddr_in *sockaddr2)
+{
+ return ((sockaddr1->sin_family == sockaddr2->sin_family) &&
+ (sockaddr1->sin_port == sockaddr2->sin_port) &&
+ (sockaddr1->sin_addr.s_addr == sockaddr2->sin_addr.s_addr));
+}
+
+/** Return 1 iff <b>sockaddr1</b> and <b>sockaddr2</b> represent
+ * the same IP address and port combination. Otherwise, return 0.
+ */
+static uint8_t
+sockaddr_in6_are_equal(struct sockaddr_in6 *sockaddr1,
+ struct sockaddr_in6 *sockaddr2)
+{
+ return ((sockaddr1->sin6_family == sockaddr2->sin6_family) &&
+ (sockaddr1->sin6_port == sockaddr2->sin6_port) &&
+ (tor_memeq(sockaddr1->sin6_addr.s6_addr,
+ sockaddr2->sin6_addr.s6_addr,16)));
+}
+
+/** Create a sockaddr_in structure from IP address string <b>ip_str</b>.
+ *
+ * If <b>out</b> is not NULL, write the result
+ * to the memory address in <b>out</b>. Otherwise, allocate the memory
+ * for result. On success, return pointer to result. Otherwise, return
+ * NULL.
+ */
+static struct sockaddr_in *
+sockaddr_in_from_string(const char *ip_str, struct sockaddr_in *out)
+{
+ // [FIXME: add some error checking?]
+ if (!out)
+ out = tor_malloc_zero(sizeof(struct sockaddr_in));
+
+ out->sin_family = AF_INET;
+ out->sin_port = 0;
+ tor_inet_pton(AF_INET,ip_str,&(out->sin_addr));
+
+ return out;
+}
+
+/** Return 1 iff <b>smartlist</b> contains a tor_addr_t structure
+ * that points to 127.0.0.1. Otherwise, return 0.
+ */
+static int
+smartlist_contains_localhost_tor_addr(smartlist_t *smartlist)
+{
+ int found_localhost = 0;
+
+ struct sockaddr_in *sockaddr_localhost;
+ struct sockaddr_storage *sockaddr_to_check;
+
+ sockaddr_localhost = sockaddr_in_from_string("127.0.0.1",NULL);
+
+ sockaddr_to_check = tor_malloc(sizeof(struct sockaddr_in));
+
+ SMARTLIST_FOREACH_BEGIN(smartlist, tor_addr_t *, tor_addr) {
+ tor_addr_to_sockaddr(tor_addr,0,(struct sockaddr *)sockaddr_to_check,
+ sizeof(struct sockaddr_in));
+
+ if (sockaddr_in_are_equal((struct sockaddr_in *)sockaddr_to_check,
+ sockaddr_localhost)) {
+ found_localhost = 1;
+ break;
+ }
+ } SMARTLIST_FOREACH_END(tor_addr);
+
+ tor_free(sockaddr_localhost);
+ tor_free(sockaddr_to_check);
+
+ return found_localhost;
+}
+
+#ifdef HAVE_IFADDRS_TO_SMARTLIST
+static void
+test_address_ifaddrs_to_smartlist(void *arg)
+{
+ struct ifaddrs *ifa = NULL;
+ struct ifaddrs *ifa_ipv4 = NULL;
+ struct ifaddrs *ifa_ipv6 = NULL;
+ struct sockaddr_in *ipv4_sockaddr_local = NULL;
+ struct sockaddr_in *netmask_slash8 = NULL;
+ struct sockaddr_in *ipv4_sockaddr_remote = NULL;
+ struct sockaddr_in6 *ipv6_sockaddr = NULL;
+ smartlist_t *smartlist = NULL;
+ tor_addr_t *tor_addr = NULL;
+ struct sockaddr *sockaddr_to_check = NULL;
+ socklen_t addr_len;
+
+ (void)arg;
+
+ netmask_slash8 = sockaddr_in_from_string("255.0.0.0",NULL);
+ ipv4_sockaddr_local = sockaddr_in_from_string("127.0.0.1",NULL);
+ ipv4_sockaddr_remote = sockaddr_in_from_string("128.52.160.20",NULL);
+
+ ipv6_sockaddr = tor_malloc(sizeof(struct sockaddr_in6));
+ ipv6_sockaddr->sin6_family = AF_INET6;
+ ipv6_sockaddr->sin6_port = 0;
+ inet_pton(AF_INET6, "2001:db8:8714:3a90::12",
+ &(ipv6_sockaddr->sin6_addr));
+
+ ifa = tor_malloc(sizeof(struct ifaddrs));
+ ifa_ipv4 = tor_malloc(sizeof(struct ifaddrs));
+ ifa_ipv6 = tor_malloc(sizeof(struct ifaddrs));
+
+ ifa->ifa_next = ifa_ipv4;
+ ifa->ifa_name = tor_strdup("eth0");
+ ifa->ifa_flags = IFF_UP | IFF_RUNNING;
+ ifa->ifa_addr = (struct sockaddr *)ipv4_sockaddr_local;
+ ifa->ifa_netmask = (struct sockaddr *)netmask_slash8;
+ ifa->ifa_dstaddr = NULL;
+ ifa->ifa_data = NULL;
+
+ ifa_ipv4->ifa_next = ifa_ipv6;
+ ifa_ipv4->ifa_name = tor_strdup("eth1");
+ ifa_ipv4->ifa_flags = IFF_UP | IFF_RUNNING;
+ ifa_ipv4->ifa_addr = (struct sockaddr *)ipv4_sockaddr_remote;
+ ifa_ipv4->ifa_netmask = (struct sockaddr *)netmask_slash8;
+ ifa_ipv4->ifa_dstaddr = NULL;
+ ifa_ipv4->ifa_data = NULL;
+
+ ifa_ipv6->ifa_next = NULL;
+ ifa_ipv6->ifa_name = tor_strdup("eth2");
+ ifa_ipv6->ifa_flags = IFF_UP | IFF_RUNNING;
+ ifa_ipv6->ifa_addr = (struct sockaddr *)ipv6_sockaddr;
+ ifa_ipv6->ifa_netmask = NULL;
+ ifa_ipv6->ifa_dstaddr = NULL;
+ ifa_ipv6->ifa_data = NULL;
+
+ smartlist = ifaddrs_to_smartlist(ifa);
+
+ tt_assert(smartlist);
+ tt_assert(smartlist_len(smartlist) == 3);
+
+ sockaddr_to_check = tor_malloc(sizeof(struct sockaddr_in6));
+
+ tor_addr = smartlist_get(smartlist,0);
+ addr_len =
+ tor_addr_to_sockaddr(tor_addr,0,sockaddr_to_check,
+ sizeof(struct sockaddr_in));
+
+ tt_int_op(addr_len,==,sizeof(struct sockaddr_in));
+ tt_assert(sockaddr_in_are_equal((struct sockaddr_in *)sockaddr_to_check,
+ ipv4_sockaddr_local));
+
+ tor_addr = smartlist_get(smartlist,1);
+ addr_len =
+ tor_addr_to_sockaddr(tor_addr,0,sockaddr_to_check,
+ sizeof(struct sockaddr_in));
+
+ tt_int_op(addr_len,==,sizeof(struct sockaddr_in));
+ tt_assert(sockaddr_in_are_equal((struct sockaddr_in *)sockaddr_to_check,
+ ipv4_sockaddr_remote));
+
+ tor_addr = smartlist_get(smartlist,2);
+ addr_len =
+ tor_addr_to_sockaddr(tor_addr,0,sockaddr_to_check,
+ sizeof(struct sockaddr_in6));
+
+ tt_int_op(addr_len,==,sizeof(struct sockaddr_in6));
+ tt_assert(sockaddr_in6_are_equal((struct sockaddr_in6*)sockaddr_to_check,
+ ipv6_sockaddr));
+
+ done:
+ tor_free(netmask_slash8);
+ tor_free(ipv4_sockaddr_local);
+ tor_free(ipv4_sockaddr_remote);
+ tor_free(ipv6_sockaddr);
+ tor_free(ifa);
+ tor_free(ifa_ipv4);
+ tor_free(ifa_ipv6);
+ tor_free(sockaddr_to_check);
+ SMARTLIST_FOREACH(smartlist, tor_addr_t *, t, tor_free(t));
+ smartlist_free(smartlist);
+
+ return;
+}
+
+static void
+test_address_get_if_addrs_ifaddrs(void *arg)
+{
+
+ smartlist_t *results = NULL;
+
+ (void)arg;
+
+ results = get_interface_addresses_ifaddrs(0);
+
+ tt_int_op(smartlist_len(results),>=,1);
+ tt_assert(smartlist_contains_localhost_tor_addr(results));
+
+ done:
+ SMARTLIST_FOREACH(results, tor_addr_t *, t, tor_free(t));
+ tor_free(results);
+ return;
+}
+
+#endif
+
+#ifdef HAVE_IP_ADAPTER_TO_SMARTLIST
+
+static void
+test_address_get_if_addrs_win32(void *arg)
+{
+
+ smartlist_t *results = NULL;
+
+ (void)arg;
+
+ results = get_interface_addresses_win32(0);
+
+ tt_int_op(smartlist_len(results),>=,1);
+ tt_assert(smartlist_contains_localhost_tor_addr(results));
+
+ done:
+ SMARTLIST_FOREACH(results, tor_addr_t *, t, tor_free(t));
+ tor_free(results);
+ return;
+}
+
+static void
+test_address_ip_adapter_addresses_to_smartlist(void *arg)
+{
+
+ IP_ADAPTER_ADDRESSES *addrs1;
+ IP_ADAPTER_ADDRESSES *addrs2;
+
+ IP_ADAPTER_UNICAST_ADDRESS *unicast11;
+ IP_ADAPTER_UNICAST_ADDRESS *unicast12;
+ IP_ADAPTER_UNICAST_ADDRESS *unicast21;
+
+ smartlist_t *result = NULL;
+
+ struct sockaddr_in *sockaddr_test1;
+ struct sockaddr_in *sockaddr_test2;
+ struct sockaddr_in *sockaddr_localhost;
+ struct sockaddr_in *sockaddr_to_check;
+
+ tor_addr_t *tor_addr;
+
+ (void)arg;
+ (void)sockaddr_in6_are_equal;
+
+ sockaddr_to_check = tor_malloc_zero(sizeof(struct sockaddr_in));
+
+ addrs1 =
+ tor_malloc_zero(sizeof(IP_ADAPTER_ADDRESSES));
+
+ addrs1->FirstUnicastAddress =
+ unicast11 = tor_malloc_zero(sizeof(IP_ADAPTER_UNICAST_ADDRESS));
+ sockaddr_test1 = sockaddr_in_from_string("86.59.30.40",NULL);
+ unicast11->Address.lpSockaddr = (LPSOCKADDR)sockaddr_test1;
+
+ unicast11->Next = unicast12 =
+ tor_malloc_zero(sizeof(IP_ADAPTER_UNICAST_ADDRESS));
+ sockaddr_test2 = sockaddr_in_from_string("93.95.227.222", NULL);
+ unicast12->Address.lpSockaddr = (LPSOCKADDR)sockaddr_test2;
+
+ addrs1->Next = addrs2 =
+ tor_malloc_zero(sizeof(IP_ADAPTER_ADDRESSES));
+
+ addrs2->FirstUnicastAddress =
+ unicast21 = tor_malloc_zero(sizeof(IP_ADAPTER_UNICAST_ADDRESS));
+ sockaddr_localhost = sockaddr_in_from_string("127.0.0.1", NULL);
+ unicast21->Address.lpSockaddr = (LPSOCKADDR)sockaddr_localhost;
+
+ result = ip_adapter_addresses_to_smartlist(addrs1);
+
+ tt_assert(result);
+ tt_assert(smartlist_len(result) == 3);
+
+ tor_addr = smartlist_get(result,0);
+
+ tor_addr_to_sockaddr(tor_addr,0,(struct sockaddr *)sockaddr_to_check,
+ sizeof(struct sockaddr_in));
+
+ tt_assert(sockaddr_in_are_equal(sockaddr_test1,sockaddr_to_check));
+
+ tor_addr = smartlist_get(result,1);
+
+ tor_addr_to_sockaddr(tor_addr,0,(struct sockaddr *)sockaddr_to_check,
+ sizeof(struct sockaddr_in));
+
+ tt_assert(sockaddr_in_are_equal(sockaddr_test2,sockaddr_to_check));
+
+ tor_addr = smartlist_get(result,2);
+
+ tor_addr_to_sockaddr(tor_addr,0,(struct sockaddr *)sockaddr_to_check,
+ sizeof(struct sockaddr_in));
+
+ tt_assert(sockaddr_in_are_equal(sockaddr_localhost,sockaddr_to_check));
+
+ done:
+ SMARTLIST_FOREACH(result, tor_addr_t *, t, tor_free(t));
+ smartlist_free(result);
+ tor_free(addrs1);
+ tor_free(addrs2);
+ tor_free(unicast11->Address.lpSockaddr);
+ tor_free(unicast11);
+ tor_free(unicast12->Address.lpSockaddr);
+ tor_free(unicast12);
+ tor_free(unicast21->Address.lpSockaddr);
+ tor_free(unicast21);
+ tor_free(sockaddr_to_check);
+ return;
+}
+#endif
+
+#ifdef HAVE_IFCONF_TO_SMARTLIST
+
+static void
+test_address_ifreq_to_smartlist(void *arg)
+{
+ smartlist_t *results = NULL;
+ tor_addr_t *tor_addr = NULL;
+ struct sockaddr_in *sockaddr = NULL;
+ struct sockaddr_in *sockaddr_eth1 = NULL;
+ struct sockaddr_in *sockaddr_to_check = NULL;
+
+ struct ifconf *ifc;
+ struct ifreq *ifr;
+ struct ifreq *ifr_next;
+
+ socklen_t addr_len;
+
+ (void)arg;
+
+ sockaddr_to_check = tor_malloc(sizeof(struct sockaddr_in));
+
+ ifr = tor_malloc(sizeof(struct ifreq));
+ memset(ifr,0,sizeof(struct ifreq));
+ strlcpy(ifr->ifr_name,"lo",3);
+ sockaddr = (struct sockaddr_in *) &(ifr->ifr_ifru.ifru_addr);
+ sockaddr_in_from_string("127.0.0.1",sockaddr);
+
+ ifc = tor_malloc(sizeof(struct ifconf));
+ memset(ifc,0,sizeof(struct ifconf));
+ ifc->ifc_len = sizeof(struct ifreq);
+ ifc->ifc_ifcu.ifcu_req = ifr;
+
+ results = ifreq_to_smartlist((struct ifreq *)ifc->ifc_buf,ifc->ifc_len);
+ tt_int_op(smartlist_len(results),==,1);
+
+ tor_addr = smartlist_get(results, 0);
+ addr_len =
+ tor_addr_to_sockaddr(tor_addr,0,(struct sockaddr *)sockaddr_to_check,
+ sizeof(struct sockaddr_in));
+
+ tt_int_op(addr_len,==,sizeof(struct sockaddr_in));
+ tt_assert(sockaddr_in_are_equal(sockaddr,sockaddr_to_check));
+
+ ifr = tor_realloc(ifr,2*sizeof(struct ifreq));
+ ifr_next = ifr+1;
+ strlcpy(ifr_next->ifr_name,"eth1",5);
+ ifc->ifc_len = 2*sizeof(struct ifreq);
+ ifc->ifc_ifcu.ifcu_req = ifr;
+ sockaddr = (struct sockaddr_in *) &(ifr->ifr_ifru.ifru_addr);
+
+ sockaddr_eth1 = (struct sockaddr_in *) &(ifr_next->ifr_ifru.ifru_addr);
+ sockaddr_in_from_string("192.168.10.55",sockaddr_eth1);
+
+ smartlist_free(results);
+
+ results = ifreq_to_smartlist((struct ifreq *)ifc->ifc_buf,ifc->ifc_len);
+ tt_int_op(smartlist_len(results),==,2);
+
+ tor_addr = smartlist_get(results, 0);
+ addr_len =
+ tor_addr_to_sockaddr(tor_addr,0,(struct sockaddr *)sockaddr_to_check,
+ sizeof(struct sockaddr_in));
+
+ tt_int_op(addr_len,==,sizeof(struct sockaddr_in));
+ tt_assert(sockaddr_in_are_equal(sockaddr,sockaddr_to_check));
+
+ tor_addr = smartlist_get(results, 1);
+ addr_len =
+ tor_addr_to_sockaddr(tor_addr,0,(struct sockaddr *)sockaddr_to_check,
+ sizeof(struct sockaddr_in));
+
+ tt_int_op(addr_len,==,sizeof(struct sockaddr_in));
+ tt_assert(sockaddr_in_are_equal(sockaddr_eth1,sockaddr_to_check));
+
+ done:
+ tor_free(sockaddr_to_check);
+ smartlist_free(results);
+ tor_free(tor_addr);
+ tor_free(ifc);
+ tor_free(ifr);
+ return;
+}
+
+static void
+test_address_get_if_addrs_ioctl(void *arg)
+{
+
+ smartlist_t *result = NULL;
+
+ (void)arg;
+
+ result = get_interface_addresses_ioctl(LOG_ERR);
+
+ tt_assert(result);
+ tt_int_op(smartlist_len(result),>=,1);
+
+ tt_assert(smartlist_contains_localhost_tor_addr(result));
+
+ done:
+ SMARTLIST_FOREACH(result, tor_addr_t *, t, tor_free(t));
+ smartlist_free(result);
+ return;
+}
+
+#endif
+
+#define ADDRESS_TEST(name, flags) \
+ { #name, test_address_ ## name, flags, NULL, NULL }
+
+struct testcase_t address_tests[] = {
+#ifdef HAVE_IFADDRS_TO_SMARTLIST
+ ADDRESS_TEST(get_if_addrs_ifaddrs, TT_FORK),
+ ADDRESS_TEST(ifaddrs_to_smartlist, 0),
+#endif
+#ifdef HAVE_IP_ADAPTER_TO_SMARTLIST
+ ADDRESS_TEST(get_if_addrs_win32, TT_FORK),
+ ADDRESS_TEST(ip_adapter_addresses_to_smartlist, 0),
+#endif
+#ifdef HAVE_IFCONF_TO_SMARTLIST
+ ADDRESS_TEST(get_if_addrs_ioctl, TT_FORK),
+ ADDRESS_TEST(ifreq_to_smartlist, 0),
+#endif
+ END_OF_TESTCASES
+};
+
More information about the tor-commits
mailing list