diff options
author | Nick Mathewson <nickm@torproject.org> | 2020-05-07 08:19:11 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2020-05-07 08:19:11 -0400 |
commit | b7a165228f02e693b3e777b4c815214bb6e05691 (patch) | |
tree | b79cd6d72f3dffbdee88b9b77b1b5f0240e872e9 | |
parent | 3a785dd5beeaadcd4205f24d6949fdbbdfb5651e (diff) | |
parent | c81c5a2646763c651a9bc17b6213bd25a480eca9 (diff) | |
download | tor-b7a165228f02e693b3e777b4c815214bb6e05691.tar.gz tor-b7a165228f02e693b3e777b4c815214bb6e05691.zip |
Merge remote-tracking branch 'tor-github/pr/1880/head'
26 files changed, 520 insertions, 417 deletions
diff --git a/changes/ticket33789 b/changes/ticket33789 new file mode 100644 index 0000000000..a7e69793e6 --- /dev/null +++ b/changes/ticket33789 @@ -0,0 +1,4 @@ + o Code simplification and refactoring (relay address): + - Move a series of functions related to address resolving into their own + files. Closes ticket 33789. + diff --git a/scripts/maint/practracker/exceptions.txt b/scripts/maint/practracker/exceptions.txt index 8f718deff2..fc9a05c84f 100644 --- a/scripts/maint/practracker/exceptions.txt +++ b/scripts/maint/practracker/exceptions.txt @@ -36,7 +36,6 @@ problem file-size /src/app/config/config.c 7525 problem include-count /src/app/config/config.c 80 problem function-size /src/app/config/config.c:options_act() 381 -problem function-size /src/app/config/config.c:resolve_my_address() 191 problem function-size /src/app/config/config.c:options_validate_cb() 794 problem function-size /src/app/config/config.c:options_init_from_torrc() 192 problem function-size /src/app/config/config.c:options_init_from_string() 103 @@ -47,6 +46,7 @@ problem function-size /src/app/config/config.c:parse_dir_authority_line() 150 problem function-size /src/app/config/config.c:parse_dir_fallback_line() 101 problem function-size /src/app/config/config.c:port_parse_config() 435 problem function-size /src/app/config/config.c:parse_ports() 132 +problem function-size /src/app/config/resolve_addr.c:resolve_my_address() 191 problem file-size /src/app/config/or_options_st.h 1050 problem include-count /src/app/main/main.c 68 problem function-size /src/app/main/main.c:dumpstats() 102 diff --git a/src/app/config/config.c b/src/app/config/config.c index 0ae650eb08..7ed373c548 100644 --- a/src/app/config/config.c +++ b/src/app/config/config.c @@ -2722,23 +2722,6 @@ list_enabled_modules(void) // test variants in test_parseconf.sh to no useful purpose. } -/** Last value actually set by resolve_my_address. */ -static uint32_t last_resolved_addr = 0; - -/** Accessor for last_resolved_addr from outside this file. */ -uint32_t -get_last_resolved_addr(void) -{ - return last_resolved_addr; -} - -/** Reset last_resolved_addr from outside this file. */ -void -reset_last_resolved_addr(void) -{ - last_resolved_addr = 0; -} - /* Return true if <b>options</b> is using the default authorities, and false * if any authority-related option has been overridden. */ int @@ -2747,278 +2730,6 @@ using_default_dir_authorities(const or_options_t *options) return (!options->DirAuthorities && !options->AlternateDirAuthority); } -/** - * Attempt getting our non-local (as judged by tor_addr_is_internal() - * function) IP address using following techniques, listed in - * order from best (most desirable, try first) to worst (least - * desirable, try if everything else fails). - * - * First, attempt using <b>options-\>Address</b> to get our - * non-local IP address. - * - * If <b>options-\>Address</b> represents a non-local IP address, - * consider it ours. - * - * If <b>options-\>Address</b> is a DNS name that resolves to - * a non-local IP address, consider this IP address ours. - * - * If <b>options-\>Address</b> is NULL, fall back to getting local - * hostname and using it in above-described ways to try and - * get our IP address. - * - * In case local hostname cannot be resolved to a non-local IP - * address, try getting an IP address of network interface - * in hopes it will be non-local one. - * - * Fail if one or more of the following is true: - * - DNS name in <b>options-\>Address</b> cannot be resolved. - * - <b>options-\>Address</b> is a local host address. - * - Attempt at getting local hostname fails. - * - Attempt at getting network interface address fails. - * - * Return 0 if all is well, or -1 if we can't find a suitable - * public IP address. - * - * If we are returning 0: - * - Put our public IP address (in host order) into *<b>addr_out</b>. - * - If <b>method_out</b> is non-NULL, set *<b>method_out</b> to a static - * string describing how we arrived at our answer. - * - "CONFIGURED" - parsed from IP address string in - * <b>options-\>Address</b> - * - "RESOLVED" - resolved from DNS name in <b>options-\>Address</b> - * - "GETHOSTNAME" - resolved from a local hostname. - * - "INTERFACE" - retrieved from a network interface. - * - If <b>hostname_out</b> is non-NULL, and we resolved a hostname to - * get our address, set *<b>hostname_out</b> to a newly allocated string - * holding that hostname. (If we didn't get our address by resolving a - * hostname, set *<b>hostname_out</b> to NULL.) - * - * XXXX ipv6 - */ -int -resolve_my_address(int warn_severity, const or_options_t *options, - uint32_t *addr_out, - const char **method_out, char **hostname_out) -{ - struct in_addr in; - uint32_t addr; /* host order */ - char hostname[256]; - const char *method_used; - const char *hostname_used; - int explicit_ip=1; - int explicit_hostname=1; - int from_interface=0; - char *addr_string = NULL; - const char *address = options->Address; - int notice_severity = warn_severity <= LOG_NOTICE ? - LOG_NOTICE : warn_severity; - - tor_addr_t myaddr; - tor_assert(addr_out); - - /* - * Step one: Fill in 'hostname' to be our best guess. - */ - - if (address && *address) { - strlcpy(hostname, address, sizeof(hostname)); - } else { /* then we need to guess our address */ - explicit_ip = 0; /* it's implicit */ - explicit_hostname = 0; /* it's implicit */ - - if (tor_gethostname(hostname, sizeof(hostname)) < 0) { - log_fn(warn_severity, LD_NET,"Error obtaining local hostname"); - return -1; - } - log_debug(LD_CONFIG, "Guessed local host name as '%s'", hostname); - } - - /* - * Step two: Now that we know 'hostname', parse it or resolve it. If - * it doesn't parse or resolve, look at the interface address. Set 'addr' - * to be our (host-order) 32-bit answer. - */ - - if (tor_inet_aton(hostname, &in) == 0) { - /* then we have to resolve it */ - explicit_ip = 0; - if (tor_lookup_hostname(hostname, &addr)) { /* failed to resolve */ - uint32_t interface_ip; /* host order */ - - if (explicit_hostname) { - log_fn(warn_severity, LD_CONFIG, - "Could not resolve local Address '%s'. Failing.", hostname); - return -1; - } - log_fn(notice_severity, LD_CONFIG, - "Could not resolve guessed local hostname '%s'. " - "Trying something else.", hostname); - if (get_interface_address(warn_severity, &interface_ip)) { - log_fn(warn_severity, LD_CONFIG, - "Could not get local interface IP address. Failing."); - return -1; - } - from_interface = 1; - addr = interface_ip; - log_fn(notice_severity, LD_CONFIG, "Learned IP address '%s' for " - "local interface. Using that.", fmt_addr32(addr)); - strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname)); - } else { /* resolved hostname into addr */ - tor_addr_from_ipv4h(&myaddr, addr); - - if (!explicit_hostname && - tor_addr_is_internal(&myaddr, 0)) { - tor_addr_t interface_ip; - - log_fn(notice_severity, LD_CONFIG, "Guessed local hostname '%s' " - "resolves to a private IP address (%s). Trying something " - "else.", hostname, fmt_addr32(addr)); - - if (get_interface_address6(warn_severity, AF_INET, &interface_ip)<0) { - log_fn(warn_severity, LD_CONFIG, - "Could not get local interface IP address. Too bad."); - } else if (tor_addr_is_internal(&interface_ip, 0)) { - log_fn(notice_severity, LD_CONFIG, - "Interface IP address '%s' is a private address too. " - "Ignoring.", fmt_addr(&interface_ip)); - } else { - from_interface = 1; - addr = tor_addr_to_ipv4h(&interface_ip); - log_fn(notice_severity, LD_CONFIG, - "Learned IP address '%s' for local interface." - " Using that.", fmt_addr32(addr)); - strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname)); - } - } - } - } else { - addr = ntohl(in.s_addr); /* set addr so that addr_string is not - * illformed */ - } - - /* - * Step three: Check whether 'addr' is an internal IP address, and error - * out if it is and we don't want that. - */ - - tor_addr_from_ipv4h(&myaddr,addr); - - addr_string = tor_dup_ip(addr); - if (tor_addr_is_internal(&myaddr, 0)) { - /* make sure we're ok with publishing an internal IP */ - if (using_default_dir_authorities(options)) { - /* if they are using the default authorities, disallow internal IPs - * always. For IPv6 ORPorts, this check is done in - * router_get_advertised_ipv6_or_ap(). See #33681. */ - log_fn(warn_severity, LD_CONFIG, - "Address '%s' resolves to private IP address '%s'. " - "Tor servers that use the default DirAuthorities must have " - "public IP addresses.", hostname, addr_string); - tor_free(addr_string); - return -1; - } - if (!explicit_ip) { - /* even if they've set their own authorities, require an explicit IP if - * they're using an internal address. */ - log_fn(warn_severity, LD_CONFIG, "Address '%s' resolves to private " - "IP address '%s'. Please set the Address config option to be " - "the IP address you want to use.", hostname, addr_string); - tor_free(addr_string); - return -1; - } - } - - /* - * Step four: We have a winner! 'addr' is our answer for sure, and - * 'addr_string' is its string form. Fill out the various fields to - * say how we decided it. - */ - - log_debug(LD_CONFIG, "Resolved Address to '%s'.", addr_string); - - if (explicit_ip) { - method_used = "CONFIGURED"; - hostname_used = NULL; - } else if (explicit_hostname) { - method_used = "RESOLVED"; - hostname_used = hostname; - } else if (from_interface) { - method_used = "INTERFACE"; - hostname_used = NULL; - } else { - method_used = "GETHOSTNAME"; - hostname_used = hostname; - } - - *addr_out = addr; - if (method_out) - *method_out = method_used; - if (hostname_out) - *hostname_out = hostname_used ? tor_strdup(hostname_used) : NULL; - - /* - * Step five: Check if the answer has changed since last time (or if - * there was no last time), and if so call various functions to keep - * us up-to-date. - */ - - if (last_resolved_addr && last_resolved_addr != *addr_out) { - /* Leave this as a notice, regardless of the requested severity, - * at least until dynamic IP address support becomes bulletproof. */ - log_notice(LD_NET, - "Your IP address seems to have changed to %s " - "(METHOD=%s%s%s). Updating.", - addr_string, method_used, - hostname_used ? " HOSTNAME=" : "", - hostname_used ? hostname_used : ""); - ip_address_changed(0); - } - - if (last_resolved_addr != *addr_out) { - control_event_server_status(LOG_NOTICE, - "EXTERNAL_ADDRESS ADDRESS=%s METHOD=%s%s%s", - addr_string, method_used, - hostname_used ? " HOSTNAME=" : "", - hostname_used ? hostname_used : ""); - } - last_resolved_addr = *addr_out; - - /* - * And finally, clean up and return success. - */ - - tor_free(addr_string); - return 0; -} - -/** Return true iff <b>addr</b> is judged to be on the same network as us, or - * on a private network. - */ -MOCK_IMPL(int, -is_local_addr, (const tor_addr_t *addr)) -{ - if (tor_addr_is_internal(addr, 0)) - return 1; - /* Check whether ip is on the same /24 as we are. */ - if (get_options()->EnforceDistinctSubnets == 0) - return 0; - if (tor_addr_family(addr) == AF_INET) { - uint32_t ip = tor_addr_to_ipv4h(addr); - - /* It's possible that this next check will hit before the first time - * resolve_my_address actually succeeds. (For clients, it is likely that - * resolve_my_address will never be called at all). In those cases, - * last_resolved_addr will be 0, and so checking to see whether ip is on - * the same /24 as last_resolved_addr will be the same as checking whether - * it was on net 0, which is already done by tor_addr_is_internal. - */ - if ((last_resolved_addr & (uint32_t)0xffffff00ul) - == (ip & (uint32_t)0xffffff00ul)) - return 1; - } - return 0; -} - /** Return a new empty or_options_t. Used for testing. */ or_options_t * options_new(void) diff --git a/src/app/config/config.h b/src/app/config/config.h index 460b5ef0ee..17caa0e3ff 100644 --- a/src/app/config/config.h +++ b/src/app/config/config.h @@ -55,12 +55,6 @@ typedef enum setopt_err_t { setopt_err_t options_trial_assign(struct config_line_t *list, unsigned flags, char **msg); -uint32_t get_last_resolved_addr(void); -void reset_last_resolved_addr(void); -int resolve_my_address(int warn_severity, const or_options_t *options, - uint32_t *addr_out, - const char **method_out, char **hostname_out); -MOCK_DECL(int, is_local_addr, (const tor_addr_t *addr)); void options_init(or_options_t *options); #define OPTIONS_DUMP_MINIMAL 1 diff --git a/src/app/config/include.am b/src/app/config/include.am index 5d625efecf..14320a6b11 100644 --- a/src/app/config/include.am +++ b/src/app/config/include.am @@ -3,6 +3,7 @@ LIBTOR_APP_A_SOURCES += \ src/app/config/config.c \ src/app/config/quiet_level.c \ + src/app/config/resolve_addr.c \ src/app/config/statefile.c # ADD_C_FILE: INSERT HEADERS HERE. @@ -11,6 +12,7 @@ noinst_HEADERS += \ src/app/config/or_options_st.h \ src/app/config/or_state_st.h \ src/app/config/quiet_level.h \ + src/app/config/resolve_addr.h \ src/app/config/statefile.h \ src/app/config/tor_cmdline_mode.h diff --git a/src/app/config/resolve_addr.c b/src/app/config/resolve_addr.c new file mode 100644 index 0000000000..b551615c02 --- /dev/null +++ b/src/app/config/resolve_addr.c @@ -0,0 +1,308 @@ +/* Copyright (c) 2020, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file resolve_addr.c + * \brief Implement resolving address functions + **/ + +#define RESOLVE_ADDR_PRIVATE + +#include "app/config/config.h" +#include "app/config/resolve_addr.h" + +#include "core/mainloop/mainloop.h" + +#include "feature/control/control_events.h" + +#include "lib/net/gethostname.h" +#include "lib/net/resolve.h" + +/** Last value actually set by resolve_my_address. */ +static uint32_t last_resolved_addr = 0; + +/** Accessor for last_resolved_addr from outside this file. */ +uint32_t +get_last_resolved_addr(void) +{ + return last_resolved_addr; +} + +/** Reset last_resolved_addr from outside this file. */ +void +reset_last_resolved_addr(void) +{ + last_resolved_addr = 0; +} + +/** + * Attempt getting our non-local (as judged by tor_addr_is_internal() + * function) IP address using following techniques, listed in + * order from best (most desirable, try first) to worst (least + * desirable, try if everything else fails). + * + * First, attempt using <b>options-\>Address</b> to get our + * non-local IP address. + * + * If <b>options-\>Address</b> represents a non-local IP address, + * consider it ours. + * + * If <b>options-\>Address</b> is a DNS name that resolves to + * a non-local IP address, consider this IP address ours. + * + * If <b>options-\>Address</b> is NULL, fall back to getting local + * hostname and using it in above-described ways to try and + * get our IP address. + * + * In case local hostname cannot be resolved to a non-local IP + * address, try getting an IP address of network interface + * in hopes it will be non-local one. + * + * Fail if one or more of the following is true: + * - DNS name in <b>options-\>Address</b> cannot be resolved. + * - <b>options-\>Address</b> is a local host address. + * - Attempt at getting local hostname fails. + * - Attempt at getting network interface address fails. + * + * Return 0 if all is well, or -1 if we can't find a suitable + * public IP address. + * + * If we are returning 0: + * - Put our public IP address (in host order) into *<b>addr_out</b>. + * - If <b>method_out</b> is non-NULL, set *<b>method_out</b> to a static + * string describing how we arrived at our answer. + * - "CONFIGURED" - parsed from IP address string in + * <b>options-\>Address</b> + * - "RESOLVED" - resolved from DNS name in <b>options-\>Address</b> + * - "GETHOSTNAME" - resolved from a local hostname. + * - "INTERFACE" - retrieved from a network interface. + * - If <b>hostname_out</b> is non-NULL, and we resolved a hostname to + * get our address, set *<b>hostname_out</b> to a newly allocated string + * holding that hostname. (If we didn't get our address by resolving a + * hostname, set *<b>hostname_out</b> to NULL.) + * + * XXXX ipv6 + */ +int +resolve_my_address(int warn_severity, const or_options_t *options, + uint32_t *addr_out, + const char **method_out, char **hostname_out) +{ + struct in_addr in; + uint32_t addr; /* host order */ + char hostname[256]; + const char *method_used; + const char *hostname_used; + int explicit_ip=1; + int explicit_hostname=1; + int from_interface=0; + char *addr_string = NULL; + const char *address = options->Address; + int notice_severity = warn_severity <= LOG_NOTICE ? + LOG_NOTICE : warn_severity; + + tor_addr_t myaddr; + tor_assert(addr_out); + + /* + * Step one: Fill in 'hostname' to be our best guess. + */ + + if (address && *address) { + strlcpy(hostname, address, sizeof(hostname)); + } else { /* then we need to guess our address */ + explicit_ip = 0; /* it's implicit */ + explicit_hostname = 0; /* it's implicit */ + + if (tor_gethostname(hostname, sizeof(hostname)) < 0) { + log_fn(warn_severity, LD_NET,"Error obtaining local hostname"); + return -1; + } + log_debug(LD_CONFIG, "Guessed local host name as '%s'", hostname); + } + + /* + * Step two: Now that we know 'hostname', parse it or resolve it. If + * it doesn't parse or resolve, look at the interface address. Set 'addr' + * to be our (host-order) 32-bit answer. + */ + + if (tor_inet_aton(hostname, &in) == 0) { + /* then we have to resolve it */ + explicit_ip = 0; + if (tor_lookup_hostname(hostname, &addr)) { /* failed to resolve */ + uint32_t interface_ip; /* host order */ + + if (explicit_hostname) { + log_fn(warn_severity, LD_CONFIG, + "Could not resolve local Address '%s'. Failing.", hostname); + return -1; + } + log_fn(notice_severity, LD_CONFIG, + "Could not resolve guessed local hostname '%s'. " + "Trying something else.", hostname); + if (get_interface_address(warn_severity, &interface_ip)) { + log_fn(warn_severity, LD_CONFIG, + "Could not get local interface IP address. Failing."); + return -1; + } + from_interface = 1; + addr = interface_ip; + log_fn(notice_severity, LD_CONFIG, "Learned IP address '%s' for " + "local interface. Using that.", fmt_addr32(addr)); + strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname)); + } else { /* resolved hostname into addr */ + tor_addr_from_ipv4h(&myaddr, addr); + + if (!explicit_hostname && + tor_addr_is_internal(&myaddr, 0)) { + tor_addr_t interface_ip; + + log_fn(notice_severity, LD_CONFIG, "Guessed local hostname '%s' " + "resolves to a private IP address (%s). Trying something " + "else.", hostname, fmt_addr32(addr)); + + if (get_interface_address6(warn_severity, AF_INET, &interface_ip)<0) { + log_fn(warn_severity, LD_CONFIG, + "Could not get local interface IP address. Too bad."); + } else if (tor_addr_is_internal(&interface_ip, 0)) { + log_fn(notice_severity, LD_CONFIG, + "Interface IP address '%s' is a private address too. " + "Ignoring.", fmt_addr(&interface_ip)); + } else { + from_interface = 1; + addr = tor_addr_to_ipv4h(&interface_ip); + log_fn(notice_severity, LD_CONFIG, + "Learned IP address '%s' for local interface." + " Using that.", fmt_addr32(addr)); + strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname)); + } + } + } + } else { + addr = ntohl(in.s_addr); /* set addr so that addr_string is not + * illformed */ + } + + /* + * Step three: Check whether 'addr' is an internal IP address, and error + * out if it is and we don't want that. + */ + + tor_addr_from_ipv4h(&myaddr,addr); + + addr_string = tor_dup_ip(addr); + if (tor_addr_is_internal(&myaddr, 0)) { + /* make sure we're ok with publishing an internal IP */ + if (using_default_dir_authorities(options)) { + /* if they are using the default authorities, disallow internal IPs + * always. For IPv6 ORPorts, this check is done in + * router_get_advertised_ipv6_or_ap(). See #33681. */ + log_fn(warn_severity, LD_CONFIG, + "Address '%s' resolves to private IP address '%s'. " + "Tor servers that use the default DirAuthorities must have " + "public IP addresses.", hostname, addr_string); + tor_free(addr_string); + return -1; + } + if (!explicit_ip) { + /* even if they've set their own authorities, require an explicit IP if + * they're using an internal address. */ + log_fn(warn_severity, LD_CONFIG, "Address '%s' resolves to private " + "IP address '%s'. Please set the Address config option to be " + "the IP address you want to use.", hostname, addr_string); + tor_free(addr_string); + return -1; + } + } + + /* + * Step four: We have a winner! 'addr' is our answer for sure, and + * 'addr_string' is its string form. Fill out the various fields to + * say how we decided it. + */ + + log_debug(LD_CONFIG, "Resolved Address to '%s'.", addr_string); + + if (explicit_ip) { + method_used = "CONFIGURED"; + hostname_used = NULL; + } else if (explicit_hostname) { + method_used = "RESOLVED"; + hostname_used = hostname; + } else if (from_interface) { + method_used = "INTERFACE"; + hostname_used = NULL; + } else { + method_used = "GETHOSTNAME"; + hostname_used = hostname; + } + + *addr_out = addr; + if (method_out) + *method_out = method_used; + if (hostname_out) + *hostname_out = hostname_used ? tor_strdup(hostname_used) : NULL; + + /* + * Step five: Check if the answer has changed since last time (or if + * there was no last time), and if so call various functions to keep + * us up-to-date. + */ + + if (last_resolved_addr && last_resolved_addr != *addr_out) { + /* Leave this as a notice, regardless of the requested severity, + * at least until dynamic IP address support becomes bulletproof. */ + log_notice(LD_NET, + "Your IP address seems to have changed to %s " + "(METHOD=%s%s%s). Updating.", + addr_string, method_used, + hostname_used ? " HOSTNAME=" : "", + hostname_used ? hostname_used : ""); + ip_address_changed(0); + } + + if (last_resolved_addr != *addr_out) { + control_event_server_status(LOG_NOTICE, + "EXTERNAL_ADDRESS ADDRESS=%s METHOD=%s%s%s", + addr_string, method_used, + hostname_used ? " HOSTNAME=" : "", + hostname_used ? hostname_used : ""); + } + last_resolved_addr = *addr_out; + + /* + * And finally, clean up and return success. + */ + + tor_free(addr_string); + return 0; +} + +/** Return true iff <b>addr</b> is judged to be on the same network as us, or + * on a private network. + */ +MOCK_IMPL(int, +is_local_addr, (const tor_addr_t *addr)) +{ + if (tor_addr_is_internal(addr, 0)) + return 1; + /* Check whether ip is on the same /24 as we are. */ + if (get_options()->EnforceDistinctSubnets == 0) + return 0; + if (tor_addr_family(addr) == AF_INET) { + uint32_t ip = tor_addr_to_ipv4h(addr); + + /* It's possible that this next check will hit before the first time + * resolve_my_address actually succeeds. (For clients, it is likely that + * resolve_my_address will never be called at all). In those cases, + * last_resolved_addr will be 0, and so checking to see whether ip is on + * the same /24 as last_resolved_addr will be the same as checking whether + * it was on net 0, which is already done by tor_addr_is_internal. + */ + if ((last_resolved_addr & (uint32_t)0xffffff00ul) + == (ip & (uint32_t)0xffffff00ul)) + return 1; + } + return 0; +} diff --git a/src/app/config/resolve_addr.h b/src/app/config/resolve_addr.h new file mode 100644 index 0000000000..3747546402 --- /dev/null +++ b/src/app/config/resolve_addr.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2020, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file resolve_addr.h + * \brief Header file for resolve_addr.c. + **/ + +#ifndef TOR_CONFIG_RESOLVE_ADDR_H +#define TOR_CONFIG_RESOLVE_ADDR_H + +#include "app/config/or_options_st.h" + +int resolve_my_address(int warn_severity, const or_options_t *options, + uint32_t *addr_out, + const char **method_out, char **hostname_out); + +uint32_t get_last_resolved_addr(void); +void reset_last_resolved_addr(void); + +MOCK_DECL(int, is_local_addr, (const tor_addr_t *addr)); + +#ifdef RESOLVE_ADDR_PRIVATE + +#endif /* RESOLVE_ADDR_PRIVATE */ + +#endif /* TOR_CONFIG_RESOLVE_ADDR_H */ + diff --git a/src/core/mainloop/connection.c b/src/core/mainloop/connection.c index db59e6b28d..a8417e46d9 100644 --- a/src/core/mainloop/connection.c +++ b/src/core/mainloop/connection.c @@ -67,6 +67,7 @@ */ #define CHANNEL_OBJECT_PRIVATE #include "app/config/config.h" +#include "app/config/resolve_addr.h" #include "core/mainloop/connection.h" #include "core/mainloop/mainloop.h" #include "core/mainloop/netstatus.h" diff --git a/src/core/or/channeltls.c b/src/core/or/channeltls.c index e73340ca29..395fbf3455 100644 --- a/src/core/or/channeltls.c +++ b/src/core/or/channeltls.c @@ -45,6 +45,7 @@ #include "core/or/circuitmux_ewma.h" #include "core/or/command.h" #include "app/config/config.h" +#include "app/config/resolve_addr.h" #include "core/mainloop/connection.h" #include "core/or/connection_or.h" #include "feature/relay/relay_handshake.h" diff --git a/src/core/stA1RajU b/src/core/stA1RajU new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/src/core/stA1RajU diff --git a/src/core/stiysZND b/src/core/stiysZND Binary files differnew file mode 100644 index 0000000000..faa365b769 --- /dev/null +++ b/src/core/stiysZND diff --git a/src/feature/client/transports.c b/src/feature/client/transports.c index 55069bb60a..2bdc0ae151 100644 --- a/src/feature/client/transports.c +++ b/src/feature/client/transports.c @@ -97,6 +97,7 @@ #include "core/or/circuitbuild.h" #include "feature/client/transports.h" #include "feature/relay/router.h" +#include "feature/relay/relay_find_addr.h" /* 31851: split the server transport code out of the client module */ #include "feature/relay/transport_config.h" #include "app/config/statefile.h" diff --git a/src/feature/control/control_getinfo.c b/src/feature/control/control_getinfo.c index 5dcc4b170d..685deb8ecc 100644 --- a/src/feature/control/control_getinfo.c +++ b/src/feature/control/control_getinfo.c @@ -44,6 +44,7 @@ #include "feature/nodelist/nodelist.h" #include "feature/nodelist/routerinfo.h" #include "feature/nodelist/routerlist.h" +#include "feature/relay/relay_find_addr.h" #include "feature/relay/router.h" #include "feature/relay/routermode.h" #include "feature/relay/selftest.h" diff --git a/src/feature/dirauth/dirauth_config.c b/src/feature/dirauth/dirauth_config.c index 38d2a8bc5a..a0b6de7eca 100644 --- a/src/feature/dirauth/dirauth_config.c +++ b/src/feature/dirauth/dirauth_config.c @@ -20,6 +20,7 @@ /* Required for dirinfo_type_t in or_options_t */ #include "core/or/or.h" #include "app/config/config.h" +#include "app/config/resolve_addr.h" #include "feature/dirauth/voting_schedule.h" #include "feature/stats/rephist.h" diff --git a/src/feature/dirauth/dirvote.c b/src/feature/dirauth/dirvote.c index 7eb2b720a6..6bf30d083b 100644 --- a/src/feature/dirauth/dirvote.c +++ b/src/feature/dirauth/dirvote.c @@ -6,6 +6,7 @@ #define DIRVOTE_PRIVATE #include "core/or/or.h" #include "app/config/config.h" +#include "app/config/resolve_addr.h" #include "core/or/policies.h" #include "core/or/protover.h" #include "core/or/tor_version_st.h" diff --git a/src/feature/dircache/dircache.c b/src/feature/dircache/dircache.c index 4f7f209207..ca127720f2 100644 --- a/src/feature/dircache/dircache.c +++ b/src/feature/dircache/dircache.c @@ -13,6 +13,7 @@ #include "core/or/or.h" #include "app/config/config.h" +#include "app/config/resolve_addr.h" #include "core/mainloop/connection.h" #include "core/or/relay.h" #include "feature/dirauth/dirvote.h" diff --git a/src/feature/dirclient/dirclient.c b/src/feature/dirclient/dirclient.c index 5388209f67..ae1e018df2 100644 --- a/src/feature/dirclient/dirclient.c +++ b/src/feature/dirclient/dirclient.c @@ -44,6 +44,7 @@ #include "feature/nodelist/routerinfo.h" #include "feature/nodelist/routerlist.h" #include "feature/nodelist/routerset.h" +#include "feature/relay/relay_find_addr.h" #include "feature/relay/routermode.h" #include "feature/relay/selftest.h" #include "feature/rend/rendcache.h" diff --git a/src/feature/dirclient/dirclient_modes.c b/src/feature/dirclient/dirclient_modes.c index 23fd1a2f6e..31a3f8af58 100644 --- a/src/feature/dirclient/dirclient_modes.c +++ b/src/feature/dirclient/dirclient_modes.c @@ -16,6 +16,7 @@ #include "feature/dirclient/dirclient_modes.h" #include "feature/dircache/dirserv.h" +#include "feature/relay/relay_find_addr.h" #include "feature/relay/router.h" #include "feature/relay/routermode.h" #include "feature/stats/predict_ports.h" diff --git a/src/feature/nodelist/dirlist.c b/src/feature/nodelist/dirlist.c index ad3af0a143..d7069bb0ec 100644 --- a/src/feature/nodelist/dirlist.c +++ b/src/feature/nodelist/dirlist.c @@ -27,6 +27,7 @@ #include "core/or/or.h" #include "app/config/config.h" +#include "app/config/resolve_addr.h" #include "core/or/policies.h" #include "feature/control/control_events.h" #include "feature/dirauth/authmode.h" diff --git a/src/feature/relay/include.am b/src/feature/relay/include.am index 654432c34b..84bb1ff35e 100644 --- a/src/feature/relay/include.am +++ b/src/feature/relay/include.am @@ -2,6 +2,7 @@ # Legacy shared relay code: migrate to the relay module over time LIBTOR_APP_A_SOURCES += \ src/feature/relay/onion_queue.c \ + src/feature/relay/relay_find_addr.c \ src/feature/relay/router.c # The Relay module. @@ -31,6 +32,7 @@ noinst_HEADERS += \ src/feature/relay/relay_handshake.h \ src/feature/relay/relay_periodic.h \ src/feature/relay/relay_sys.h \ + src/feature/relay/relay_find_addr.h \ src/feature/relay/router.h \ src/feature/relay/routerkeys.h \ src/feature/relay/routermode.h \ diff --git a/src/feature/relay/relay_find_addr.c b/src/feature/relay/relay_find_addr.c new file mode 100644 index 0000000000..86cd799d42 --- /dev/null +++ b/src/feature/relay/relay_find_addr.c @@ -0,0 +1,133 @@ +/* Copyright (c) 2001-2020, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file relay_find_addr.c + * \brief Implement mechanism for a relay to find its address. + **/ + +#include "core/or/or.h" + +#include "app/config/config.h" +#include "app/config/resolve_addr.h" + +#include "core/mainloop/mainloop.h" + +#include "feature/control/control_events.h" +#include "feature/dircommon/dir_connection_st.h" +#include "feature/relay/relay_find_addr.h" +#include "feature/relay/router.h" +#include "feature/relay/routermode.h" + +/** The most recently guessed value of our IP address, based on directory + * headers. */ +static tor_addr_t last_guessed_ip = TOR_ADDR_NULL; + +/** We failed to resolve our address locally, but we'd like to build + * a descriptor and publish / test reachability. If we have a guess + * about our address based on directory headers, answer it and return + * 0; else return -1. */ +static int +router_guess_address_from_dir_headers(uint32_t *guess) +{ + if (!tor_addr_is_null(&last_guessed_ip)) { + *guess = tor_addr_to_ipv4h(&last_guessed_ip); + return 0; + } + return -1; +} + +/** A directory server <b>d_conn</b> told us our IP address is + * <b>suggestion</b>. + * If this address is different from the one we think we are now, and + * if our computer doesn't actually know its IP address, then switch. */ +void +router_new_address_suggestion(const char *suggestion, + const dir_connection_t *d_conn) +{ + tor_addr_t addr; + uint32_t cur = 0; /* Current IPv4 address. */ + const or_options_t *options = get_options(); + + /* first, learn what the IP address actually is */ + if (tor_addr_parse(&addr, suggestion) == -1) { + log_debug(LD_DIR, "Malformed X-Your-Address-Is header %s. Ignoring.", + escaped(suggestion)); + return; + } + + log_debug(LD_DIR, "Got X-Your-Address-Is: %s.", suggestion); + + if (!server_mode(options)) { + tor_addr_copy(&last_guessed_ip, &addr); + return; + } + + /* XXXX ipv6 */ + cur = get_last_resolved_addr(); + if (cur || + resolve_my_address(LOG_INFO, options, &cur, NULL, NULL) >= 0) { + /* We're all set -- we already know our address. Great. */ + tor_addr_from_ipv4h(&last_guessed_ip, cur); /* store it in case we + need it later */ + return; + } + if (tor_addr_is_internal(&addr, 0)) { + /* Don't believe anybody who says our IP is, say, 127.0.0.1. */ + return; + } + if (tor_addr_eq(&d_conn->base_.addr, &addr)) { + /* Don't believe anybody who says our IP is their IP. */ + log_debug(LD_DIR, "A directory server told us our IP address is %s, " + "but they are just reporting their own IP address. Ignoring.", + suggestion); + return; + } + + /* Okay. We can't resolve our own address, and X-Your-Address-Is is giving + * us an answer different from what we had the last time we managed to + * resolve it. */ + if (!tor_addr_eq(&last_guessed_ip, &addr)) { + control_event_server_status(LOG_NOTICE, + "EXTERNAL_ADDRESS ADDRESS=%s METHOD=DIRSERV", + suggestion); + log_addr_has_changed(LOG_NOTICE, &last_guessed_ip, &addr, + d_conn->base_.address); + ip_address_changed(0); + tor_addr_copy(&last_guessed_ip, &addr); /* router_rebuild_descriptor() + will fetch it */ + } +} + +/** Make a current best guess at our address, either because + * it's configured in torrc, or because we've learned it from + * dirserver headers. Place the answer in *<b>addr</b> and return + * 0 on success, else return -1 if we have no guess. + * + * If <b>cache_only</b> is true, just return any cached answers, and + * don't try to get any new answers. + */ +MOCK_IMPL(int, +router_pick_published_address, (const or_options_t *options, uint32_t *addr, + int cache_only)) +{ + /* First, check the cached output from resolve_my_address(). */ + *addr = get_last_resolved_addr(); + if (*addr) + return 0; + + /* Second, consider doing a resolve attempt right here. */ + if (!cache_only) { + if (resolve_my_address(LOG_INFO, options, addr, NULL, NULL) >= 0) { + log_info(LD_CONFIG,"Success: chose address '%s'.", fmt_addr32(*addr)); + return 0; + } + } + + /* Third, check the cached output from router_new_address_suggestion(). */ + if (router_guess_address_from_dir_headers(addr) >= 0) + return 0; + + /* We have no useful cached answers. Return failure. */ + return -1; +} diff --git a/src/feature/relay/relay_find_addr.h b/src/feature/relay/relay_find_addr.h new file mode 100644 index 0000000000..ac51a977e6 --- /dev/null +++ b/src/feature/relay/relay_find_addr.h @@ -0,0 +1,23 @@ +/* Copyright (c) 2020, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file relay_find_addr.h + * \brief Header file for relay_find_addr.c. + **/ + +#ifndef TOR_RELAY_FIND_ADDR_H +#define TOR_RELAY_FIND_ADDR_H + +MOCK_DECL(int, router_pick_published_address, + (const or_options_t *options, uint32_t *addr, int cache_only)); + +void router_new_address_suggestion(const char *suggestion, + const dir_connection_t *d_conn); + +#ifdef RELAY_FIND_ADDR_PRIVATE + +#endif /* RELAY_FIND_ADDR_PRIVATE */ + +#endif /* TOR_RELAY_FIND_ADDR_H */ + diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c index 2858371af5..267dee8483 100644 --- a/src/feature/relay/router.c +++ b/src/feature/relay/router.c @@ -8,6 +8,7 @@ #include "core/or/or.h" #include "app/config/config.h" +#include "app/config/resolve_addr.h" #include "app/config/statefile.h" #include "app/main/main.h" #include "core/mainloop/connection.h" @@ -36,6 +37,7 @@ #include "feature/nodelist/torcert.h" #include "feature/relay/dns.h" #include "feature/relay/relay_config.h" +#include "feature/relay/relay_find_addr.h" #include "feature/relay/router.h" #include "feature/relay/routerkeys.h" #include "feature/relay/routermode.h" @@ -1763,41 +1765,6 @@ router_get_descriptor_gen_reason(void) return desc_gen_reason; } -static int router_guess_address_from_dir_headers(uint32_t *guess); - -/** Make a current best guess at our address, either because - * it's configured in torrc, or because we've learned it from - * dirserver headers. Place the answer in *<b>addr</b> and return - * 0 on success, else return -1 if we have no guess. - * - * If <b>cache_only</b> is true, just return any cached answers, and - * don't try to get any new answers. - */ -MOCK_IMPL(int, -router_pick_published_address,(const or_options_t *options, uint32_t *addr, - int cache_only)) -{ - /* First, check the cached output from resolve_my_address(). */ - *addr = get_last_resolved_addr(); - if (*addr) - return 0; - - /* Second, consider doing a resolve attempt right here. */ - if (!cache_only) { - if (resolve_my_address(LOG_INFO, options, addr, NULL, NULL) >= 0) { - log_info(LD_CONFIG,"Success: chose address '%s'.", fmt_addr32(*addr)); - return 0; - } - } - - /* Third, check the cached output from router_new_address_suggestion(). */ - if (router_guess_address_from_dir_headers(addr) >= 0) - return 0; - - /* We have no useful cached answers. Return failure. */ - return -1; -} - /* Like router_check_descriptor_address_consistency, but specifically for the * ORPort or DirPort. * listener_type is either CONN_TYPE_OR_LISTENER or CONN_TYPE_DIR_LISTENER. */ @@ -2523,7 +2490,7 @@ check_descriptor_bandwidth_changed(time_t now) /** Note at log level severity that our best guess of address has changed from * <b>prev</b> to <b>cur</b>. */ -static void +void log_addr_has_changed(int severity, const tor_addr_t *prev, const tor_addr_t *cur, @@ -2595,86 +2562,6 @@ check_descriptor_ipaddress_changed(time_t now) tor_free(hostname); } -/** The most recently guessed value of our IP address, based on directory - * headers. */ -static tor_addr_t last_guessed_ip = TOR_ADDR_NULL; - -/** A directory server <b>d_conn</b> told us our IP address is - * <b>suggestion</b>. - * If this address is different from the one we think we are now, and - * if our computer doesn't actually know its IP address, then switch. */ -void -router_new_address_suggestion(const char *suggestion, - const dir_connection_t *d_conn) -{ - tor_addr_t addr; - uint32_t cur = 0; /* Current IPv4 address. */ - const or_options_t *options = get_options(); - - /* first, learn what the IP address actually is */ - if (tor_addr_parse(&addr, suggestion) == -1) { - log_debug(LD_DIR, "Malformed X-Your-Address-Is header %s. Ignoring.", - escaped(suggestion)); - return; - } - - log_debug(LD_DIR, "Got X-Your-Address-Is: %s.", suggestion); - - if (!server_mode(options)) { - tor_addr_copy(&last_guessed_ip, &addr); - return; - } - - /* XXXX ipv6 */ - cur = get_last_resolved_addr(); - if (cur || - resolve_my_address(LOG_INFO, options, &cur, NULL, NULL) >= 0) { - /* We're all set -- we already know our address. Great. */ - tor_addr_from_ipv4h(&last_guessed_ip, cur); /* store it in case we - need it later */ - return; - } - if (tor_addr_is_internal(&addr, 0)) { - /* Don't believe anybody who says our IP is, say, 127.0.0.1. */ - return; - } - if (tor_addr_eq(&d_conn->base_.addr, &addr)) { - /* Don't believe anybody who says our IP is their IP. */ - log_debug(LD_DIR, "A directory server told us our IP address is %s, " - "but they are just reporting their own IP address. Ignoring.", - suggestion); - return; - } - - /* Okay. We can't resolve our own address, and X-Your-Address-Is is giving - * us an answer different from what we had the last time we managed to - * resolve it. */ - if (!tor_addr_eq(&last_guessed_ip, &addr)) { - control_event_server_status(LOG_NOTICE, - "EXTERNAL_ADDRESS ADDRESS=%s METHOD=DIRSERV", - suggestion); - log_addr_has_changed(LOG_NOTICE, &last_guessed_ip, &addr, - d_conn->base_.address); - ip_address_changed(0); - tor_addr_copy(&last_guessed_ip, &addr); /* router_rebuild_descriptor() - will fetch it */ - } -} - -/** We failed to resolve our address locally, but we'd like to build - * a descriptor and publish / test reachability. If we have a guess - * about our address based on directory headers, answer it and return - * 0; else return -1. */ -static int -router_guess_address_from_dir_headers(uint32_t *guess) -{ - if (!tor_addr_is_null(&last_guessed_ip)) { - *guess = tor_addr_to_ipv4h(&last_guessed_ip); - return 0; - } - return -1; -} - /** Set <b>platform</b> (max length <b>len</b>) to a NUL-terminated short * string describing the version of Tor and the operating system we're * currently running on. diff --git a/src/feature/relay/router.h b/src/feature/relay/router.h index 39c550dd25..50790a73dd 100644 --- a/src/feature/relay/router.h +++ b/src/feature/relay/router.h @@ -87,8 +87,6 @@ void mark_my_descriptor_dirty(const char *reason); void check_descriptor_bandwidth_changed(time_t now); void check_descriptor_ipaddress_changed(time_t now); int router_has_bandwidth_to_be_dirserver(const or_options_t *options); -void router_new_address_suggestion(const char *suggestion, - const dir_connection_t *d_conn); int router_compare_to_my_exit_policy(const tor_addr_t *addr, uint16_t port); MOCK_DECL(int, router_my_exit_policy_is_reject_star,(void)); MOCK_DECL(const routerinfo_t *, router_get_my_routerinfo, (void)); @@ -100,9 +98,6 @@ int router_digest_is_me(const char *digest); const uint8_t *router_get_my_id_digest(void); int router_extrainfo_digest_is_me(const char *digest); int router_is_me(const routerinfo_t *router); -MOCK_DECL(int,router_pick_published_address,(const or_options_t *options, - uint32_t *addr, - int cache_only)); int router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e); int router_rebuild_descriptor(int force); char *router_dump_router_to_string(routerinfo_t *router, @@ -120,6 +115,9 @@ int extrainfo_dump_to_string(char **s, extrainfo_t *extrainfo, const char *routerinfo_err_to_string(int err); int routerinfo_err_is_transient(int err); +void log_addr_has_changed(int severity, const tor_addr_t *prev, + const tor_addr_t *cur, const char *source); + void router_reset_warnings(void); void router_free_all(void); diff --git a/src/test/test_channeltls.c b/src/test/test_channeltls.c index 94ce56f2be..f4f5cb447e 100644 --- a/src/test/test_channeltls.c +++ b/src/test/test_channeltls.c @@ -14,6 +14,7 @@ #include "core/mainloop/connection.h" #include "core/or/connection_or.h" #include "app/config/config.h" +#include "app/config/resolve_addr.h" /* For init/free stuff */ #include "core/or/scheduler.h" #include "lib/tls/tortls.h" diff --git a/src/test/test_config.c b/src/test/test_config.c index 9ccdbc72c0..095eb24c49 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -18,6 +18,7 @@ #include "core/or/circuitmux_ewma.h" #include "core/or/circuitbuild.h" #include "app/config/config.h" +#include "app/config/resolve_addr.h" #include "feature/relay/relay_config.h" #include "feature/relay/transport_config.h" #include "lib/confmgt/confmgt.h" @@ -42,6 +43,7 @@ #include "core/or/policies.h" #include "feature/rend/rendclient.h" #include "feature/rend/rendservice.h" +#include "feature/relay/relay_find_addr.h" #include "feature/relay/router.h" #include "feature/relay/routermode.h" #include "feature/nodelist/dirlist.h" |