Commit 1f4b6944 authored by Nick Mathewson's avatar Nick Mathewson 🐘
Browse files

Upload descriptors more often when recent desc is unlisted

Right now we only force a new descriptor upload every 18 hours.
This can make servers become unlisted if they upload a descriptor at
time T which the authorities reject as being "too similar" to one
they uploaded before. Nothing will actually make the server upload a
new descriptor later on, until another 18 hours have passed.

This patch changes the upload behavior so that the 18 hour interval
applies only when we're listed in a live consensus with a descriptor
published within the last 18 hours.  Otherwise--if we're not listed
in the live consensus, or if we're listed with a publication time
over 18 hours in the past--we upload a new descriptor every 90
minutes.

This is an attempted bugfix for #3327.  If we merge it, it should
obsolete #535.
parent 41eef668
Loading
Loading
Loading
Loading

changes/bug3327

0 → 100644
+8 −0
Changes for changes/bug3327: 8 added lines, 0 removed lines.
Original line number Diff line number Diff line
  o Major features:
    - Relays now try regenerating and uploading their descriptor more
      frequently if they are not listed in the consensus, or if the
      version of their descriptor listed in the consensus is too
      old. This fix should prevent situations where a server declines
      to re-publish itself because it has done so too recently, even
      though the authorities decided not to list its recent-enough
      descriptor. Fix for bug 3327.
+1 −5
Changes for src/or/main.c: 1 added line, 5 removed lines.
Original line number Diff line number Diff line
@@ -1326,11 +1326,7 @@ run_scheduled_events(time_t now)
      time_to_check_ipaddress = now + CHECK_IPADDRESS_INTERVAL;
      check_descriptor_ipaddress_changed(now);
    }
/** If our router descriptor ever goes this long without being regenerated
 * because something changed, we force an immediate regenerate-and-upload. */
#define FORCE_REGENERATE_DESCRIPTOR_INTERVAL (18*60*60)
    mark_my_descriptor_dirty_if_older_than(
                                  now - FORCE_REGENERATE_DESCRIPTOR_INTERVAL);
    mark_my_descriptor_dirty_if_too_old(now);
    consider_publishable_server(0);
    /* also, check religiously for reachability, if it's within the first
     * 20 minutes of our uptime. */
+41 −3
Changes for src/or/router.c: 41 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -1610,12 +1610,50 @@ router_rebuild_descriptor(int force)
  return 0;
}

/** Mark descriptor out of date if it's older than <b>when</b> */
/** If our router descriptor ever goes this long without being regenerated
 * because something changed, we force an immediate regenerate-and-upload. */
#define FORCE_REGENERATE_DESCRIPTOR_INTERVAL (18*60*60)

/** If our router descriptor seems to be missing or unacceptable according
 * to the authorities, regenerate and reupload it _this_ often. */
#define FAST_RETRY_DESCRIPTOR_INTERVAL (90*60)

/** Mark descriptor out of date if it's been "too long" since we last tried
 * to upload one. */
void
mark_my_descriptor_dirty_if_older_than(time_t when)
mark_my_descriptor_dirty_if_too_old(time_t now)
{
  if (desc_clean_since < when)
  networkstatus_t *ns;
  routerstatus_t *rs;
  const char *retry_fast_reason = NULL; /* Set if we should retry frequently */
  const time_t slow_cutoff = now - FORCE_REGENERATE_DESCRIPTOR_INTERVAL;
  const time_t fast_cutoff = now - FAST_RETRY_DESCRIPTOR_INTERVAL;

  /* If it's already dirty, don't mark it. */
  if (! desc_clean_since)
    return;

  /* If it's older than FORCE_REGENERATE_DESCRIPTOR_INTERVAL, it's always
   * time to rebuild it. */
  if (desc_clean_since < slow_cutoff) {
    mark_my_descriptor_dirty("time for new descriptor");
    return;
  }
  /* Now we see whether we want to be retrying frequently or no.  The
   * rule here is that we'll retry frequently if we aren't listed in the
   * live consensus we have, or if the publication time of the
   * descriptor listed for us in the consensus is very old. */
  ns = networkstatus_get_live_consensus(now);
  if (ns) {
    rs = networkstatus_vote_find_entry(ns, server_identitykey_digest);
    if (rs == NULL)
      retry_fast_reason = "not listed in consensus";
    else if (rs->published_on < slow_cutoff)
      retry_fast_reason = "version listed in consensus is quite old";
  }

  if (retry_fast_reason && desc_clean_since < fast_cutoff)
    mark_my_descriptor_dirty(retry_fast_reason);
}

/** Call when the current descriptor is out of date. */
+1 −1
Changes for src/or/router.h: 1 added line, 1 removed line.
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ void consider_publishable_server(int force);
int should_refuse_unknown_exits(const or_options_t *options);

void router_upload_dir_desc_to_dirservers(int force);
void mark_my_descriptor_dirty_if_older_than(time_t when);
void mark_my_descriptor_dirty_if_too_old(time_t now);
void mark_my_descriptor_dirty(const char *reason);
void check_descriptor_bandwidth_changed(time_t now);
void check_descriptor_ipaddress_changed(time_t now);