Merge branch 'ticket33236_045_01'

This commit is contained in:
David Goulet
2020-07-07 11:01:26 -04:00
4 changed files with 149 additions and 9 deletions
+4
View File
@@ -0,0 +1,4 @@
o Minor feature (relay, address discovery):
- If Address is not found in torrc, attempt to learn our address with the
configured ORPort address if any. Closes ticket 33236.
+58
View File
@@ -370,6 +370,63 @@ get_address_from_interface(const or_options_t *options, int warn_severity,
return FN_RET_OK;
}
/** @brief Get IP address from the ORPort (if any).
*
* @param options Global configuration options.
* @param warn_severity Log level that should be used on error.
* @param family IP address family. Only AF_INET and AF_INET6 are supported.
* @param method_out OUT: Always "CONFIGURED_ORPORT" on success which is
* detailed in the control-spec.txt as actions
* for "STATUS_SERVER".
* @param hostname_out OUT: String containing the ORPort hostname if any.
* @param addr_out OUT: Tor address found if any.
*
* @return Return 0 on success that is an address has been found. Return
* error code ERR_* found at the top of the file.
*/
static fn_address_ret_t
get_address_from_orport(const or_options_t *options, int warn_severity,
int family, const char **method_out,
char **hostname_out, tor_addr_t *addr_out)
{
int ret;
const tor_addr_t *addr;
tor_assert(method_out);
tor_assert(hostname_out);
tor_assert(addr_out);
log_debug(LD_CONFIG, "Attempting to get address from ORPort");
if (!options->ORPort_set) {
log_info(LD_CONFIG, "No ORPort found in configuration.");
/* No ORPort statement, inform caller to try next method. */
return FN_RET_NEXT;
}
/* Get ORPort for requested family. */
addr = get_orport_addr(family);
if (!addr) {
/* No address configured for the ORPort. Ignore. */
return FN_RET_NEXT;
}
/* We found the ORPort address. Just make sure it can be used. */
ret = address_can_be_used(addr, options, warn_severity, true);
if (ret < 0) {
/* Unable to use address. Inform caller to try next method. */
return FN_RET_NEXT;
}
/* Found it! */
*method_out = "CONFIGURED_ORPORT";
tor_addr_copy(addr_out, addr);
log_fn(warn_severity, LD_CONFIG, "Address found from ORPort: %s",
fmt_addr(addr_out));
return FN_RET_OK;
}
/** @brief Update the last resolved address cache using the given address.
*
* A log notice is emitted if the given address has changed from before. Not
@@ -450,6 +507,7 @@ static fn_address_ret_t
{
/* These functions are in order for our find address algorithm. */
get_address_from_config,
get_address_from_orport,
get_address_from_interface,
get_address_from_hostname,
};
+6
View File
@@ -9,8 +9,14 @@
#ifndef TOR_CONFIG_RESOLVE_ADDR_H
#define TOR_CONFIG_RESOLVE_ADDR_H
#include "app/config/config.h"
#include "core/mainloop/connection.h"
#include "app/config/or_options_st.h"
#define get_orport_addr(family) \
(get_first_advertised_addr_by_type_af(CONN_TYPE_OR_LISTENER, family))
bool find_my_address(const or_options_t *options, int family,
int warn_severity, tor_addr_t *addr_out,
const char **method_out, char **hostname_out);
+81 -9
View File
@@ -1256,13 +1256,15 @@ get_interface_address6_failure(int severity, sa_family_t family,
/** Helper macro: Cleanup the address and variables used after a
* find_my_address() call. */
#undef CLEANUP_FOUND_ADDRESS
#define CLEANUP_FOUND_ADDRESS \
do { \
config_free_lines(options->Address); \
tor_free(options->DirAuthorities); \
tor_free(hostname_out); \
tor_addr_make_unspec(&resolved_addr); \
tor_addr_make_unspec(&test_addr); \
#define CLEANUP_FOUND_ADDRESS \
do { \
config_free_lines(options->Address); \
config_free_lines(options->ORPort_lines); \
options->ORPort_set = 0; \
tor_free(options->DirAuthorities); \
tor_free(hostname_out); \
tor_addr_make_unspec(&resolved_addr); \
tor_addr_make_unspec(&test_addr); \
} while (0)
/** Test both IPv4 and IPv6 coexisting together in the configuration. */
@@ -1418,6 +1420,7 @@ typedef struct find_my_address_params_t {
int family;
const char *public_ip;
const char *internal_ip;
const char *orport;
} find_my_address_params_t;
static find_my_address_params_t addr_param_v4 = {
@@ -1430,8 +1433,8 @@ static find_my_address_params_t addr_param_v4 = {
static find_my_address_params_t addr_param_v6 = {
.idx = 1,
.family = AF_INET6,
.public_ip = "4242::4242",
.internal_ip = "::1",
.public_ip = "[4242::4242]",
.internal_ip = "[::1]",
};
static void
@@ -1733,6 +1736,75 @@ test_config_find_my_address(void *arg)
VALIDATE_FOUND_ADDRESS(false, NULL, NULL);
CLEANUP_FOUND_ADDRESS;
/*
* Case 13:
* 1. Address is NULL.
* 2. ORPort has a valid public address.
*/
{
char *msg = NULL;
int n, w, ret;
char *orport_line = NULL;
options->Address = NULL;
tor_asprintf(&orport_line, "%s:9001", p->public_ip);
config_line_append(&options->ORPort_lines, "ORPort", orport_line);
tor_free(orport_line);
if (p->family == AF_INET6) {
/* XXX: Tor does _not_ allow an IPv6 only ORPort thus we need to add a
* bogus IPv4 at the moment. */
config_line_append(&options->ORPort_lines, "ORPort", "1.1.1.1:9001");
}
ret = parse_ports(options, 0, &msg, &n, &w);
tt_int_op(ret, OP_EQ, 0);
tor_addr_parse(&test_addr, p->public_ip);
}
retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
&method_used, &hostname_out);
VALIDATE_FOUND_ADDRESS(true, "CONFIGURED_ORPORT", NULL);
CLEANUP_FOUND_ADDRESS;
/*
* Case 14:
* 1. Address is NULL.
* 2. ORPort has an internal address thus fails.
* 3. Interface as a valid address.
*/
{
char *msg = NULL;
int n, w, ret;
char *orport_line = NULL;
options->Address = NULL;
tor_asprintf(&orport_line, "%s:9001", p->internal_ip);
config_line_append(&options->ORPort_lines, "ORPort", orport_line);
tor_free(orport_line);
if (p->family == AF_INET6) {
/* XXX: Tor does _not_ allow an IPv6 only ORPort thus we need to add a
* bogus IPv4 at the moment. */
config_line_append(&options->ORPort_lines, "ORPort", "1.1.1.1:9001");
}
ret = parse_ports(options, 0, &msg, &n, &w);
tt_int_op(ret, OP_EQ, 0);
}
tor_addr_parse(&test_addr, ret_get_interface_address6_08080808[p->idx]);
MOCK(get_interface_address6, get_interface_address6_08080808);
prev_n_get_interface_address6 = n_get_interface_address6;
retval = find_my_address(options, p->family, LOG_NOTICE, &resolved_addr,
&method_used, &hostname_out);
tt_int_op(n_get_interface_address6, OP_EQ, ++prev_n_get_interface_address6);
VALIDATE_FOUND_ADDRESS(true, "INTERFACE", NULL);
CLEANUP_FOUND_ADDRESS;
UNMOCK(get_interface_address6);
UNMOCK(tor_gethostname);
UNMOCK(tor_addr_lookup);