mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 13:13:44 +01:00
Merge branch 'if_addr_refactoring_squashed'
Conflicts: src/test/include.am src/test/test.c
This commit is contained in:
commit
420037dcef
11
changes/ticket12376_part2
Normal file
11
changes/ticket12376_part2
Normal file
@ -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.
|
||||
|
@ -8,6 +8,18 @@
|
||||
* \brief Functions to use and manipulate the tor_addr_t structure.
|
||||
**/
|
||||
|
||||
#define ADDRESS_PRIVATE
|
||||
|
||||
#ifdef _WIN32
|
||||
/* 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"
|
||||
@ -16,16 +28,6 @@
|
||||
#include "container.h"
|
||||
#include "sandbox.h"
|
||||
|
||||
#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 <iphlpapi.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
@ -131,7 +133,7 @@ tor_addr_make_af_unix(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)
|
||||
@ -1225,26 +1227,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))
|
||||
@ -1259,9 +1252,72 @@ get_interface_addresses_raw(int severity)
|
||||
smartlist_add(result, tor_memdup(&tmp, sizeof(tmp)));
|
||||
}
|
||||
|
||||
freeifaddrs(ifa);
|
||||
return result;
|
||||
#elif defined(_WIN32)
|
||||
}
|
||||
|
||||
/** 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;
|
||||
}
|
||||
|
||||
/** 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.
|
||||
@ -1270,7 +1326,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;
|
||||
|
||||
@ -1305,63 +1361,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;
|
||||
|
@ -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;
|
||||
@ -241,5 +272,27 @@ MOCK_DECL(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
|
||||
|
||||
|
@ -19,6 +19,7 @@ src_test_test_SOURCES = \
|
||||
src/test/test.c \
|
||||
src/test/test_accounting.c \
|
||||
src/test/test_addr.c \
|
||||
src/test/test_address.c \
|
||||
src/test/test_buffers.c \
|
||||
src/test/test_cell_formats.c \
|
||||
src/test/test_cell_queue.c \
|
||||
|
@ -1296,6 +1296,7 @@ static struct testcase_t test_array[] = {
|
||||
|
||||
extern struct testcase_t accounting_tests[];
|
||||
extern struct testcase_t addr_tests[];
|
||||
extern struct testcase_t address_tests[];
|
||||
extern struct testcase_t buffer_tests[];
|
||||
extern struct testcase_t cell_format_tests[];
|
||||
extern struct testcase_t cell_queue_tests[];
|
||||
@ -1338,6 +1339,7 @@ static struct testgroup_t testgroups[] = {
|
||||
{ "", test_array },
|
||||
{ "accounting/", accounting_tests },
|
||||
{ "addr/", addr_tests },
|
||||
{ "address/", address_tests },
|
||||
{ "buffer/", buffer_tests },
|
||||
{ "cellfmt/", cell_format_tests },
|
||||
{ "cellqueue/", cell_queue_tests },
|
||||
|
467
src/test/test_address.c
Normal file
467
src/test/test_address.c
Normal file
@ -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
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user