#define ADDRESS_PRIVATE
#include "orconfig.h"
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#error "orconfig.h didn't define WIN32_LEAN_AND_MEAN"
#endif
#ifndef WINVER
#error "orconfig.h didn't define WINVER"
#endif
#ifndef _WIN32_WINNT
#error "orconfig.h didn't define _WIN32_WINNT"
#endif
#if WINVER < 0x0501
#error "winver too low"
#endif
#if _WIN32_WINNT < 0x0501
#error "winver too low"
#endif
#include <winsock2.h>
#include <process.h>
#include <windows.h>
#include <iphlpapi.h>
#endif
#include "lib/net/address.h"
#include "lib/net/socket.h"
#include "lib/cc/ctassert.h"
#include "lib/container/smartlist.h"
#include "lib/ctime/di_ops.h"
#include "lib/log/log.h"
#include "lib/log/escape.h"
#include "lib/malloc/malloc.h"
#include "lib/net/inaddr.h"
#include "lib/string/compat_ctype.h"
#include "lib/string/compat_string.h"
#include "lib/string/parse_int.h"
#include "lib/string/printf.h"
#include "lib/string/util_string.h"
#include "ext/siphash.h"
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif
#ifdef HAVE_IFADDRS_H
#include <ifaddrs.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if AF_UNSPEC != 0
#error "We rely on AF_UNSPEC being 0. Yours isn't. Please tell us more!"
#endif
CTASSERT(AF_UNSPEC == 0);
socklen_t
tor_addr_to_sockaddr(const tor_addr_t *a,
uint16_t port,
struct sockaddr *sa_out,
socklen_t len)
{
memset(sa_out, 0, len);
sa_family_t family = tor_addr_family(a);
if (family == AF_INET) {
struct sockaddr_in *sin;
if (len < (int)sizeof(struct sockaddr_in))
return 0;
sin = (struct sockaddr_in *)sa_out;
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
sin->sin_len = sizeof(struct sockaddr_in);
#endif
sin->sin_family = AF_INET;
sin->sin_port = htons(port);
sin->sin_addr.s_addr = tor_addr_to_ipv4n(a);
return sizeof(struct sockaddr_in);
} else if (family == AF_INET6) {
struct sockaddr_in6 *sin6;
if (len < (int)sizeof(struct sockaddr_in6))
return 0;
sin6 = (struct sockaddr_in6 *)sa_out;
#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
sin6->sin6_len = sizeof(struct sockaddr_in6);
#endif
sin6->sin6_family = AF_INET6;
sin6->sin6_port = htons(port);
memcpy(&sin6->sin6_addr, tor_addr_to_in6_assert(a),
sizeof(struct in6_addr));
return sizeof(struct sockaddr_in6);
} else {
return 0;
}
}
static void
tor_addr_make_af_unix(tor_addr_t *a)
{
memset(a, 0, sizeof(*a));
a->family = AF_UNIX;
}
int
tor_addr_from_sockaddr(tor_addr_t *a, const struct sockaddr *sa,
uint16_t *port_out)
{
tor_assert(a);
tor_assert(sa);
memset(a, 0, sizeof(*a));
if (sa->sa_family == AF_INET) {
struct sockaddr_in *sin = (struct sockaddr_in *) sa;
tor_addr_from_ipv4n(a, sin->sin_addr.s_addr);
if (port_out)
*port_out = ntohs(sin->sin_port);
} else if (sa->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
tor_addr_from_in6(a, &sin6->sin6_addr);
if (port_out)
*port_out = ntohs(sin6->sin6_port);
} else if (sa->sa_family == AF_UNIX) {
tor_addr_make_af_unix(a);
return 0;
} else {
tor_addr_make_unspec(a);
return -1;
}
return 0;
}
char *
tor_sockaddr_to_str(const struct sockaddr *sa)
{
char address[TOR_ADDR_BUF_LEN];
char *result;
tor_addr_t addr;
uint16_t port;
#ifdef HAVE_SYS_UN_H
if (sa->sa_family == AF_UNIX) {
struct sockaddr_un *s_un = (struct sockaddr_un *)sa;
tor_asprintf(&result, "unix:%s", s_un->sun_path);
return result;
}
#endif
if (sa->sa_family == AF_UNSPEC)
return tor_strdup("unspec");
if (tor_addr_from_sockaddr(&addr, sa, &port) < 0)
return NULL;
if (! tor_addr_to_str(address, &addr, sizeof(address), 1))
return NULL;
tor_asprintf(&result, "%s:%d", address, (int)port);
return result;
}
void
tor_addr_make_unspec(tor_addr_t *a)
{
memset(a, 0, sizeof(*a));
a->family = AF_UNSPEC;
}
void
tor_addr_make_null(tor_addr_t *a, sa_family_t family)
{
memset(a, 0, sizeof(*a));
a->family = family;
}
int
tor_addr_is_internal_(const tor_addr_t *addr, int for_listening,
const char *filename, int lineno)
{
uint32_t iph4 = 0;
uint32_t iph6[4];
tor_assert(addr);
sa_family_t v_family = tor_addr_family(addr);
if (v_family == AF_INET) {
iph4 = tor_addr_to_ipv4h(addr);
} else if (v_family == AF_INET6) {
if (tor_addr_is_v4(addr)) {
uint32_t *addr32 = NULL;
v_family = AF_INET;
addr32 = tor_addr_to_in6_addr32(addr);
tor_assert(addr32);
iph4 = ntohl(addr32[3]);
}
}
if (v_family == AF_INET6) {
const uint32_t *a32 = tor_addr_to_in6_addr32(addr);
iph6[0] = ntohl(a32[0]);
iph6[1] = ntohl(a32[1]);
iph6[2] = ntohl(a32[2]);
iph6[3] = ntohl(a32[3]);
if (for_listening && !iph6[0] && !iph6[1] && !iph6[2] && !iph6[3])
return 0;
if (((iph6[0] & 0xfe000000) == 0xfc000000) ||
((iph6[0] & 0xffc00000) == 0xfe800000) ||
((iph6[0] & 0xffc00000) == 0xfec00000))
return 1;
if (!iph6[0] && !iph6[1] && !iph6[2] &&
((iph6[3] & 0xfffffffe) == 0x00000000))
return 1;
return 0;
} else if (v_family == AF_INET) {
if (for_listening && (!iph4 || ((iph4 & 0xffc00000) == 0x64400000)))
return 0;
if (((iph4 & 0xff000000) == 0x0a000000) ||
((iph4 & 0xff000000) == 0x00000000) ||
((iph4 & 0xff000000) == 0x7f000000) ||
((iph4 & 0xffc00000) == 0x64400000) ||
((iph4 & 0xffff0000) == 0xa9fe0000) ||
((iph4 & 0xfff00000) == 0xac100000) ||
((iph4 & 0xffff0000) == 0xc0a80000))
return 1;
return 0;
}
log_warn(LD_BUG, "tor_addr_is_internal() called from %s:%d with a "
"non-IP address of type %d", filename, lineno, (int)v_family);
tor_fragile_assert();
return 1;
}
const char *
tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len, int decorate)
{
const char *ptr;
tor_assert(addr && dest);
switch (tor_addr_family(addr)) {
case AF_INET:
if (len < 8)
return NULL;
ptr = tor_inet_ntop(AF_INET, &addr->addr.in_addr, dest, len);
break;
case AF_INET6:
if (len < (3u + (decorate ? 2 : 0)))
return NULL;
if (decorate)
ptr = tor_inet_ntop(AF_INET6, &addr->addr.in6_addr, dest+1, len-2);
else
ptr = tor_inet_ntop(AF_INET6, &addr->addr.in6_addr, dest, len);
if (ptr && decorate) {
*dest = '[';
memcpy(dest+strlen(dest), "]", 2);
tor_assert(ptr == dest+1);
ptr = dest;
}
break;
case AF_UNIX:
tor_snprintf(dest, len, "AF_UNIX");
ptr = dest;
break;
default:
return NULL;
}
return ptr;
}
int
tor_addr_parse_PTR_name(tor_addr_t *result, const char *address,
int family, int accept_regular)
{
if (!strcasecmpend(address, ".in-addr.arpa")) {
char buf[INET_NTOA_BUF_LEN];
size_t len;
struct in_addr inaddr;
if (family == AF_INET6)
return -1;
len = strlen(address) - strlen(".in-addr.arpa");
if (len >= INET_NTOA_BUF_LEN)
return -1;
memcpy(buf, address, len);
buf[len] = '\0';
if (tor_inet_aton(buf, &inaddr) == 0)
return -1;
inaddr.s_addr = (uint32_t)
(((inaddr.s_addr & 0x000000ff) << 24)
|((inaddr.s_addr & 0x0000ff00) << 8)
|((inaddr.s_addr & 0x00ff0000) >> 8)
|((inaddr.s_addr & 0xff000000) >> 24));
if (result) {
tor_addr_from_in(result, &inaddr);
}
return 1;
}
if (!strcasecmpend(address, ".ip6.arpa")) {
const char *cp;
int n0, n1;
struct in6_addr in6;
if (family == AF_INET)
return -1;
cp = address;
for (int i = 0; i < 16; ++i) {
n0 = hex_decode_digit(*cp++);
if (*cp++ != '.') return -1;
n1 = hex_decode_digit(*cp++);
if (*cp++ != '.') return -1;
if (n0<0 || n1 < 0)
return -1;
in6.s6_addr[15-i] = n0 | (n1 << 4);
}
if (strcasecmp(cp, "ip6.arpa"))
return -1;
if (result) {
tor_addr_from_in6(result, &in6);
}
return 1;
}
if (accept_regular) {
tor_addr_t tmp;
int r = tor_addr_parse(&tmp, address);
if (r < 0)
return 0;
if (r != family && family != AF_UNSPEC)
return -1;
if (result)
memcpy(result, &tmp, sizeof(tor_addr_t));
return 1;
}
return 0;
}
int
tor_addr_to_PTR_name(char *out, size_t outlen,
const tor_addr_t *addr)
{
tor_assert(out);
tor_assert(addr);
if (addr->family == AF_INET) {
uint32_t a = tor_addr_to_ipv4h(addr);
return tor_snprintf(out, outlen, "%d.%d.%d.%d.in-addr.arpa",
(int)(uint8_t)((a )&0xff),
(int)(uint8_t)((a>>8 )&0xff),
(int)(uint8_t)((a>>16)&0xff),
(int)(uint8_t)((a>>24)&0xff));
} else if (addr->family == AF_INET6) {
int i;
char *cp = out;
const uint8_t *bytes = tor_addr_to_in6_addr8(addr);
if (outlen < REVERSE_LOOKUP_NAME_BUF_LEN)
return -1;
for (i = 15; i >= 0; --i) {
uint8_t byte = bytes[i];
*cp++ = "0123456789abcdef"[byte & 0x0f];
*cp++ = '.';
*cp++ = "0123456789abcdef"[byte >> 4];
*cp++ = '.';
}
memcpy(cp, "ip6.arpa", 9);
return 32 * 2 + 8;
}
return -1;
}
int
tor_addr_parse_mask_ports(const char *s,
unsigned flags,
tor_addr_t *addr_out,
maskbits_t *maskbits_out,
uint16_t *port_min_out, uint16_t *port_max_out)
{
char *base = NULL, *address, *mask = NULL, *port = NULL, *rbracket = NULL;
char *endptr;
int any_flag=0, v4map=0;
sa_family_t family;
struct in6_addr in6_tmp;
struct in_addr in_tmp = { .s_addr = 0 };
tor_assert(s);
tor_assert(addr_out);
tor_assert(!((flags & TAPMP_STAR_IPV4_ONLY)
&& (flags & TAPMP_STAR_IPV6_ONLY)));
#define MAX_ADDRESS_LENGTH (TOR_ADDR_BUF_LEN+2+(1+INET_NTOA_BUF_LEN)+12+1)
if (strlen(s) > MAX_ADDRESS_LENGTH) {
log_warn(LD_GENERAL, "Impossibly long IP %s; rejecting", escaped(s));
goto err;
}
base = tor_strdup(s);
address = base;
if (*address == '[') {
address++;
rbracket = strchr(address, ']');
if (!rbracket) {
log_warn(LD_GENERAL,
"No closing IPv6 bracket in address pattern; rejecting.");
goto err;
}
}
mask = strchr((rbracket?rbracket:address),'/');
port = strchr((mask?mask:(rbracket?rbracket:address)), ':');
if (port)
*port++ = '\0';
if (mask)
*mask++ = '\0';
if (rbracket)
*rbracket = '\0';
if (port && mask)
tor_assert(port > mask);
if (mask && rbracket)
tor_assert(mask > rbracket);
memset(addr_out, 0, sizeof(tor_addr_t));
if (!strcmp(address, "*")) {
if (flags & TAPMP_EXTENDED_STAR) {
if (flags & TAPMP_STAR_IPV4_ONLY) {
family = AF_INET;
tor_addr_from_ipv4h(addr_out, 0);
} else if (flags & TAPMP_STAR_IPV6_ONLY) {
static uint8_t nil_bytes[16] =
{ [0]=0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
family = AF_INET6;
tor_addr_from_ipv6_bytes(addr_out, nil_bytes);
} else {
family = AF_UNSPEC;
tor_addr_make_unspec(addr_out);
log_info(LD_GENERAL,
"'%s' expands into rules which apply to all IPv4 and IPv6 "
"addresses. (Use accept/reject *4:* for IPv4 or "
"accept[6]/reject[6] *6:* for IPv6.)", s);
}
} else {
family = AF_INET;
tor_addr_from_ipv4h(addr_out, 0);
}
any_flag = 1;
} else if (!strcmp(address, "*4") && (flags & TAPMP_EXTENDED_STAR)) {
family = AF_INET;
tor_addr_from_ipv4h(addr_out, 0);
any_flag = 1;
} else if (!strcmp(address, "*6") && (flags & TAPMP_EXTENDED_STAR)) {
static uint8_t nil_bytes[16] = { [0]=0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
family = AF_INET6;
tor_addr_from_ipv6_bytes(addr_out, nil_bytes);
any_flag = 1;
} else if (tor_inet_pton(AF_INET6, address, &in6_tmp) > 0) {
family = AF_INET6;
tor_addr_from_in6(addr_out, &in6_tmp);
} else if (tor_inet_pton(AF_INET, address, &in_tmp) > 0) {
family = AF_INET;
tor_addr_from_in(addr_out, &in_tmp);
} else {
log_warn(LD_GENERAL, "Malformed IP %s in address pattern; rejecting.",
escaped(address));
goto err;
}
v4map = tor_addr_is_v4(addr_out);
if (maskbits_out) {
int bits = 0;
struct in_addr v4mask;
if (mask) {
bits = (int) strtol(mask, &endptr, 10);
if (!*endptr) {
if ((bits<0 || bits>128) ||
(family == AF_INET && bits > 32)) {
log_warn(LD_GENERAL,
"Bad number of mask bits (%d) on address range; rejecting.",
bits);
goto err;
}
} else {
if (tor_inet_pton(AF_INET, mask, &v4mask) > 0) {
bits = addr_mask_get_bits(ntohl(v4mask.s_addr));
if (bits < 0) {
log_warn(LD_GENERAL,
"IPv4-style mask %s is not a prefix address; rejecting.",
escaped(mask));
goto err;
}
} else {
log_warn(LD_GENERAL,
"Malformed mask on address range %s; rejecting.",
escaped(s));
goto err;
}
}
if (family == AF_INET6 && v4map) {
if (bits > 32 && bits < 96) {
log_warn(LD_GENERAL,
"Bad mask bits %d for V4-mapped V6 address; rejecting.",
bits);
goto err;
}
bits = 96 + bits%32;
}
if (any_flag) {
log_warn(LD_GENERAL,
"Found bit prefix with wildcard address; rejecting");
goto err;
}
} else {
if (any_flag)
bits = 0;
else if (tor_addr_family(addr_out) == AF_INET)
bits = 32;
else if (tor_addr_family(addr_out) == AF_INET6)
bits = 128;
}
*maskbits_out = (maskbits_t) bits;
} else {
if (mask) {
log_warn(LD_GENERAL,
"Unexpected mask in address %s; rejecting", escaped(s));
goto err;
}
}
if (port_min_out) {
uint16_t port2;
if (!port_max_out)
port_max_out = &port2;
if (parse_port_range(port, port_min_out, port_max_out) < 0) {
goto err;
} else if ((*port_min_out != *port_max_out) && port_max_out == &port2) {
log_warn(LD_GENERAL,
"Wanted one port from address range, but there are two.");
port_max_out = NULL;
goto err;
}
} else {
if (port) {
log_warn(LD_GENERAL,
"Unexpected ports in address %s; rejecting", escaped(s));
goto err;
}
}
tor_free(base);
return tor_addr_family(addr_out);
err:
tor_free(base);
return -1;
}
int
tor_addr_is_v4(const tor_addr_t *addr)
{
tor_assert(addr);
if (tor_addr_family(addr) == AF_INET)
return 1;
if (tor_addr_family(addr) == AF_INET6) {
uint32_t *a32 = tor_addr_to_in6_addr32(addr);
if (a32[0] == 0 && a32[1] == 0 && ntohl(a32[2]) == 0x0000ffffu)
return 1;
}
return 0;
}
int
tor_addr_is_null(const tor_addr_t *addr)
{
tor_assert(addr);
switch (tor_addr_family(addr)) {
case AF_INET6: {
uint32_t *a32 = tor_addr_to_in6_addr32(addr);
return (a32[0] == 0) && (a32[1] == 0) && (a32[2] == 0) && (a32[3] == 0);
}
case AF_INET:
return (tor_addr_to_ipv4n(addr) == 0);
case AF_UNIX:
return 1;
case AF_UNSPEC:
return 1;
default:
log_warn(LD_BUG, "Called with unknown address family %d",
(int)tor_addr_family(addr));
return 0;
}
}
int
tor_addr_is_loopback(const tor_addr_t *addr)
{
tor_assert(addr);
switch (tor_addr_family(addr)) {
case AF_INET6: {
uint32_t *a32 = tor_addr_to_in6_addr32(addr);
return (a32[0] == 0) && (a32[1] == 0) && (a32[2] == 0) &&
(ntohl(a32[3]) == 1);
}
case AF_INET:
return (tor_addr_to_ipv4h(addr) & 0xff000000) == 0x7f000000;
case AF_UNSPEC:
return 0;
default:
tor_fragile_assert();
return 0;
}
}
int
tor_addr_is_valid(const tor_addr_t *addr, int for_listening)
{
if (addr == NULL) {
return 0;
}
if (for_listening) {
if (addr->family == AF_INET || addr->family == AF_INET6) {
return 1;
}
}
return !tor_addr_is_null(addr);
}
int
tor_addr_is_valid_ipv4n(uint32_t v4n_addr, int for_listening)
{
if (for_listening) {
return 1;
}
return v4n_addr != 0;
}
int
tor_port_is_valid(uint16_t port, int for_listening)
{
if (for_listening) {
return 1;
}
return port != 0;
}
void
tor_addr_from_ipv4n(tor_addr_t *dest, uint32_t v4addr)
{
tor_assert(dest);
memset(dest, 0, sizeof(tor_addr_t));
dest->family = AF_INET;
dest->addr.in_addr.s_addr = v4addr;
}
void
tor_addr_from_ipv6_bytes(tor_addr_t *dest, const uint8_t *ipv6_bytes)
{
tor_assert(dest);
tor_assert(ipv6_bytes);
memset(dest, 0, sizeof(tor_addr_t));
dest->family = AF_INET6;
memcpy(dest->addr.in6_addr.s6_addr, ipv6_bytes, 16);
}
void
tor_addr_from_in6(tor_addr_t *dest, const struct in6_addr *in6)
{
tor_addr_from_ipv6_bytes(dest, in6->s6_addr);
}
void
tor_addr_copy_ipv6_bytes(uint8_t *dest, const tor_addr_t *src)
{
tor_assert(dest);
tor_assert(src);
memset(dest, 0, 16);
IF_BUG_ONCE(src->family != AF_INET6)
return;
memcpy(dest, src->addr.in6_addr.s6_addr, 16);
}
void
tor_addr_copy(tor_addr_t *dest, const tor_addr_t *src)
{
if (src == dest)
return;
tor_assert(src);
tor_assert(dest);
memcpy(dest, src, sizeof(tor_addr_t));
}
void
tor_addr_copy_tight(tor_addr_t *dest, const tor_addr_t *src)
{
tor_assert(src != dest);
tor_assert(src);
tor_assert(dest);
memset(dest, 0, sizeof(tor_addr_t));
dest->family = src->family;
switch (tor_addr_family(src))
{
case AF_INET:
dest->addr.in_addr.s_addr = src->addr.in_addr.s_addr;
break;
case AF_INET6:
memcpy(dest->addr.in6_addr.s6_addr, src->addr.in6_addr.s6_addr, 16);
break;
case AF_UNSPEC:
break;
default:
tor_fragile_assert();
}
}
int
tor_addr_compare(const tor_addr_t *addr1, const tor_addr_t *addr2,
tor_addr_comparison_t how)
{
return tor_addr_compare_masked(addr1, addr2, 128, how);
}
int
tor_addr_compare_masked(const tor_addr_t *addr1, const tor_addr_t *addr2,
maskbits_t mbits, tor_addr_comparison_t how)
{
#define TRISTATE(a,b) (((a)<(b))?-1: (((a)==(b))?0:1))
sa_family_t family1, family2, v_family1, v_family2;
tor_assert(addr1 && addr2);
v_family1 = family1 = tor_addr_family(addr1);
v_family2 = family2 = tor_addr_family(addr2);
if (family1==family2) {
int r;
switch (family1) {
case AF_UNSPEC:
return 0;
case AF_INET: {
uint32_t a1 = tor_addr_to_ipv4h(addr1);
uint32_t a2 = tor_addr_to_ipv4h(addr2);
if (mbits <= 0)
return 0;
if (mbits > 32)
mbits = 32;
a1 >>= (32-mbits);
a2 >>= (32-mbits);
r = TRISTATE(a1, a2);
return r;
}
case AF_INET6: {
if (mbits > 128)
mbits = 128;
const uint8_t *a1 = tor_addr_to_in6_addr8(addr1);
const uint8_t *a2 = tor_addr_to_in6_addr8(addr2);
const int bytes = mbits >> 3;
const int leftover_bits = mbits & 7;
if (bytes && (r = tor_memcmp(a1, a2, bytes))) {
return r;
} else if (leftover_bits) {
uint8_t b1 = a1[bytes] >> (8-leftover_bits);
uint8_t b2 = a2[bytes] >> (8-leftover_bits);
return TRISTATE(b1, b2);
} else {
return 0;
}
}
case AF_UNIX:
if (addr1 < addr2)
return -1;
else if (addr1 == addr2)
return 0;
else
return 1;
default:
tor_fragile_assert();
return 0;
}
} else if (how == CMP_EXACT) {
return TRISTATE(family1, family2);
}
if (mbits == 0)
return 0;
if (family1 == AF_INET6 && tor_addr_is_v4(addr1))
v_family1 = AF_INET;
if (family2 == AF_INET6 && tor_addr_is_v4(addr2))
v_family2 = AF_INET;
if (v_family1 == v_family2) {
uint32_t a1, a2;
if (family1 == AF_INET6) {
a1 = tor_addr_to_mapped_ipv4h(addr1);
if (mbits <= 96)
return 0;
mbits -= 96;
} else {
a1 = tor_addr_to_ipv4h(addr1);
}
if (family2 == AF_INET6) {
a2 = tor_addr_to_mapped_ipv4h(addr2);
} else {
a2 = tor_addr_to_ipv4h(addr2);
}
if (mbits > 32) mbits = 32;
a1 >>= (32-mbits);
a2 >>= (32-mbits);
return TRISTATE(a1, a2);
} else {
return TRISTATE(family1, family2);
}
}
static const uint32_t unspec_hash_input[] = { 0x4e4df09f, 0x92985342 };
uint64_t
tor_addr_hash(const tor_addr_t *addr)
{
switch (tor_addr_family(addr)) {
case AF_INET:
return siphash24g(&addr->addr.in_addr.s_addr, 4);
case AF_UNSPEC:
return siphash24g(unspec_hash_input, sizeof(unspec_hash_input));
case AF_INET6:
return siphash24g(&addr->addr.in6_addr.s6_addr, 16);
default:
tor_fragile_assert();
return 0;
}
}
uint64_t
tor_addr_keyed_hash(const struct sipkey *key, const tor_addr_t *addr)
{
switch (tor_addr_family(addr)) {
case AF_INET:
return siphash24(&addr->addr.in_addr.s_addr, 4, key);
case AF_UNSPEC:
return siphash24(unspec_hash_input, sizeof(unspec_hash_input), key);
case AF_INET6:
return siphash24(&addr->addr.in6_addr.s6_addr, 16, key);
default:
tor_fragile_assert();
return 0;
}
}
char *
tor_addr_to_str_dup(const tor_addr_t *addr)
{
char buf[TOR_ADDR_BUF_LEN];
if (tor_addr_to_str(buf, addr, sizeof(buf), 0)) {
return tor_strdup(buf);
} else {
return tor_strdup("<unknown address type>");
}
}
const char *
fmt_addr_impl(const tor_addr_t *addr, int decorate)
{
static char buf[TOR_ADDR_BUF_LEN];
if (!addr) return "<null>";
if (tor_addr_to_str(buf, addr, sizeof(buf), decorate))
return buf;
else
return "???";
}
const char *
fmt_addrport(const tor_addr_t *addr, uint16_t port)
{
static char buf[TOR_ADDRPORT_BUF_LEN];
tor_snprintf(buf, sizeof(buf), "%s:%u", fmt_and_decorate_addr(addr), port);
return buf;
}
const char *
fmt_addr32(uint32_t addr)
{
static char buf[INET_NTOA_BUF_LEN];
struct in_addr in;
int success;
in.s_addr = htonl(addr);
success = tor_inet_ntoa(&in, buf, sizeof(buf));
tor_assertf_nonfatal(success >= 0,
"Failed to convert IP 0x%08X (HBO) to string", addr);
IF_BUG_ONCE(success < 0) {
memset(buf, 0, INET_NTOA_BUF_LEN);
}
return buf;
}
const char *
fmt_addr_family(const tor_addr_t *addr)
{
static int default_bug_once = 0;
IF_BUG_ONCE(!addr)
return "NULL pointer";
switch (tor_addr_family(addr)) {
case AF_INET6:
return "IPv6";
case AF_INET:
return "IPv4";
case AF_UNIX:
return "UNIX socket";
case AF_UNSPEC:
return "unspecified";
default:
if (!default_bug_once) {
log_warn(LD_BUG, "Called with unknown address family %d",
(int)tor_addr_family(addr));
default_bug_once = 1;
}
return "unknown";
}
}
static int
tor_addr_parse_impl(tor_addr_t *addr, const char *src,
bool allow_ipv6_without_brackets)
{
char *tmp = NULL;
int result = -1;
struct in_addr in_tmp;
struct in6_addr in6_tmp;
int brackets_detected = 0;
tor_assert(addr && src);
size_t len = strlen(src);
if (len && src[0] == '[' && src[len - 1] == ']') {
brackets_detected = 1;
src = tmp = tor_strndup(src+1, strlen(src)-2);
}
if (brackets_detected || allow_ipv6_without_brackets) {
if (tor_inet_pton(AF_INET6, src, &in6_tmp) > 0) {
result = AF_INET6;
tor_addr_from_in6(addr, &in6_tmp);
}
}
if (!brackets_detected) {
if (tor_inet_pton(AF_INET, src, &in_tmp) > 0) {
result = AF_INET;
tor_addr_from_in(addr, &in_tmp);
}
}
if (result == -1) {
memset(addr, 0, sizeof(tor_addr_t));
}
tor_free(tmp);
return result;
}
int
tor_addr_parse(tor_addr_t *addr, const char *src)
{
return tor_addr_parse_impl(addr, src, 1);
}
#ifdef HAVE_IFADDRS_TO_SMARTLIST
STATIC smartlist_t *
ifaddrs_to_smartlist(const struct ifaddrs *ifa, sa_family_t family)
{
smartlist_t *result = smartlist_new();
const struct ifaddrs *i;
for (i = ifa; i; i = i->ifa_next) {
tor_addr_t tmp;
if ((i->ifa_flags & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING))
continue;
if (!i->ifa_addr)
continue;
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)));
}
return result;
}
STATIC smartlist_t *
get_interface_addresses_ifaddrs(int severity, sa_family_t family)
{
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, family);
freeifaddrs(ifa);
return result;
}
#endif
#ifdef HAVE_IP_ADAPTER_TO_SMARTLIST
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) {
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;
}
STATIC smartlist_t *
get_interface_addresses_win32(int severity, sa_family_t family)
{
smartlist_t *result = NULL;
ULONG size, res;
IP_ADAPTER_ADDRESSES *addresses = NULL;
(void) severity;
#define FLAGS (GAA_FLAG_SKIP_ANYCAST | \
GAA_FLAG_SKIP_MULTICAST | \
GAA_FLAG_SKIP_DNS_SERVER)
size = 15*1024;
addresses = tor_malloc(size);
res = GetAdaptersAddresses(family, FLAGS, NULL, addresses, &size);
if (res == ERROR_BUFFER_OVERFLOW) {
tor_free(addresses);
addresses = tor_malloc(size);
res = GetAdaptersAddresses(AF_UNSPEC, FLAGS, NULL, addresses, &size);
}
if (res != NO_ERROR) {
log_fn(severity, LD_NET, "GetAdaptersAddresses failed (result: %lu)", res);
goto done;
}
result = ip_adapter_addresses_to_smartlist(addresses);
done:
tor_free(addresses);
return result;
}
#endif
#ifdef HAVE_IFCONF_TO_SMARTLIST
#define IFREQ_SIZE 4096
#ifndef _SIZEOF_ADDR_IFREQ
#define _SIZEOF_ADDR_IFREQ(x) sizeof(x)
#endif
static void
ifconf_free_ifc_buf(struct ifconf *ifc)
{
raw_free(ifc->ifc_buf);
ifc->ifc_buf = NULL;
}
STATIC smartlist_t *
ifreq_to_smartlist(const uint8_t *buf, size_t buflen)
{
smartlist_t *result = smartlist_new();
const uint8_t *end = buf + buflen;
struct ifreq *r = tor_malloc(IFREQ_SIZE);
while (buf < end) {
memcpy(r, buf, end - buf < IFREQ_SIZE ? end - buf : IFREQ_SIZE);
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)));
buf += _SIZEOF_ADDR_IFREQ(*r);
}
tor_free(r);
return result;
}
STATIC smartlist_t *
get_interface_addresses_ioctl(int severity, sa_family_t family)
{
struct ifconf ifc;
ifc.ifc_buf = NULL;
int fd;
smartlist_t *result = NULL;
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;
}
int mult = 1;
do {
mult *= 2;
ifc.ifc_len = mult * IFREQ_SIZE;
ifc.ifc_buf = tor_realloc(ifc.ifc_buf, ifc.ifc_len);
tor_assert(ifc.ifc_buf);
if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) {
tor_log(severity, LD_NET, "ioctl failed: %s", strerror(errno));
goto done;
}
} while (mult * IFREQ_SIZE - ifc.ifc_len <= IFREQ_SIZE);
result = ifreq_to_smartlist((const uint8_t *)ifc.ifc_buf, ifc.ifc_len);
done:
if (fd >= 0)
close(fd);
ifconf_free_ifc_buf(&ifc);
return result;
}
#endif
MOCK_IMPL(smartlist_t *,
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, family)))
return result;
#endif
#if defined(HAVE_IP_ADAPTER_TO_SMARTLIST)
if ((result = get_interface_addresses_win32(severity, family)))
return result;
#endif
#if defined(HAVE_IFCONF_TO_SMARTLIST)
if ((result = get_interface_addresses_ioctl(severity, family)))
return result;
#endif
(void) severity;
(void) result;
return NULL;
}
int
tor_addr_is_multicast(const tor_addr_t *a)
{
sa_family_t family = tor_addr_family(a);
if (family == AF_INET) {
uint32_t ipv4h = tor_addr_to_ipv4h(a);
if ((ipv4h >> 24) == 0xe0)
return 1;
} else if (family == AF_INET6) {
const uint8_t *a32 = tor_addr_to_in6_addr8(a);
if (a32[0] == 0xff)
return 1;
}
return 0;
}
MOCK_IMPL(int,
get_interface_address6_via_udp_socket_hack,(int severity,
sa_family_t family,
tor_addr_t *addr))
{
struct sockaddr_storage target_addr;
int sock=-1, r=-1;
socklen_t addr_len;
memset(addr, 0, sizeof(tor_addr_t));
memset(&target_addr, 0, sizeof(target_addr));
if (family == AF_INET6) {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&target_addr;
sin6->sin6_port = htons(9);
sock = tor_open_socket(PF_INET6,SOCK_DGRAM,IPPROTO_UDP);
addr_len = (socklen_t)sizeof(struct sockaddr_in6);
sin6->sin6_family = AF_INET6;
S6_ADDR16(sin6->sin6_addr)[0] = htons(0x2002);
} else if (family == AF_INET) {
struct sockaddr_in *sin = (struct sockaddr_in*)&target_addr;
sin->sin_port = htons(9);
sock = tor_open_socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
addr_len = (socklen_t)sizeof(struct sockaddr_in);
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = htonl(0x12000001);
} else {
return -1;
}
if (sock < 0) {
int e = tor_socket_errno(-1);
log_fn(severity, LD_NET, "unable to create socket: %s",
tor_socket_strerror(e));
goto err;
}
if (tor_connect_socket(sock,(struct sockaddr *)&target_addr,
addr_len) < 0) {
int e = tor_socket_errno(sock);
log_fn(severity, LD_NET, "connect() failed: %s", tor_socket_strerror(e));
goto err;
}
if (tor_addr_from_getsockname(addr, sock) < 0) {
int e = tor_socket_errno(sock);
log_fn(severity, LD_NET, "getsockname() to determine interface failed: %s",
tor_socket_strerror(e));
goto err;
}
if (tor_addr_is_loopback(addr) || tor_addr_is_multicast(addr)) {
log_fn(severity, LD_NET, "Address that we determined via UDP socket"
" magic is unsuitable for public comms.");
} else {
r=0;
}
err:
if (sock >= 0)
tor_close_socket(sock);
if (r == -1)
memset(addr, 0, sizeof(tor_addr_t));
return r;
}
MOCK_IMPL(int,
get_interface_address6,(int severity, sa_family_t family, tor_addr_t *addr))
{
smartlist_t *addrs;
int rv = -1;
tor_assert(addr);
memset(addr, 0, sizeof(tor_addr_t));
addrs = get_interface_address6_list(severity, family, 1);
SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, a) {
tor_addr_copy(addr, a);
const bool is_internal = tor_addr_is_internal(a, 0);
rv = 0;
log_debug(LD_NET, "Found %s interface address '%s'",
(is_internal ? "internal" : "external"), fmt_addr(addr));
if (!is_internal)
break;
} SMARTLIST_FOREACH_END(a);
interface_address6_list_free(addrs);
return rv;
}
void
interface_address6_list_free_(smartlist_t *addrs)
{
if (addrs != NULL) {
SMARTLIST_FOREACH(addrs, tor_addr_t *, a, tor_free(a));
smartlist_free(addrs);
}
}
MOCK_IMPL(smartlist_t *,
get_interface_address6_list,(int severity,
sa_family_t family,
int include_internal))
{
smartlist_t *addrs;
tor_addr_t addr;
if ((addrs = get_interface_addresses_raw(severity, family))) {
SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, a)
{
if (tor_addr_is_loopback(a) ||
tor_addr_is_multicast(a)) {
SMARTLIST_DEL_CURRENT_KEEPORDER(addrs, a);
tor_free(a);
continue;
}
if (!include_internal && tor_addr_is_internal(a, 0)) {
SMARTLIST_DEL_CURRENT_KEEPORDER(addrs, a);
tor_free(a);
continue;
}
} SMARTLIST_FOREACH_END(a);
}
if (addrs && smartlist_len(addrs) > 0) {
return addrs;
}
if (addrs) {
smartlist_free(addrs);
}
addrs = smartlist_new();
if (family == AF_INET || family == AF_UNSPEC) {
if (get_interface_address6_via_udp_socket_hack(severity,AF_INET,
&addr) == 0) {
if (include_internal || !tor_addr_is_internal(&addr, 0)) {
smartlist_add(addrs, tor_memdup(&addr, sizeof(addr)));
}
}
}
if (family == AF_INET6 || family == AF_UNSPEC) {
if (get_interface_address6_via_udp_socket_hack(severity,AF_INET6,
&addr) == 0) {
if (include_internal || !tor_addr_is_internal(&addr, 0)) {
smartlist_add(addrs, tor_memdup(&addr, sizeof(addr)));
}
}
}
return addrs;
}
int
tor_addr_port_parse(int severity, const char *addrport,
tor_addr_t *address_out, uint16_t *port_out,
int default_port)
{
int retval = -1;
int r;
char *addr_tmp = NULL;
bool has_port;
tor_assert(addrport);
tor_assert(address_out);
tor_assert(port_out);
r = tor_addr_port_split(severity, addrport, &addr_tmp, port_out);
if (r < 0)
goto done;
has_port = !! *port_out;
if (!has_port) {
if (default_port >= 0)
*port_out = default_port;
else
goto done;
}
if (tor_addr_parse_impl(address_out, addr_tmp, !has_port) < 0)
goto done;
retval = 0;
done:
if (retval == -1) {
memset(address_out, 0, sizeof(tor_addr_t));
*port_out = 0;
}
tor_free(addr_tmp);
return retval;
}
int
tor_addr_port_split(int severity, const char *addrport,
char **address_out, uint16_t *port_out)
{
tor_addr_t a_tmp;
tor_assert(addrport);
tor_assert(address_out);
tor_assert(port_out);
if (tor_addr_parse(&a_tmp, addrport) == AF_INET6) {
*port_out = 0;
*address_out = tor_strdup(addrport);
return 0;
}
const char *colon;
char *address_ = NULL;
int port_;
int ok = 1;
colon = strrchr(addrport, ':');
if (colon) {
address_ = tor_strndup(addrport, colon-addrport);
port_ = (int) tor_parse_long(colon+1,10,1,65535,NULL,NULL);
if (!port_) {
log_fn(severity, LD_GENERAL, "Port %s out of range", escaped(colon+1));
ok = 0;
}
if (!port_out) {
char *esc_addrport = esc_for_log(addrport);
log_fn(severity, LD_GENERAL,
"Port %s given on %s when not required",
escaped(colon+1), esc_addrport);
tor_free(esc_addrport);
ok = 0;
}
} else {
address_ = tor_strdup(addrport);
port_ = 0;
}
if (ok) {
*address_out = address_;
} else {
*address_out = NULL;
tor_free(address_);
}
*port_out = ok ? ((uint16_t) port_) : 0;
return ok ? 0 : -1;
}
int
addr_mask_get_bits(uint32_t mask)
{
int i;
if (mask == 0)
return 0;
if (mask == 0xFFFFFFFFu)
return 32;
for (i=1; i<=32; ++i) {
if (mask == (uint32_t) ~((1u<<(32-i))-1)) {
return i;
}
}
return -1;
}
int
parse_port_range(const char *port, uint16_t *port_min_out,
uint16_t *port_max_out)
{
int port_min, port_max, ok;
tor_assert(port_min_out);
tor_assert(port_max_out);
if (!port || *port == '\0' || strcmp(port, "*") == 0) {
port_min = 1;
port_max = 65535;
} else {
char *endptr = NULL;
port_min = (int)tor_parse_long(port, 10, 0, 65535, &ok, &endptr);
if (!ok) {
log_warn(LD_GENERAL,
"Malformed port %s on address range; rejecting.",
escaped(port));
return -1;
} else if (endptr && *endptr == '-') {
port = endptr+1;
endptr = NULL;
port_max = (int)tor_parse_long(port, 10, 1, 65535, &ok, &endptr);
if (!ok) {
log_warn(LD_GENERAL,
"Malformed port %s on address range; rejecting.",
escaped(port));
return -1;
}
} else {
port_max = port_min;
}
if (port_min > port_max) {
log_warn(LD_GENERAL, "Insane port range on address policy; rejecting.");
return -1;
}
}
if (port_min < 1)
port_min = 1;
if (port_max > 65535)
port_max = 65535;
*port_min_out = (uint16_t) port_min;
*port_max_out = (uint16_t) port_max;
return 0;
}
char *
tor_dup_ip(uint32_t addr)
{
const char *ip_str;
char buf[TOR_ADDR_BUF_LEN];
struct in_addr in;
in.s_addr = htonl(addr);
ip_str = tor_inet_ntop(AF_INET, &in, buf, sizeof(buf));
tor_assertf_nonfatal(ip_str, "Failed to duplicate IP %08X", addr);
if (ip_str)
return tor_strdup(buf);
return NULL;
}
MOCK_IMPL(int,
get_interface_address,(int severity, uint32_t *addr))
{
tor_addr_t local_addr;
int r;
memset(addr, 0, sizeof(uint32_t));
r = get_interface_address6(severity, AF_INET, &local_addr);
if (r>=0)
*addr = tor_addr_to_ipv4h(&local_addr);
return r;
}
int
tor_addr_hostname_is_local(const char *name)
{
return !strcasecmp(name, "localhost") ||
!strcasecmp(name, "local") ||
!strcasecmpend(name, ".local");
}
tor_addr_port_t *
tor_addr_port_new(const tor_addr_t *addr, uint16_t port)
{
tor_addr_port_t *ap = tor_malloc_zero(sizeof(tor_addr_port_t));
if (addr)
tor_addr_copy(&ap->addr, addr);
ap->port = port;
return ap;
}
int
tor_addr_port_eq(const tor_addr_port_t *a,
const tor_addr_port_t *b)
{
return tor_addr_eq(&a->addr, &b->addr) && a->port == b->port;
}
int
string_is_valid_ipv4_address(const char *string)
{
struct in_addr addr;
return (tor_inet_pton(AF_INET,string,&addr) == 1);
}
int
string_is_valid_ipv6_address(const char *string)
{
struct in6_addr addr;
return (tor_inet_pton(AF_INET6,string,&addr) == 1);
}
int
string_is_valid_dest(const char *string)
{
char *tmp = NULL;
int retval;
size_t len;
if (string == NULL)
return 0;
len = strlen(string);
if (len == 0)
return 0;
if (string[0] == '[' && string[len - 1] == ']')
string = tmp = tor_strndup(string + 1, len - 2);
retval = string_is_valid_ipv4_address(string) ||
string_is_valid_ipv6_address(string) ||
string_is_valid_nonrfc_hostname(string);
tor_free(tmp);
return retval;
}
int
string_is_valid_nonrfc_hostname(const char *string)
{
int result = 1;
int has_trailing_dot;
char *last_label;
smartlist_t *components;
if (!string || strlen(string) == 0)
return 0;
if (string_is_valid_ipv4_address(string))
return 0;
components = smartlist_new();
smartlist_split_string(components,string,".",0,0);
if (BUG(smartlist_len(components) == 0)) {
smartlist_free(components);
return 0;
}
last_label = (char *)smartlist_get(components,
smartlist_len(components) - 1);
has_trailing_dot = (last_label[0] == '\0');
if (has_trailing_dot) {
smartlist_pop_last(components);
tor_free(last_label);
last_label = NULL;
}
SMARTLIST_FOREACH_BEGIN(components, char *, c) {
if ((c[0] == '-') || (*c == '_')) {
result = 0;
break;
}
do {
result = (TOR_ISALNUM(*c) || (*c == '-') || (*c == '_'));
c++;
} while (result && *c);
if (result == 0) {
break;
}
} SMARTLIST_FOREACH_END(c);
SMARTLIST_FOREACH_BEGIN(components, char *, c) {
tor_free(c);
} SMARTLIST_FOREACH_END(c);
smartlist_free(components);
return result;
}