mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
More work towards making bridge users able to connect via bridges:
- demand options->Bridges and options->TunnelDirConns if options->UseBridges is set. - after directory fetches, accept descriptors that aren't referenced by our networkstatuses, *if* they're for a configured bridge. - delay directory fetching until we have at least one bridge descriptor. - learn how to build a one-hop circuit when we have neither routerinfo nor routerstatus for our destination. - teach directory connections how to pick a bridge as the destination directory when doing non-anonymous fetches. - tolerate directory commands for which the dir_port is 0. - remember descriptors when the requested_resource was "authority", rather than just ignoring them. - put bridges on our entry_guards list once we have a descriptor for them. When UseBridges is set, only pick entry guards that are bridges. Else vice versa. svn:r10571
This commit is contained in:
parent
622dd4927e
commit
af658b7828
11
doc/TODO
11
doc/TODO
@ -219,10 +219,19 @@ Things we'd like to do in 0.2.0.x:
|
||||
D Do we want to maintain our own set of entryguards that we use
|
||||
after the bridge? Open research question; let's say no for 0.2.0
|
||||
unless we learn otherwise.
|
||||
- Ask all directory questions to bridge via BEGIN_DIR.
|
||||
o if you don't have any routerinfos for your bridges, or you don't
|
||||
like the ones you have, ask a new bridge for its server/authority.
|
||||
. Ask all directory questions to bridge via BEGIN_DIR.
|
||||
- use the bridges for dir fetches even when our dirport is open.
|
||||
N - Design/implement the "local-status" or something like it, from the
|
||||
"Descriptor purposes: how to tell them apart" section of
|
||||
http://archives.seul.org/or/dev/May-2007/msg00008.html
|
||||
- timeout and retry schedules for fetching bridge descriptors
|
||||
- give extend_info_t a router_purpose again
|
||||
- react faster to download networkstatuses after the first bridge
|
||||
descriptor arrives
|
||||
- be more robust to bridges being marked as down and leaving us
|
||||
stranded without any known "running" bridges.
|
||||
- Bridges operators (rudimentary version)
|
||||
- Ability to act as dir cache without a dir port.
|
||||
o Bridges publish to bridge authorities
|
||||
|
@ -192,14 +192,13 @@ $Id$
|
||||
corresponding roughly to "status votes" above. They would compute the
|
||||
result of the vote on the client side.
|
||||
|
||||
Authorities used sign documents using the same private keys they used
|
||||
Authorities used to sign documents using the same private keys they used
|
||||
for their roles as routers. This forced them to keep these extremely
|
||||
sensitive keys in memory unencrypted.
|
||||
|
||||
All of the information in extra-info documents used to be kept in the
|
||||
main descriptors.
|
||||
|
||||
|
||||
1.2. Document meta-format
|
||||
|
||||
Router descriptors, directories, and running-routers documents all obey the
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -1034,18 +1034,22 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
|
||||
want_onehop, conn->chosen_exit_name);
|
||||
if (want_onehop && conn->chosen_exit_name[0] == '$') {
|
||||
/* We're asking for a one-hop circuit to a router that
|
||||
* we don't have a routerinfo about. Hope we have a
|
||||
* routerstatus or equivalent. */
|
||||
routerstatus_t *s =
|
||||
routerstatus_get_by_hexdigest(conn->chosen_exit_name+1);
|
||||
if (s) {
|
||||
extend_info = extend_info_from_routerstatus(s);
|
||||
} else {
|
||||
log_warn(LD_APP,
|
||||
"Requested router '%s' is not known. Closing.",
|
||||
conn->chosen_exit_name);
|
||||
* we don't have a routerinfo about. Make up an extend_info. */
|
||||
char digest[DIGEST_LEN];
|
||||
char *hexdigest = conn->chosen_exit_name+1;
|
||||
struct in_addr in;
|
||||
if (strlen(hexdigest) < HEX_DIGEST_LEN ||
|
||||
base16_decode(digest,DIGEST_LEN,hexdigest,HEX_DIGEST_LEN)<0) {
|
||||
log_info(LD_DIR, "Broken exit digest on tunnel conn. Closing.");
|
||||
return -1;
|
||||
}
|
||||
if (!tor_inet_aton(conn->socks_request->address, &in)) {
|
||||
log_info(LD_DIR, "Broken address on tunnel conn. Closing.");
|
||||
return -1;
|
||||
}
|
||||
extend_info = extend_info_alloc(conn->chosen_exit_name+1,
|
||||
digest, NULL, ntohl(in.s_addr),
|
||||
conn->socks_request->port);
|
||||
} else {
|
||||
/* We will need an onion key for the router, and we
|
||||
* don't have one. Refuse or relax requirements. */
|
||||
|
@ -2914,6 +2914,10 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
||||
}
|
||||
}
|
||||
|
||||
if (options->UseBridges && !options->Bridges)
|
||||
REJECT("If you set UseBridges, you must specify at least one bridge.");
|
||||
if (options->UseBridges && !options->TunnelDirConns)
|
||||
REJECT("If you set UseBridges, you must set TunnelDirConns.");
|
||||
if (options->Bridges) {
|
||||
for (cl = options->Bridges; cl; cl = cl->next) {
|
||||
if (parse_bridge_line(cl->value, 1)<0)
|
||||
|
@ -230,7 +230,21 @@ directory_get_from_dirserver(uint8_t dir_purpose, const char *resource,
|
||||
if (!options->FetchServerDescriptors && type != HIDSERV_AUTHORITY)
|
||||
return;
|
||||
|
||||
if (directconn) {
|
||||
if (directconn && options->UseBridges) {
|
||||
/* want to pick a bridge for which we have a descriptor. */
|
||||
routerinfo_t *ri = choose_random_entry(NULL);
|
||||
if (ri) {
|
||||
directory_initiate_command(ri->address, ri->addr,
|
||||
ri->or_port, 0,
|
||||
1, ri->cache_info.identity_digest,
|
||||
dir_purpose,
|
||||
ROUTER_PURPOSE_GENERAL,
|
||||
0, resource, NULL, 0);
|
||||
} else
|
||||
log_notice(LD_DIR, "Ignoring directory request, since no bridge "
|
||||
"nodes are available yet.");
|
||||
return;
|
||||
} else if (directconn) {
|
||||
if (prefer_authority) {
|
||||
/* only ask authdirservers, and don't ask myself */
|
||||
rs = router_pick_trusteddirserver(type, 1, 1,
|
||||
@ -259,8 +273,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, const char *resource,
|
||||
directconn = 0; /* last resort: try routing it via Tor */
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!directconn) {
|
||||
} else { /* !directconn */
|
||||
/* Never use fascistfirewall; we're going via Tor. */
|
||||
if (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) {
|
||||
/* only ask hidserv authorities, any of them will do */
|
||||
@ -463,7 +476,7 @@ directory_initiate_command(const char *address, uint32_t addr,
|
||||
|
||||
tor_assert(address);
|
||||
tor_assert(addr);
|
||||
tor_assert(dir_port);
|
||||
tor_assert(or_port || dir_port);
|
||||
tor_assert(digest);
|
||||
|
||||
log_debug(LD_DIR, "anonymized %d, want_to_tunnel %d.",
|
||||
@ -1221,7 +1234,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
|
||||
smartlist_t *which = NULL;
|
||||
int n_asked_for = 0;
|
||||
log_info(LD_DIR,"Received %s (size %d) from server '%s:%d'",
|
||||
was_ei ? "server info" : "extra server info",
|
||||
was_ei ? "extra server info" : "server info",
|
||||
(int)body_len, conn->_base.address, conn->_base.port);
|
||||
if (was_ei)
|
||||
note_request(was_compressed?"dl/extra.z":"dl/extra", orig_len);
|
||||
@ -1255,13 +1268,15 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
|
||||
tor_free(body); tor_free(headers); tor_free(reason);
|
||||
return dir_okay ? 0 : -1;
|
||||
}
|
||||
/* Learn the routers, assuming we requested by fingerprint or "all".
|
||||
* Right now, we only use "authority" to fetch ourself, so we don't want
|
||||
* to risk replacing ourself with a router running at the addr:port we
|
||||
* think we have.
|
||||
/* Learn the routers, assuming we requested by fingerprint or "all"
|
||||
* or "authority". (We use "authority" to fetch our own descriptor for
|
||||
* testing, and to fetch bridge descriptors for bootstrapping.)
|
||||
*/
|
||||
/* XXX020 We now risk replacing ourself with a router running at
|
||||
* the addr:port we think we have. Might want to check more carefully. */
|
||||
if (which || (conn->requested_resource &&
|
||||
!strcmpstart(conn->requested_resource, "all"))) {
|
||||
(!strcmpstart(conn->requested_resource, "all") ||
|
||||
!strcmpstart(conn->requested_resource, "authority")))) {
|
||||
/* as we learn from them, we remove them from 'which' */
|
||||
if (was_ei) {
|
||||
router_load_extrainfo_from_string(body, NULL, SAVED_NOWHERE, which);
|
||||
|
@ -884,6 +884,8 @@ run_scheduled_events(time_t now)
|
||||
|
||||
if (time_to_reset_descriptor_failures < now) {
|
||||
router_reset_descriptor_download_failures();
|
||||
if (options->UseBridges)
|
||||
fetch_bridge_descriptors(); /* XXX get this its own retry schedule -RD */
|
||||
time_to_reset_descriptor_failures =
|
||||
now + DESCRIPTOR_FAILURE_RESET_INTERVAL;
|
||||
}
|
||||
@ -951,6 +953,7 @@ run_scheduled_events(time_t now)
|
||||
* and the rend cache. */
|
||||
rep_history_clean(now - options->RephistTrackTime);
|
||||
rend_cache_clean();
|
||||
/* XXX020 we only clean this stuff if DirPort is set?! -RD */
|
||||
}
|
||||
|
||||
/* 2b. Once per minute, regenerate and upload the descriptor if the old
|
||||
|
18
src/or/or.h
18
src/or/or.h
@ -1384,7 +1384,7 @@ typedef struct extend_info_t {
|
||||
* display. */
|
||||
char identity_digest[DIGEST_LEN]; /**< Hash of this router's identity key. */
|
||||
uint16_t port; /**< OR port. */
|
||||
uint8_t router_purpose; /**< General, controller, or bridge. */
|
||||
// uint8_t router_purpose; /**< General, controller, or bridge. */
|
||||
uint32_t addr; /**< IP address in host order. */
|
||||
crypto_pk_env_t *onion_key; /**< Current onionskin key. */
|
||||
} extend_info_t;
|
||||
@ -2200,8 +2200,11 @@ int circuit_all_predicted_ports_handled(time_t now, int *need_uptime,
|
||||
int circuit_append_new_exit(origin_circuit_t *circ, extend_info_t *info);
|
||||
int circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *info);
|
||||
void onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop);
|
||||
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 *extend_info_from_router(routerinfo_t *r);
|
||||
extend_info_t *extend_info_from_routerstatus(routerstatus_t *s);
|
||||
//extend_info_t *extend_info_from_routerstatus(routerstatus_t *s);
|
||||
extend_info_t *extend_info_dup(extend_info_t *info);
|
||||
void extend_info_free(extend_info_t *info);
|
||||
routerinfo_t *build_state_get_exit_router(cpath_build_state_t *state);
|
||||
@ -2211,15 +2214,19 @@ void entry_guards_compute_status(void);
|
||||
int entry_guard_register_connect_status(const char *digest, int succeeded,
|
||||
time_t now);
|
||||
void entry_nodes_should_be_added(void);
|
||||
void entry_guards_update_state(or_state_t *state);
|
||||
routerinfo_t *choose_random_entry(cpath_build_state_t *state);
|
||||
int entry_guards_parse_state(or_state_t *state, int set, char **msg);
|
||||
void entry_guards_update_state(or_state_t *state);
|
||||
int getinfo_helper_entry_guards(control_connection_t *conn,
|
||||
const char *question, char **answer);
|
||||
void entry_guards_free_all(void);
|
||||
|
||||
void clear_bridge_list(void);
|
||||
int identity_digest_is_a_bridge(const char *digest);
|
||||
void bridge_add_from_config(uint32_t addr, uint16_t port, char *digest);
|
||||
void learn_bridge_descriptors(void);
|
||||
void fetch_bridge_descriptors(void);
|
||||
void learned_bridge_descriptor(routerinfo_t *ri);
|
||||
int any_bridge_descriptors_known(void);
|
||||
|
||||
/********************************* circuitlist.c ***********************/
|
||||
|
||||
@ -3315,7 +3322,8 @@ local_routerstatus_t *router_get_combined_status_by_digest(const char *digest);
|
||||
local_routerstatus_t *router_get_combined_status_by_descriptor_digest(
|
||||
const char *digest);
|
||||
|
||||
routerstatus_t *routerstatus_get_by_hexdigest(const char *hexdigest);
|
||||
//routerstatus_t *routerstatus_get_by_hexdigest(const char *hexdigest);
|
||||
int should_delay_dir_fetches(or_options_t *options);
|
||||
void update_networkstatus_downloads(time_t now);
|
||||
void update_router_descriptor_downloads(time_t now);
|
||||
void update_extrainfo_downloads(time_t now);
|
||||
|
@ -2340,7 +2340,7 @@ router_set_status(const char *digest, int up)
|
||||
*
|
||||
* This function should be called *after*
|
||||
* routers_update_status_from_networkstatus; subsequently, you should call
|
||||
* router_rebuild_store and control_event_descriptors_changed.
|
||||
* router_rebuild_store and routerlist_descriptors_added.
|
||||
*/
|
||||
int
|
||||
router_add_to_routerlist(routerinfo_t *router, const char **msg,
|
||||
@ -2387,7 +2387,8 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
|
||||
/* Only check the descriptor digest against the network statuses when
|
||||
* we are receiving in response to a fetch. */
|
||||
|
||||
if (!signed_desc_digest_is_recognized(&router->cache_info)) {
|
||||
if (!signed_desc_digest_is_recognized(&router->cache_info) &&
|
||||
!identity_digest_is_a_bridge(router->cache_info.identity_digest)) {
|
||||
/* We asked for it, so some networkstatus must have listed it when we
|
||||
* did. Save it if we're a cache in case somebody else asks for it. */
|
||||
log_info(LD_DIR,
|
||||
@ -2725,6 +2726,19 @@ routerlist_remove_old_routers(void)
|
||||
digestmap_free(retain, NULL);
|
||||
}
|
||||
|
||||
/** We just added a new descriptor that isn't of purpose
|
||||
* ROUTER_PURPOSE_GENERAL. Take whatever extra steps we need. */
|
||||
static void
|
||||
routerlist_descriptors_added(smartlist_t *sl)
|
||||
{
|
||||
tor_assert(sl);
|
||||
control_event_descriptors_changed(sl);
|
||||
SMARTLIST_FOREACH(sl, routerinfo_t *, ri,
|
||||
if (ri->purpose == ROUTER_PURPOSE_BRIDGE)
|
||||
learned_bridge_descriptor(ri);
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Code to parse a single router descriptor and insert it into the
|
||||
* routerlist. Return -1 if the descriptor was ill-formed; 0 if the
|
||||
@ -2753,7 +2767,7 @@ router_load_single_router(const char *s, uint8_t purpose, const char **msg)
|
||||
return -1;
|
||||
}
|
||||
ri->purpose = purpose;
|
||||
if (purpose != ROUTER_PURPOSE_GENERAL)
|
||||
if (ri->purpose != ROUTER_PURPOSE_GENERAL)
|
||||
ri->cache_info.do_not_cache = 1;
|
||||
if (router_is_me(ri)) {
|
||||
log_warn(LD_DIR, "Router's identity key matches mine; dropping.");
|
||||
@ -2774,7 +2788,7 @@ router_load_single_router(const char *s, uint8_t purpose, const char **msg)
|
||||
smartlist_free(lst);
|
||||
return 0;
|
||||
} else {
|
||||
control_event_descriptors_changed(lst);
|
||||
routerlist_descriptors_added(lst);
|
||||
smartlist_free(lst);
|
||||
log_debug(LD_DIR, "Added router to list");
|
||||
return 1;
|
||||
@ -2837,7 +2851,7 @@ router_load_routers_from_string(const char *s, const char *eos,
|
||||
});
|
||||
|
||||
if (smartlist_len(changed))
|
||||
control_event_descriptors_changed(changed);
|
||||
routerlist_descriptors_added(changed);
|
||||
|
||||
routerlist_assert_ok(routerlist);
|
||||
router_rebuild_store(0, 0);
|
||||
@ -3272,6 +3286,7 @@ router_get_combined_status_by_nickname(const char *nickname,
|
||||
return best;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/** Find a routerstatus_t that corresponds to <b>hexdigest</b>, if
|
||||
* any. Prefer ones that belong to authorities. */
|
||||
routerstatus_t *
|
||||
@ -3290,6 +3305,7 @@ routerstatus_get_by_hexdigest(const char *hexdigest)
|
||||
return &(rs->status);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Return true iff any networkstatus includes a descriptor whose digest
|
||||
* is that of <b>desc</b>. */
|
||||
@ -3503,11 +3519,26 @@ update_networkstatus_client_downloads(time_t now)
|
||||
smartlist_free(missing);
|
||||
}
|
||||
|
||||
/** Return 1 if there's a reason we shouldn't try any directory
|
||||
* fetches yet (e.g. we demand bridges and none are yet known).
|
||||
* Else return 0. */
|
||||
int
|
||||
should_delay_dir_fetches(or_options_t *options)
|
||||
{
|
||||
if (options->UseBridges && !any_bridge_descriptors_known()) {
|
||||
log_notice(LD_DIR, "delaying dir fetches");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Launch requests for networkstatus documents as appropriate. */
|
||||
void
|
||||
update_networkstatus_downloads(time_t now)
|
||||
{
|
||||
or_options_t *options = get_options();
|
||||
if (should_delay_dir_fetches(options))
|
||||
return;
|
||||
if (options->DirPort)
|
||||
update_networkstatus_cache_downloads(now);
|
||||
else
|
||||
@ -4729,6 +4760,8 @@ void
|
||||
update_router_descriptor_downloads(time_t now)
|
||||
{
|
||||
or_options_t *options = get_options();
|
||||
if (should_delay_dir_fetches(options))
|
||||
return;
|
||||
if (options->DirPort) {
|
||||
update_router_descriptor_cache_downloads(now);
|
||||
} else {
|
||||
@ -4753,7 +4786,7 @@ should_download_extrainfo(signed_descriptor_t *sd,
|
||||
!digestmap_get(pending, d));
|
||||
}
|
||||
|
||||
/** Laucnch extrainfo downloads as needed. */
|
||||
/** Launch extrainfo downloads as needed. */
|
||||
void
|
||||
update_extrainfo_downloads(time_t now)
|
||||
{
|
||||
@ -4764,6 +4797,8 @@ update_extrainfo_downloads(time_t now)
|
||||
int i;
|
||||
if (! options->DownloadExtraInfo)
|
||||
return;
|
||||
if (should_delay_dir_fetches(options))
|
||||
return;
|
||||
|
||||
pending = digestmap_new();
|
||||
list_pending_descriptor_downloads(pending, 1);
|
||||
@ -4853,6 +4888,12 @@ update_router_have_minimum_dir_info(void)
|
||||
routerlist_remove_old_routers();
|
||||
networkstatus_list_clean(now);
|
||||
|
||||
if (should_delay_dir_fetches(get_options())) {
|
||||
log_notice(LD_DIR, "no bridge descs known yet");
|
||||
res = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
n_authorities = get_n_v2_authorities();
|
||||
n_ns = smartlist_len(networkstatus_list);
|
||||
if (n_ns<=n_authorities/2) {
|
||||
|
Loading…
Reference in New Issue
Block a user