|  | @@ -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.");
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 |