aboutsummaryrefslogtreecommitdiff
path: root/src/or/config.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/config.c')
-rw-r--r--src/or/config.c107
1 files changed, 80 insertions, 27 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.");
}