commit 809c8647079e3e84d401db25055144c5180aa75d Author: David Goulet <dgou...@torproject.org> Date: Mon Jul 6 11:09:39 2020 -0400
addr: Attempt to learn our address with ORPort If no Address statement are found in the configuration file, attempt to learn our address by looking at the ORPort address if any. Specifying an address is optional so if we can't find one, it is fine, we move on to the next discovery mechanism. Note that specifying a hostname on the ORPort is not yet supported at this commit. Closes #33236 Signed-off-by: David Goulet <dgou...@torproject.org> --- changes/ticket33236 | 4 ++ src/app/config/resolve_addr.c | 58 ++++++++++++++++++++++++++++ src/app/config/resolve_addr.h | 6 +++ src/test/test_config.c | 90 ++++++++++++++++++++++++++++++++++++++----- 4 files changed, 149 insertions(+), 9 deletions(-) diff --git a/changes/ticket33236 b/changes/ticket33236 new file mode 100644 index 000000000..d2b1d7e4d --- /dev/null +++ b/changes/ticket33236 @@ -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. + diff --git a/src/app/config/resolve_addr.c b/src/app/config/resolve_addr.c index 808c5ddf0..caca5a37d 100644 --- a/src/app/config/resolve_addr.c +++ b/src/app/config/resolve_addr.c @@ -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, }; diff --git a/src/app/config/resolve_addr.h b/src/app/config/resolve_addr.h index 54f55ba36..e6f8a7255 100644 --- a/src/app/config/resolve_addr.h +++ b/src/app/config/resolve_addr.h @@ -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); diff --git a/src/test/test_config.c b/src/test/test_config.c index 765db03c0..0862ba5c4 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -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); _______________________________________________ tor-commits mailing list tor-commits@lists.torproject.org https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits