commit e93ad428e2507f676ce97450b919c2d849633669
Author: Nick Mathewson <ni...@torproject.org>
Date:   Tue Jun 30 16:06:05 2020 -0400

    Allow multiple addresses in extend_info_t.
    
    In practice, there will be at most one ipv4 address and ipv6 address
    for now, but this code is designed to not care which address is
    which until forced to do so.
    
    This patch does not yet actually create extend_info_t objects with
    multiple addresses.
    
    Closes #34069.
---
 src/core/or/circuitbuild.c       | 79 ++++++++++++++++++------------------
 src/core/or/extend_info_st.h     | 10 ++++-
 src/core/or/extendinfo.c         | 86 ++++++++++++++++++++++++++++++++++++++--
 src/core/or/extendinfo.h         |  7 ++++
 src/feature/client/bridges.c     | 17 +++++++-
 src/feature/nodelist/describe.c  | 10 ++++-
 src/feature/nodelist/routerset.c | 19 ++++++---
 src/feature/relay/selftest.c     |  5 ++-
 src/feature/rend/rendclient.c    | 10 ++++-
 src/feature/rend/rendcommon.c    |  9 ++++-
 src/feature/rend/rendparse.c     | 17 +++++---
 src/feature/rend/rendservice.c   | 16 +++++---
 src/test/rend_test_helpers.c     | 13 ++++--
 src/test/test.c                  | 21 +++++++---
 src/test/test_circuitbuild.c     | 10 ++---
 src/test/test_hs_client.c        |  5 ++-
 src/test/test_nodelist.c         |  4 +-
 src/test/test_policy.c           |  4 +-
 18 files changed, 250 insertions(+), 92 deletions(-)

diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c
index d1f097c25..59ae58b98 100644
--- a/src/core/or/circuitbuild.c
+++ b/src/core/or/circuitbuild.c
@@ -98,12 +98,13 @@ channel_connect_for_circuit,(const extend_info_t *ei))
 {
   channel_t *chan;
 
-  const tor_addr_t *addr = &ei->addr;
-  uint16_t port = ei->port;
+  const tor_addr_port_t *orport = extend_info_pick_orport(ei);
+  if (!orport)
+    return NULL;
   const char *id_digest = ei->identity_digest;
   const ed25519_public_key_t *ed_id = &ei->ed_identity;
 
-  chan = channel_connect(addr, port, id_digest, ed_id);
+  chan = channel_connect(&orport->addr, orport->port, id_digest, ed_id);
   if (chan) command_setup_channel(chan);
 
   return chan;
@@ -551,7 +552,7 @@ circuit_handle_first_hop(origin_circuit_t *circ)
    * - the address is internal, and
    * - we're not connecting to a configured bridge, and
    * - we're not configured to allow extends to private addresses. */
-  if (tor_addr_is_internal(&firsthop->extend_info->addr, 0) &&
+  if (extend_info_any_orport_addr_is_internal(firsthop->extend_info) &&
       !extend_info_is_a_configured_bridge(firsthop->extend_info) &&
       !options->ExtendAllowPrivateAddresses) {
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
@@ -560,19 +561,19 @@ circuit_handle_first_hop(origin_circuit_t *circ)
   }
 
   /* now see if we're already connected to the first OR in 'route' */
-  log_debug(LD_CIRC,"Looking for firsthop '%s'",
-            fmt_addrport(&firsthop->extend_info->addr,
-                         firsthop->extend_info->port));
-
-  /* We'll cleanup this code in #33220, when we add an IPv6 address to
-   * extend_info_t. */
-  const bool addr_is_ipv4 =
-    (tor_addr_family(&firsthop->extend_info->addr) == AF_INET);
+  // TODO XXXX S55 -- remove this log
+  log_debug(LD_CIRC,"Looking for firsthop for %s",
+            extend_info_describe(firsthop->extend_info));
+
+  const tor_addr_port_t *orport4 =
+    extend_info_get_orport(firsthop->extend_info, AF_INET);
+  const tor_addr_port_t *orport6 =
+    extend_info_get_orport(firsthop->extend_info, AF_INET6);
   n_chan = channel_get_for_extend(
                           firsthop->extend_info->identity_digest,
                           &firsthop->extend_info->ed_identity,
-                          addr_is_ipv4 ? &firsthop->extend_info->addr : NULL,
-                          addr_is_ipv4 ? NULL : &firsthop->extend_info->addr,
+                          orport4 ? &orport4->addr : NULL,
+                          orport6 ? &orport6->addr : NULL,
                           &msg,
                           &should_launch);
 
@@ -1075,42 +1076,40 @@ circuit_send_intermediate_onion_skin(origin_circuit_t 
*circ,
                                      crypt_path_t *hop)
 {
   int len;
-  int family = tor_addr_family(&hop->extend_info->addr);
   extend_cell_t ec;
+  /* Relays and bridges can send IPv6 extends. But for clients, it's an
+   * obvious version distinguisher. */
+  const bool include_ipv6 = server_mode(get_options());
   memset(&ec, 0, sizeof(ec));
+  tor_addr_make_unspec(&ec.orport_ipv4.addr);
+  tor_addr_make_unspec(&ec.orport_ipv6.addr);
 
   log_debug(LD_CIRC,"starting to send subsequent skin.");
 
-  /* Relays and bridges can send IPv6 extends. But for clients, it's an
-   * obvious version distinguisher. */
-  if (server_mode(get_options())) {
-    if (family != AF_INET && family != AF_INET6) {
-      log_warn(LD_BUG, "Server trying to extend to an invalid address "
-               "family.");
-      return - END_CIRC_REASON_INTERNAL;
-    }
-  } else {
-    if (family != AF_INET) {
-      log_warn(LD_BUG, "Client trying to extend to a non-IPv4 address.");
-      return - END_CIRC_REASON_INTERNAL;
-    }
-  }
-
   circuit_pick_extend_handshake(&ec.cell_type,
                                 &ec.create_cell.cell_type,
                                 &ec.create_cell.handshake_type,
                                 hop->extend_info);
 
-  /* At the moment, extend_info only has one ORPort address. We'll add a
-   * second address in #34069, to support dual-stack extend cells. */
-  if (family == AF_INET) {
-    tor_addr_copy(&ec.orport_ipv4.addr, &hop->extend_info->addr);
-    ec.orport_ipv4.port = hop->extend_info->port;
-    tor_addr_make_unspec(&ec.orport_ipv6.addr);
-  } else {
-    tor_addr_copy(&ec.orport_ipv6.addr, &hop->extend_info->addr);
-    ec.orport_ipv6.port = hop->extend_info->port;
-    tor_addr_make_unspec(&ec.orport_ipv4.addr);
+  const tor_addr_port_t *orport4 =
+    extend_info_get_orport(hop->extend_info, AF_INET);
+  const tor_addr_port_t *orport6 =
+    extend_info_get_orport(hop->extend_info, AF_INET6);
+  int n_addrs_set = 0;
+  if (orport4) {
+    tor_addr_copy(&ec.orport_ipv4.addr, &orport4->addr);
+    ec.orport_ipv4.port = orport4->port;
+    ++n_addrs_set;
+  }
+  if (orport6 && include_ipv6) {
+    tor_addr_copy(&ec.orport_ipv6.addr, &orport6->addr);
+    ec.orport_ipv6.port = orport6->port;
+    ++n_addrs_set;
+  }
+
+  if (n_addrs_set == 0) {
+    log_warn(LD_BUG, "No supported address family found in extend_info.");
+    return - END_CIRC_REASON_INTERNAL;
   }
   memcpy(ec.node_id, hop->extend_info->identity_digest, DIGEST_LEN);
   /* Set the ED25519 identity too -- it will only get included
diff --git a/src/core/or/extend_info_st.h b/src/core/or/extend_info_st.h
index 7f1187cb8..757c6a177 100644
--- a/src/core/or/extend_info_st.h
+++ b/src/core/or/extend_info_st.h
@@ -15,6 +15,11 @@
 #include "lib/crypt_ops/crypto_curve25519.h"
 #include "lib/crypt_ops/crypto_ed25519.h"
 
+/** Largest number of addresses we handle in an extend_info.
+ *
+ * More are permitted in an EXTEND cell, but we won't handle them. */
+#define EXTEND_INFO_MAX_ADDRS 2
+
 /** Information on router used when extending a circuit. We don't need a
  * full routerinfo_t to extend: we only need addr:port:keyid to build an OR
  * connection, and onion_key to create the onionskin. Note that for one-hop
@@ -26,8 +31,9 @@ struct extend_info_t {
   char identity_digest[DIGEST_LEN];
   /** Ed25519 identity for this router, if any. */
   ed25519_public_key_t ed_identity;
-  uint16_t port; /**< OR port. */
-  tor_addr_t addr; /**< IP address. */
+  /** IP/Port values for this hop's ORPort(s).  Any unused values are set
+   * to a null address. */
+  tor_addr_port_t orports[EXTEND_INFO_MAX_ADDRS];
   /** TAP onion key for this hop. */
   crypto_pk_t *onion_key;
   /** Ntor onion key for this hop. */
diff --git a/src/core/or/extendinfo.c b/src/core/or/extendinfo.c
index 8f506d774..e4aec634a 100644
--- a/src/core/or/extendinfo.c
+++ b/src/core/or/extendinfo.c
@@ -46,11 +46,35 @@ extend_info_new(const char *nickname,
   if (ntor_key)
     memcpy(&info->curve25519_onion_key, ntor_key,
            sizeof(curve25519_public_key_t));
-  tor_addr_copy(&info->addr, addr);
-  info->port = port;
+  for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
+    tor_addr_make_unspec(&info->orports[i].addr);
+  }
+
+  if (addr) {
+    extend_info_add_orport(info, addr, port);
+  }
   return info;
 }
 
+/**
+ * Add another address:port pair to a given extend_info_t, if there is
+ * room.  Return 0 on success, -1 on failure.
+ **/
+int
+extend_info_add_orport(extend_info_t *ei,
+                       const tor_addr_t *addr,
+                       uint16_t port)
+{
+  for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
+    if (tor_addr_is_unspec(&ei->orports[i].addr)) {
+      tor_addr_copy(&ei->orports[i].addr, addr);
+      ei->orports[i].port = port;
+      return 0;
+    }
+  }
+  return -1;
+}
+
 /** Allocate and return a new extend_info that can be used to build a
  * circuit to or through the node <b>node</b>. Use the primary address
  * of the node (i.e. its IPv4 address) unless
@@ -219,5 +243,61 @@ extend_info_has_orport(const extend_info_t *ei,
   IF_BUG_ONCE(ei == NULL)
     return false;
 
-  return tor_addr_eq(&ei->addr, addr) && ei->port == port;
+  for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
+    const tor_addr_port_t *ei_ap = &ei->orports[i];
+    if (tor_addr_eq(&ei_ap->addr, addr) && ei_ap->port == port)
+      return true;
+  }
+  return false;
+}
+
+/**
+ * If the extend_info @a ei has an orport of the chosen family, then return
+ * that orport.  Otherwise, return NULL.
+ **/
+const tor_addr_port_t *
+extend_info_get_orport(const extend_info_t *ei, int family)
+{
+  for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
+    if (tor_addr_is_unspec(&ei->orports[i].addr))
+      continue;
+    if (tor_addr_family(&ei->orports[i].addr) == family)
+      return &ei->orports[i];
+  }
+  return NULL;
+}
+
+/**
+ * Chose an addr_port_t within @a ei to connect to.
+ **/
+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;
+  }
+
+  if (tor_addr_is_unspec(&ei->orports[0].addr)) {
+    return NULL;
+  }
+  return &ei->orports[0];
+}
+
+/**
+ * Return true if any orport address in @a ei is an internal address.
+ **/
+bool
+extend_info_any_orport_addr_is_internal(const extend_info_t *ei)
+{
+  IF_BUG_ONCE(ei == NULL)
+    return false;
+
+  for (int i = 0; i < EXTEND_INFO_MAX_ADDRS; ++i) {
+    if (! tor_addr_is_unspec(&ei->orports[i].addr) &&
+        tor_addr_is_internal(&ei->orports[i].addr, 0))
+      return true;
+  }
+  return false;
 }
diff --git a/src/core/or/extendinfo.h b/src/core/or/extendinfo.h
index 6ebacccf1..0049dd018 100644
--- a/src/core/or/extendinfo.h
+++ b/src/core/or/extendinfo.h
@@ -29,5 +29,12 @@ int extend_info_supports_ntor(const extend_info_t* ei);
 int extend_info_has_preferred_onion_key(const extend_info_t* ei);
 bool extend_info_has_orport(const extend_info_t *ei,
                             const tor_addr_t *addr, uint16_t port);
+int extend_info_add_orport(extend_info_t *ei,
+                           const tor_addr_t *addr,
+                           uint16_t port);
+const tor_addr_port_t *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);
+bool extend_info_any_orport_addr_is_internal(const extend_info_t *ei);
 
 #endif /* !defined(TOR_CORE_OR_EXTENDINFO_H) */
diff --git a/src/feature/client/bridges.c b/src/feature/client/bridges.c
index 66b04f3bc..3a3d1bb68 100644
--- a/src/feature/client/bridges.c
+++ b/src/feature/client/bridges.c
@@ -259,12 +259,25 @@ addr_is_a_configured_bridge(const tor_addr_t *addr,
 /** If we have a bridge configured whose digest matches
  * <b>ei->identity_digest</b>, or a bridge with no known digest whose address
  * matches <b>ei->addr</b>:<b>ei->port</b>, return 1.  Else return 0.
- * If <b>ei->onion_key</b> is NULL, check for address/port matches only. */
+ * If <b>ei->onion_key</b> is NULL, check for address/port matches only.
+ *
+ * Note that if the extend_info_t contains multiple addresses, we return true
+ * only if _every_ address is a bridge.
+ */
 int
 extend_info_is_a_configured_bridge(const extend_info_t *ei)
 {
   const char *digest = ei->onion_key ? ei->identity_digest : NULL;
-  return addr_is_a_configured_bridge(&ei->addr, ei->port, digest);
+  const tor_addr_port_t *ap1 = NULL, *ap2 = NULL;
+  if (! tor_addr_is_null(&ei->orports[0].addr))
+    ap1 = &ei->orports[0];
+  if (! tor_addr_is_null(&ei->orports[1].addr))
+    ap2 = &ei->orports[1];
+  IF_BUG_ONCE(ap1 == NULL)
+    return 0;
+  return addr_is_a_configured_bridge(&ap1->addr, ap1->port, digest) &&
+    (ap2 == NULL ||
+     addr_is_a_configured_bridge(&ap2->addr, ap2->port, digest));
 }
 
 /** Wrapper around get_configured_bridge_by_addr_port_digest() to look
diff --git a/src/feature/nodelist/describe.c b/src/feature/nodelist/describe.c
index 00896d5a4..f11843649 100644
--- a/src/feature/nodelist/describe.c
+++ b/src/feature/nodelist/describe.c
@@ -12,6 +12,7 @@
 #define DESCRIBE_PRIVATE
 
 #include "core/or/or.h"
+#include "core/or/extendinfo.h"
 #include "feature/nodelist/describe.h"
 
 #include "core/or/extend_info_st.h"
@@ -208,11 +209,16 @@ extend_info_describe(const extend_info_t *ei)
   if (!ei)
     return "<null>";
 
+  const tor_addr_port_t *ap4 = extend_info_get_orport(ei, AF_INET);
+  const tor_addr_port_t *ap6 = extend_info_get_orport(ei, AF_INET6);
+  uint32_t addr4 = ap4 ? tor_addr_to_ipv4h(&ap4->addr) : 0;
+  const tor_addr_t *addr6 = ap6 ? &ap6->addr : NULL;
+
   return format_node_description(buf,
                                  ei->identity_digest,
                                  ei->nickname,
-                                 &ei->addr,
-                                 0);
+                                 addr6,
+                                 addr4);
 }
 
 /** Set <b>buf</b> (which must have MAX_VERBOSE_NICKNAME_LEN+1 bytes) to the
diff --git a/src/feature/nodelist/routerset.c b/src/feature/nodelist/routerset.c
index ebc08b7a5..cba7203d4 100644
--- a/src/feature/nodelist/routerset.c
+++ b/src/feature/nodelist/routerset.c
@@ -306,12 +306,19 @@ routerset_add_unknown_ccs(routerset_t **setp, int 
only_if_some_cc_set)
 int
 routerset_contains_extendinfo(const routerset_t *set, const extend_info_t *ei)
 {
-  return routerset_contains(set,
-                            &ei->addr,
-                            ei->port,
-                            ei->nickname,
-                            ei->identity_digest,
-                            -1 /*country*/);
+  const tor_addr_port_t *ap1 = NULL, *ap2 = NULL;
+  if (! tor_addr_is_null(&ei->orports[0].addr))
+    ap1 = &ei->orports[0];
+  if (! tor_addr_is_null(&ei->orports[1].addr))
+    ap2 = &ei->orports[1];
+  return routerset_contains2(set,
+                             ap1 ? &ap1->addr : NULL,
+                             ap1 ? ap1->port : 0,
+                             ap2 ? &ap2->addr : NULL,
+                             ap2 ? ap2->port : 0,
+                             ei->nickname,
+                             ei->identity_digest,
+                             -1 /*country*/);
 }
 
 /** Return true iff <b>ri</b> is in <b>set</b>.  If country is <b>-1</b>, we
diff --git a/src/feature/relay/selftest.c b/src/feature/relay/selftest.c
index c663eb26b..77c04abdd 100644
--- a/src/feature/relay/selftest.c
+++ b/src/feature/relay/selftest.c
@@ -256,14 +256,15 @@ router_do_orport_reachability_checks(const routerinfo_t 
*me,
    * be NULL. */
   if (ei) {
     const char *family_name = fmt_af_family(family);
+    const tor_addr_port_t *ap = extend_info_get_orport(ei, family);
     log_info(LD_CIRC, "Testing %s of my %s ORPort: %s.",
              !orport_reachable ? "reachability" : "bandwidth",
-             family_name, fmt_addrport(&ei->addr, ei->port));
+             family_name, fmt_addrport_ap(ap));
     if (!orport_reachable) {
       /* This is only a 'reachability test' if we don't already think that
        * the port is reachable.  If we _do_ think it's reachable, then
        * it counts as a 'bandwidth test'. */
-      inform_testing_reachability(&ei->addr, ei->port, false);
+      inform_testing_reachability(&ap->addr, ap->port, false);
     }
     circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei,
                                   CIRCLAUNCH_NEED_CAPACITY|
diff --git a/src/feature/rend/rendclient.c b/src/feature/rend/rendclient.c
index 9c2286bbc..e171562d1 100644
--- a/src/feature/rend/rendclient.c
+++ b/src/feature/rend/rendclient.c
@@ -235,9 +235,15 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
     /* version 2 format */
     extend_info_t *extend_info = rendcirc->build_state->chosen_exit;
     int klen;
+    const tor_addr_port_t *orport =
+      extend_info_get_orport(extend_info, AF_INET);
+    IF_BUG_ONCE(! orport) {
+      /* we should never put an IPv6 address here. */
+      goto perm_err;
+    }
     /* nul pads */
-    set_uint32(tmp+v3_shift+1, tor_addr_to_ipv4n(&extend_info->addr));
-    set_uint16(tmp+v3_shift+5, htons(extend_info->port));
+    set_uint32(tmp+v3_shift+1, tor_addr_to_ipv4n(&orport->addr));
+    set_uint16(tmp+v3_shift+5, htons(orport->port));
     memcpy(tmp+v3_shift+7, extend_info->identity_digest, DIGEST_LEN);
     klen = crypto_pk_asn1_encode(extend_info->onion_key,
                                  tmp+v3_shift+7+DIGEST_LEN+2,
diff --git a/src/feature/rend/rendcommon.c b/src/feature/rend/rendcommon.c
index 07cbeaa2f..775d48780 100644
--- a/src/feature/rend/rendcommon.c
+++ b/src/feature/rend/rendcommon.c
@@ -234,7 +234,12 @@ rend_encode_v2_intro_points(char **encoded, 
rend_service_descriptor_t *desc)
       goto done;
     }
     /* Assemble everything for this introduction point. */
-    address = tor_addr_to_str_dup(&info->addr);
+    const tor_addr_port_t *orport = extend_info_get_orport(info, AF_INET);
+    IF_BUG_ONCE(!orport) {
+      /* There must be an IPv4 address for v2 hs. */
+      goto done;
+    }
+    address = tor_addr_to_str_dup(&orport->addr);
     res = tor_snprintf(unenc + unenc_written, unenc_len - unenc_written,
                          "introduction-point %s\n"
                          "ip-address %s\n"
@@ -243,7 +248,7 @@ rend_encode_v2_intro_points(char **encoded, 
rend_service_descriptor_t *desc)
                          "service-key\n%s",
                        id_base32,
                        address,
-                       info->port,
+                       orport->port,
                        onion_key,
                        service_key);
     tor_free(address);
diff --git a/src/feature/rend/rendparse.c b/src/feature/rend/rendparse.c
index 0979d767a..c28add5ca 100644
--- a/src/feature/rend/rendparse.c
+++ b/src/feature/rend/rendparse.c
@@ -10,6 +10,7 @@
  **/
 
 #include "core/or/or.h"
+#include "core/or/extendinfo.h"
 #include "feature/dirparse/parsecommon.h"
 #include "feature/dirparse/sigcommon.h"
 #include "feature/rend/rendcommon.h"
@@ -428,7 +429,8 @@ rend_parse_introduction_points(rend_service_descriptor_t 
*parsed,
     }
     /* Allocate new intro point and extend info. */
     intro = tor_malloc_zero(sizeof(rend_intro_point_t));
-    info = intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
+    info = intro->extend_info =
+      extend_info_new(NULL, NULL, NULL, NULL, NULL, NULL, 0);
     /* Parse identifier. */
     tok = find_by_keyword(tokens, R_IPO_IDENTIFIER);
     if (base32_decode(info->identity_digest, DIGEST_LEN,
@@ -446,12 +448,13 @@ rend_parse_introduction_points(rend_service_descriptor_t 
*parsed,
                   info->identity_digest, DIGEST_LEN);
     /* Parse IP address. */
     tok = find_by_keyword(tokens, R_IPO_IP_ADDRESS);
-    if (tor_addr_parse(&info->addr, tok->args[0])<0) {
+    tor_addr_t addr;
+    if (tor_addr_parse(&addr, tok->args[0])<0) {
       log_warn(LD_REND, "Could not parse introduction point address.");
       rend_intro_point_free(intro);
       goto err;
     }
-    if (tor_addr_family(&info->addr) != AF_INET) {
+    if (tor_addr_family(&addr) != AF_INET) {
       log_warn(LD_REND, "Introduction point address was not ipv4.");
       rend_intro_point_free(intro);
       goto err;
@@ -459,14 +462,18 @@ rend_parse_introduction_points(rend_service_descriptor_t 
*parsed,
 
     /* Parse onion port. */
     tok = find_by_keyword(tokens, R_IPO_ONION_PORT);
-    info->port = (uint16_t) tor_parse_long(tok->args[0],10,1,65535,
+    uint16_t port = (uint16_t) tor_parse_long(tok->args[0],10,1,65535,
                                            &num_ok,NULL);
-    if (!info->port || !num_ok) {
+    if (!port || !num_ok) {
       log_warn(LD_REND, "Introduction point onion port %s is invalid",
                escaped(tok->args[0]));
       rend_intro_point_free(intro);
       goto err;
     }
+
+    /* Add the address and port. */
+    extend_info_add_orport(info, &addr, port);
+
     /* Parse onion key. */
     tok = find_by_keyword(tokens, R_IPO_ONION_KEY);
     if (!crypto_pk_public_exponent_ok(tok->key)) {
diff --git a/src/feature/rend/rendservice.c b/src/feature/rend/rendservice.c
index 8154840f1..1c456cb6e 100644
--- a/src/feature/rend/rendservice.c
+++ b/src/feature/rend/rendservice.c
@@ -1832,8 +1832,11 @@ rend_service_use_direct_connection(const or_options_t* 
options,
   /* We'll connect directly all reachable addresses, whether preferred or not.
    * The prefer_ipv6 argument to fascist_firewall_allows_address_addr is
    * ignored, because pref_only is 0. */
+  const tor_addr_port_t *ap = extend_info_get_orport(ei, AF_INET);
+  if (!ap)
+    return 0;
   return (rend_service_allow_non_anonymous_connection(options) &&
-          fascist_firewall_allows_address_addr(&ei->addr, ei->port,
+          fascist_firewall_allows_address_addr(&ap->addr, ap->port,
                                                FIREWALL_OR_CONNECTION, 0, 0));
 }
 
@@ -2262,7 +2265,8 @@ find_rp_for_intro(const rend_intro_cell_t *intro,
   /* Make sure the RP we are being asked to connect to is _not_ a private
    * address unless it's allowed. Let's avoid to build a circuit to our
    * second middle node and fail right after when extending to the RP. */
-  if (!extend_info_addr_is_allowed(&rp->addr)) {
+  const tor_addr_port_t *orport = extend_info_get_orport(rp, AF_INET);
+  if (! orport || !extend_info_addr_is_allowed(&orport->addr)) {
     if (err_msg_out) {
       tor_asprintf(&err_msg,
                    "Relay IP in INTRODUCE2 cell is private address.");
@@ -2531,9 +2535,11 @@ rend_service_parse_intro_for_v2(
     goto err;
   }
 
-  extend_info = tor_malloc_zero(sizeof(extend_info_t));
-  tor_addr_from_ipv4n(&extend_info->addr, get_uint32(buf + 1));
-  extend_info->port = ntohs(get_uint16(buf + 5));
+  extend_info = extend_info_new(NULL, NULL, NULL, NULL, NULL, NULL, 0);
+  tor_addr_t addr;
+  tor_addr_from_ipv4n(&addr, get_uint32(buf + 1));
+  uint16_t port = ntohs(get_uint16(buf + 5));
+  extend_info_add_orport(extend_info, &addr, port);
   memcpy(extend_info->identity_digest, buf + 7, DIGEST_LEN);
   extend_info->nickname[0] = '$';
   base16_encode(extend_info->nickname + 1, sizeof(extend_info->nickname) - 1,
diff --git a/src/test/rend_test_helpers.c b/src/test/rend_test_helpers.c
index 61bacb4d2..8e40167ae 100644
--- a/src/test/rend_test_helpers.c
+++ b/src/test/rend_test_helpers.c
@@ -2,6 +2,7 @@
 /* See LICENSE for licensing information */
 
 #include "core/or/or.h"
+#include "core/or/extendinfo.h"
 #include "lib/crypt_ops/crypto_rand.h"
 #include "test/test.h"
 #include "feature/rend/rendcommon.h"
@@ -58,7 +59,8 @@ create_descriptor(rend_service_descriptor_t **generated, char 
**service_id,
   for (i = 0; i < intro_points; i++) {
     rend_intro_point_t *intro = tor_malloc_zero(sizeof(rend_intro_point_t));
     crypto_pk_t *okey = pk_generate(2 + i);
-    intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
+    intro->extend_info =
+      extend_info_new(NULL, NULL, NULL, NULL, NULL, NULL, 0);
     intro->extend_info->onion_key = okey;
     crypto_pk_get_digest(intro->extend_info->onion_key,
                          intro->extend_info->identity_digest);
@@ -66,8 +68,12 @@ create_descriptor(rend_service_descriptor_t **generated, 
char **service_id,
     base16_encode(intro->extend_info->nickname + 1,
                   sizeof(intro->extend_info->nickname) - 1,
                   intro->extend_info->identity_digest, DIGEST_LEN);
-    tor_addr_from_ipv4h(&intro->extend_info->addr, crypto_rand_int(65536));
-    intro->extend_info->port = 1 + crypto_rand_int(65535);
+    tor_addr_t addr;
+    uint16_t port;
+    /* Does not cover all IP addresses. */
+    tor_addr_from_ipv4h(&addr, crypto_rand_int(65536) + 1);
+    port = 1 + crypto_rand_int(65535);
+    extend_info_add_orport(intro->extend_info, &addr, port);
     intro->intro_key = crypto_pk_dup_key(pk2);
     smartlist_add((*generated)->intro_nodes, intro);
   }
@@ -91,4 +97,3 @@ mock_rend_data(const char *onion_address)
                                                  DIGEST_LEN));
   return rend_query;
 }
-
diff --git a/src/test/test.c b/src/test/test.c
index 4b6082ce4..2961669c4 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -1,5 +1,5 @@
 /* Copyright (c) 2001-2004, Roger Dingledine.
- * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+->a * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  * Copyright (c) 2007-2020, The Tor Project, Inc. */
 /* See LICENSE for licensing information */
 
@@ -44,6 +44,7 @@
 #include "lib/compress/compress.h"
 #include "app/config/config.h"
 #include "core/or/connection_edge.h"
+#include "core/or/extendinfo.h"
 #include "feature/rend/rendcommon.h"
 #include "feature/rend/rendcache.h"
 #include "feature/rend/rendparse.h"
@@ -564,7 +565,8 @@ test_rend_fns(void *arg)
   for (i = 0; i < 3; i++) {
     rend_intro_point_t *intro = tor_malloc_zero(sizeof(rend_intro_point_t));
     crypto_pk_t *okey = pk_generate(2 + i);
-    intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
+    intro->extend_info =
+      extend_info_new(NULL, NULL, NULL, NULL, NULL, NULL, 0);
     intro->extend_info->onion_key = okey;
     crypto_pk_get_digest(intro->extend_info->onion_key,
                          intro->extend_info->identity_digest);
@@ -573,9 +575,12 @@ test_rend_fns(void *arg)
     base16_encode(intro->extend_info->nickname + 1,
                   sizeof(intro->extend_info->nickname) - 1,
                   intro->extend_info->identity_digest, DIGEST_LEN);
+    tor_addr_t addr;
+    uint16_t port;
     /* Does not cover all IP addresses. */
-    tor_addr_from_ipv4h(&intro->extend_info->addr, crypto_rand_int(65536));
-    intro->extend_info->port = 1 + crypto_rand_int(65535);
+    tor_addr_from_ipv4h(&addr, crypto_rand_int(65536) + 1);
+    port = 1 + crypto_rand_int(65535);
+    extend_info_add_orport(intro->extend_info, &addr, port);
     intro->intro_key = crypto_pk_dup_key(pk2);
     smartlist_add(generated->intro_nodes, intro);
   }
@@ -613,8 +618,12 @@ test_rend_fns(void *arg)
     tt_mem_op(gen_info->identity_digest,OP_EQ, par_info->identity_digest,
                DIGEST_LEN);
     tt_str_op(gen_info->nickname,OP_EQ, par_info->nickname);
-    tt_assert(tor_addr_eq(&gen_info->addr, &par_info->addr));
-    tt_int_op(gen_info->port,OP_EQ, par_info->port);
+    const tor_addr_port_t *a1, *a2;
+    a1 = extend_info_get_orport(gen_info, AF_INET);
+    a2 = extend_info_get_orport(par_info, AF_INET);
+    tt_assert(a1 && a2);
+    tt_assert(tor_addr_eq(&a1->addr, &a2->addr));
+    tt_int_op(a2->port,OP_EQ, a2->port);
   }
 
   rend_service_descriptor_free(parsed);
diff --git a/src/test/test_circuitbuild.c b/src/test/test_circuitbuild.c
index f7a27146b..8f0e8b54e 100644
--- a/src/test/test_circuitbuild.c
+++ b/src/test/test_circuitbuild.c
@@ -1677,14 +1677,14 @@ test_circuit_send_next_onion_skin(void *arg)
 
   extend_info_t ipv6_hop;
   memset(&ipv6_hop, 0, sizeof(ipv6_hop));
-  tor_addr_make_null(&ipv6_hop.addr, AF_INET6);
+  tor_addr_parse(&ipv6_hop.orports[0].addr, "1::2");
   extend_info_t *multi_ipv6_hop[DEFAULT_ROUTE_LEN] = {&ipv6_hop,
                                                       &ipv6_hop,
                                                       &ipv6_hop};
 
   extend_info_t ipv4_hop;
   memset(&ipv4_hop, 0, sizeof(ipv4_hop));
-  tor_addr_make_null(&ipv4_hop.addr, AF_INET);
+  tor_addr_from_ipv4h(&ipv4_hop.orports[0].addr, 0x20304050);
   extend_info_t *multi_ipv4_hop[DEFAULT_ROUTE_LEN] = {&ipv4_hop,
                                                       &ipv4_hop,
                                                       &ipv4_hop};
@@ -1737,7 +1737,7 @@ test_circuit_send_next_onion_skin(void *arg)
   /* Fail because the address family is invalid */
   tt_int_op(circuit_send_next_onion_skin(origin_circ), OP_EQ,
             -END_CIRC_REASON_INTERNAL);
-  expect_log_msg("Client trying to extend to a non-IPv4 address.\n");
+  expect_log_msg("No supported address family found in extend_info.\n");
   mock_clean_saved_logs();
 
   /* Try an extend, but fail the server valid address check */
@@ -1751,7 +1751,7 @@ test_circuit_send_next_onion_skin(void *arg)
   mock_circuit_deliver_create_cell_expect_direct = false;
   tt_int_op(circuit_send_next_onion_skin(origin_circ), OP_EQ,
             -END_CIRC_REASON_INTERNAL);
-  expect_log_msg("Server trying to extend to an invalid address family.\n");
+  expect_log_msg("No supported address family found in extend_info.\n");
   mock_clean_saved_logs();
 
   /* Try an extend, but fail in the client code, with an IPv6 address */
@@ -1765,7 +1765,7 @@ test_circuit_send_next_onion_skin(void *arg)
   mock_circuit_deliver_create_cell_expect_direct = false;
   tt_int_op(circuit_send_next_onion_skin(origin_circ), OP_EQ,
             -END_CIRC_REASON_INTERNAL);
-  expect_log_msg("Client trying to extend to a non-IPv4 address.\n");
+  expect_log_msg("No supported address family found in extend_info.\n");
   mock_clean_saved_logs();
 
   /* Stop capturing bugs, but keep capturing logs */
diff --git a/src/test/test_hs_client.c b/src/test/test_hs_client.c
index 3fef1b41c..f965344ce 100644
--- a/src/test/test_hs_client.c
+++ b/src/test/test_hs_client.c
@@ -530,7 +530,7 @@ test_client_pick_intro(void *arg)
         get_options_mutable()->ClientUseIPv6 = 1;
         intro_ei = hs_get_extend_info_from_lspecs(ip->link_specifiers,
                                                   &ip->onion_key, 1);
-        tt_assert(tor_addr_family(&intro_ei->addr) == AF_INET6);
+        tt_assert(tor_addr_family(&intro_ei->orports[0].addr) == AF_INET6);
       }
       tt_assert(intro_ei);
       if (intro_ei) {
@@ -538,7 +538,8 @@ test_client_pick_intro(void *arg)
         char ip_addr[TOR_ADDR_BUF_LEN];
         /* We need to decorate in case it is an IPv6 else routerset_parse()
          * doesn't like it. */
-        ptr = tor_addr_to_str(ip_addr, &intro_ei->addr, sizeof(ip_addr), 1);
+        ptr = tor_addr_to_str(ip_addr, &intro_ei->orports[0].addr,
+                              sizeof(ip_addr), 1);
         tt_assert(ptr == ip_addr);
         ret = routerset_parse(get_options_mutable()->ExcludeNodes,
                               ip_addr, "");
diff --git a/src/test/test_nodelist.c b/src/test/test_nodelist.c
index fbbbf0a99..93d1ce453 100644
--- a/src/test/test_nodelist.c
+++ b/src/test/test_nodelist.c
@@ -1182,11 +1182,11 @@ test_nodelist_extend_info_describe(void *arg)
          sizeof(mock_ei_ipv4.identity_digest));
   strlcpy(mock_ei_ipv4.nickname, "TestOR7890123456789",
           sizeof(mock_ei_ipv4.nickname));
-  tor_addr_parse(&mock_ei_ipv4.addr, "111.222.233.244");
+  tor_addr_parse(&mock_ei_ipv4.orports[0].addr, "111.222.233.244");
 
   /* Create and modify the other extend info. */
   memcpy(&mock_ei_ipv6, &mock_ei_ipv4, sizeof(mock_ei_ipv6));
-  tor_addr_parse(&mock_ei_ipv6.addr,
+  tor_addr_parse(&mock_ei_ipv6.orports[0].addr,
                  "[1111:2222:3333:4444:5555:6666:7777:8888]");
 
   /* We don't test the no-nickname and no-IP cases, because they're covered by
diff --git a/src/test/test_policy.c b/src/test/test_policy.c
index 6cb588a0e..388b5c74c 100644
--- a/src/test/test_policy.c
+++ b/src/test/test_policy.c
@@ -2085,8 +2085,8 @@ test_policies_fascist_firewall_allows_address(void *arg)
       expect_single_log_msg("Specified link specifiers is null"); \
     } else { \
       expect_no_log_entry(); \
-      tt_assert(tor_addr_eq(&(expect_ap).addr, &ei->addr)); \
-      tt_int_op((expect_ap).port, OP_EQ, ei->port); \
+      tt_assert(tor_addr_eq(&(expect_ap).addr, &ei->orports[0].addr)); \
+      tt_int_op((expect_ap).port, OP_EQ, ei->orports[0].port); \
       extend_info_free(ei); \
     } \
     teardown_capture_of_logs(); \



_______________________________________________
tor-commits mailing list
tor-commits@lists.torproject.org
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits

Reply via email to