[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r16554: {tor} Add exitpolicy summaries to the consensus (in tor/trunk: doc/spec/proposals src/or)



Author: weasel
Date: 2008-08-14 19:01:31 -0400 (Thu, 14 Aug 2008)
New Revision: 16554

Modified:
   tor/trunk/doc/spec/proposals/141-jit-sd-downloads.txt
   tor/trunk/src/or/dirvote.c
Log:
Add exitpolicy summaries to the consensus

Modified: tor/trunk/doc/spec/proposals/141-jit-sd-downloads.txt
===================================================================
--- tor/trunk/doc/spec/proposals/141-jit-sd-downloads.txt	2008-08-14 23:01:21 UTC (rev 16553)
+++ tor/trunk/doc/spec/proposals/141-jit-sd-downloads.txt	2008-08-14 23:01:31 UTC (rev 16554)
@@ -259,12 +259,33 @@
   use an accept-style summary and list as much of the port list as is
   possible within these 1000 bytes.
 
-  Similarly to IP address, ports, and timestamp a consensus should list
-  the exit policy matching the descriptor digest referenced in the
-  consensus document (See dir-spec section 3.4).
+3.4.1 Consensus selection
 
-3.4.1 Client behaviour
+  When building a consensus, authorities have to agree on a digest of
+  the server descriptor to list in the router line for each router.
+  This is documented in dir-spec section 3.4.
 
+  All authorities that listed that agreed upon descriptor digest in
+  their vote should also list the same exit policy summary - or list
+  none at all if the authority has not been upgraded to list that
+  information in their vote.
+
+  If we have votes with matching server descriptor digest of which at
+  least one of them has an exit policy then we differ between two cases:
+   a) all authorities agree (or abstained) on the policy summary, and we
+      use the exit policy summary that they all listed in their vote,
+   b) something went wrong (or some authority is playing foul) and we
+      have different policy summaries.  In that case we pick the one
+      that is most commonly listed in votes with the matching
+      descriptor.  We break ties in favour of the lexigraphically larger
+      vote.
+
+  If none one of the votes with a matching server descriptor digest has
+  an exit policy summary we use the most commonly listed one in all
+  votes, breaking ties like in case b above.
+
+3.4.2 Client behaviour
+
   When choosing an exit node for a specific request a Tor client will
   choose from the list of nodes that exit to the requested port as given
   by the consensus document.  If a client has additional knowledge (like

Modified: tor/trunk/src/or/dirvote.c
===================================================================
--- tor/trunk/src/or/dirvote.c	2008-08-14 23:01:21 UTC (rev 16553)
+++ tor/trunk/src/or/dirvote.c	2008-08-14 23:01:31 UTC (rev 16554)
@@ -688,6 +688,7 @@
     smartlist_t *matching_descs = smartlist_create();
     smartlist_t *chosen_flags = smartlist_create();
     smartlist_t *versions = smartlist_create();
+    smartlist_t *exitsummaries = smartlist_create();
     uint32_t *bandwidths = tor_malloc(sizeof(uint32_t) * smartlist_len(votes));
     int num_bandwidths;
 
@@ -799,6 +800,7 @@
       const char *lowest_id = NULL;
       const char *chosen_version;
       const char *chosen_name = NULL;
+      int exitsummary_disagreement = 0;
       int is_named = 0, is_unnamed = 0, is_running = 0;
       int naming_conflict = 0;
       int n_listing = 0;
@@ -935,6 +937,85 @@
         rs_out.bandwidth = median_uint32(bandwidths, num_bandwidths);
       }
 
+      /* Ok, we already picked a descriptor digest we want to list
+       * previously.  Now we want to use the exit policy summary from
+       * that descriptor.  If everybody plays nice all the voters who
+       * listed that descriptor will have the same summary.  If not then
+       * something is fishy and we'll use the most common one (breaking
+       * ties in favor of lexigraphically larger one (only because it
+       * lets me reuse more existing code.
+       *
+       * The other case that can happen is that no authority that voted
+       * for that descriptor has an exit policy summary.  That's
+       * probably quite unlikely but can happen.  In that case we use
+       * the policy that was most often listed in votes, again breaking
+       * ties like in the previous case.
+       */
+      if (consensus_method >= 5) {
+        /* Okay, go through all the votes for this router.  We prepared
+         * that list previously */
+        const char *chosen_exitsummary = NULL;
+        smartlist_clear(exitsummaries);
+        SMARTLIST_FOREACH(matching_descs, vote_routerstatus_t *, vsr, {
+          /* Check if the vote where this status comes from had the
+           * proper descriptor */
+          tor_assert(!memcmp(rs_out.identity_digest, vsr->status.identity_digest, DIGEST_LEN));
+          if (vsr->status.has_exitsummary &&
+               !memcmp(rs_out.descriptor_digest, vsr->status.descriptor_digest, DIGEST_LEN)) {
+            tor_assert(vsr->status.exitsummary);
+            smartlist_add(exitsummaries, vsr->status.exitsummary);
+            if (!chosen_exitsummary) {
+              chosen_exitsummary = vsr->status.exitsummary;
+            } else if (strcmp(chosen_exitsummary, vsr->status.exitsummary)) {
+              /* Great.  There's disagreement among the voters.  That
+               * really shouldn't be */
+              exitsummary_disagreement = 1;
+            }
+          }
+        });
+
+        if (exitsummary_disagreement) {
+          char id[HEX_DIGEST_LEN+1];
+          char dd[HEX_DIGEST_LEN+1];
+          base16_encode(id, sizeof(dd), rs_out.identity_digest, DIGEST_LEN);
+          base16_encode(dd, sizeof(dd), rs_out.descriptor_digest, DIGEST_LEN);
+          log_warn(LD_DIR, "The voters disgreed on the exit policy summary for"
+                   " router %s with descriptor %s.  This really shouldn't"
+                   " have happened.", id, dd);
+
+          smartlist_sort_strings(exitsummaries);
+          chosen_exitsummary = get_most_frequent_member(exitsummaries);
+        } else if (!chosen_exitsummary) {
+          char id[HEX_DIGEST_LEN+1];
+          char dd[HEX_DIGEST_LEN+1];
+          base16_encode(id, sizeof(dd), rs_out.identity_digest, DIGEST_LEN);
+          base16_encode(dd, sizeof(dd), rs_out.descriptor_digest, DIGEST_LEN);
+          log_warn(LD_DIR, "Not one of the voters that made us select"
+                   "descriptor %s for router %s had an exit policy"
+                   "summary", dd, id);
+
+          /* Ok, none of those voting for the digest we chose had an
+           * exit policy for us.  Well, that kinda sucks.
+           */
+          smartlist_clear(exitsummaries);
+          SMARTLIST_FOREACH(matching_descs, vote_routerstatus_t *, vsr, {
+            if (vsr->status.has_exitsummary)
+              smartlist_add(exitsummaries, vsr->status.exitsummary);
+          });
+          smartlist_sort_strings(exitsummaries);
+          chosen_exitsummary = get_most_frequent_member(exitsummaries);
+
+          if (!chosen_exitsummary)
+            log_warn(LD_DIR, "Wow, not one of the voters had an exit "
+                     "policy summary for %s.  Wow.", id);
+        }
+
+        if (chosen_exitsummary) {
+          rs_out.has_exitsummary = 1;
+          rs_out.exitsummary = (char *)chosen_exitsummary; /* yea, discards the const */
+        }
+      }
+
       /* Okay!! Now we can write the descriptor... */
       /*     First line goes into "buf". */
       routerstatus_format_entry(buf, sizeof(buf), &rs_out, NULL, 1, 0);
@@ -957,6 +1038,15 @@
         }
         smartlist_add(chunks, tor_strdup(buf));
       };
+      /*     Now the exitpolicy summary line. */
+      if (rs_out.has_exitsummary) {
+        int r = tor_snprintf(buf, sizeof(buf), "p %s\n", rs_out.exitsummary);
+        if (r<0) {
+          log_warn(LD_BUG, "Not enough space in buffer for exitpolicy line.");
+          *buf = '\0';
+        }
+        smartlist_add(chunks, tor_strdup(buf));
+      };
 
       /* And the loop is over and we move on to the next router */
     }
@@ -975,6 +1065,7 @@
     smartlist_free(matching_descs);
     smartlist_free(chosen_flags);
     smartlist_free(versions);
+    smartlist_free(exitsummaries);
   }
 
   /* Add a signature. */