[tor-commits] [tor/master] When choosing an orport from an extendinfo, pick randomly.

nickm at torproject.org nickm at torproject.org
Tue Jul 21 13:33:48 UTC 2020


commit ff68aeb49244d65398b5fabaf87d65da51343006
Author: Nick Mathewson <nickm at torproject.org>
Date:   Fri Jul 17 09:06:35 2020 -0400

    When choosing an orport from an extendinfo, pick randomly.
    
    (This is not fully general yet: we only pick randomly among
    _supported_ addresses, and each extendinfo contains at most one IPv4
    address and at most one IPv6 address, no matter what the extend cell
    had.)
    
    This change will help dual-stack relays do IPv6 reachability tests,
    in theory, by having them sometimes do IPv4 connections and
    sometimes do ipv6 connections.
    
    Closes ticket 33220.
---
 changes/ticket33220      |  5 +++++
 src/core/or/extendinfo.c | 33 +++++++++++++++++++++++++++++----
 2 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/changes/ticket33220 b/changes/ticket33220
new file mode 100644
index 0000000000..e064dcd1c1
--- /dev/null
+++ b/changes/ticket33220
@@ -0,0 +1,5 @@
+  o Major features (relay, IPv6):
+    - When a relay with IPv6 support opens a connection to another
+      relay, and the extend cell lists both IPv4 and IPv6 addresses, the
+      first relay now picks randomly which address to use.  Closes
+      ticket 33220.
diff --git a/src/core/or/extendinfo.c b/src/core/or/extendinfo.c
index bcdb57d5a0..ffc88295cf 100644
--- a/src/core/or/extendinfo.c
+++ b/src/core/or/extendinfo.c
@@ -19,6 +19,9 @@
 #include "core/or/policies.h"
 #include "feature/nodelist/describe.h"
 #include "feature/nodelist/nodelist.h"
+#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
+#include "lib/crypt_ops/crypto_rand.h"
 
 #include "core/or/extend_info_st.h"
 #include "feature/nodelist/node_st.h"
@@ -274,16 +277,38 @@ extend_info_get_orport(const extend_info_t *ei, int family)
 const tor_addr_port_t *
 extend_info_pick_orport(const extend_info_t *ei)
 {
-  // XXXX S55 -- for now, we just pick the first.  We'll work on
-  // XXXX more choices as we move forward.
   IF_BUG_ONCE(!ei) {
     return NULL;
   }
+  const or_options_t *options = get_options();
+  if (!server_mode(options)) {
+    // If we aren't a server, just pick the first address we built into
+    // this extendinfo.
+    return &ei->orports[0];
+  }
+
+  const bool ipv6_ok = router_can_extend_over_ipv6(options);
+
+  // Use 'usable' to collect the usable orports, then pick one.
+  const tor_addr_port_t *usable[EXTEND_INFO_MAX_ADDRS];
+  int n_usable = 0;
+  for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
+    const tor_addr_port_t *a = &ei->orports[i];
+    const int family = tor_addr_family(&a->addr);
+    if (family == AF_INET || (ipv6_ok && family == AF_INET6)) {
+      usable[n_usable++] = a;
+    }
+  }
 
-  if (tor_addr_is_unspec(&ei->orports[0].addr)) {
+  if (n_usable == 0) {
+    // Need to bail out early, since nothing will work.
     return NULL;
   }
-  return &ei->orports[0];
+
+  crypto_fast_rng_t *rng = get_thread_fast_rng();
+  const int idx = crypto_fast_rng_get_uint(rng, n_usable);
+
+  return usable[idx];
 }
 
 /**





More information about the tor-commits mailing list