[tor-commits] [tor/master] relay: Refactor circuit_open_connection_for_extend()

nickm at torproject.org nickm at torproject.org
Wed Apr 29 23:23:42 UTC 2020


commit 9a6186c267c613ab1cbcb7544e988fe62aab8548
Author: teor <teor at torproject.org>
Date:   Wed Apr 29 20:29:15 2020 +1000

    relay: Refactor circuit_open_connection_for_extend()
    
    Refactor circuit_open_connection_for_extend(), splitting out the IP
    address choice code into a new function.
    
    Adds unit tests. No behaviour changes in tor.
    
    Part of 33817.
---
 src/feature/relay/circuitbuild_relay.c | 77 +++++++++++++++++++++-------------
 src/feature/relay/circuitbuild_relay.h |  3 ++
 2 files changed, 51 insertions(+), 29 deletions(-)

diff --git a/src/feature/relay/circuitbuild_relay.c b/src/feature/relay/circuitbuild_relay.c
index 261fbc7e4..2bf08547d 100644
--- a/src/feature/relay/circuitbuild_relay.c
+++ b/src/feature/relay/circuitbuild_relay.c
@@ -239,6 +239,50 @@ circuit_extend_lspec_valid_helper(const struct extend_cell_t *ec,
   return 0;
 }
 
+/* If possible, return a supported, non-NULL IP address.
+ *
+ * If both addresses are supported and non-NULL, choose one uniformly at
+ * random.
+ *
+ * If we have an IPv6-only extend, but IPv6 is not supported, returns NULL.
+ * If both addresses are NULL, also returns NULL. */
+STATIC const tor_addr_port_t *
+circuit_choose_ip_ap_for_extend(const tor_addr_port_t *ipv4_ap,
+                                const tor_addr_port_t *ipv6_ap)
+{
+  /* If we could make an IPv4 or an IPv6 connection, make an IPv6 connection
+   * at random, with probability 1 in N.
+   *   1 means "always IPv6 (and no IPv4)"
+   *   2 means "equal probability of IPv4 or IPv6"
+   *   ... (and so on) ...
+   *   (UINT_MAX - 1) means "almost always IPv4 (and almost never IPv6)"
+   * To disable IPv6, set ipv6_supported to 0.
+   */
+#define IPV6_CONNECTION_ONE_IN_N 2
+
+  /* IPv4 is always supported */
+  const bool ipv6_supported = router_has_advertised_ipv6_orport(get_options());
+
+  if (ipv4_ap && ipv6_ap && ipv6_supported) {
+    /* Choose between IPv4 and IPv6 at random */
+    bool choose_ipv6 = crypto_fast_rng_one_in_n(get_thread_fast_rng(),
+                                                IPV6_CONNECTION_ONE_IN_N);
+    if (choose_ipv6) {
+      return ipv6_ap;
+    } else {
+      return ipv4_ap;
+    }
+  } else if (ipv6_ap && ipv6_supported) {
+    /* There's only one valid address: try to use it */
+    return ipv6_ap;
+  } else if (ipv4_ap) {
+    return ipv4_ap;
+  } else {
+    /* IPv6-only extend, but IPv6 is not supported. */
+    return NULL;
+  }
+}
+
 /* When there is no open channel for an extend cell <b>ec</b>, set up the
  * circuit <b>circ</b> to wait for a new connection.
  *
@@ -278,35 +322,10 @@ circuit_open_connection_for_extend(const struct extend_cell_t *ec,
     return;
   }
 
-  /* If we could make an IPv4 or an IPv6 connection, make an IPv6 connection
-   * at random, with probability 1 in N.
-   *   1 means "always IPv6 (and no IPv4)"
-   *   2 means "equal probability of IPv4 or IPv6"
-   *   ... (and so on) ...
-   *   (UINT_MAX - 1) means "almost always IPv4 (and almost never IPv6)"
-   * To disable IPv6, set ipv6_supported to 0.
-   */
-#define IPV6_CONNECTION_ONE_IN_N 2
-
-  const bool ipv6_supported = router_has_advertised_ipv6_orport(get_options());
-  const tor_addr_port_t *chosen_ap = NULL;
-
-  /* IPv4 is always supported */
-  if (ipv4_valid && ipv6_valid && ipv6_supported) {
-    /* Choose between IPv4 and IPv6 at random */
-    bool choose_ipv6 = crypto_fast_rng_one_in_n(get_thread_fast_rng(),
-                                                IPV6_CONNECTION_ONE_IN_N);
-    if (choose_ipv6) {
-      chosen_ap = &ec->orport_ipv6;
-    } else {
-      chosen_ap = &ec->orport_ipv4;
-    }
-  } else if (ipv6_valid && ipv6_supported) {
-    /* There's only one valid address: try to use it */
-    chosen_ap = &ec->orport_ipv6;
-  } else if (ipv4_valid) {
-    chosen_ap = &ec->orport_ipv4;
-  } else {
+  const tor_addr_port_t *chosen_ap = circuit_choose_ip_ap_for_extend(
+                                        ipv4_valid ? &ec->orport_ipv4 : NULL,
+                                        ipv6_valid ? &ec->orport_ipv6 : NULL);
+  if (!chosen_ap) {
     /* An IPv6-only extend, but IPv6 is not supported */
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
            "Received IPv6-only extend, but we don't have an IPv6 ORPort.");
diff --git a/src/feature/relay/circuitbuild_relay.h b/src/feature/relay/circuitbuild_relay.h
index d14f304f1..078316153 100644
--- a/src/feature/relay/circuitbuild_relay.h
+++ b/src/feature/relay/circuitbuild_relay.h
@@ -75,6 +75,9 @@ STATIC int circuit_extend_state_valid_helper(const struct circuit_t *circ);
 STATIC int circuit_extend_add_ed25519_helper(struct extend_cell_t *ec);
 STATIC int circuit_extend_lspec_valid_helper(const struct extend_cell_t *ec,
                                              const struct circuit_t *circ);
+STATIC const tor_addr_port_t * circuit_choose_ip_ap_for_extend(
+                                             const tor_addr_port_t *ipv4_ap,
+                                             const tor_addr_port_t *ipv6_ap);
 STATIC void circuit_open_connection_for_extend(const struct extend_cell_t *ec,
                                                struct circuit_t *circ,
                                                int should_launch);





More information about the tor-commits mailing list