diff options
Diffstat (limited to 'src/feature/relay/circuitbuild_relay.c')
-rw-r--r-- | src/feature/relay/circuitbuild_relay.c | 84 |
1 files changed, 74 insertions, 10 deletions
diff --git a/src/feature/relay/circuitbuild_relay.c b/src/feature/relay/circuitbuild_relay.c index b89866b477..289a5be557 100644 --- a/src/feature/relay/circuitbuild_relay.c +++ b/src/feature/relay/circuitbuild_relay.c @@ -33,6 +33,7 @@ #include "core/or/channel.h" #include "core/or/circuitbuild.h" #include "core/or/circuitlist.h" +#include "core/or/extendinfo.h" #include "core/or/onion.h" #include "core/or/relay.h" @@ -122,6 +123,52 @@ circuit_extend_add_ed25519_helper(struct extend_cell_t *ec) return 0; } +/* Make sure the extend cell <b>ec</b> has an IPv4 address if the relay + * supports in, and if not, fill it in. */ +STATIC int +circuit_extend_add_ipv4_helper(struct extend_cell_t *ec) +{ + IF_BUG_ONCE(!ec) { + return -1; + } + + const node_t *node = node_get_by_id((const char *) ec->node_id); + if (node) { + tor_addr_port_t node_ipv4; + node_get_prim_orport(node, &node_ipv4); + if (tor_addr_is_null(&ec->orport_ipv4.addr) && + !tor_addr_is_null(&node_ipv4.addr)) { + tor_addr_copy(&ec->orport_ipv4.addr, &node_ipv4.addr); + ec->orport_ipv4.port = node_ipv4.port; + } + } + + return 0; +} + +/* Make sure the extend cell <b>ec</b> has an IPv6 address if the relay + * supports in, and if not, fill it in. */ +STATIC int +circuit_extend_add_ipv6_helper(struct extend_cell_t *ec) +{ + IF_BUG_ONCE(!ec) { + return -1; + } + + const node_t *node = node_get_by_id((const char *) ec->node_id); + if (node) { + tor_addr_port_t node_ipv6; + node_get_pref_ipv6_orport(node, &node_ipv6); + if (tor_addr_is_null(&ec->orport_ipv6.addr) && + !tor_addr_is_null(&node_ipv6.addr)) { + tor_addr_copy(&ec->orport_ipv6.addr, &node_ipv6.addr); + ec->orport_ipv6.port = node_ipv6.port; + } + } + + return 0; +} + /* Check if the address and port in the tor_addr_port_t <b>ap</b> are valid, * and are allowed by the current ExtendAllowPrivateAddresses config. * @@ -354,11 +401,7 @@ circuit_open_connection_for_extend(const struct extend_cell_t *ec, if (should_launch) { /* we should try to open a connection */ - channel_t *n_chan = channel_connect_for_circuit( - &circ->n_hop->addr, - circ->n_hop->port, - circ->n_hop->identity_digest, - &circ->n_hop->ed_identity); + channel_t *n_chan = channel_connect_for_circuit(circ->n_hop); if (!n_chan) { log_info(LD_CIRC,"Launching n_chan failed. Closing circuit."); circuit_mark_for_close(circ, END_CIRC_REASON_CONNECTFAILED); @@ -412,6 +455,12 @@ circuit_extend(struct cell_t *cell, struct circuit_t *circ) if (circuit_extend_lspec_valid_helper(&ec, circ) < 0) return -1; + if (circuit_extend_add_ipv4_helper(&ec) < 0) + return -1; + + if (circuit_extend_add_ipv6_helper(&ec) < 0) + return -1; + /* Check the addresses, without logging */ const int ipv4_valid = circuit_extend_addr_port_is_valid(&ec.orport_ipv4, false, false, 0); @@ -426,6 +475,7 @@ circuit_extend(struct cell_t *cell, struct circuit_t *circ) &ec.ed_pubkey, ipv4_valid ? &ec.orport_ipv4.addr : NULL, ipv6_valid ? &ec.orport_ipv6.addr : NULL, + false, &msg, &should_launch); @@ -452,7 +502,7 @@ circuit_extend(struct cell_t *cell, struct circuit_t *circ) circ->n_chan = n_chan; log_debug(LD_CIRC, "n_chan is %s.", - channel_get_canonical_remote_descr(n_chan)); + channel_describe_peer(n_chan)); if (circuit_deliver_create_cell(circ, &ec.create_cell, 1) < 0) return -1; @@ -539,10 +589,24 @@ onionskin_answer(struct or_circuit_t *circ, if ((!channel_is_local(circ->p_chan) || get_options()->ExtendAllowPrivateAddresses) && !channel_is_outgoing(circ->p_chan)) { - /* record that we could process create cells from a non-local conn - * that we didn't initiate; presumably this means that create cells - * can reach us too. */ - router_orport_found_reachable(); + /* Okay, it's a create cell from a non-local connection + * that we didn't initiate. Presumably this means that create cells + * can reach us too. But what address can they reach us on? */ + const tor_addr_t *my_supposed_addr = &circ->p_chan->addr_according_to_peer; + if (router_addr_is_my_published_addr(my_supposed_addr)) { + /* Great, this create cell came on connection where the peer says + * that the our address is an address we're actually advertising! + * That should mean that we're reachable. But before we finally + * declare ourselves reachable, make sure that the address listed + * by the peer is the same family as the peer is actually using. + */ + tor_addr_t remote_addr; + int family = tor_addr_family(my_supposed_addr); + if (channel_get_addr_if_possible(circ->p_chan, &remote_addr) && + tor_addr_family(&remote_addr) == family) { + router_orport_found_reachable(family); + } + } } return 0; |