diff options
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/config.c | 107 | ||||
-rw-r--r-- | src/or/config.h | 3 | ||||
-rw-r--r-- | src/or/dirserv.c | 8 | ||||
-rw-r--r-- | src/or/router.c | 12 | ||||
-rw-r--r-- | src/or/routerlist.c | 4 |
5 files changed, 98 insertions, 36 deletions
diff --git a/src/or/config.c b/src/or/config.c index 31695baa73..3d054e6c1d 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -1891,20 +1891,32 @@ list_torrc_options(void) /** Last value actually set by resolve_my_address. */ static uint32_t last_resolved_addr = 0; /** - * Based on <b>options-\>Address</b>, guess our public IP address and put it - * (in host order) into *<b>addr_out</b>. If <b>hostname_out</b> is provided, - * set *<b>hostname_out</b> to a new string holding the hostname we used to - * get the address. Return 0 if all is well, or -1 if we can't find a suitable + * Use <b>options-\>Address</b> to guess our public IP address. + * + * 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. + * - 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, char **hostname_out) + 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; @@ -1915,6 +1927,10 @@ resolve_my_address(int warn_severity, const or_options_t *options, 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 */ @@ -1925,10 +1941,14 @@ resolve_my_address(int warn_severity, const or_options_t *options, log_fn(warn_severity, LD_NET,"Error obtaining local hostname"); return -1; } - log_debug(LD_CONFIG,"Guessed local host name as '%s'",hostname); + log_debug(LD_CONFIG, "Guessed local host name as '%s'", hostname); } - /* now we know hostname. resolve it and keep only the IP address */ + /* + * 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 */ @@ -1985,6 +2005,11 @@ resolve_my_address(int warn_severity, const or_options_t *options, * illformed */ } + /* + * Step three: Check whether 'addr' is an internal IP address, and error + * out if it is and we don't want that. + */ + addr_string = tor_dup_ip(addr); if (is_internal_IP(addr, 0)) { /* make sure we're ok with publishing an internal IP */ @@ -2009,37 +2034,65 @@ resolve_my_address(int warn_severity, const or_options_t *options, } } - log_debug(LD_CONFIG, "Resolved Address to '%s'.", fmt_addr32(addr)); + /* + * 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. Updating.", - addr_string); + "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) { - const char *method; - const char *h = hostname; - if (explicit_ip) { - method = "CONFIGURED"; - h = NULL; - } else if (explicit_hostname) { - method = "RESOLVED"; - } else if (from_interface) { - method = "INTERFACE"; - h = NULL; - } else { - method = "GETHOSTNAME"; - } control_event_server_status(LOG_NOTICE, "EXTERNAL_ADDRESS ADDRESS=%s METHOD=%s %s%s", - addr_string, method, h?"HOSTNAME=":"", h); + addr_string, method_used, + hostname_used ? "HOSTNAME=" : "", + hostname_used ? hostname_used : ""); } last_resolved_addr = *addr_out; - if (hostname_out) - *hostname_out = tor_strdup(hostname); + + /* + * And finally, clean up and return success. + */ + tor_free(addr_string); return 0; } @@ -2287,7 +2340,7 @@ options_validate(or_options_t *old_options, or_options_t *options, if (authdir_mode(options)) { /* confirm that our address isn't broken, so we can complain now */ uint32_t tmp; - if (resolve_my_address(LOG_WARN, options, &tmp, NULL) < 0) + if (resolve_my_address(LOG_WARN, options, &tmp, NULL, NULL) < 0) REJECT("Failed to resolve/guess local address. See logs for details."); } diff --git a/src/or/config.h b/src/or/config.h index 8e34655805..e0748a07bf 100644 --- a/src/or/config.h +++ b/src/or/config.h @@ -27,7 +27,8 @@ setopt_err_t options_trial_assign(config_line_t *list, int use_defaults, int clear_first, char **msg); int resolve_my_address(int warn_severity, const or_options_t *options, - uint32_t *addr, char **hostname_out); + uint32_t *addr_out, + const char **method_out, char **hostname_out); int is_local_addr(const tor_addr_t *addr); void options_init(or_options_t *options); char *options_dump(const or_options_t *options, int minimal); diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 6209842881..a8f7d46592 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -2763,11 +2763,11 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, tor_assert(private_key); tor_assert(cert); - if (resolve_my_address(LOG_WARN, options, &addr, &hostname)<0) { + if (resolve_my_address(LOG_WARN, options, &addr, NULL, &hostname)<0) { log_warn(LD_NET, "Couldn't resolve my hostname"); return NULL; } - if (!strchr(hostname, '.')) { + if (!hostname || !strchr(hostname, '.')) { tor_free(hostname); hostname = tor_dup_ip(addr); } @@ -2990,10 +2990,12 @@ generate_v2_networkstatus_opinion(void) private_key = get_server_identity_key(); - if (resolve_my_address(LOG_WARN, options, &addr, &hostname)<0) { + if (resolve_my_address(LOG_WARN, options, &addr, NULL, &hostname)<0) { log_warn(LD_NET, "Couldn't resolve my hostname"); goto done; } + if (!hostname) + hostname = tor_dup_ip(addr); format_iso_time(published, now); diff --git a/src/or/router.c b/src/or/router.c index 6c05af9173..735b579fcb 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -1712,7 +1712,7 @@ static int router_guess_address_from_dir_headers(uint32_t *guess); int router_pick_published_address(const or_options_t *options, uint32_t *addr) { - if (resolve_my_address(LOG_INFO, options, addr, NULL) < 0) { + if (resolve_my_address(LOG_INFO, options, addr, NULL, NULL) < 0) { log_info(LD_CONFIG, "Could not determine our address locally. " "Checking if directory headers provide any hints."); if (router_guess_address_from_dir_headers(addr) < 0) { @@ -2089,6 +2089,7 @@ check_descriptor_ipaddress_changed(time_t now) { uint32_t prev, cur; const or_options_t *options = get_options(); + const char *method = NULL; char *hostname = NULL; (void) now; @@ -2098,7 +2099,7 @@ check_descriptor_ipaddress_changed(time_t now) /* XXXX ipv6 */ prev = desc_routerinfo->addr; - if (resolve_my_address(LOG_INFO, options, &cur, &hostname) < 0) { + if (resolve_my_address(LOG_INFO, options, &cur, &method, &hostname) < 0) { log_info(LD_CONFIG,"options->Address didn't resolve into an IP."); return; } @@ -2110,7 +2111,10 @@ check_descriptor_ipaddress_changed(time_t now) tor_addr_from_ipv4h(&tmp_prev, prev); tor_addr_from_ipv4h(&tmp_cur, cur); - tor_asprintf(&source, "resolved from %s", hostname); + tor_asprintf(&source, "METHOD=%s %s%s", method, + hostname ? "HOSTNAME=" : "", + hostname ? hostname : ""); + log_addr_has_changed(LOG_NOTICE, &tmp_prev, &tmp_cur, source); tor_free(source); @@ -2151,7 +2155,7 @@ router_new_address_suggestion(const char *suggestion, } /* XXXX ipv6 */ - if (resolve_my_address(LOG_INFO, options, &cur, NULL) >= 0) { + if (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 */ diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 8f19947600..90b707bcdb 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -3951,12 +3951,14 @@ trusted_dir_server_new(const char *nickname, const char *address, dir_server_t *result; if (!address) { /* The address is us; we should guess. */ - if (resolve_my_address(LOG_WARN, get_options(), &a, &hostname) < 0) { + if (resolve_my_address(LOG_WARN, get_options(), &a, NULL, &hostname) < 0) { log_warn(LD_CONFIG, "Couldn't find a suitable address when adding ourself as a " "trusted directory server."); return NULL; } + if (!hostname) + hostname = tor_dup_ip(a); } else { if (tor_lookup_hostname(address, &a)) { log_warn(LD_CONFIG, |