summaryrefslogtreecommitdiff
path: root/src/or/router.c
diff options
context:
space:
mode:
authorRoger Dingledine <arma@torproject.org>2006-07-17 06:35:06 +0000
committerRoger Dingledine <arma@torproject.org>2006-07-17 06:35:06 +0000
commit9db7b2c0687a3ee28e96e0c0db6c2a3e7ef4c626 (patch)
tree08ce2b504d2a41655d2945304b3474733cad6b20 /src/or/router.c
parent8868830ac5730e455bbc727893b2234b5f1f33fe (diff)
downloadtor-9db7b2c0687a3ee28e96e0c0db6c2a3e7ef4c626.tar.gz
tor-9db7b2c0687a3ee28e96e0c0db6c2a3e7ef4c626.zip
Allow servers with no hostname or IP address to learn their IP address
by asking the directory authorities. This code only kicks in when you would normally have exited with a "no address" error. This design is flawed, though, since the X-Your-Address-Is header is not authenticated, and doing it this way introduces too many new attacks. The right answer is to give IP address hints inside the HELLO cell; much of this code can be reused when we switch. svn:r6774
Diffstat (limited to 'src/or/router.c')
-rw-r--r--src/or/router.c98
1 files changed, 79 insertions, 19 deletions
diff --git a/src/or/router.c b/src/or/router.c
index 9f7913cf65..0e577a8031 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -736,9 +736,11 @@ router_get_my_descriptor(void)
/*DOCDOC*/
static smartlist_t *warned_nonexistent_family = NULL;
+static int router_guess_address_from_dir_headers(uint32_t *guess);
+
/** If <b>force</b> is true, or our descriptor is out-of-date, rebuild
* a fresh routerinfo and signed server descriptor for this OR.
- * Return 0 on success, -1 on error.
+ * Return 0 on success, -1 on temporary error.
*/
int
router_rebuild_descriptor(int force)
@@ -752,9 +754,14 @@ router_rebuild_descriptor(int force)
if (desc_clean_since && !force)
return 0;
- if (resolve_my_address(LOG_WARN, options, &addr, NULL) < 0) {
- log_warn(LD_CONFIG,"options->Address didn't resolve into an IP.");
- return -1;
+ if (resolve_my_address(LOG_INFO, options, &addr, 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) {
+ log_info(LD_CONFIG, "No hints from directory headers either. "
+ "Will try again later.");
+ return -1;
+ }
}
ri = tor_malloc_zero(sizeof(routerinfo_t));
@@ -894,6 +901,26 @@ check_descriptor_bandwidth_changed(time_t now)
}
}
+static void
+log_addr_has_changed(uint32_t prev, uint32_t cur)
+{
+ char addrbuf_prev[INET_NTOA_BUF_LEN];
+ char addrbuf_cur[INET_NTOA_BUF_LEN];
+ struct in_addr in_prev;
+ struct in_addr in_cur;
+
+ in_prev.s_addr = htonl(prev);
+ tor_inet_ntoa(&in_prev, addrbuf_prev, sizeof(addrbuf_prev));
+
+ in_cur.s_addr = htonl(cur);
+ tor_inet_ntoa(&in_cur, addrbuf_cur, sizeof(addrbuf_cur));
+
+ log_info(LD_GENERAL,
+ "Our IP Address has changed from %s to %s; "
+ "rebuilding descriptor.",
+ addrbuf_prev, addrbuf_cur);
+}
+
/** 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. */
@@ -908,29 +935,62 @@ check_descriptor_ipaddress_changed(time_t now)
return;
prev = desc_routerinfo->addr;
- if (resolve_my_address(LOG_WARN, options, &cur, NULL) < 0) {
- log_warn(LD_CONFIG,"options->Address didn't resolve into an IP.");
+ if (resolve_my_address(LOG_INFO, options, &cur, NULL) < 0) {
+ log_info(LD_CONFIG,"options->Address didn't resolve into an IP.");
return;
}
if (prev != cur) {
- char addrbuf_prev[INET_NTOA_BUF_LEN];
- char addrbuf_cur[INET_NTOA_BUF_LEN];
- struct in_addr in_prev;
- struct in_addr in_cur;
+ log_addr_has_changed(prev, cur);
+ mark_my_descriptor_dirty();
+ /* the above call is probably redundant, since resolve_my_address()
+ * probably already noticed and marked it dirty. */
+ }
+}
+
+static uint32_t last_guessed_ip = 0;
- in_prev.s_addr = htonl(prev);
- tor_inet_ntoa(&in_prev, addrbuf_prev, sizeof(addrbuf_prev));
+/** A directory authority 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)
+{
+ uint32_t addr, cur;
+ struct in_addr in;
- in_cur.s_addr = htonl(cur);
- tor_inet_ntoa(&in_cur, addrbuf_cur, sizeof(addrbuf_cur));
+ /* first, learn what the IP address actually is */
+ if (!tor_inet_aton(suggestion, &in)) {
+ log_debug(LD_DIR, "Malformed X-Your-Address-Is header. Ignoring.");
+ return;
+ }
+ addr = ntohl(in.s_addr);
- log_info(LD_GENERAL,
- "Our IP Address has changed from %s to %s; "
- "rebuilding descriptor.",
- addrbuf_prev, addrbuf_cur);
- mark_my_descriptor_dirty();
+ if (resolve_my_address(LOG_INFO, get_options(), &cur, NULL) >= 0) {
+ /* We're all set -- we already know our address. Great. */
+ last_guessed_ip = cur; /* store it in case we need it later */
+ return;
+ }
+
+ if (last_guessed_ip != addr) {
+ log_addr_has_changed(last_guessed_ip, addr);
+ server_has_changed_ip();
+ 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 (last_guessed_ip) {
+ *guess = last_guessed_ip;
+ return 0;
}
+ return -1;
}
/** Set <b>platform</b> (max length <b>len</b>) to a NUL-terminated short