aboutsummaryrefslogtreecommitdiff
path: root/src/or/dirserv.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/dirserv.c')
-rw-r--r--src/or/dirserv.c226
1 files changed, 161 insertions, 65 deletions
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index aa2e74b0b..be62459b1 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -212,7 +212,7 @@ dirserv_load_fingerprint_file(void)
authdir_config_t *fingerprint_list_new;
int result;
config_line_t *front=NULL, *list;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
fname = get_datadir_fname("approved-routers");
log_info(LD_GENERAL,
@@ -518,14 +518,15 @@ dirserv_router_has_valid_address(routerinfo_t *ri)
if (get_options()->DirAllowPrivateAddresses)
return 0; /* whatever it is, we're fine with it */
if (!tor_inet_aton(ri->address, &iaddr)) {
- log_info(LD_DIRSERV,"Router '%s' published non-IP address '%s'. Refusing.",
- ri->nickname, ri->address);
+ log_info(LD_DIRSERV,"Router %s published non-IP address '%s'. Refusing.",
+ router_describe(ri),
+ ri->address);
return -1;
}
if (is_internal_IP(ntohl(iaddr.s_addr), 0)) {
log_info(LD_DIRSERV,
- "Router '%s' published internal IP address '%s'. Refusing.",
- ri->nickname, ri->address);
+ "Router %s published internal IP address '%s'. Refusing.",
+ router_describe(ri), ri->address);
return -1; /* it's a private IP, we should reject it */
}
return 0;
@@ -554,10 +555,11 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
/* Is there too much clock skew? */
now = time(NULL);
if (ri->cache_info.published_on > now+ROUTER_ALLOW_SKEW) {
- log_fn(severity, LD_DIRSERV, "Publication time for nickname '%s' is too "
+ log_fn(severity, LD_DIRSERV, "Publication time for %s is too "
"far (%d minutes) in the future; possible clock skew. Not adding "
"(%s)",
- ri->nickname, (int)((ri->cache_info.published_on-now)/60),
+ router_describe(ri),
+ (int)((ri->cache_info.published_on-now)/60),
esc_router_info(ri));
*msg = "Rejected: Your clock is set too far in the future, or your "
"timezone is not correct.";
@@ -565,9 +567,10 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
}
if (ri->cache_info.published_on < now-ROUTER_MAX_AGE_TO_PUBLISH) {
log_fn(severity, LD_DIRSERV,
- "Publication time for router with nickname '%s' is too far "
+ "Publication time for %s is too far "
"(%d minutes) in the past. Not adding (%s)",
- ri->nickname, (int)((now-ri->cache_info.published_on)/60),
+ router_describe(ri),
+ (int)((now-ri->cache_info.published_on)/60),
esc_router_info(ri));
*msg = "Rejected: Server is expired, or your clock is too far in the past,"
" or your timezone is not correct.";
@@ -575,9 +578,10 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
}
if (dirserv_router_has_valid_address(ri) < 0) {
log_fn(severity, LD_DIRSERV,
- "Router with nickname '%s' has invalid address '%s'. "
+ "Router %s has invalid address '%s'. "
"Not adding (%s).",
- ri->nickname, ri->address,
+ router_describe(ri),
+ ri->address,
esc_router_info(ri));
*msg = "Rejected: Address is not an IP, or IP is a private address.";
return -1;
@@ -729,9 +733,9 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
&& router_differences_are_cosmetic(ri_old, ri)
&& !router_is_me(ri)) {
log_info(LD_DIRSERV,
- "Not replacing descriptor from '%s' (source: %s); "
+ "Not replacing descriptor from %s (source: %s); "
"differences are cosmetic.",
- ri->nickname, source);
+ router_describe(ri), source);
*msg = "Not replacing router descriptor; no information has changed since "
"the last one with this identity.";
control_event_or_authdir_new_descriptor("DROPPED",
@@ -831,13 +835,15 @@ directory_remove_invalid(void)
SMARTLIST_FOREACH_BEGIN(nodes, node_t *, node) {
const char *msg;
routerinfo_t *ent = node->ri;
+ char description[NODE_DESC_BUF_LEN];
uint32_t r;
if (!ent)
continue;
r = dirserv_router_get_status(ent, &msg);
+ router_get_description(description, ent);
if (r & FP_REJECT) {
- log_info(LD_DIRSERV, "Router '%s' is now rejected: %s",
- ent->nickname, msg?msg:"");
+ log_info(LD_DIRSERV, "Router %s is now rejected: %s",
+ description, msg?msg:"");
routerlist_remove(rl, ent, 0, time(NULL));
changed = 1;
continue;
@@ -845,33 +851,33 @@ directory_remove_invalid(void)
#if 0
if (bool_neq((r & FP_NAMED), ent->auth_says_is_named)) {
log_info(LD_DIRSERV,
- "Router '%s' is now %snamed.", ent->nickname,
+ "Router %s is now %snamed.", description,
(r&FP_NAMED)?"":"un");
ent->is_named = (r&FP_NAMED)?1:0;
changed = 1;
}
if (bool_neq((r & FP_UNNAMED), ent->auth_says_is_unnamed)) {
log_info(LD_DIRSERV,
- "Router '%s' is now %snamed. (FP_UNNAMED)", ent->nickname,
+ "Router '%s' is now %snamed. (FP_UNNAMED)", description,
(r&FP_NAMED)?"":"un");
ent->is_named = (r&FP_NUNAMED)?0:1;
changed = 1;
}
#endif
if (bool_neq((r & FP_INVALID), !node->is_valid)) {
- log_info(LD_DIRSERV, "Router '%s' is now %svalid.", ent->nickname,
+ log_info(LD_DIRSERV, "Router '%s' is now %svalid.", description,
(r&FP_INVALID) ? "in" : "");
node->is_valid = (r&FP_INVALID)?0:1;
changed = 1;
}
if (bool_neq((r & FP_BADDIR), node->is_bad_directory)) {
- log_info(LD_DIRSERV, "Router '%s' is now a %s directory", ent->nickname,
+ log_info(LD_DIRSERV, "Router '%s' is now a %s directory", description,
(r & FP_BADDIR) ? "bad" : "good");
node->is_bad_directory = (r&FP_BADDIR) ? 1: 0;
changed = 1;
}
if (bool_neq((r & FP_BADEXIT), node->is_bad_exit)) {
- log_info(LD_DIRSERV, "Router '%s' is now a %s exit", ent->nickname,
+ log_info(LD_DIRSERV, "Router '%s' is now a %s exit", description,
(r & FP_BADEXIT) ? "bad" : "good");
node->is_bad_exit = (r&FP_BADEXIT) ? 1: 0;
changed = 1;
@@ -1026,7 +1032,7 @@ list_server_status_v1(smartlist_t *routers, char **router_status_out,
smartlist_t *rs_entries;
time_t now = time(NULL);
time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
/* We include v2 dir auths here too, because they need to answer
* controllers. Eventually we'll deprecate this whole function;
* see also networkstatus_getinfo_by_purpose(). */
@@ -1193,7 +1199,7 @@ dirserv_dump_directory_to_string(char **dir_out,
/** Return 1 if we fetch our directory material directly from the
* authorities, rather than from a mirror. */
int
-directory_fetches_from_authorities(or_options_t *options)
+directory_fetches_from_authorities(const or_options_t *options)
{
const routerinfo_t *me;
uint32_t addr;
@@ -1220,7 +1226,7 @@ directory_fetches_from_authorities(or_options_t *options)
* on the "mirror" schedule rather than the "client" schedule.
*/
int
-directory_fetches_dir_info_early(or_options_t *options)
+directory_fetches_dir_info_early(const or_options_t *options)
{
return directory_fetches_from_authorities(options);
}
@@ -1232,7 +1238,7 @@ directory_fetches_dir_info_early(or_options_t *options)
* client as a directory guard.
*/
int
-directory_fetches_dir_info_later(or_options_t *options)
+directory_fetches_dir_info_later(const or_options_t *options)
{
return options->UseBridges != 0;
}
@@ -1240,7 +1246,7 @@ directory_fetches_dir_info_later(or_options_t *options)
/** Return 1 if we want to cache v2 dir info (each status file).
*/
int
-directory_caches_v2_dir_info(or_options_t *options)
+directory_caches_v2_dir_info(const or_options_t *options)
{
return options->DirPort != 0;
}
@@ -1249,7 +1255,7 @@ directory_caches_v2_dir_info(or_options_t *options)
* and we're willing to serve them to others. Else return 0.
*/
int
-directory_caches_dir_info(or_options_t *options)
+directory_caches_dir_info(const or_options_t *options)
{
if (options->BridgeRelay || options->DirPort)
return 1;
@@ -1265,7 +1271,7 @@ directory_caches_dir_info(or_options_t *options)
* requests via the "begin_dir" interface, which doesn't require
* having any separate port open. */
int
-directory_permits_begindir_requests(or_options_t *options)
+directory_permits_begindir_requests(const or_options_t *options)
{
return options->BridgeRelay != 0 || options->DirPort != 0;
}
@@ -1274,7 +1280,7 @@ directory_permits_begindir_requests(or_options_t *options)
* requests via the controller interface, which doesn't require
* having any separate port open. */
int
-directory_permits_controller_requests(or_options_t *options)
+directory_permits_controller_requests(const or_options_t *options)
{
return options->DirPort != 0;
}
@@ -1284,7 +1290,8 @@ directory_permits_controller_requests(or_options_t *options)
* lately.
*/
int
-directory_too_idle_to_fetch_descriptors(or_options_t *options, time_t now)
+directory_too_idle_to_fetch_descriptors(const or_options_t *options,
+ time_t now)
{
return !directory_caches_dir_info(options) &&
!options->FetchUselessDescriptors &&
@@ -1554,7 +1561,7 @@ dirserv_pick_cached_dir_obj(cached_dir_t *cache_src,
const char *name,
dirinfo_type_t auth_type)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int authority = (auth_type == V1_DIRINFO && authdir_mode_v1(options)) ||
(auth_type == V2_DIRINFO && authdir_mode_v2(options));
@@ -1713,12 +1720,6 @@ should_generate_v2_networkstatus(void)
/** If a router's MTBF is at least this value, then it is always stable.
* See above. (Corresponds to about 7 days for current decay rates.) */
#define MTBF_TO_GUARANTEE_STABLE (60*60*24*5)
-/** Similarly, we protect sufficiently fast nodes from being pushed
- * out of the set of Fast nodes. */
-#define BANDWIDTH_TO_GUARANTEE_FAST ROUTER_REQUIRED_MIN_BANDWIDTH
-/** Similarly, every node with sufficient bandwidth can be considered
- * for Guard status. */
-#define BANDWIDTH_TO_GUARANTEE_GUARD (250*1024)
/** Similarly, every node with at least this much weighted time known can be
* considered familiar enough to be a guard. Corresponds to about 20 days for
* current decay rates.
@@ -1863,6 +1864,7 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
long *tks;
double *mtbfs, *wfus;
time_t now = time(NULL);
+ const or_options_t *options = get_options();
/* initialize these all here, in case there are no routers */
stable_uptime = 0;
@@ -1935,8 +1937,11 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
if (guard_tk > TIME_KNOWN_TO_GUARANTEE_FAMILIAR)
guard_tk = TIME_KNOWN_TO_GUARANTEE_FAMILIAR;
- if (fast_bandwidth > BANDWIDTH_TO_GUARANTEE_FAST)
- fast_bandwidth = BANDWIDTH_TO_GUARANTEE_FAST;
+ /* Protect sufficiently fast nodes from being pushed out of the set
+ * of Fast nodes. */
+ if (options->AuthDirFastGuarantee &&
+ fast_bandwidth > options->AuthDirFastGuarantee)
+ fast_bandwidth = (uint32_t)options->AuthDirFastGuarantee;
/* Now that we have a time-known that 7/8 routers are known longer than,
* fill wfus with the wfu of every such "familiar" router. */
@@ -2245,7 +2250,7 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b)
static digestmap_t *
get_possible_sybil_list(const smartlist_t *routers)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
digestmap_t *omit_as_sybil;
smartlist_t *routers_by_ip = smartlist_create();
uint32_t last_addr;
@@ -2281,6 +2286,75 @@ get_possible_sybil_list(const smartlist_t *routers)
return omit_as_sybil;
}
+/** Return non-zero iff a relay running the Tor version specified in
+ * <b>platform</b> is suitable for use as a potential entry guard. */
+static int
+is_router_version_good_for_possible_guard(const char *platform)
+{
+ static int parsed_versions_initialized = 0;
+ static tor_version_t first_good_0_2_1_guard_version;
+ static tor_version_t first_good_0_2_2_guard_version;
+ static tor_version_t first_good_later_guard_version;
+
+ tor_version_t router_version;
+
+ /* XXX023 This block should be extracted into its own function. */
+ /* XXXX Begin code copied from tor_version_as_new_as (in routerparse.c) */
+ {
+ char *s, *s2, *start;
+ char tmp[128];
+
+ tor_assert(platform);
+
+ /* nonstandard Tor; be safe and say yes */
+ if (strcmpstart(platform,"Tor "))
+ return 1;
+
+ start = (char *)eat_whitespace(platform+3);
+ if (!*start) return 0;
+ s = (char *)find_whitespace(start); /* also finds '\0', which is fine */
+ s2 = (char*)eat_whitespace(s);
+ if (!strcmpstart(s2, "(r") || !strcmpstart(s2, "(git-"))
+ s = (char*)find_whitespace(s2);
+
+ if ((size_t)(s-start+1) >= sizeof(tmp)) /* too big, no */
+ return 0;
+ strlcpy(tmp, start, s-start+1);
+
+ if (tor_version_parse(tmp, &router_version)<0) {
+ log_info(LD_DIR,"Router version '%s' unparseable.",tmp);
+ return 1; /* be safe and say yes */
+ }
+ }
+ /* XXXX End code copied from tor_version_as_new_as (in routerparse.c) */
+
+ if (!parsed_versions_initialized) {
+ /* CVE-2011-2769 was fixed on the relay side in Tor versions
+ * 0.2.1.31, 0.2.2.34, and 0.2.3.6-alpha. */
+ tor_assert(tor_version_parse("0.2.1.31",
+ &first_good_0_2_1_guard_version)>=0);
+ tor_assert(tor_version_parse("0.2.2.34",
+ &first_good_0_2_2_guard_version)>=0);
+ tor_assert(tor_version_parse("0.2.3.6-alpha",
+ &first_good_later_guard_version)>=0);
+
+ /* Don't parse these constant version strings once for every relay
+ * for every vote. */
+ parsed_versions_initialized = 1;
+ }
+
+ return ((tor_version_same_series(&first_good_0_2_1_guard_version,
+ &router_version) &&
+ tor_version_compare(&first_good_0_2_1_guard_version,
+ &router_version) <= 0) ||
+ (tor_version_same_series(&first_good_0_2_2_guard_version,
+ &router_version) &&
+ tor_version_compare(&first_good_0_2_2_guard_version,
+ &router_version) <= 0) ||
+ (tor_version_compare(&first_good_later_guard_version,
+ &router_version) <= 0));
+}
+
/** Extract status information from <b>ri</b> and from other authority
* functions and store it in <b>rs</b>>. If <b>naming</b>, consider setting
* the named flag in <b>rs</b>.
@@ -2294,10 +2368,13 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs,
routerinfo_t *ri,
time_t now,
int naming, int listbadexits,
- int listbaddirs)
+ int listbaddirs, int vote_on_hsdirs)
{
+ const or_options_t *options = get_options();
int unstable_version =
!tor_version_as_new_as(ri->platform,"0.1.1.16-rc-cvs");
+ uint32_t routerbw = router_get_advertised_bandwidth(ri);
+
memset(rs, 0, sizeof(routerstatus_t));
rs->is_authority =
@@ -2323,20 +2400,25 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs,
rs->is_valid = node->is_valid;
if (node->is_fast &&
- (router_get_advertised_bandwidth(ri) >= BANDWIDTH_TO_GUARANTEE_GUARD ||
- router_get_advertised_bandwidth(ri) >=
- MIN(guard_bandwidth_including_exits,
- guard_bandwidth_excluding_exits))) {
- long tk = rep_hist_get_weighted_time_known(node->identity, now);
- double wfu = rep_hist_get_weighted_fractional_uptime(node->identity, now);
+ ((options->AuthDirGuardBWGuarantee &&
+ routerbw >= options->AuthDirGuardBWGuarantee) ||
+ routerbw >= MIN(guard_bandwidth_including_exits,
+ guard_bandwidth_excluding_exits)) &&
+ (options->GiveGuardFlagTo_CVE_2011_2768_VulnerableRelays ||
+ is_router_version_good_for_possible_guard(ri->platform))) {
+ long tk = rep_hist_get_weighted_time_known(
+ node->identity, now);
+ double wfu = rep_hist_get_weighted_fractional_uptime(
+ node->identity, now);
rs->is_possible_guard = (wfu >= guard_wfu && tk >= guard_tk) ? 1 : 0;
} else {
rs->is_possible_guard = 0;
}
+
rs->is_bad_directory = listbaddirs && node->is_bad_directory;
rs->is_bad_exit = listbadexits && node->is_bad_exit;
node->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, node, now);
- rs->is_hs_dir = node->is_hs_dir;
+ rs->is_hs_dir = vote_on_hsdirs && node->is_hs_dir;
rs->is_v2_dir = ri->dir_port != 0;
if (!strcasecmp(ri->nickname, UNNAMED_ROUTER_NICKNAME))
@@ -2433,7 +2515,7 @@ measured_bw_line_parse(measured_bw_line_t *out, const char *orig_line)
tor_free(line);
return -1;
}
- strncpy(out->node_hex, cp, sizeof(out->node_hex));
+ strlcpy(out->node_hex, cp, sizeof(out->node_hex));
got_node_id=1;
}
} while ((cp = tor_strtok_r(NULL, " \t", &strtok_state)));
@@ -2545,7 +2627,7 @@ networkstatus_t *
dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
authority_cert_t *cert)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
networkstatus_t *v3_out = NULL;
uint32_t addr;
char *hostname = NULL, *client_versions = NULL, *server_versions = NULL;
@@ -2556,6 +2638,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
int naming = options->NamingAuthoritativeDir;
int listbadexits = options->AuthDirListBadExits;
int listbaddirs = options->AuthDirListBadDirs;
+ int vote_on_hsdirs = options->VoteOnHidServDirectoriesV2;
routerlist_t *rl = router_get_routerlist();
time_t now = time(NULL);
time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
@@ -2622,7 +2705,8 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
rs = &vrs->status;
set_routerstatus_from_routerinfo(rs, node, ri, now,
- naming, listbadexits, listbaddirs);
+ naming, listbadexits, listbaddirs,
+ vote_on_hsdirs);
if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest))
clear_status_flags_on_sybil(rs);
@@ -2699,7 +2783,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
v3_out->server_versions = server_versions;
v3_out->known_flags = smartlist_create();
smartlist_split_string(v3_out->known_flags,
- "Authority Exit Fast Guard HSDir Stable V2Dir Valid",
+ "Authority Exit Fast Guard Stable V2Dir Valid",
0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
if (vote_on_reachability)
smartlist_add(v3_out->known_flags, tor_strdup("Running"));
@@ -2711,6 +2795,8 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
smartlist_add(v3_out->known_flags, tor_strdup("Named"));
smartlist_add(v3_out->known_flags, tor_strdup("Unnamed"));
}
+ if (vote_on_hsdirs)
+ smartlist_add(v3_out->known_flags, tor_strdup("HSDir"));
smartlist_sort_strings(v3_out->known_flags);
if (options->ConsensusParams) {
@@ -2726,7 +2812,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
voter->sigs = smartlist_create();
voter->address = hostname;
voter->addr = addr;
- voter->dir_port = router_get_advertised_dir_port(options);
+ voter->dir_port = router_get_advertised_dir_port(options, 0);
voter->or_port = router_get_advertised_or_port(options);
voter->contact = tor_strdup(contact);
if (options->V3AuthUseLegacyKey) {
@@ -2760,7 +2846,7 @@ generate_v2_networkstatus_opinion(void)
char *status = NULL, *client_versions = NULL, *server_versions = NULL,
*identity_pkey = NULL, *hostname = NULL;
char *outp, *endp;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
char fingerprint[FINGERPRINT_LEN+1];
char published[ISO_TIME_LEN+1];
char digest[DIGEST_LEN];
@@ -2773,6 +2859,7 @@ generate_v2_networkstatus_opinion(void)
int versioning = options->VersioningAuthoritativeDir;
int listbaddirs = options->AuthDirListBadDirs;
int listbadexits = options->AuthDirListBadExits;
+ int vote_on_hsdirs = options->VoteOnHidServDirectoriesV2;
const char *contact;
char *version_lines = NULL;
smartlist_t *routers = NULL;
@@ -2801,7 +2888,7 @@ generate_v2_networkstatus_opinion(void)
goto done;
}
- contact = get_options()->ContactInfo;
+ contact = options->ContactInfo;
if (!contact)
contact = "(none)";
@@ -2830,7 +2917,7 @@ generate_v2_networkstatus_opinion(void)
"%s" /* client version line, server version line. */
"dir-signing-key\n%s",
hostname, fmt_addr32(addr),
- (int)router_get_advertised_dir_port(options),
+ (int)router_get_advertised_dir_port(options, 0),
fingerprint,
contact,
published,
@@ -2867,7 +2954,8 @@ generate_v2_networkstatus_opinion(void)
continue;
}
set_routerstatus_from_routerinfo(&rs, node, ri, now,
- naming, listbadexits, listbaddirs);
+ naming, listbadexits, listbaddirs,
+ vote_on_hsdirs);
if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest))
clear_status_flags_on_sybil(&rs);
@@ -2883,7 +2971,7 @@ generate_v2_networkstatus_opinion(void)
});
if (tor_snprintf(outp, endp-outp, "directory-signature %s\n",
- get_options()->Nickname)<0) {
+ options->Nickname)<0) {
log_warn(LD_BUG, "Unable to write signature line.");
goto done;
}
@@ -3191,8 +3279,9 @@ dirserv_orconn_tls_done(const char *address,
if (!bridge_auth || ri->purpose == ROUTER_PURPOSE_BRIDGE) {
tor_addr_t addr, *addrp=NULL;
log_info(LD_DIRSERV, "Found router %s to be reachable at %s:%d. Yay.",
- ri->nickname, address, ri->or_port );
- if (tor_addr_from_str(&addr, ri->address) != -1)
+ router_describe(ri),
+ address, ri->or_port);
+ if (tor_addr_parse(&addr, ri->address) != -1)
addrp = &addr;
else
log_warn(LD_BUG, "Couldn't parse IP address \"%s\"", ri->address);
@@ -3467,15 +3556,14 @@ connection_dirserv_finish_spooling(dir_connection_t *conn)
static int
connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn)
{
-#ifdef TRACK_SERVED_TIME
- time_t now = time(NULL);
-#endif
int by_fp = (conn->dir_spool_src == DIR_SPOOL_SERVER_BY_FP ||
conn->dir_spool_src == DIR_SPOOL_EXTRA_BY_FP);
int extra = (conn->dir_spool_src == DIR_SPOOL_EXTRA_BY_FP ||
conn->dir_spool_src == DIR_SPOOL_EXTRA_BY_DIGEST);
time_t publish_cutoff = time(NULL)-ROUTER_MAX_AGE_TO_PUBLISH;
+ const or_options_t *options = get_options();
+
while (smartlist_len(conn->fingerprint_stack) &&
connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN) {
const char *body;
@@ -3497,9 +3585,17 @@ connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn)
* unknown bridge descriptor has shown up between then and now. */
continue;
}
-#ifdef TRACK_SERVED_TIME
- sd->last_served_at = now;
-#endif
+
+ /** If we are the bridge authority and the descriptor is a bridge
+ * descriptor, remember that we served this descriptor for desc stats. */
+ if (options->BridgeAuthoritativeDir && by_fp) {
+ const routerinfo_t *router =
+ router_get_by_id_digest(sd->identity_digest);
+ /* router can be NULL here when the bridge auth is asked for its own
+ * descriptor. */
+ if (router && router->purpose == ROUTER_PURPOSE_BRIDGE)
+ rep_hist_note_desc_served(sd->identity_digest);
+ }
body = signed_descriptor_get_body(sd);
if (conn->zlib_state) {
/* XXXX022 This 'last' business should actually happen on the last