handle fetching bridge descriptors from the bridge authority too.

svn:r10898
This commit is contained in:
Roger Dingledine 2007-07-22 00:16:48 +00:00
parent 56d3119581
commit 6fc336d217
8 changed files with 84 additions and 57 deletions

View File

@ -1583,8 +1583,7 @@ choose_good_middle_server(uint8_t purpose,
options->ExcludeNodes, excluded,
state->need_uptime, state->need_capacity, 0,
options->_AllowInvalid & ALLOW_INVALID_MIDDLE, 0, 0);
if (preferred)
tor_free(preferred);
tor_free(preferred);
smartlist_free(excluded);
return choice;
}
@ -1885,8 +1884,8 @@ entry_guard_set_status(entry_guard_t *e, routerinfo_t *ri,
return changed;
}
/** Return true iff enough time has passed since we last tried connect to the
* unreachable guard <b>e</b> that we're willing to try again. */
/** Return true iff enough time has passed since we last tried to connect
* to the unreachable guard <b>e</b> that we're willing to try again. */
static int
entry_is_time_to_retry(entry_guard_t *e, time_t now)
{
@ -1913,7 +1912,7 @@ entry_is_time_to_retry(entry_guard_t *e, time_t now)
* if demanded by <b>need_uptime</b> or <b>need_capacity</b>;
* (This check is currently redundant with the Guard flag, but in
* the future that might change. Best to leave it in for now.)
* - Allowed by our current ReachableAddresses config option; and
* - Allowed by our current ReachableORAddresses config option; and
* - Currently thought to be reachable by us (unless assume_reachable
* is true).
*/
@ -1937,8 +1936,7 @@ entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity,
return NULL;
if (router_is_unreliable(r, need_uptime, need_capacity, 0))
return NULL;
if (firewall_is_fascist_or() &&
!fascist_firewall_allows_address_or(r->addr,r->or_port))
if (!fascist_firewall_allows_address_or(r->addr,r->or_port))
return NULL;
return r;
}
@ -2778,10 +2776,10 @@ fetch_bridge_descriptors(time_t now)
SMARTLIST_FOREACH(bridge_list, bridge_info_t *, bridge,
{
if (bridge->fetch_status.next_attempt_at >= now)
if (bridge->fetch_status.next_attempt_at > now)
continue; /* don't bother, no need to retry yet */
/* schedule another fetch as if this one failed, in case it does */
/* schedule another fetch as if this one will fail, in case it does */
bridge_fetch_status_increment(bridge, now);
in.s_addr = htonl(bridge->addr);
@ -2813,8 +2811,18 @@ fetch_bridge_descriptors(time_t now)
0, "authority.z", NULL, 0);
}
} else {
/* we have a digest and we want to ask an authority. */
// XXX
/* We have a digest and we want to ask an authority. We could
* combine all the requests into one, but that may give more
* hints to the bridge authority than we want to give. */
char resource[10 + HEX_DIGEST_LEN];
memcpy(resource, "fp/", 3);
base16_encode(resource+3, HEX_DIGEST_LEN+1,
bridge->identity, DIGEST_LEN);
memcpy(resource+3+HEX_DIGEST_LEN, ".z", 3);
log_info(LD_DIR, "Fetching bridge info '%s' from bridge authority.",
resource);
directory_get_from_dirserver(DIR_PURPOSE_FETCH_SERVERDESC,
ROUTER_PURPOSE_BRIDGE, resource, 1);
}
});
}

View File

@ -36,7 +36,7 @@ directory_send_command(dir_connection_t *conn,
const char *payload, size_t payload_len);
static int directory_handle_command(dir_connection_t *conn);
static int body_is_plausible(const char *body, size_t body_len, int purpose);
static int purpose_needs_anonymity(uint8_t purpose);
static int purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose);
static char *http_get_header(const char *headers, const char *which);
static void http_set_address_origin(const char *headers, connection_t *conn);
static void connection_dir_download_networkstatus_failed(
@ -71,16 +71,18 @@ static void note_request(const char *key, size_t bytes);
/** Return true iff the directory purpose 'purpose' must use an
* anonymous connection to a directory. */
static int
purpose_needs_anonymity(uint8_t purpose)
purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose)
{
if (get_options()->AllDirActionsPrivate)
return 1;
if (purpose == DIR_PURPOSE_FETCH_DIR ||
purpose == DIR_PURPOSE_UPLOAD_DIR ||
purpose == DIR_PURPOSE_FETCH_RUNNING_LIST ||
purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS ||
purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
purpose == DIR_PURPOSE_FETCH_EXTRAINFO)
if (router_purpose == ROUTER_PURPOSE_BRIDGE)
return 1; /* if we have to ask, better make it anonymous */
if (dir_purpose == DIR_PURPOSE_FETCH_DIR ||
dir_purpose == DIR_PURPOSE_UPLOAD_DIR ||
dir_purpose == DIR_PURPOSE_FETCH_RUNNING_LIST ||
dir_purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS ||
dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
dir_purpose == DIR_PURPOSE_FETCH_EXTRAINFO)
return 0;
return 1;
}
@ -147,7 +149,8 @@ router_supports_extrainfo(const char *identity_digest, int is_authority)
* support it.
*/
void
directory_post_to_dirservers(uint8_t purpose, authority_type_t type,
directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
authority_type_t type,
const char *payload,
size_t payload_len, size_t extrainfo_len)
{
@ -167,7 +170,7 @@ directory_post_to_dirservers(uint8_t purpose, authority_type_t type,
continue;
found = 1; /* at least one authority of this type was listed */
if (purpose == DIR_PURPOSE_UPLOAD_DIR)
if (dir_purpose == DIR_PURPOSE_UPLOAD_DIR)
ds->has_accepted_serverdesc = 0;
if (extrainfo_len && router_supports_extrainfo(ds->digest, 1)) {
@ -175,10 +178,10 @@ directory_post_to_dirservers(uint8_t purpose, authority_type_t type,
log_info(LD_DIR, "Uploading an extrainfo (length %d)",
(int) extrainfo_len);
}
post_via_tor = purpose_needs_anonymity(purpose) ||
post_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose) ||
!fascist_firewall_allows_address_dir(ds->addr, ds->dir_port);
directory_initiate_command_routerstatus(rs, purpose,
ROUTER_PURPOSE_GENERAL,
directory_initiate_command_routerstatus(rs, dir_purpose,
router_purpose,
post_via_tor,
NULL, payload, upload_len);
});
@ -191,29 +194,33 @@ directory_post_to_dirservers(uint8_t purpose, authority_type_t type,
}
/** Start a connection to a random running directory server, using
* connection purpose 'purpose' and requesting 'resource'.
* connection purpose <b>dir_purpose</b>, intending to fetch descriptors
* of purpose <b>router_purpose</b>, and requesting <b>resource</b>.
* If <b>retry_if_no_servers</b>, then if all the possible servers seem
* down, mark them up and try again.
*/
void
directory_get_from_dirserver(uint8_t dir_purpose, const char *resource,
int retry_if_no_servers)
directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
const char *resource, int retry_if_no_servers)
{
routerstatus_t *rs = NULL;
or_options_t *options = get_options();
int prefer_authority = server_mode(options) && options->DirPort != 0;
int directconn = !purpose_needs_anonymity(dir_purpose);
int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose);
authority_type_t type;
/* FFFF we could break this switch into its own function, and call
* it elsewhere in directory.c. -RD */
switch (dir_purpose) {
case DIR_PURPOSE_FETCH_EXTRAINFO:
type = EXTRAINFO_CACHE | V2_AUTHORITY;
type = EXTRAINFO_CACHE |
(router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY :
V2_AUTHORITY);
break;
case DIR_PURPOSE_FETCH_NETWORKSTATUS:
case DIR_PURPOSE_FETCH_SERVERDESC:
type = V2_AUTHORITY;
type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY :
V2_AUTHORITY);
break;
case DIR_PURPOSE_FETCH_DIR:
case DIR_PURPOSE_FETCH_RUNNING_LIST:
@ -230,21 +237,21 @@ directory_get_from_dirserver(uint8_t dir_purpose, const char *resource,
if (!options->FetchServerDescriptors && type != HIDSERV_AUTHORITY)
return;
if (directconn && options->UseBridges) {
/* want to pick a bridge for which we have a descriptor. */
if (!get_via_tor && options->UseBridges) {
/* want to ask a running 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,
router_purpose,
0, resource, NULL, 0);
} else
log_notice(LD_DIR, "Ignoring directory request, since no bridge "
"nodes are available yet.");
return;
} else if (directconn) {
} else if (!get_via_tor) {
if (prefer_authority) {
/* only ask authdirservers, and don't ask myself */
rs = router_pick_trusteddirserver(type, 1, 1,
@ -270,10 +277,10 @@ directory_get_from_dirserver(uint8_t dir_purpose, const char *resource,
rs = router_pick_trusteddirserver(type, 1, 1,
retry_if_no_servers);
if (!rs)
directconn = 0; /* last resort: try routing it via Tor */
get_via_tor = 1; /* last resort: try routing it via Tor */
}
}
} else { /* !directconn */
} else { /* get_via_tor */
/* Never use fascistfirewall; we're going via Tor. */
if (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) {
/* only ask hidserv authorities, any of them will do */
@ -291,15 +298,15 @@ directory_get_from_dirserver(uint8_t dir_purpose, const char *resource,
if (rs)
directory_initiate_command_routerstatus(rs, dir_purpose,
ROUTER_PURPOSE_GENERAL,
!directconn,
router_purpose,
get_via_tor,
resource, NULL, 0);
else {
log_notice(LD_DIR,
"While fetching directory info, "
"no running dirservers known. Will try again later. "
"(purpose %d)", dir_purpose);
if (!purpose_needs_anonymity(dir_purpose)) {
if (!purpose_needs_anonymity(dir_purpose, router_purpose)) {
/* remember we tried them all and failed. */
directory_all_unreachable(time(NULL));
}
@ -387,8 +394,8 @@ connection_dir_request_failed(dir_connection_t *conn)
conn->_base.purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
log_info(LD_DIR, "Giving up on directory server at '%s:%d'; retrying",
conn->_base.address, conn->_base.port);
directory_get_from_dirserver(conn->_base.purpose, NULL,
0 /* don't retry_if_no_servers */);
directory_get_from_dirserver(conn->_base.purpose, conn->router_purpose,
NULL, 0 /* don't retry_if_no_servers */);
} else if (conn->_base.purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
conn->_base.address);
@ -422,8 +429,8 @@ connection_dir_download_networkstatus_failed(dir_connection_t *conn,
smartlist_t *trusted_dirs = router_get_trusted_dir_servers();
SMARTLIST_FOREACH(trusted_dirs, trusted_dir_server_t *, ds,
++ds->n_networkstatus_failures);
directory_get_from_dirserver(conn->_base.purpose, "all.z",
0 /* don't retry_if_no_servers */);
directory_get_from_dirserver(conn->_base.purpose, conn->router_purpose,
"all.z", 0 /* don't retry_if_no_servers */);
} else if (!strcmpstart(conn->requested_resource, "fp/")) {
/* We were trying to download by fingerprint; mark them all as having
* failed, and possibly retry them later.*/
@ -1699,7 +1706,8 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
/* try to get a new one now */
if (!already_fetching_directory(DIR_PURPOSE_FETCH_DIR) &&
!should_delay_dir_fetches(options))
directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR, NULL, 1);
directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR,
ROUTER_PURPOSE_GENERAL, NULL, 1);
tor_free(url);
return 0;
}
@ -1750,7 +1758,8 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
/* try to get a new one now */
if (!already_fetching_directory(DIR_PURPOSE_FETCH_RUNNING_LIST) &&
!should_delay_dir_fetches(options))
directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST, NULL, 1);
directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST,
ROUTER_PURPOSE_GENERAL, NULL, 1);
tor_free(url);
return 0;
}

View File

@ -939,7 +939,8 @@ run_scheduled_events(time_t now)
* our dirport. not simply if we configured one. -RD */
if (any_trusted_dir_is_v1_authority() &&
!should_delay_dir_fetches(options))
directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR, NULL, 1);
directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR,
ROUTER_PURPOSE_GENERAL, NULL, 1);
}
/** How often do we (as a cache) fetch a new V1 directory? */
#define V1_DIR_FETCH_PERIOD (6*60*60)
@ -949,7 +950,8 @@ run_scheduled_events(time_t now)
/* Caches need to fetch running_routers; directory clients don't. */
if (options->DirPort && time_to_fetch_running_routers < now) {
if (!authdir_mode_v1(options) && !should_delay_dir_fetches(options)) {
directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST, NULL, 1);
directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST,
ROUTER_PURPOSE_GENERAL, NULL, 1);
}
/** How often do we (as a cache) fetch a new V1 runningrouters document? */
#define V1_RUNNINGROUTERS_FETCH_PERIOD (30*60)

View File

@ -2670,10 +2670,11 @@ int assign_to_cpuworker(connection_t *cpuworker, uint8_t question_type,
/********************************* directory.c ***************************/
char *authority_type_to_string(authority_type_t auth);
void directory_post_to_dirservers(uint8_t purpose, authority_type_t type,
const char *payload,
void directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
authority_type_t type, const char *payload,
size_t payload_len, size_t extrainfo_len);
void directory_get_from_dirserver(uint8_t dir_purpose, const char *resource,
void directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
const char *resource,
int retry_if_no_servers);
void directory_initiate_command_routerstatus(routerstatus_t *status,
uint8_t dir_purpose,

View File

@ -261,7 +261,8 @@ rend_client_refetch_renddesc(const char *query)
"already in progress.", escaped_safe_str(query));
} else {
/* not one already; initiate a dir rend desc lookup */
directory_get_from_dirserver(DIR_PURPOSE_FETCH_RENDDESC, query, 1);
directory_get_from_dirserver(DIR_PURPOSE_FETCH_RENDDESC,
ROUTER_PURPOSE_GENERAL, query, 1);
}
}

View File

@ -948,6 +948,7 @@ upload_service_descriptor(rend_service_t *service, int version)
/* Post it to the dirservers */
directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_RENDDESC,
ROUTER_PURPOSE_GENERAL,
HIDSERV_AUTHORITY, desc, desc_len, 0);
tor_free(desc);

View File

@ -909,8 +909,11 @@ router_upload_dir_desc_to_dirservers(int force)
}
msg[desc_len+extra_len] = 0;
directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_DIR, auth,
msg, desc_len, extra_len);
directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_DIR,
(auth & BRIDGE_AUTHORITY) ?
ROUTER_PURPOSE_BRIDGE :
ROUTER_PURPOSE_GENERAL,
auth, msg, desc_len, extra_len);
tor_free(msg);
}

View File

@ -3416,7 +3416,8 @@ update_networkstatus_cache_downloads(time_t now)
/* (Check whether we're currently fetching network-status objects.) */
if (!connection_get_by_type_purpose(CONN_TYPE_DIR,
DIR_PURPOSE_FETCH_NETWORKSTATUS))
directory_get_from_dirserver(DIR_PURPOSE_FETCH_NETWORKSTATUS,"all.z",1);
directory_get_from_dirserver(DIR_PURPOSE_FETCH_NETWORKSTATUS,
ROUTER_PURPOSE_GENERAL, "all.z",1);
}
}
@ -3541,7 +3542,8 @@ update_networkstatus_client_downloads(time_t now)
*cp++ = '+';
});
memcpy(cp, ".z", 3);
directory_get_from_dirserver(DIR_PURPOSE_FETCH_NETWORKSTATUS, resource, 1);
directory_get_from_dirserver(DIR_PURPOSE_FETCH_NETWORKSTATUS,
ROUTER_PURPOSE_GENERAL, resource, 1);
tor_free(resource);
smartlist_free(missing);
}
@ -4469,13 +4471,13 @@ initiate_descriptor_downloads(routerstatus_t *source,
0, /* not private */
resource, NULL, 0);
} else {
directory_get_from_dirserver(purpose, resource, 1);
directory_get_from_dirserver(purpose, ROUTER_PURPOSE_GENERAL, resource, 1);
}
tor_free(resource);
}
/** Clients don't download any descriptor this recent, since it will probably
* not have propageted to enough caches. */
* not have propagated to enough caches. */
#define ESTIMATED_PROPAGATION_TIME (10*60)
/** Return 0 if this routerstatus is obsolete, too new, isn't