diff options
author | Roger Dingledine <arma@torproject.org> | 2006-07-17 06:35:06 +0000 |
---|---|---|
committer | Roger Dingledine <arma@torproject.org> | 2006-07-17 06:35:06 +0000 |
commit | 9db7b2c0687a3ee28e96e0c0db6c2a3e7ef4c626 (patch) | |
tree | 08ce2b504d2a41655d2945304b3474733cad6b20 /src/or/router.c | |
parent | 8868830ac5730e455bbc727893b2234b5f1f33fe (diff) | |
download | tor-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.c | 98 |
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 |