summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/address.h7
-rw-r--r--src/or/circuitbuild.c75
-rw-r--r--src/or/circuitbuild.h6
-rw-r--r--src/or/circuituse.c5
-rw-r--r--src/or/control.c2
-rw-r--r--src/or/nodelist.c121
-rw-r--r--src/or/nodelist.h16
-rw-r--r--src/or/or.h2
-rw-r--r--src/or/rendclient.c2
-rw-r--r--src/or/rendservice.c4
-rw-r--r--src/or/router.c56
-rw-r--r--src/or/router.h7
12 files changed, 253 insertions, 50 deletions
diff --git a/src/common/address.h b/src/common/address.h
index bc225a65ea..4568c32bf9 100644
--- a/src/common/address.h
+++ b/src/common/address.h
@@ -31,6 +31,13 @@ typedef struct tor_addr_t
} addr;
} tor_addr_t;
+/** Holds an IP address and a TCP/UDP port. */
+typedef struct tor_addr_port_t
+{
+ tor_addr_t addr;
+ uint16_t port;
+} tor_addr_port_t;
+
static INLINE const struct in6_addr *tor_addr_to_in6(const tor_addr_t *a);
static INLINE uint32_t tor_addr_to_ipv4n(const tor_addr_t *a);
static INLINE uint32_t tor_addr_to_ipv4h(const tor_addr_t *a);
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 1cfeb030d3..fbd55ddfee 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -3012,7 +3012,7 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit)
log_warn(LD_CIRC,"failed to choose an exit server");
return -1;
}
- exit = extend_info_from_node(node);
+ exit = extend_info_from_node(node, 0);
tor_assert(exit);
}
state->chosen_exit = exit;
@@ -3254,14 +3254,19 @@ onion_extend_cpath(origin_circuit_t *circ)
} else if (cur_len == 0) { /* picking first node */
const node_t *r = choose_good_entry_server(purpose, state);
if (r) {
- info = extend_info_from_node(r);
+ /* If we're extending to a bridge, use the preferred address
+ rather than the primary, for potentially extending to an IPv6
+ bridge. */
+ int use_pref_addr = (r->ri != NULL &&
+ r->ri->purpose == ROUTER_PURPOSE_BRIDGE);
+ info = extend_info_from_node(r, use_pref_addr);
tor_assert(info);
}
} else {
const node_t *r =
choose_good_middle_server(purpose, state, circ->cpath, cur_len);
if (r) {
- info = extend_info_from_node(r);
+ info = extend_info_from_node(r, 0);
tor_assert(info);
}
}
@@ -3320,28 +3325,37 @@ extend_info_alloc(const char *nickname, const char *digest,
return info;
}
-/** Allocate and return a new extend_info_t that can be used to build a
- * circuit to or through the router <b>r</b>. */
+/** Allocate and return a new extend_info_t that can be used to build
+ * a circuit to or through the router <b>r</b>. Use the primary
+ * address of the router unless <b>for_direct_connect</b> is true, in
+ * which case the preferred address is used instead. */
extend_info_t *
-extend_info_from_router(const routerinfo_t *r)
+extend_info_from_router(const routerinfo_t *r, int for_direct_connect)
{
tor_addr_t addr;
+ uint16_t port;
tor_assert(r);
- tor_addr_from_ipv4h(&addr, r->addr);
+
+ if (for_direct_connect)
+ router_get_pref_addr_port(r, &addr, &port);
+ else
+ router_get_prim_addr_port(r, &addr, &port);
return extend_info_alloc(r->nickname, r->cache_info.identity_digest,
- r->onion_pkey, &addr, r->or_port);
+ r->onion_pkey, &addr, port);
}
-/** Allocate and return a new extend_info that can be used to build a ircuit
- * to or through the node <b>node</b>. May return NULL if there is not
- * enough info about <b>node</b> to extend to it--for example, if there
- * is no routerinfo_t or microdesc_t.
+/** Allocate and return a new extend_info that can be used to build a
+ * ircuit to or through the node <b>node</b>. Use the primary address
+ * of the node unless <b>for_direct_connect</b> is true, in which case
+ * the preferred address is used instead. May return NULL if there is
+ * not enough info about <b>node</b> to extend to it--for example, if
+ * there is no routerinfo_t or microdesc_t.
**/
extend_info_t *
-extend_info_from_node(const node_t *node)
+extend_info_from_node(const node_t *node, int for_direct_connect)
{
if (node->ri) {
- return extend_info_from_router(node->ri);
+ return extend_info_from_router(node->ri, for_direct_connect);
} else if (node->rs && node->md) {
tor_addr_t addr;
tor_addr_from_ipv4h(&addr, node->rs->addr);
@@ -4858,18 +4872,31 @@ routerinfo_is_a_configured_bridge(const routerinfo_t *ri)
int
node_is_a_configured_bridge(const node_t *node)
{
- tor_addr_t addr;
- uint16_t orport;
+ int retval = 0; /* Negative. */
+ smartlist_t *orports = NULL;
+
if (!node)
- return 0;
- if (node_get_addr(node, &addr) < 0)
- return 0;
- orport = node_get_orport(node);
- if (orport == 0)
- return 0;
+ goto out;
+
+ orports = node_get_all_orports(node);
+ if (orports == NULL)
+ goto out;
- return get_configured_bridge_by_addr_port_digest(
- &addr, orport, node->identity) != NULL;
+ SMARTLIST_FOREACH_BEGIN(orports, tor_addr_port_t *, orport) {
+ if (get_configured_bridge_by_addr_port_digest(&orport->addr, orport->port,
+ node->identity) != NULL) {
+ retval = 1;
+ goto out;
+ }
+ } SMARTLIST_FOREACH_END(orport);
+
+out:
+ if (orports != NULL) {
+ SMARTLIST_FOREACH(orports, tor_addr_port_t *, p, tor_free(p));
+ smartlist_free(orports);
+ orports = NULL;
+ }
+ return retval;
}
/** We made a connection to a router at <b>addr</b>:<b>port</b>
diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h
index 1052db6153..8df2748708 100644
--- a/src/or/circuitbuild.h
+++ b/src/or/circuitbuild.h
@@ -59,8 +59,10 @@ void onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop);
extend_info_t *extend_info_alloc(const char *nickname, const char *digest,
crypto_pk_env_t *onion_key,
const tor_addr_t *addr, uint16_t port);
-extend_info_t *extend_info_from_router(const routerinfo_t *r);
-extend_info_t *extend_info_from_node(const node_t *node);
+extend_info_t *extend_info_from_router(const routerinfo_t *r,
+ int for_direct_connect);
+extend_info_t *extend_info_from_node(const node_t *node,
+ int for_direct_connect);
extend_info_t *extend_info_dup(extend_info_t *info);
void extend_info_free(extend_info_t *info);
const node_t *build_state_get_exit_node(cpath_build_state_t *state);
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 23efe05348..4382d44127 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -1439,7 +1439,10 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
int opt = conn->chosen_exit_optional;
r = node_get_by_nickname(conn->chosen_exit_name, 1);
if (r && node_has_descriptor(r)) {
- extend_info = extend_info_from_node(r);
+ /* We might want to connect to an IPv6 bridge for loading
+ descriptors so we use the preferred address rather than
+ the primary. */
+ extend_info = extend_info_from_node(r, conn->want_onehop ? 1 : 0);
} else {
log_debug(LD_DIR, "considering %d, %s",
want_onehop, conn->chosen_exit_name);
diff --git a/src/or/control.c b/src/or/control.c
index e2d0eece02..65b161996a 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -2402,7 +2402,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
/* now circ refers to something that is ready to be extended */
SMARTLIST_FOREACH(nodes, const node_t *, node,
{
- extend_info_t *info = extend_info_from_node(node);
+ extend_info_t *info = extend_info_from_node(node, 0);
tor_assert(info); /* True, since node_has_descriptor(node) == true */
circuit_append_new_exit(circ, info);
extend_info_free(info);
diff --git a/src/or/nodelist.c b/src/or/nodelist.c
index b93b919c13..08dcde6f02 100644
--- a/src/or/nodelist.c
+++ b/src/or/nodelist.c
@@ -646,24 +646,59 @@ node_exit_policy_rejects_all(const node_t *node)
return 1;
}
-/** Copy the address for <b>node</b> into *<b>addr_out</b>. */
-int
-node_get_addr(const node_t *node, tor_addr_t *addr_out)
+/** Return list of tor_addr_port_t with all OR ports (in the sense IP
+ * addr + TCP port) for <b>node</b>. Caller must free all elements
+ * using tor_free() and free the list using smartlist_free().
+ *
+ * XXX this is potentially a memory fragmentation hog -- if on
+ * critical path consider the option of having the caller allocate the
+ * memory
+ */
+smartlist_t *
+node_get_all_orports(const node_t *node)
+{
+ smartlist_t *sl = smartlist_create();
+
+ if (node->ri != NULL) {
+ if (node->ri->addr != 0) {
+ tor_addr_port_t *ap = tor_malloc(sizeof(tor_addr_port_t));
+ tor_addr_from_ipv4h(&ap->addr, node->ri->addr);
+ ap->port = node->ri->or_port;
+ smartlist_add(sl, ap);
+ }
+ if (!tor_addr_is_null(&node->ri->ipv6_addr)) {
+ tor_addr_port_t *ap = tor_malloc(sizeof(tor_addr_port_t));
+ tor_addr_copy(&ap->addr, &node->ri->ipv6_addr);
+ ap->port = node->ri->or_port;
+ smartlist_add(sl, ap);
+ }
+ } else if (node->rs != NULL) {
+ tor_addr_port_t *ap = tor_malloc(sizeof(tor_addr_port_t));
+ tor_addr_from_ipv4h(&ap->addr, node->rs->addr);
+ ap->port = node->rs->or_port;
+ smartlist_add(sl, ap);
+ }
+
+ return sl;
+}
+
+/** Copy the primary, IPv4, address for <b>node</b> into
+ * *<b>addr_out</b>. */
+void
+node_get_prim_addr(const node_t *node, tor_addr_t *addr_out)
{
if (node->ri) {
- tor_addr_from_ipv4h(addr_out, node->ri->addr);
- return 0;
- } else if (node->rs) {
+ router_get_prim_addr_port(node->ri, addr_out, NULL);
+ }
+ else if (node->rs) {
tor_addr_from_ipv4h(addr_out, node->rs->addr);
- return 0;
}
- return -1;
}
/** Return the host-order IPv4 address for <b>node</b>, or 0 if it doesn't
* seem to have one. */
uint32_t
-node_get_addr_ipv4h(const node_t *node)
+node_get_prim_addr_ipv4h(const node_t *node)
{
if (node->ri) {
return node->ri->addr;
@@ -673,9 +708,45 @@ node_get_addr_ipv4h(const node_t *node)
return 0;
}
-/** Copy a string representation of the IP address for <b>node</b> into the
- * <b>len</b>-byte buffer at <b>buf</b>.
- */
+/** Return 1 if we prefer the IPv6 address of <b>node</b>, else 0. */
+static int
+node_ipv6_preferred(const node_t *node)
+{
+ if (node->ri != NULL)
+ return router_ipv6_preferred(node->ri);
+ return 0;
+}
+
+/** Copy the preferred address for <b>node</b> into
+ * <b>addr_out</b>. */
+void
+node_get_pref_addr(const node_t *node, tor_addr_t *addr_out)
+{
+ if (node->ri) {
+ router_get_pref_addr_port(node->ri, addr_out, NULL);
+ } else if (node->rs) {
+ /* No IPv6 in routerstatus_t yet. XXXprop186 ok for private
+ bridges but needs fixing */
+ tor_addr_from_ipv4h(addr_out, node->rs->addr);
+ }
+}
+
+/** Copy the preferred IPv6 address for <b>node</b> into
+ * *<b>addr_out</b>. */
+void
+node_get_pref_ipv6_addr(const node_t *node, tor_addr_t *addr_out)
+{
+ if (node->ri) {
+ tor_addr_copy(addr_out, &node->ri->ipv6_addr);
+ } else if (node->rs) {
+ /* No IPv6 in routerstatus_t yet. XXXprop186 ok for private
+ bridges but needs fixing */
+ tor_addr_make_unspec(addr_out);
+ }
+}
+
+/** Copy a string representation of an IP address for <b>node</b> into
+ * the <b>len</b>-byte buffer at <b>buf</b>. */
void
node_get_address_string(const node_t *node, char *buf, size_t len)
{
@@ -701,9 +772,9 @@ node_get_declared_uptime(const node_t *node)
return -1;
}
-/** Return <b>node</b>'s declared or_port */
+/** Return <b>node</b>'s declared primary (IPv4) or_port. */
uint16_t
-node_get_orport(const node_t *node)
+node_get_prim_orport(const node_t *node)
{
if (node->ri)
return node->ri->or_port;
@@ -713,6 +784,28 @@ node_get_orport(const node_t *node)
return 0;
}
+/** Return <b>node</b>'s preferred or_port. */
+uint16_t
+node_get_pref_orport(const node_t *node)
+{
+ if (node_ipv6_preferred(node))
+ return node_get_pref_ipv6_orport(node);
+ else
+ return node_get_prim_orport(node);
+}
+
+/** Return <b>node</b>'s preferred IPv6 or_port. */
+uint16_t
+node_get_pref_ipv6_orport(const node_t *node)
+{
+ if (node->ri)
+ return node->ri->ipv6_orport;
+ else if (node->rs)
+ return 0; /* No IPv6 in routerstatus_t yet. */
+ else
+ return 0;
+}
+
/** Return <b>node</b>'s platform string, or NULL if we don't know it. */
const char *
node_get_platform(const node_t *node)
diff --git a/src/or/nodelist.h b/src/or/nodelist.h
index bd2e63953c..70c76d6d13 100644
--- a/src/or/nodelist.h
+++ b/src/or/nodelist.h
@@ -37,10 +37,15 @@ int node_get_purpose(const node_t *node);
(node_get_purpose((node)) == ROUTER_PURPOSE_BRIDGE)
int node_is_me(const node_t *node);
int node_exit_policy_rejects_all(const node_t *node);
-int node_get_addr(const node_t *node, tor_addr_t *addr_out);
-uint32_t node_get_addr_ipv4h(const node_t *node);
+smartlist_t *node_get_all_orports(const node_t *node);
+void node_get_prim_addr(const node_t *node, tor_addr_t *addr_out);
+void node_get_pref_addr(const node_t *node, tor_addr_t *addr_out);
+void node_get_pref_ipv6_addr(const node_t *node, tor_addr_t *addr_out);
+uint32_t node_get_prim_addr_ipv4h(const node_t *node);
int node_allows_single_hop_exits(const node_t *node);
-uint16_t node_get_orport(const node_t *node);
+uint16_t node_get_prim_orport(const node_t *node);
+uint16_t node_get_pref_orport(const node_t *node);
+uint16_t node_get_pref_ipv6_orport(const node_t *node);
const char *node_get_nickname(const node_t *node);
const char *node_get_platform(const node_t *node);
void node_get_address_string(const node_t *node, char *cp, size_t len);
@@ -50,6 +55,11 @@ const smartlist_t *node_get_declared_family(const node_t *node);
smartlist_t *nodelist_get_list(void);
+/* Temporary aliases during transition to multiple addresses. */
+#define node_get_addr(n,a) node_get_prim_addr((n),(a))
+#define node_get_addr_ipv4h(n) node_get_prim_addr_ipv4h((n))
+#define node_get_orport(n) node_get_prim_orport((n))
+
/* XXXX These need to move out of routerlist.c */
void nodelist_refresh_countries(void);
void node_set_country(node_t *node);
diff --git a/src/or/or.h b/src/or/or.h
index 2adaa2239c..c342880fbc 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1760,6 +1760,8 @@ typedef struct {
/** True if, after we have added this router, we should re-launch
* tests for it. */
unsigned int needs_retest_if_added:1;
+ /** True if ipv6_addr:ipv6_orport is preferred. */
+ unsigned int ipv6_preferred:1;
/** Tor can use this router for general positions in circuits; we got it
* from a directory server as usual, or we're an authority and a server
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index 6a45207e29..cda03c21ef 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -1059,7 +1059,7 @@ rend_client_get_random_intro_impl(const rend_cache_entry_t *entry,
smartlist_del(usable_nodes, i);
goto again;
}
- new_extend_info = extend_info_from_node(node);
+ new_extend_info = extend_info_from_node(node, 0);
if (!new_extend_info) {
log_info(LD_REND, "We don't have a descriptor for the intro-point relay "
"'%s'; trying another.",
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 0ded538bef..b4ef8b4708 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -1142,7 +1142,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
goto err;
}
- extend_info = extend_info_from_node(node);
+ extend_info = extend_info_from_node(node, 0);
}
if (len != REND_COOKIE_LEN+DH_KEY_LEN) {
@@ -2151,7 +2151,7 @@ rend_services_introduce(void)
intro_point_set_changed = 1;
smartlist_add(intro_nodes, (void*)node);
intro = tor_malloc_zero(sizeof(rend_intro_point_t));
- intro->extend_info = extend_info_from_node(node);
+ intro->extend_info = extend_info_from_node(node, 0);
intro->intro_key = crypto_new_pk_env();
tor_assert(!crypto_pk_generate_key(intro->intro_key));
intro->time_published = -1;
diff --git a/src/or/router.c b/src/or/router.c
index c92c5bd3ef..d0217371ed 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -893,7 +893,8 @@ consider_testing_reachability(int test_or, int test_dir)
log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.",
!orport_reachable ? "reachability" : "bandwidth",
me->address, me->or_port);
- ei = extend_info_from_router(me);
+ /* XXX IPv6 self testing IPv6 orports will need pref_addr */
+ ei = extend_info_from_router(me, 0);
circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei,
CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
extend_info_free(ei);
@@ -1201,7 +1202,6 @@ consider_publishable_server(int force)
/** Return the port that we should advertise as our ORPort; this is either
* the one configured in the ORPort option, or the one we actually bound to
* if ORPort is "auto".
- * DOCDOC
*/
uint16_t
router_get_advertised_or_port(const or_options_t *options)
@@ -2121,6 +2121,58 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
return (int)written+1;
}
+
+/** Copy the primary, IPv4, address and port for <b>router</b> into
+ *<b>addr_out</b> and *<b>port_out</b>. */
+void
+router_get_prim_addr_port(const routerinfo_t *router, tor_addr_t *addr_out,
+ uint16_t *port_out)
+{
+ if (addr_out != NULL)
+ tor_addr_from_ipv4h(addr_out, router->addr);
+ if (port_out != NULL)
+ *port_out = router->or_port;
+}
+
+/** Copy the alternative, presumably IPv6, address and port for
+ <b>router</b> into *<b>addr_out</b> and *<b>port_out</b>. */
+void
+router_get_alt_addr_port(const routerinfo_t *router,
+ tor_addr_t *addr_out,
+ uint16_t *port_out)
+{
+ if (addr_out != NULL)
+ tor_addr_copy(addr_out, &router->ipv6_addr);
+ if (port_out != NULL)
+ *port_out = router->ipv6_orport;
+}
+
+/** Return 1 if we prefer the IPv6 address of <b>router</b>, else 0.
+
+ We prefer the IPv6 address if the router has one and
+ i) the routerinfo_t says so
+ or
+ ii) the router has no IPv4 address. */
+int
+router_ipv6_preferred(const routerinfo_t *router)
+{
+ return (!tor_addr_is_null(&router->ipv6_addr)
+ && (router->ipv6_preferred || router->addr == 0));
+}
+
+/** Copy the preferred IP address and port for <b>router</b> into
+ *<b>addr_out</b> and *<b>port_out</b> . */
+void
+router_get_pref_addr_port(const routerinfo_t *router,
+ tor_addr_t *addr_out,
+ uint16_t *port_out)
+{
+ if (router_ipv6_preferred(router))
+ router_get_alt_addr_port(router, addr_out, port_out);
+ else
+ router_get_prim_addr_port(router, addr_out, port_out);
+}
+
/** Load the contents of <b>filename</b>, find the last line starting with
* <b>end_line</b>, ensure that its timestamp is not more than 25 hours in
* the past or more than 1 hour in the future with respect to <b>now</b>,
diff --git a/src/or/router.h b/src/or/router.h
index 6a9851cdbd..4094b665dc 100644
--- a/src/or/router.h
+++ b/src/or/router.h
@@ -85,6 +85,13 @@ int router_pick_published_address(const or_options_t *options, uint32_t *addr);
int router_rebuild_descriptor(int force);
int router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
crypto_pk_env_t *ident_key);
+void router_get_prim_addr_port(const routerinfo_t *router, tor_addr_t *addr_out,
+ uint16_t *port_out);
+void router_get_alt_addr_port(const routerinfo_t *router, tor_addr_t *addr_out,
+ uint16_t *port_out);
+void router_get_pref_addr_port(const routerinfo_t *router, tor_addr_t *addr_out,
+ uint16_t *port_out);
+int router_ipv6_preferred(const routerinfo_t *router);
int extrainfo_dump_to_string(char **s, extrainfo_t *extrainfo,
crypto_pk_env_t *ident_key);
int is_legal_nickname(const char *s);