summaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
Diffstat (limited to 'src/or')
-rw-r--r--src/or/directory.c31
-rw-r--r--src/or/networkstatus.c21
-rw-r--r--src/or/networkstatus.h2
3 files changed, 52 insertions, 2 deletions
diff --git a/src/or/directory.c b/src/or/directory.c
index ba6d38c426..b5c9d49d17 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -2939,6 +2939,28 @@ handle_get_frontpage(dir_connection_t *conn, const get_handler_args_t *args)
return 0;
}
+/** Warn that the consensus <b>v</b> of type <b>flavor</b> is too old and will
+ * not be served to clients. Rate-limit the warning to avoid logging an entry
+ * on every request.
+ */
+static void
+warn_consensus_is_too_old(networkstatus_t *v, const char *flavor, time_t now)
+{
+#define TOO_OLD_WARNING_INTERVAL (60*60)
+ static ratelim_t warned = RATELIM_INIT(TOO_OLD_WARNING_INTERVAL);
+ char timestamp[ISO_TIME_LEN+1];
+ char *dupes;
+
+ if ((dupes = rate_limit_log(&warned, now))) {
+ format_local_iso_time(timestamp, v->valid_until);
+ log_warn(LD_DIRSERV, "Our %s%sconsensus is too old, so we will not "
+ "serve it to clients. It was valid until %s local time and we "
+ "continued to serve it for up to 24 hours after it expired.%s",
+ flavor ? flavor : "", flavor ? " " : "", timestamp, dupes);
+ tor_free(dupes);
+ }
+}
+
/** Helper function for GET /tor/status-vote/current/consensus
*/
static int
@@ -2983,6 +3005,15 @@ handle_get_current_consensus(dir_connection_t *conn,
v = networkstatus_get_latest_consensus_by_flavor(flav);
+ if (v && !networkstatus_consensus_reasonably_live(v, now)) {
+ write_http_status_line(conn, 404, "Consensus is too old");
+ warn_consensus_is_too_old(v, flavor, now);
+ smartlist_free(dir_fps);
+ geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND);
+ tor_free(flavor);
+ goto done;
+ }
+
if (v && want_fps &&
!client_likes_consensus(v, want_fps)) {
write_http_status_line(conn, 404, "Consensus not signed by sufficient "
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index ed888fb53e..fde0b18a5a 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -1342,6 +1342,24 @@ networkstatus_get_live_consensus,(time_t now))
return NULL;
}
+/** Determine if <b>consensus</b> is valid or expired recently enough that
+ * we can still use it.
+ *
+ * Return 1 if the consensus is reasonably live, or 0 if it is too old.
+ */
+int
+networkstatus_consensus_reasonably_live(networkstatus_t *consensus, time_t now)
+{
+#define REASONABLY_LIVE_TIME (24*60*60)
+ if (BUG(!consensus))
+ return 0;
+
+ if (now <= consensus->valid_until + REASONABLY_LIVE_TIME)
+ return 1;
+
+ return 0;
+}
+
/* XXXX remove this in favor of get_live_consensus. But actually,
* leave something like it for bridge users, who need to not totally
* lose if they spend a while fetching a new consensus. */
@@ -1350,12 +1368,11 @@ networkstatus_get_live_consensus,(time_t now))
networkstatus_t *
networkstatus_get_reasonably_live_consensus(time_t now, int flavor)
{
-#define REASONABLY_LIVE_TIME (24*60*60)
networkstatus_t *consensus =
networkstatus_get_latest_consensus_by_flavor(flavor);
if (consensus &&
consensus->valid_after <= now &&
- now <= consensus->valid_until+REASONABLY_LIVE_TIME)
+ networkstatus_consensus_reasonably_live(consensus, now))
return consensus;
else
return NULL;
diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h
index 71f36b69ed..172c0ea480 100644
--- a/src/or/networkstatus.h
+++ b/src/or/networkstatus.h
@@ -79,6 +79,8 @@ MOCK_DECL(networkstatus_t *,networkstatus_get_latest_consensus,(void));
MOCK_DECL(networkstatus_t *,networkstatus_get_latest_consensus_by_flavor,
(consensus_flavor_t f));
MOCK_DECL(networkstatus_t *, networkstatus_get_live_consensus,(time_t now));
+int networkstatus_consensus_reasonably_live(networkstatus_t *consensus,
+ time_t now);
networkstatus_t *networkstatus_get_reasonably_live_consensus(time_t now,
int flavor);
MOCK_DECL(int, networkstatus_consensus_is_bootstrapping,(time_t now));