diff options
Diffstat (limited to 'src/or/circuitbuild.c')
-rw-r--r-- | src/or/circuitbuild.c | 153 |
1 files changed, 118 insertions, 35 deletions
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index ae25ac50e..a58c68d19 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -55,7 +55,6 @@ static int onion_extend_cpath(origin_circuit_t *circ); static int count_acceptable_routers(smartlist_t *routers); static int onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice); -static routerinfo_t *choose_random_entry(cpath_build_state_t *state); static void entry_guards_changed(void); /** Iterate over values of circ_id, starting from conn-\>next_circ_id, @@ -1581,10 +1580,10 @@ choose_good_middle_server(uint8_t purpose, /** Pick a good entry server for the circuit to be built according to * <b>state</b>. Don't reuse a chosen exit (if any), don't use this * router (if we're an OR), and respect firewall settings; if we're - * using entry_guards, return one. + * configured to use entry guards, return one. * - * If <b>state</b> is NULL, we're choosing routers to serve as entry - * nodes, not for any particular circuit. + * If <b>state</b> is NULL, we're choosing a router to serve as an entry + * guard, not for any particular circuit. */ static routerinfo_t * choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state) @@ -1721,49 +1720,62 @@ onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice) return 0; } +/** Allocate a new extend_info object based on the various arguments. */ +extend_info_t * +extend_info_alloc(const char *nickname, const char *digest, + crypto_pk_env_t *onion_key, + uint32_t addr, uint16_t port) +{ + extend_info_t *info = tor_malloc_zero(sizeof(extend_info_t)); + memcpy(info->identity_digest, digest, DIGEST_LEN); + if (nickname) + strlcpy(info->nickname, nickname, sizeof(info->nickname)); + else { + /* make one up */ + } + if (onion_key) + info->onion_key = crypto_pk_dup_key(onion_key); + info->addr = addr; + info->port = port; + return info; +} + /** Allocate and return a new extend_info_t that can be used to build a * circuit to or through the router <b>r</b>. */ extend_info_t * extend_info_from_router(routerinfo_t *r) { - extend_info_t *info; tor_assert(r); - info = tor_malloc_zero(sizeof(extend_info_t)); - strlcpy(info->nickname, r->nickname, sizeof(info->nickname)); - memcpy(info->identity_digest, r->cache_info.identity_digest, DIGEST_LEN); - info->onion_key = crypto_pk_dup_key(r->onion_pkey); - info->addr = r->addr; - info->port = r->or_port; - info->router_purpose = r->purpose; - return info; + return extend_info_alloc(r->nickname, r->cache_info.identity_digest, + r->onion_pkey, r->addr, r->or_port); } +#if 0 /** What router purpose is <b>digest</b>? * It's a general purpose router unless it's on our bridges list. */ static uint8_t get_router_purpose_from_digest(char *digest) { - (void)digest; - return ROUTER_PURPOSE_GENERAL; /* XXX020 */ + if (digest_is_a_bridge(digest)) + return ROUTER_PURPOSE_BRIDGE; + return ROUTER_PURPOSE_GENERAL; } +#endif +#if 0 /** Allocate and return a new extend_info_t that can be used to build a * circuit to or through the router <b>r</b>. */ extend_info_t * extend_info_from_routerstatus(routerstatus_t *s) { - extend_info_t *info; tor_assert(s); - info = tor_malloc_zero(sizeof(extend_info_t)); - strlcpy(info->nickname, s->nickname, sizeof(info->nickname)); - memcpy(info->identity_digest, s->identity_digest, DIGEST_LEN); - info->onion_key = NULL; /* routerstatus doesn't know this */ - info->addr = s->addr; - info->port = s->or_port; - info->router_purpose = get_router_purpose_from_digest(info->identity_digest); - return info; + /* routerstatus doesn't know onion_key; leave it NULL */ + return extend_info_alloc(s->nickname, s->identity_digest, + NULL, s->addr, s->or_port); +// get_router_purpose_from_digest(s->identity_digest)); } +#endif /** Release storage held by an extend_info_t struct. */ void @@ -1834,7 +1846,9 @@ entry_guard_set_status(entry_guard_t *e, routerinfo_t *ri, reason = "unlisted"; else if (!ri->is_running) reason = "down"; - else if (!ri->is_possible_guard && + else if (options->UseBridges && ri->purpose != ROUTER_PURPOSE_BRIDGE) + reason = "not a bridge"; + else if (!options->UseBridges && !ri->is_possible_guard && !router_nickname_is_in_list(ri, options->EntryNodes)) reason = "not recommended as a guard"; else if (router_nickname_is_in_list(ri, options->ExcludeNodes)) @@ -1909,6 +1923,10 @@ entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity, r = router_get_by_digest(e->identity); if (!r) return NULL; + if (get_options()->UseBridges && r->purpose != ROUTER_PURPOSE_BRIDGE) + return NULL; + if (!get_options()->UseBridges && r->purpose != ROUTER_PURPOSE_GENERAL) + return NULL; if (router_is_unreliable(r, need_uptime, need_capacity, 0)) return NULL; if (firewall_is_fascist_or() && @@ -2337,18 +2355,33 @@ entry_guards_prepend_from_config(void) entry_guards_changed(); } -/** Pick a live (up and listed) entry guard from entry_guards, and - * make sure not to pick this circuit's exit. */ -static routerinfo_t * +/** Return 1 if we're fine adding arbitrary routers out of the + * directory to our entry guard list. Else return 0. */ +static int +can_grow_entry_list(or_options_t *options) +{ + if (options->StrictEntryNodes) + return 0; + if (options->UseBridges) + return 0; + return 1; +} + +/** Pick a live (up and listed) entry guard from entry_guards. If + * <b>state</b> is non-NULL, this is for a specific circuit -- + * make sure not to pick this circuit's exit or any node in the + * exit's family. If <b>state</b> is NULL, we're looking for a random + * guard (likely a bridge). */ +routerinfo_t * choose_random_entry(cpath_build_state_t *state) { or_options_t *options = get_options(); smartlist_t *live_entry_guards = smartlist_create(); smartlist_t *exit_family = smartlist_create(); - routerinfo_t *chosen_exit = build_state_get_exit_router(state); + routerinfo_t *chosen_exit = state?build_state_get_exit_router(state) : NULL; routerinfo_t *r = NULL; - int need_uptime = state->need_uptime; - int need_capacity = state->need_capacity; + int need_uptime = state ? state->need_uptime : 0; + int need_capacity = state ? state->need_capacity : 0; if (chosen_exit) { smartlist_add(exit_family, chosen_exit); @@ -2361,7 +2394,7 @@ choose_random_entry(cpath_build_state_t *state) if (should_add_entry_nodes) entry_guards_prepend_from_config(); - if (!options->StrictEntryNodes && + if (can_grow_entry_list(options) && (! entry_guards || smartlist_len(entry_guards) < options->NumEntryGuards)) pick_entry_guards(); @@ -2383,7 +2416,7 @@ choose_random_entry(cpath_build_state_t *state) * using him. * (We might get 2 live-but-crummy entry guards, but so be it.) */ if (smartlist_len(live_entry_guards) < 2) { - if (!options->StrictEntryNodes) { + if (can_grow_entry_list(options)) { /* still no? try adding a new entry then */ /* XXX if guard doesn't imply fast and stable, then we need * to tell add_an_entry_guard below what we want, or it might @@ -2403,7 +2436,7 @@ choose_random_entry(cpath_build_state_t *state) need_capacity = 0; goto retry; } - /* live_entry_guards will be empty below. Oh well, we tried. */ + /* live_entry_guards may be empty below. Oh well, we tried. */ } r = smartlist_choose(live_entry_guards); @@ -2641,6 +2674,18 @@ clear_bridge_list(void) smartlist_clear(bridge_list); } +/** Return 1 if <b>digest</b> is one of our known bridges. */ +int +identity_digest_is_a_bridge(const char *digest) +{ + SMARTLIST_FOREACH(bridge_list, bridge_info_t *, bridge, + { + if (!memcmp(bridge->identity, digest, DIGEST_LEN)) + return 1; + }); + return 0; +} + /** Remember a new bridge at <b>addr</b>:<b>port</b>. If <b>digest</b> * is set, it tells us the identity key too. */ void @@ -2660,7 +2705,7 @@ bridge_add_from_config(uint32_t addr, uint16_t port, char *digest) * descriptor, fetch a new copy of its descriptor -- either directly * from the bridge or via a bridge authority. */ void -learn_bridge_descriptors(void) +fetch_bridge_descriptors(void) { char address_buf[INET_NTOA_BUF_LEN+1]; struct in_addr in; @@ -2698,3 +2743,41 @@ learn_bridge_descriptors(void) }); } +/** We just learned a descriptor for a bridge. See if that + * digest is in our entry guard list, and add it if not. */ +void +learned_bridge_descriptor(routerinfo_t *ri) +{ + tor_assert(ri); + tor_assert(ri->purpose == ROUTER_PURPOSE_BRIDGE); + if (get_options()->UseBridges) { + ri->is_running = 1; + add_an_entry_guard(ri); + log_notice(LD_DIR, "new bridge descriptor '%s'", ri->nickname); + } +} + +/** Return 1 if any of our entry guards have descriptors that + * are marked with purpose 'bridge'. Else return 0. + * + * We use this function to decide if we're ready to start building + * circuits through our bridges, or if we need to wait until the + * directory "server/authority" requests finish. */ +int +any_bridge_descriptors_known(void) +{ + return choose_random_entry(NULL)!=NULL ? 1 : 0; +#if 0 + routerinfo_t *ri; + if (!entry_guards) + entry_guards = smartlist_create(); + SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e, + { + ri = router_get_by_digest(e->identity); + if (ri && ri->purpose == ROUTER_PURPOSE_BRIDGE) + return 1; + }); + return 0; +#endif +} + |