diff --git a/src/app/config/resolve_addr.c b/src/app/config/resolve_addr.c index 34b33e2887..798c703f0a 100644 --- a/src/app/config/resolve_addr.c +++ b/src/app/config/resolve_addr.c @@ -651,6 +651,7 @@ find_my_address(const or_options_t *options, int family, int warn_severity, tor_assert(addr_out); /* Set them to NULL for safety reasons. */ + tor_addr_make_unspec(addr_out); if (method_out) *method_out = NULL; if (hostname_out) *hostname_out = NULL; diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c index 97a77f9578..4a0a4203aa 100644 --- a/src/feature/relay/router.c +++ b/src/feature/relay/router.c @@ -2589,51 +2589,59 @@ log_addr_has_changed(int severity, addrbuf_cur, source); } -/** Check whether our own address as defined by the Address configuration - * has changed. This is for routers that get their address from a service - * like dyndns. If our address has changed, mark our descriptor dirty. */ +/** Check whether our own address has changed versus the one we have in our + * current descriptor. + * + * If our address has changed, call ip_address_changed() which takes + * appropriate actions. */ void check_descriptor_ipaddress_changed(time_t now) { - uint32_t prev, cur; - tor_addr_t addr; - const or_options_t *options = get_options(); + const routerinfo_t *my_ri = router_get_my_routerinfo(); const char *method = NULL; char *hostname = NULL; - const routerinfo_t *my_ri = router_get_my_routerinfo(); + int families[2] = { AF_INET, AF_INET6 }; + bool has_changed = false; (void) now; - if (my_ri == NULL) /* make sure routerinfo exists */ - return; - - /* XXXX ipv6 */ - prev = tor_addr_to_ipv4h(&my_ri->ipv4_addr); - if (!find_my_address(options, AF_INET, LOG_INFO, &addr, &method, - &hostname)) { - log_info(LD_CONFIG,"options->Address didn't resolve into an IP."); + /* We can't learn our descriptor address without one. */ + if (my_ri == NULL) { return; } - cur = tor_addr_to_ipv4h(&addr); - if (prev != cur) { - char *source; - tor_addr_t tmp_prev, tmp_cur; + for (size_t i = 0; i < ARRAY_LENGTH(families); i++) { + tor_addr_t current; + const tor_addr_t *previous; + int family = families[i]; - tor_addr_from_ipv4h(&tmp_prev, prev); - tor_addr_from_ipv4h(&tmp_cur, cur); + /* Get the descriptor address from the family we are looking up. */ + previous = &my_ri->ipv4_addr; + if (family == AF_INET6) { + previous = &my_ri->ipv6_addr; + } - tor_asprintf(&source, "METHOD=%s%s%s", method, - hostname ? " HOSTNAME=" : "", - hostname ? hostname : ""); + /* Ignore returned value because we want to notice not only an address + * change but also if an address is lost (current == UNSPEC). */ + find_my_address(get_options(), family, LOG_INFO, ¤t, &method, + &hostname); - log_addr_has_changed(LOG_NOTICE, &tmp_prev, &tmp_cur, source); - tor_free(source); + if (!tor_addr_eq(previous, ¤t)) { + char *source; + tor_asprintf(&source, "METHOD=%s%s%s", + method ? method : "UNKNOWN", + hostname ? " HOSTNAME=" : "", + hostname ? hostname : ""); + log_addr_has_changed(LOG_NOTICE, previous, ¤t, source); + tor_free(source); + has_changed = true; + } + tor_free(hostname); + } + if (has_changed) { ip_address_changed(0); } - - tor_free(hostname); } /** Set platform (max length len) to a NUL-terminated short