Merge branch 'bug30721_squashed'

This commit is contained in:
Nick Mathewson
2019-06-26 09:57:20 -04:00
5 changed files with 843 additions and 276 deletions
+10
View File
@@ -0,0 +1,10 @@
o Minor bugfixes (networking, IP addresses):
- When parsing addreses via Tor's internal DNS lookup API, reject IPv4
addresses in square brackets, and accept IPv6 addresses in square
brackets. This change completes the work started in 23082, making
address parsing consistent between tor's internal DNS lookup and address
parsing APIs. Fixes bug 30721; bugfix on 0.2.1.5-alpha.
- When parsing addreses via Tor's internal address:port parsing and
DNS lookup APIs, require IPv6 addresses with ports to have square
brackets. But allow IPv6 addresses without ports, whether or not they
have square brackets. Fixes bug 30721; bugfix on 0.2.1.5-alpha.
-1
View File
@@ -266,7 +266,6 @@ problem function-size /src/lib/math/prob_distr.c:sample_uniform_interval() 145
problem function-size /src/lib/net/address.c:tor_addr_parse_mask_ports() 198
problem function-size /src/lib/net/address.c:tor_addr_compare_masked() 111
problem function-size /src/lib/net/inaddr.c:tor_inet_pton() 107
problem function-size /src/lib/net/resolve.c:tor_addr_lookup() 110
problem function-size /src/lib/net/socketpair.c:tor_ersatz_socketpair() 102
problem function-size /src/lib/osinfo/uname.c:get_uname() 116
problem function-size /src/lib/process/process_unix.c:process_unix_exec() 220
+84 -26
View File
@@ -373,7 +373,8 @@ tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len, int decorate)
*
* If <b>accept_regular</b> is set and the address is in neither recognized
* reverse lookup hostname format, try parsing the address as a regular
* IPv4 or IPv6 address too.
* IPv4 or IPv6 address too. This mode will accept IPv6 addresses with or
* without square brackets.
*/
int
tor_addr_parse_PTR_name(tor_addr_t *result, const char *address,
@@ -1187,17 +1188,22 @@ fmt_addr32(uint32_t addr)
}
/** Convert the string in <b>src</b> to a tor_addr_t <b>addr</b>. The string
* may be an IPv4 address, an IPv6 address, or an IPv6 address surrounded by
* square brackets.
* may be an IPv4 address, or an IPv6 address surrounded by square brackets.
*
* Return an address family on success, or -1 if an invalid address string is
* provided. */
int
tor_addr_parse(tor_addr_t *addr, const char *src)
* If <b>allow_ipv6_without_brackets</b> is true, also allow IPv6 addresses
* without brackets.
*
* Always rejects IPv4 addresses with brackets.
*
* Returns an address family on success, or -1 if an invalid address string is
* provided. */
static int
tor_addr_parse_impl(tor_addr_t *addr, const char *src,
bool allow_ipv6_without_brackets)
{
/* Holds substring of IPv6 address after removing square brackets */
char *tmp = NULL;
int result;
int result = -1;
struct in_addr in_tmp;
struct in6_addr in6_tmp;
int brackets_detected = 0;
@@ -1211,21 +1217,46 @@ tor_addr_parse(tor_addr_t *addr, const char *src)
src = tmp = tor_strndup(src+1, strlen(src)-2);
}
if (tor_inet_pton(AF_INET6, src, &in6_tmp) > 0) {
result = AF_INET6;
tor_addr_from_in6(addr, &in6_tmp);
} else if (!brackets_detected &&
tor_inet_pton(AF_INET, src, &in_tmp) > 0) {
result = AF_INET;
tor_addr_from_in(addr, &in_tmp);
} else {
result = -1;
/* Try to parse an IPv6 address if it has brackets, or if IPv6 addresses
* without brackets are allowed */
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);
}
}
/* Try to parse an IPv4 address without brackets */
if (!brackets_detected) {
if (tor_inet_pton(AF_INET, src, &in_tmp) > 0) {
result = AF_INET;
tor_addr_from_in(addr, &in_tmp);
}
}
/* Clear the address on error, to avoid returning uninitialised or partly
* parsed data.
*/
if (result == -1) {
memset(addr, 0, sizeof(tor_addr_t));
}
tor_free(tmp);
return result;
}
/** Convert the string in <b>src</b> to a tor_addr_t <b>addr</b>. The string
* may be an IPv4 address, an IPv6 address, or an IPv6 address surrounded by
* square brackets.
*
* Returns an address family on success, or -1 if an invalid address string is
* provided. */
int
tor_addr_parse(tor_addr_t *addr, const char *src)
{
return tor_addr_parse_impl(addr, src, 1);
}
#ifdef HAVE_IFADDRS_TO_SMARTLIST
/*
* Convert a linked list consisting of <b>ifaddrs</b> structures
@@ -1718,6 +1749,11 @@ get_interface_address6_list,(int severity,
* form "ip" or "ip:0". Otherwise, accept those forms, and set
* *<b>port_out</b> to <b>default_port</b>.
*
* This function accepts:
* - IPv6 address and port, when the IPv6 address is in square brackets,
* - IPv6 address with square brackets,
* - IPv6 address without square brackets.
*
* Return 0 on success, -1 on failure. */
int
tor_addr_port_parse(int severity, const char *addrport,
@@ -1727,6 +1763,7 @@ tor_addr_port_parse(int severity, const char *addrport,
int retval = -1;
int r;
char *addr_tmp = NULL;
bool has_port;
tor_assert(addrport);
tor_assert(address_out);
@@ -1736,28 +1773,47 @@ tor_addr_port_parse(int severity, const char *addrport,
if (r < 0)
goto done;
if (!*port_out) {
has_port = !! *port_out;
/* If there's no port, use the default port, or fail if there is no default
*/
if (!has_port) {
if (default_port >= 0)
*port_out = default_port;
else
goto done;
}
/* make sure that address_out is an IP address */
if (tor_addr_parse(address_out, addr_tmp) < 0)
/* Make sure that address_out is an IP address.
* If there is no port in addrport, allow IPv6 addresses without brackets. */
if (tor_addr_parse_impl(address_out, addr_tmp, !has_port) < 0)
goto done;
retval = 0;
done:
/* Clear the address and port on error, to avoid returning uninitialised or
* partly parsed data.
*/
if (retval == -1) {
memset(address_out, 0, sizeof(tor_addr_t));
*port_out = 0;
}
tor_free(addr_tmp);
return retval;
}
/** Given an address of the form "host[:port]", try to divide it into its host
* and port portions, setting *<b>address_out</b> to a newly allocated string
* holding the address portion and *<b>port_out</b> to the port (or 0 if no
* port is given). Return 0 on success, -1 on failure. */
* and port portions.
*
* Like tor_addr_port_parse(), this function accepts:
* - IPv6 address and port, when the IPv6 address is in square brackets,
* - IPv6 address with square brackets,
* - IPv6 address without square brackets.
*
* Sets *<b>address_out</b> to a newly allocated string holding the address
* portion, and *<b>port_out</b> to the port (or 0 if no port is given).
*
* Return 0 on success, -1 on failure. */
int
tor_addr_port_split(int severity, const char *addrport,
char **address_out, uint16_t *port_out)
@@ -1766,8 +1822,11 @@ tor_addr_port_split(int severity, const char *addrport,
tor_assert(addrport);
tor_assert(address_out);
tor_assert(port_out);
/* We need to check for IPv6 manually because the logic below doesn't
* do a good job on IPv6 addresses that lack a port. */
* do a good job on IPv6 addresses that lack a port.
* If an IPv6 address without square brackets is ambiguous, it gets parsed
* here as an address, rather than address:port. */
if (tor_addr_parse(&a_tmp, addrport) == AF_INET6) {
*port_out = 0;
*address_out = tor_strdup(addrport);
@@ -1807,8 +1866,7 @@ tor_addr_port_split(int severity, const char *addrport,
tor_free(address_);
}
if (port_out)
*port_out = ok ? ((uint16_t) port_) : 0;
*port_out = ok ? ((uint16_t) port_) : 0;
return ok ? 0 : -1;
}
+212 -127
View File
@@ -35,6 +35,8 @@
* *<b>addr</b> to the proper IP address, in host byte order. Returns 0
* on success, -1 on failure; 1 on transient failure.
*
* This function only accepts IPv4 addresses.
*
* (This function exists because standard windows gethostbyname
* doesn't treat raw IP addresses properly.)
*/
@@ -45,6 +47,11 @@ tor_lookup_hostname,(const char *name, uint32_t *addr))
tor_addr_t myaddr;
int ret;
if (BUG(!addr))
return -1;
*addr = 0;
if ((ret = tor_addr_lookup(name, AF_INET, &myaddr)))
return ret;
@@ -56,12 +63,125 @@ tor_lookup_hostname,(const char *name, uint32_t *addr))
return -1;
}
#ifdef HAVE_GETADDRINFO
/* Host lookup helper for tor_addr_lookup(), when getaddrinfo() is
* available on this system.
*
* See tor_addr_lookup() for details.
*/
static int
tor_addr_lookup_host_getaddrinfo(const char *name,
uint16_t family,
tor_addr_t *addr)
{
int err;
struct addrinfo *res=NULL, *res_p;
struct addrinfo *best=NULL;
struct addrinfo hints;
int result = -1;
memset(&hints, 0, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
err = tor_getaddrinfo(name, NULL, &hints, &res);
/* The check for 'res' here shouldn't be necessary, but it makes static
* analysis tools happy. */
if (!err && res) {
best = NULL;
for (res_p = res; res_p; res_p = res_p->ai_next) {
if (family == AF_UNSPEC) {
if (res_p->ai_family == AF_INET) {
best = res_p;
break;
} else if (res_p->ai_family == AF_INET6 && !best) {
best = res_p;
}
} else if (family == res_p->ai_family) {
best = res_p;
break;
}
}
if (!best)
best = res;
if (best->ai_family == AF_INET) {
tor_addr_from_in(addr,
&((struct sockaddr_in*)best->ai_addr)->sin_addr);
result = 0;
} else if (best->ai_family == AF_INET6) {
tor_addr_from_in6(addr,
&((struct sockaddr_in6*)best->ai_addr)->sin6_addr);
result = 0;
}
tor_freeaddrinfo(res);
return result;
}
return (err == EAI_AGAIN) ? 1 : -1;
}
#else /* !(defined(HAVE_GETADDRINFO)) */
/* Host lookup helper for tor_addr_lookup(), which calls getaddrinfo().
* Used when gethostbyname() is not available on this system.
*
* See tor_addr_lookup() for details.
*/
static int
tor_addr_lookup_host_gethostbyname(const char *name,
tor_addr_t *addr)
{
struct hostent *ent;
int err;
#ifdef HAVE_GETHOSTBYNAME_R_6_ARG
char buf[2048];
struct hostent hostent;
int r;
r = gethostbyname_r(name, &hostent, buf, sizeof(buf), &ent, &err);
#elif defined(HAVE_GETHOSTBYNAME_R_5_ARG)
char buf[2048];
struct hostent hostent;
ent = gethostbyname_r(name, &hostent, buf, sizeof(buf), &err);
#elif defined(HAVE_GETHOSTBYNAME_R_3_ARG)
struct hostent_data data;
struct hostent hent;
memset(&data, 0, sizeof(data));
err = gethostbyname_r(name, &hent, &data);
ent = err ? NULL : &hent;
#else
ent = gethostbyname(name);
#ifdef _WIN32
err = WSAGetLastError();
#else
err = h_errno;
#endif /* defined(_WIN32) */
#endif /* defined(HAVE_GETHOSTBYNAME_R_6_ARG) || ... */
if (ent) {
if (ent->h_addrtype == AF_INET) {
tor_addr_from_in(addr, (struct in_addr*) ent->h_addr);
} else if (ent->h_addrtype == AF_INET6) {
tor_addr_from_in6(addr, (struct in6_addr*) ent->h_addr);
} else {
tor_assert(0); // LCOV_EXCL_LINE: gethostbyname() returned bizarre type
}
return 0;
}
#ifdef _WIN32
return (err == WSATRY_AGAIN) ? 1 : -1;
#else
return (err == TRY_AGAIN) ? 1 : -1;
#endif
}
#endif /* defined(HAVE_GETADDRINFO) */
/** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set
* *<b>addr</b> to the proper IP address and family. The <b>family</b>
* argument (which must be AF_INET, AF_INET6, or AF_UNSPEC) declares a
* <i>preferred</i> family, though another one may be returned if only one
* family is implemented for this address.
*
* Like tor_addr_parse(), this function accepts IPv6 addresses with or without
* square brackets.
*
* Return 0 on success, -1 on failure; 1 on transient failure.
*/
MOCK_IMPL(int,
@@ -70,169 +190,134 @@ tor_addr_lookup,(const char *name, uint16_t family, tor_addr_t *addr))
/* Perhaps eventually this should be replaced by a tor_getaddrinfo or
* something.
*/
struct in_addr iaddr;
struct in6_addr iaddr6;
int parsed_family = 0;
int result = -1;
tor_assert(name);
tor_assert(addr);
tor_assert(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC);
if (!*name) {
/* Empty address is an error. */
return -1;
} else if (tor_inet_pton(AF_INET, name, &iaddr)) {
/* It's an IPv4 IP. */
if (family == AF_INET6)
return -1;
tor_addr_from_in(addr, &iaddr);
return 0;
} else if (tor_inet_pton(AF_INET6, name, &iaddr6)) {
if (family == AF_INET)
return -1;
tor_addr_from_in6(addr, &iaddr6);
return 0;
goto permfail;
}
/* Is it an IP address? */
parsed_family = tor_addr_parse(addr, name);
if (parsed_family >= 0) {
/* If the IP address family matches, or was unspecified */
if (parsed_family == family || family == AF_UNSPEC) {
goto success;
} else {
goto permfail;
}
} else {
/* Clear the address after a failed tor_addr_parse(). */
memset(addr, 0, sizeof(tor_addr_t));
#ifdef HAVE_GETADDRINFO
int err;
struct addrinfo *res=NULL, *res_p;
struct addrinfo *best=NULL;
struct addrinfo hints;
int result = -1;
memset(&hints, 0, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
err = tor_getaddrinfo(name, NULL, &hints, &res);
/* The check for 'res' here shouldn't be necessary, but it makes static
* analysis tools happy. */
if (!err && res) {
best = NULL;
for (res_p = res; res_p; res_p = res_p->ai_next) {
if (family == AF_UNSPEC) {
if (res_p->ai_family == AF_INET) {
best = res_p;
break;
} else if (res_p->ai_family == AF_INET6 && !best) {
best = res_p;
}
} else if (family == res_p->ai_family) {
best = res_p;
break;
}
}
if (!best)
best = res;
if (best->ai_family == AF_INET) {
tor_addr_from_in(addr,
&((struct sockaddr_in*)best->ai_addr)->sin_addr);
result = 0;
} else if (best->ai_family == AF_INET6) {
tor_addr_from_in6(addr,
&((struct sockaddr_in6*)best->ai_addr)->sin6_addr);
result = 0;
}
tor_freeaddrinfo(res);
return result;
}
return (err == EAI_AGAIN) ? 1 : -1;
result = tor_addr_lookup_host_getaddrinfo(name, family, addr);
goto done;
#else /* !(defined(HAVE_GETADDRINFO)) */
struct hostent *ent;
int err;
#ifdef HAVE_GETHOSTBYNAME_R_6_ARG
char buf[2048];
struct hostent hostent;
int r;
r = gethostbyname_r(name, &hostent, buf, sizeof(buf), &ent, &err);
#elif defined(HAVE_GETHOSTBYNAME_R_5_ARG)
char buf[2048];
struct hostent hostent;
ent = gethostbyname_r(name, &hostent, buf, sizeof(buf), &err);
#elif defined(HAVE_GETHOSTBYNAME_R_3_ARG)
struct hostent_data data;
struct hostent hent;
memset(&data, 0, sizeof(data));
err = gethostbyname_r(name, &hent, &data);
ent = err ? NULL : &hent;
#else
ent = gethostbyname(name);
#ifdef _WIN32
err = WSAGetLastError();
#else
err = h_errno;
#endif
#endif /* defined(HAVE_GETHOSTBYNAME_R_6_ARG) || ... */
if (ent) {
if (ent->h_addrtype == AF_INET) {
tor_addr_from_in(addr, (struct in_addr*) ent->h_addr);
} else if (ent->h_addrtype == AF_INET6) {
tor_addr_from_in6(addr, (struct in6_addr*) ent->h_addr);
} else {
tor_assert(0); // LCOV_EXCL_LINE: gethostbyname() returned bizarre type
}
return 0;
}
#ifdef _WIN32
return (err == WSATRY_AGAIN) ? 1 : -1;
#else
return (err == TRY_AGAIN) ? 1 : -1;
#endif
result = tor_addr_lookup_host_gethostbyname(name, addr);
goto done;
#endif /* defined(HAVE_GETADDRINFO) */
}
/* If we weren't successful, and haven't already set the result,
* assume it's a permanent failure */
permfail:
result = -1;
goto done;
success:
result = 0;
/* We have set the result, now it's time to clean up */
done:
if (result) {
/* Clear the address on error */
memset(addr, 0, sizeof(tor_addr_t));
}
return result;
}
/** Parse an address or address-port combination from <b>s</b>, resolve the
* address as needed, and put the result in <b>addr_out</b> and (optionally)
* <b>port_out</b>. Return 0 on success, negative on failure. */
* <b>port_out</b>.
*
* Like tor_addr_port_parse(), this function accepts:
* - IPv6 address and port, when the IPv6 address is in square brackets,
* - IPv6 address with square brackets,
* - IPv6 address without square brackets.
*
* Return 0 on success, negative on failure. */
int
tor_addr_port_lookup(const char *s, tor_addr_t *addr_out, uint16_t *port_out)
{
const char *port;
tor_addr_t addr;
uint16_t portval;
uint16_t portval = 0;
char *tmp = NULL;
int rv = 0;
int result;
tor_assert(s);
tor_assert(addr_out);
s = eat_whitespace(s);
if (*s == '[') {
port = strstr(s, "]");
if (!port)
goto err;
tmp = tor_strndup(s+1, port-(s+1));
port = port+1;
if (*port == ':')
port++;
else
port = NULL;
} else {
port = strchr(s, ':');
if (port)
tmp = tor_strndup(s, port-s);
else
tmp = tor_strdup(s);
if (port)
++port;
/* Try parsing s as an address:port first, so we don't have to duplicate
* the logic that rejects IPv6:Port with no square brackets. */
rv = tor_addr_port_parse(LOG_WARN, s, &addr, &portval, 0);
/* That was easy, no DNS required. */
if (rv == 0)
goto success;
/* Now let's check for malformed IPv6 addresses and ports:
* tor_addr_port_parse() requires squared brackes if there is a port,
* and we want tor_addr_port_lookup() to have the same requirement.
* But we strip the port using tor_addr_port_split(), so tor_addr_lookup()
* only sees the address, and will accept it without square brackets. */
int family = tor_addr_parse(&addr, s);
/* If tor_addr_parse() succeeds where tor_addr_port_parse() failed, we need
* to reject this address as malformed. */
if (family >= 0) {
/* Double-check it's an IPv6 address. If not, we have a parsing bug.
*/
tor_assertf_nonfatal(family == AF_INET6,
"Wrong family: %d (should be IPv6: %d) which "
"failed IP:port parsing, but passed IP parsing. "
"input string: '%s'; parsed address: '%s'.",
family, AF_INET6, s, fmt_addr(&addr));
goto err;
}
/* Now we have a hostname. Let's split off the port, if any. */
rv = tor_addr_port_split(LOG_WARN, s, &tmp, &portval);
if (rv < 0)
goto err;
/* And feed the hostname to the lookup function. */
if (tor_addr_lookup(tmp, AF_UNSPEC, &addr) != 0)
goto err;
tor_free(tmp);
if (port) {
portval = (int) tor_parse_long(port, 10, 1, 65535, NULL, NULL);
if (!portval)
goto err;
} else {
portval = 0;
}
success:
if (port_out)
*port_out = portval;
tor_addr_copy(addr_out, &addr);
result = 0;
goto done;
return 0;
err:
/* Clear the address and port on error */
memset(addr_out, 0, sizeof(tor_addr_t));
if (port_out)
*port_out = 0;
result = -1;
/* We have set the result, now it's time to clean up */
done:
tor_free(tmp);
return -1;
return result;
}
#ifdef USE_SANDBOX_GETADDRINFO
+537 -122
View File
@@ -724,155 +724,570 @@ test_addr_ip6_helpers(void *arg)
;
}
/* Test that addr_str successfully parses, and:
* - the address has family expect_family,
* - the fmt_decorated result of tor_addr_to_str() is expect_str.
*/
#define TEST_ADDR_PARSE_FMT(addr_str, expect_family, fmt_decorated, \
expect_str) \
STMT_BEGIN \
int r; \
tor_addr_t addr; \
char buf[TOR_ADDR_BUF_LEN]; \
const char *sv; \
r = tor_addr_parse(&addr, addr_str); \
tt_int_op(r, OP_EQ, expect_family); \
sv = tor_addr_to_str(buf, &addr, sizeof(buf), fmt_decorated); \
tt_str_op(sv, OP_EQ, buf); \
tt_str_op(buf, OP_EQ, expect_str); \
STMT_END
/* Test that addr_str fails to parse, and:
* - the returned address is null.
*/
#define TEST_ADDR_PARSE_XFAIL(addr_str) \
STMT_BEGIN \
int r; \
tor_addr_t addr; \
r = tor_addr_parse(&addr, addr_str); \
tt_int_op(r, OP_EQ, -1); \
tt_assert(tor_addr_is_null(&addr)); \
STMT_END
/* Test that addr_port_str and default_port successfully parse, and:
* - the address has family expect_family,
* - the fmt_decorated result of tor_addr_to_str() is expect_str,
* - the port is expect_port.
*/
#define TEST_ADDR_PORT_PARSE_FMT(addr_port_str, default_port, expect_family, \
fmt_decorated, expect_str, expect_port) \
STMT_BEGIN \
int r; \
tor_addr_t addr; \
uint16_t port; \
char buf[TOR_ADDR_BUF_LEN]; \
const char *sv; \
r = tor_addr_port_parse(LOG_DEBUG, addr_port_str, &addr, &port, \
default_port); \
tt_int_op(r, OP_EQ, 0); \
tt_int_op(tor_addr_family(&addr), OP_EQ, expect_family); \
sv = tor_addr_to_str(buf, &addr, sizeof(buf), fmt_decorated); \
tt_str_op(sv, OP_EQ, buf); \
tt_str_op(buf, OP_EQ, expect_str); \
tt_int_op(port, OP_EQ, expect_port); \
STMT_END
/* Test that addr_port_str and default_port fail to parse, and:
* - the returned address is null,
* - the returned port is 0.
*/
#define TEST_ADDR_PORT_PARSE_XFAIL(addr_port_str, default_port) \
STMT_BEGIN \
int r; \
tor_addr_t addr; \
uint16_t port; \
r = tor_addr_port_parse(LOG_DEBUG, addr_port_str, &addr, &port, \
default_port); \
tt_int_op(r, OP_EQ, -1); \
tt_assert(tor_addr_is_null(&addr)); \
tt_int_op(port, OP_EQ, 0); \
STMT_END
/* Test that addr_str successfully parses as an IPv4 address using
* tor_lookup_hostname(), and:
* - the fmt_addr32() of the result is expect_str.
*/
#define TEST_ADDR_V4_LOOKUP_HOSTNAME(addr_str, expect_str) \
STMT_BEGIN \
int r; \
uint32_t addr32h; \
r = tor_lookup_hostname(addr_str, &addr32h); \
tt_int_op(r, OP_EQ, 0); \
tt_str_op(fmt_addr32(addr32h), OP_EQ, expect_str); \
STMT_END
/* Test that bad_str fails to parse using tor_lookup_hostname(), with a
* permanent failure, and:
* - the returned address is 0.
*/
#define TEST_ADDR_V4_LOOKUP_XFAIL(bad_str) \
STMT_BEGIN \
int r; \
uint32_t addr32h; \
r = tor_lookup_hostname(bad_str, &addr32h); \
tt_int_op(r, OP_EQ, -1); \
tt_int_op(addr32h, OP_EQ, 0); \
STMT_END
/* Test that looking up host_str as an IPv4 address using tor_lookup_hostname()
* does something sensible:
* - the result is -1, 0, or 1.
* - if the result is a failure, the returned address is 0.
* We can't rely on the result of this function, because it depends on the
* network.
*/
#define TEST_HOST_V4_LOOKUP(host_str) \
STMT_BEGIN \
int r; \
uint32_t addr32h; \
r = tor_lookup_hostname(host_str, &addr32h); \
tt_int_op(r, OP_GE, -1); \
tt_int_op(r, OP_LE, 1); \
if (r != 0) \
tt_int_op(addr32h, OP_EQ, 0); \
STMT_END
/* Test that addr_str successfully parses as a require_family IP address using
* tor_addr_lookup(), and:
* - the address has family expect_family,
* - the fmt_decorated result of tor_addr_to_str() is expect_str.
*/
#define TEST_ADDR_LOOKUP_FMT(addr_str, require_family, expect_family, \
fmt_decorated, expect_str) \
STMT_BEGIN \
int r; \
tor_addr_t addr; \
char buf[TOR_ADDR_BUF_LEN]; \
const char *sv; \
r = tor_addr_lookup(addr_str, require_family, &addr); \
tt_int_op(r, OP_EQ, 0); \
tt_int_op(tor_addr_family(&addr), OP_EQ, expect_family); \
sv = tor_addr_to_str(buf, &addr, sizeof(buf), fmt_decorated); \
tt_str_op(sv, OP_EQ, buf); \
tt_str_op(buf, OP_EQ, expect_str); \
STMT_END
/* Test that bad_str fails to parse as a require_family IP address using
* tor_addr_lookup(), with a permanent failure, and:
* - the returned address is null.
*/
#define TEST_ADDR_LOOKUP_XFAIL(bad_str, require_family) \
STMT_BEGIN \
int r; \
tor_addr_t addr; \
r = tor_addr_lookup(bad_str, require_family, &addr); \
tt_int_op(r, OP_EQ, -1); \
tt_assert(tor_addr_is_null(&addr)); \
STMT_END
/* Test that looking up host_string as a require_family IP address using
* tor_addr_lookup(), does something sensible:
* - the result is -1, 0, or 1.
* - if the result is a failure, the returned address is null.
* We can't rely on the result of this function, because it depends on the
* network.
*/
#define TEST_HOST_LOOKUP(host_str, require_family) \
STMT_BEGIN \
int r; \
tor_addr_t addr; \
r = tor_addr_lookup(host_str, require_family, &addr); \
tt_int_op(r, OP_GE, -1); \
tt_int_op(r, OP_LE, 1); \
if (r != 0) \
tt_assert(tor_addr_is_null(&addr)); \
STMT_END
/* Test that addr_port_str successfully parses as an IP address and port
* using tor_addr_port_lookup(), and:
* - the address has family expect_family,
* - the fmt_decorated result of tor_addr_to_str() is expect_str,
* - the port is expect_port.
*/
#define TEST_ADDR_PORT_LOOKUP_FMT(addr_port_str, expect_family, \
fmt_decorated, expect_str, expect_port) \
STMT_BEGIN \
int r; \
tor_addr_t addr; \
uint16_t port; \
char buf[TOR_ADDR_BUF_LEN]; \
const char *sv; \
r = tor_addr_port_lookup(addr_port_str, &addr, &port); \
tt_int_op(r, OP_EQ, 0); \
tt_int_op(tor_addr_family(&addr), OP_EQ, expect_family); \
sv = tor_addr_to_str(buf, &addr, sizeof(buf), fmt_decorated); \
tt_str_op(sv, OP_EQ, buf); \
tt_str_op(buf, OP_EQ, expect_str); \
tt_int_op(port, OP_EQ, expect_port); \
STMT_END
/* Test that bad_str fails to parse as an IP address and port
* using tor_addr_port_lookup(), and:
* - the returned address is null,
* - the returned port is 0.
*/
#define TEST_ADDR_PORT_LOOKUP_XFAIL(bad_str) \
STMT_BEGIN \
int r; \
tor_addr_t addr; \
uint16_t port; \
r = tor_addr_port_lookup(bad_str, &addr, &port); \
tt_int_op(r, OP_EQ, -1); \
tt_assert(tor_addr_is_null(&addr)); \
tt_int_op(port, OP_EQ, 0); \
STMT_END
/* Test that looking up host_port_str as an IP address using
* tor_addr_port_lookup(), does something sensible:
* - the result is -1 or 0.
* - if the result is a failure, the returned address is null, and the
* returned port is zero,
* - if the result is a success, the returned port is expect_success_port,
* and the returned family is AF_INET or AF_INET6.
* We can't rely on the result of this function, because it depends on the
* network.
*/
#define TEST_HOST_PORT_LOOKUP(host_port_str, expect_success_port) \
STMT_BEGIN \
int r; \
tor_addr_t addr; \
uint16_t port; \
r = tor_addr_port_lookup(host_port_str, &addr, &port); \
tt_int_op(r, OP_GE, -1); \
tt_int_op(r, OP_LE, 0); \
if (r == -1) { \
tt_assert(tor_addr_is_null(&addr)); \
tt_int_op(port, OP_EQ, 0); \
} else { \
tt_assert(tor_addr_family(&addr) == AF_INET || \
tor_addr_family(&addr) == AF_INET6); \
tt_int_op(port, OP_EQ, expect_success_port); \
} \
STMT_END
/* Test that addr_str successfully parses as a canonical IPv4 address.
* Check for successful parsing using:
* - tor_addr_parse(),
* - tor_addr_port_parse() with a default port,
* - tor_lookup_hostname(),
* - tor_addr_lookup() with AF_INET,
* - tor_addr_lookup() with AF_UNSPEC,
* - tor_addr_port_lookup(), with a zero port.
* Check for failures using:
* - tor_addr_port_parse() without a default port, because there is no port,
* - tor_addr_lookup() with AF_INET6,
* - tor_addr_port_lookup(), because there is no port.
*/
#define TEST_ADDR_V4_PARSE_CANONICAL(addr_str) \
STMT_BEGIN \
TEST_ADDR_PARSE_FMT(addr_str, AF_INET, 0, addr_str); \
TEST_ADDR_PORT_PARSE_FMT(addr_str, 111, AF_INET, 0, \
addr_str, 111); \
TEST_ADDR_V4_LOOKUP_HOSTNAME(addr_str, addr_str); \
TEST_ADDR_PORT_LOOKUP_FMT(addr_str, AF_INET, 0, addr_str, 0); \
TEST_ADDR_LOOKUP_FMT(addr_str, AF_INET, AF_INET, 0, addr_str); \
TEST_ADDR_LOOKUP_FMT(addr_str, AF_UNSPEC, AF_INET, 0, addr_str); \
TEST_ADDR_PORT_PARSE_XFAIL(addr_str, -1); \
TEST_ADDR_LOOKUP_XFAIL(addr_str, AF_INET6); \
STMT_END
/* Test that addr_str successfully parses as a canonical fmt_decorated
* IPv6 address.
* Check for successful parsing using:
* - tor_addr_parse(),
* - tor_addr_port_parse() with a default port,
* - tor_addr_lookup() with AF_INET6,
* - tor_addr_lookup() with AF_UNSPEC,
* - tor_addr_port_lookup(), with a zero port.
* Check for failures using:
* - tor_addr_port_parse() without a default port, because there is no port,
* - tor_lookup_hostname(), because it only supports IPv4,
* - tor_addr_lookup() with AF_INET.
*/
#define TEST_ADDR_V6_PARSE_CANONICAL(addr_str, fmt_decorated) \
STMT_BEGIN \
TEST_ADDR_PARSE_FMT(addr_str, AF_INET6, fmt_decorated, addr_str); \
TEST_ADDR_PORT_PARSE_FMT(addr_str, 222, AF_INET6, fmt_decorated, \
addr_str, 222); \
TEST_ADDR_LOOKUP_FMT(addr_str, AF_INET6, AF_INET6, fmt_decorated, \
addr_str); \
TEST_ADDR_LOOKUP_FMT(addr_str, AF_UNSPEC, AF_INET6, fmt_decorated, \
addr_str); \
TEST_ADDR_PORT_LOOKUP_FMT(addr_str, AF_INET6, fmt_decorated, addr_str, \
0); \
TEST_ADDR_PORT_PARSE_XFAIL(addr_str, -1); \
TEST_ADDR_V4_LOOKUP_XFAIL(addr_str); \
TEST_ADDR_LOOKUP_XFAIL(addr_str, AF_INET); \
STMT_END
/* Test that addr_str successfully parses, and the fmt_decorated canonical
* IPv6 string is expect_str.
* Check for successful parsing using:
* - tor_addr_parse(),
* - tor_addr_port_parse() with a default port,
* - tor_addr_lookup() with AF_INET6,
* - tor_addr_lookup() with AF_UNSPEC,
* - tor_addr_port_lookup(), with a zero port.
* Check for failures using:
* - tor_addr_port_parse() without a default port, because there is no port.
* - tor_lookup_hostname(), because it only supports IPv4,
* - tor_addr_lookup() with AF_INET.
*/
#define TEST_ADDR_V6_PARSE(addr_str, fmt_decorated, expect_str) \
STMT_BEGIN \
TEST_ADDR_PARSE_FMT(addr_str, AF_INET6, fmt_decorated, expect_str); \
TEST_ADDR_PORT_PARSE_FMT(addr_str, 333, AF_INET6, fmt_decorated, \
expect_str, 333); \
TEST_ADDR_LOOKUP_FMT(addr_str, AF_INET6, AF_INET6, fmt_decorated, \
expect_str); \
TEST_ADDR_LOOKUP_FMT(addr_str, AF_UNSPEC, AF_INET6, fmt_decorated, \
expect_str); \
TEST_ADDR_PORT_LOOKUP_FMT(addr_str, AF_INET6, fmt_decorated, expect_str, \
0); \
TEST_ADDR_PORT_PARSE_XFAIL(addr_str, -1); \
TEST_ADDR_V4_LOOKUP_XFAIL(addr_str); \
TEST_ADDR_LOOKUP_XFAIL(addr_str, AF_INET); \
STMT_END
/* Test that addr_port_str successfully parses to the canonical IPv4 address
* string expect_str, and port expect_port.
* Check for successful parsing using:
* - tor_addr_port_parse() without a default port,
* - tor_addr_port_parse() with a default port,
* - tor_addr_port_lookup().
* Check for failures using:
* - tor_addr_parse(), because there is a port,
* - tor_lookup_hostname(), because there is a port.
* - tor_addr_lookup(), regardless of the address family, because there is a
* port.
*/
#define TEST_ADDR_V4_PORT_PARSE(addr_port_str, expect_str, expect_port) \
STMT_BEGIN \
TEST_ADDR_PORT_PARSE_FMT(addr_port_str, -1, AF_INET, 0, expect_str, \
expect_port); \
TEST_ADDR_PORT_PARSE_FMT(addr_port_str, 444, AF_INET, 0, expect_str, \
expect_port); \
TEST_ADDR_PORT_LOOKUP_FMT(addr_port_str, AF_INET, 0, expect_str, \
expect_port); \
TEST_ADDR_PARSE_XFAIL(addr_port_str); \
TEST_ADDR_V4_LOOKUP_XFAIL(addr_port_str); \
TEST_ADDR_LOOKUP_XFAIL(addr_port_str, AF_INET); \
TEST_ADDR_LOOKUP_XFAIL(addr_port_str, AF_UNSPEC); \
TEST_ADDR_LOOKUP_XFAIL(addr_port_str, AF_INET6); \
STMT_END
/* Test that addr_port_str successfully parses to the canonical undecorated
* IPv6 address string expect_str, and port expect_port.
* Check for successful parsing using:
* - tor_addr_port_parse() without a default port,
* - tor_addr_port_parse() with a default port,
* - tor_addr_port_lookup().
* Check for failures using:
* - tor_addr_parse(), because there is a port,
* - tor_lookup_hostname(), because there is a port, and because it only
* supports IPv4,
* - tor_addr_lookup(), regardless of the address family, because there is a
* port.
*/
#define TEST_ADDR_V6_PORT_PARSE(addr_port_str, expect_str, expect_port) \
STMT_BEGIN \
TEST_ADDR_PORT_PARSE_FMT(addr_port_str, -1, AF_INET6, 0, expect_str, \
expect_port); \
TEST_ADDR_PORT_PARSE_FMT(addr_port_str, 555, AF_INET6, 0, expect_str, \
expect_port); \
TEST_ADDR_PORT_LOOKUP_FMT(addr_port_str, AF_INET6, 0, expect_str, \
expect_port); \
TEST_ADDR_PARSE_XFAIL(addr_port_str); \
TEST_ADDR_V4_LOOKUP_XFAIL(addr_port_str); \
TEST_ADDR_LOOKUP_XFAIL(addr_port_str, AF_INET6); \
TEST_ADDR_LOOKUP_XFAIL(addr_port_str, AF_UNSPEC); \
TEST_ADDR_LOOKUP_XFAIL(addr_port_str, AF_INET); \
STMT_END
/* Test that bad_str fails to parse due to a bad address or port.
* Check for failures using:
* - tor_addr_parse(),
* - tor_addr_port_parse() without a default port,
* - tor_addr_port_parse() with a default port,
* - tor_lookup_hostname(),
* - tor_addr_lookup(), regardless of the address family,
* - tor_addr_port_lookup().
*/
#define TEST_ADDR_PARSE_XFAIL_MALFORMED(bad_str) \
STMT_BEGIN \
TEST_ADDR_PARSE_XFAIL(bad_str); \
TEST_ADDR_PORT_PARSE_XFAIL(bad_str, -1); \
TEST_ADDR_PORT_PARSE_XFAIL(bad_str, 666); \
TEST_ADDR_V4_LOOKUP_XFAIL(bad_str); \
TEST_ADDR_LOOKUP_XFAIL(bad_str, AF_UNSPEC); \
TEST_ADDR_LOOKUP_XFAIL(bad_str, AF_INET); \
TEST_ADDR_LOOKUP_XFAIL(bad_str, AF_INET6); \
TEST_ADDR_PORT_LOOKUP_XFAIL(bad_str); \
STMT_END
/* Test that host_str is treated as a hostname, and not an address.
* Check for success or failure using the network-dependent functions:
* - tor_lookup_hostname(),
* - tor_addr_lookup(), regardless of the address family,
* - tor_addr_port_lookup(), expecting a zero port.
* Check for failures using:
* - tor_addr_parse(),
* - tor_addr_port_parse() without a default port,
* - tor_addr_port_parse() with a default port.
*/
#define TEST_HOSTNAME(host_str) \
STMT_BEGIN \
TEST_HOST_V4_LOOKUP(host_str); \
TEST_HOST_LOOKUP(host_str, AF_UNSPEC); \
TEST_HOST_LOOKUP(host_str, AF_INET); \
TEST_HOST_LOOKUP(host_str, AF_INET6); \
TEST_HOST_PORT_LOOKUP(host_str, 0); \
TEST_ADDR_PARSE_XFAIL(host_str); \
TEST_ADDR_PORT_PARSE_XFAIL(host_str, -1); \
TEST_ADDR_PORT_PARSE_XFAIL(host_str, 777); \
STMT_END
/* Test that host_port_str is treated as a hostname and port, and not a
* hostname or an address.
* Check for success or failure using the network-dependent function:
* - tor_addr_port_lookup(), expecting expect_success_port if the lookup is
* successful.
* Check for failures using:
* - tor_addr_parse(),
* - tor_addr_port_parse() without a default port,
* - tor_addr_port_parse() with a default port,
* - tor_lookup_hostname(), because it doesn't support ports,
* - tor_addr_lookup(), regardless of the address family, because it doesn't
* support ports.
*/
#define TEST_HOSTNAME_PORT(host_port_str, expect_success_port) \
STMT_BEGIN \
TEST_HOST_PORT_LOOKUP(host_port_str, expect_success_port); \
TEST_ADDR_PARSE_XFAIL(host_port_str); \
TEST_ADDR_PORT_PARSE_XFAIL(host_port_str, -1); \
TEST_ADDR_PORT_PARSE_XFAIL(host_port_str, 888); \
TEST_ADDR_V4_LOOKUP_XFAIL(host_port_str); \
TEST_ADDR_LOOKUP_XFAIL(host_port_str, AF_UNSPEC); \
TEST_ADDR_LOOKUP_XFAIL(host_port_str, AF_INET); \
TEST_ADDR_LOOKUP_XFAIL(host_port_str, AF_INET6); \
STMT_END
/** Test tor_addr_parse() and tor_addr_port_parse(). */
static void
test_addr_parse(void *arg)
{
int r;
tor_addr_t addr;
char buf[TOR_ADDR_BUF_LEN];
uint16_t port = 0;
/* Correct call. */
(void)arg;
r= tor_addr_parse(&addr, "192.0.2.1");
tt_int_op(r,OP_EQ, AF_INET);
tor_addr_to_str(buf, &addr, sizeof(buf), 0);
tt_str_op(buf,OP_EQ, "192.0.2.1");
r= tor_addr_parse(&addr, "11:22::33:44");
tt_int_op(r,OP_EQ, AF_INET6);
tor_addr_to_str(buf, &addr, sizeof(buf), 0);
tt_str_op(buf,OP_EQ, "11:22::33:44");
/* Correct calls. */
TEST_ADDR_V4_PARSE_CANONICAL("192.0.2.1");
TEST_ADDR_V4_PARSE_CANONICAL("192.0.2.2");
r= tor_addr_parse(&addr, "[11:22::33:44]");
tt_int_op(r,OP_EQ, AF_INET6);
tor_addr_to_str(buf, &addr, sizeof(buf), 0);
tt_str_op(buf,OP_EQ, "11:22::33:44");
TEST_ADDR_V6_PARSE_CANONICAL("[11:22::33:44]", 1);
TEST_ADDR_V6_PARSE_CANONICAL("[::1]", 1);
TEST_ADDR_V6_PARSE_CANONICAL("[::]", 1);
TEST_ADDR_V6_PARSE_CANONICAL("[2::]", 1);
TEST_ADDR_V6_PARSE_CANONICAL("[11:22:33:44:55:66:77:88]", 1);
r= tor_addr_parse(&addr, "11:22:33:44:55:66:1.2.3.4");
tt_int_op(r,OP_EQ, AF_INET6);
tor_addr_to_str(buf, &addr, sizeof(buf), 0);
tt_str_op(buf,OP_EQ, "11:22:33:44:55:66:102:304");
/* Allow IPv6 without square brackets, when there is no port, but only if
* there is a default port */
TEST_ADDR_V6_PARSE_CANONICAL("11:22::33:44", 0);
TEST_ADDR_V6_PARSE_CANONICAL("::1", 0);
TEST_ADDR_V6_PARSE_CANONICAL("::", 0);
TEST_ADDR_V6_PARSE_CANONICAL("2::", 0);
TEST_ADDR_V6_PARSE_CANONICAL("11:22:33:44:55:66:77:88", 0);
r= tor_addr_parse(&addr, "11:22::33:44:1.2.3.4");
tt_int_op(r,OP_EQ, AF_INET6);
tor_addr_to_str(buf, &addr, sizeof(buf), 0);
tt_str_op(buf,OP_EQ, "11:22::33:44:102:304");
/* IPv6-mapped IPv4 addresses. Tor doesn't really use these. */
TEST_ADDR_V6_PARSE("11:22:33:44:55:66:1.2.3.4", 0,
"11:22:33:44:55:66:102:304");
TEST_ADDR_V6_PARSE("11:22::33:44:1.2.3.4", 0,
"11:22::33:44:102:304");
/* Ports. */
TEST_ADDR_V4_PORT_PARSE("192.0.2.1:1234", "192.0.2.1", 1234);
TEST_ADDR_V6_PORT_PARSE("[::1]:1234", "::1", 1234);
/* Host names. */
TEST_HOSTNAME("localhost");
TEST_HOSTNAME_PORT("localhost:1234", 1234);
TEST_HOSTNAME_PORT("localhost:0", 0);
TEST_HOSTNAME("torproject.org");
TEST_HOSTNAME_PORT("torproject.org:56", 56);
TEST_HOSTNAME("probably-not-a-valid-dns.name-tld");
TEST_HOSTNAME_PORT("probably-not-a-valid-dns.name-tld:789", 789);
/* Malformed addresses. */
/* Empty string. */
r= tor_addr_parse(&addr, "");
tt_int_op(r,OP_EQ, -1);
TEST_ADDR_PARSE_XFAIL_MALFORMED("");
/* Square brackets around IPv4 address. */
r= tor_addr_parse(&addr, "[192.0.2.1]");
tt_int_op(r,OP_EQ, -1);
TEST_ADDR_PARSE_XFAIL_MALFORMED("[192.0.2.1]");
TEST_ADDR_PARSE_XFAIL_MALFORMED("[192.0.2.3]:12345");
/* Only left square bracket. */
r= tor_addr_parse(&addr, "[11:22::33:44");
tt_int_op(r,OP_EQ, -1);
TEST_ADDR_PARSE_XFAIL_MALFORMED("[11:22::33:44");
/* Only right square bracket. */
r= tor_addr_parse(&addr, "11:22::33:44]");
tt_int_op(r,OP_EQ, -1);
TEST_ADDR_PARSE_XFAIL_MALFORMED("11:22::33:44]");
/* Leading colon. */
r= tor_addr_parse(&addr, ":11:22::33:44");
tt_int_op(r,OP_EQ, -1);
TEST_ADDR_PARSE_XFAIL_MALFORMED(":11:22::33:44");
/* Trailing colon. */
r= tor_addr_parse(&addr, "11:22::33:44:");
tt_int_op(r,OP_EQ, -1);
/* Too many hex words in IPv4-mapped IPv6 address. */
r= tor_addr_parse(&addr, "11:22:33:44:55:66:77:88:1.2.3.4");
tt_int_op(r,OP_EQ, -1);
/* Correct call. */
r= tor_addr_port_parse(LOG_DEBUG,
"192.0.2.1:1234",
&addr, &port, -1);
tt_int_op(r, OP_EQ, 0);
tor_addr_to_str(buf, &addr, sizeof(buf), 0);
tt_str_op(buf,OP_EQ, "192.0.2.1");
tt_int_op(port,OP_EQ, 1234);
r= tor_addr_port_parse(LOG_DEBUG,
"[::1]:1234",
&addr, &port, -1);
tt_int_op(r, OP_EQ, 0);
tor_addr_to_str(buf, &addr, sizeof(buf), 0);
tt_str_op(buf,OP_EQ, "::1");
tt_int_op(port,OP_EQ, 1234);
/* Domain name. */
r= tor_addr_port_parse(LOG_DEBUG,
"torproject.org:1234",
&addr, &port, -1);
tt_int_op(r, OP_EQ, -1);
/* Only IP. */
r= tor_addr_port_parse(LOG_DEBUG,
"192.0.2.2",
&addr, &port, -1);
tt_int_op(r, OP_EQ, -1);
r= tor_addr_port_parse(LOG_DEBUG,
"192.0.2.2",
&addr, &port, 200);
tt_int_op(r, OP_EQ, 0);
tt_int_op(port,OP_EQ,200);
r= tor_addr_port_parse(LOG_DEBUG,
"[::1]",
&addr, &port, -1);
tt_int_op(r, OP_EQ, -1);
r= tor_addr_port_parse(LOG_DEBUG,
"[::1]",
&addr, &port, 400);
tt_int_op(r, OP_EQ, 0);
tt_int_op(port,OP_EQ,400);
TEST_ADDR_PARSE_XFAIL_MALFORMED("11:22::33:44:");
TEST_ADDR_PARSE_XFAIL_MALFORMED("[::1]:");
TEST_ADDR_PARSE_XFAIL_MALFORMED("localhost:");
/* Bad port. */
r= tor_addr_port_parse(LOG_DEBUG,
"192.0.2.2:66666",
&addr, &port, -1);
tt_int_op(r, OP_EQ, -1);
r= tor_addr_port_parse(LOG_DEBUG,
"192.0.2.2:66666",
&addr, &port, 200);
tt_int_op(r, OP_EQ, -1);
TEST_ADDR_PARSE_XFAIL_MALFORMED("192.0.2.2:66666");
TEST_ADDR_PARSE_XFAIL_MALFORMED("[::1]:77777");
TEST_ADDR_PARSE_XFAIL_MALFORMED("::1:88888");
TEST_ADDR_PARSE_XFAIL_MALFORMED("localhost:99999");
/* Only domain name */
r= tor_addr_port_parse(LOG_DEBUG,
"torproject.org",
&addr, &port, -1);
tt_int_op(r, OP_EQ, -1);
r= tor_addr_port_parse(LOG_DEBUG,
"torproject.org",
&addr, &port, 200);
tt_int_op(r, OP_EQ, -1);
TEST_ADDR_PARSE_XFAIL_MALFORMED("192.0.2.2:-1");
TEST_ADDR_PARSE_XFAIL_MALFORMED("[::1]:-2");
TEST_ADDR_PARSE_XFAIL_MALFORMED("::1:-3");
TEST_ADDR_PARSE_XFAIL_MALFORMED("localhost:-4");
/* Bad IP address */
r= tor_addr_port_parse(LOG_DEBUG,
"192.0.2:1234",
&addr, &port, -1);
tt_int_op(r, OP_EQ, -1);
TEST_ADDR_PARSE_XFAIL_MALFORMED("192.0.2.2:1 bad");
TEST_ADDR_PARSE_XFAIL_MALFORMED("192.0.2.2:bad-port");
TEST_ADDR_PARSE_XFAIL_MALFORMED("[::1]:bad-port-1");
TEST_ADDR_PARSE_XFAIL_MALFORMED("::1:1-bad-port");
TEST_ADDR_PARSE_XFAIL_MALFORMED("localhost:1-bad-port");
TEST_ADDR_PARSE_XFAIL_MALFORMED("localhost:1-bad-port-1");
/* Make sure that the default port has lower priority than the real
one */
r= tor_addr_port_parse(LOG_DEBUG,
"192.0.2.2:1337",
&addr, &port, 200);
tt_int_op(r, OP_EQ, 0);
tt_int_op(port,OP_EQ,1337);
/* Bad hostname */
TEST_ADDR_PARSE_XFAIL_MALFORMED("definitely invalid");
TEST_ADDR_PARSE_XFAIL_MALFORMED("definitely invalid:22222");
r= tor_addr_port_parse(LOG_DEBUG,
"[::1]:1369",
&addr, &port, 200);
tt_int_op(r, OP_EQ, 0);
tt_int_op(port,OP_EQ,1369);
/* Ambiguous cases */
/* Too many hex words in IPv4-mapped IPv6 address.
* But some OS host lookup routines accept it as a hostname, or
* as an IP address?? (I assume they discard unused characters). */
TEST_HOSTNAME("11:22:33:44:55:66:77:88:1.2.3.4");
/* IPv6 address with port and no brackets
* We reject it, but some OS host lookup routines accept it as an
* IPv6 address:port ? */
TEST_HOSTNAME_PORT("11:22::33:44:12345", 12345);
/* Is it a port, or are there too many hex words?
* We reject it either way, but some OS host lookup routines accept it as an
* IPv6 address:port */
TEST_HOSTNAME_PORT("11:22:33:44:55:66:77:88:99", 99);
/* But we accept it if it has square brackets. */
TEST_ADDR_V6_PORT_PARSE("[11:22:33:44:55:66:77:88]:99",
"11:22:33:44:55:66:77:88",99);
/* Bad IPv4 address
* We reject it, but some OS host lookup routines accept it as an
* IPv4 address[:port], with a zero last octet */
TEST_HOSTNAME("192.0.1");
TEST_HOSTNAME_PORT("192.0.2:1234", 1234);
/* More bad IPv6 addresses and ports: no brackets
* We reject it, but some OS host lookup routines accept it as an
* IPv6 address[:port] */
TEST_HOSTNAME_PORT("::1:12345", 12345);
TEST_HOSTNAME_PORT("11:22::33:44:12345", 12345);
/* And this is an ambiguous case, which is interpreted as an IPv6 address. */
TEST_ADDR_V6_PARSE_CANONICAL("11:22::88:99", 0);
/* Use square brackets to resolve the ambiguity */
TEST_ADDR_V6_PARSE_CANONICAL("[11:22::88:99]", 1);
TEST_ADDR_V6_PORT_PARSE("[11:22::88]:99",
"11:22::88",99);
done:
;