diff options
Diffstat (limited to 'src/feature/nodelist/nodelist.c')
-rw-r--r-- | src/feature/nodelist/nodelist.c | 255 |
1 files changed, 141 insertions, 114 deletions
diff --git a/src/feature/nodelist/nodelist.c b/src/feature/nodelist/nodelist.c index 7ebc4f5fda..03b158e68d 100644 --- a/src/feature/nodelist/nodelist.c +++ b/src/feature/nodelist/nodelist.c @@ -127,7 +127,7 @@ typedef struct nodelist_t { * * Whenever a node's routerinfo or microdescriptor is about to change, * you should remove it from this map with node_remove_from_ed25519_map(). - * Whenever a node's routerinfo or microdescriptor has just chaned, + * Whenever a node's routerinfo or microdescriptor has just changed, * you should add it to this map with node_add_to_ed25519_map(). */ HT_HEAD(nodelist_ed_map, node_t) nodes_by_ed_id; @@ -451,8 +451,6 @@ node_addrs_changed(node_t *node) static void node_add_to_address_set(const node_t *node) { - tor_addr_t tmp_addr; - if (!the_nodelist || !the_nodelist->node_addrs || !the_nodelist->reentry_set) return; @@ -465,19 +463,17 @@ node_add_to_address_set(const node_t *node) * test succeeds and thus the 0 value for the DirPort. */ if (node->rs) { - if (node->rs->addr) { - tor_addr_from_ipv4h(&tmp_addr, node->rs->addr); - nodelist_add_addr_to_address_set(&tmp_addr, node->rs->or_port, 0); - } + if (!tor_addr_is_null(&node->rs->ipv4_addr)) + nodelist_add_addr_to_address_set(&node->rs->ipv4_addr, + node->rs->ipv4_orport, 0); if (!tor_addr_is_null(&node->rs->ipv6_addr)) nodelist_add_addr_to_address_set(&node->rs->ipv6_addr, node->rs->ipv6_orport, 0); } if (node->ri) { - if (node->ri->addr) { - tor_addr_from_ipv4h(&tmp_addr, node->ri->addr); - nodelist_add_addr_to_address_set(&tmp_addr, node->ri->or_port, 0); - } + if (!tor_addr_is_null(&node->ri->ipv4_addr)) + nodelist_add_addr_to_address_set(&node->ri->ipv4_addr, + node->ri->ipv4_orport, 0); if (!tor_addr_is_null(&node->ri->ipv6_addr)) nodelist_add_addr_to_address_set(&node->ri->ipv6_addr, node->ri->ipv6_orport, 0); @@ -531,7 +527,7 @@ nodelist_add_addr_to_address_set(const tor_addr_t *addr, uint16_t or_port, uint16_t dir_port) { if (BUG(!addr) || tor_addr_is_null(addr) || - (!tor_addr_is_v4(addr) && tor_addr_family(addr) != AF_INET6) || + (!tor_addr_is_v4(addr) && !tor_addr_is_v6(addr)) || !the_nodelist || !the_nodelist->node_addrs || !the_nodelist->reentry_set) { return; @@ -691,7 +687,7 @@ get_estimated_address_per_node, (void)) * and grab microdescriptors into nodes as appropriate. */ void -nodelist_set_consensus(networkstatus_t *ns) +nodelist_set_consensus(const networkstatus_t *ns) { const or_options_t *options = get_options(); int authdir = authdir_mode_v3(options); @@ -749,7 +745,7 @@ nodelist_set_consensus(networkstatus_t *ns) node->is_bad_exit = rs->is_bad_exit; node->is_hs_dir = rs->is_hs_dir; node->ipv6_preferred = 0; - if (fascist_firewall_prefer_ipv6_orport(options) && + if (reachable_addr_prefer_ipv6_orport(options) && (tor_addr_is_null(&rs->ipv6_addr) == 0 || (node->md && tor_addr_is_null(&node->md->ipv6_addr) == 0))) node->ipv6_preferred = 1; @@ -1028,7 +1024,7 @@ nodelist_assert_ok(void) /** Ensure that the nodelist has been created with the most recent consensus. * If that's not the case, make it so. */ void -nodelist_ensure_freshness(networkstatus_t *ns) +nodelist_ensure_freshness(const networkstatus_t *ns) { tor_assert(ns); @@ -1209,7 +1205,7 @@ node_ed25519_id_matches(const node_t *node, const ed25519_public_key_t *id) /** Dummy object that should be unreturnable. Used to ensure that * node_get_protover_summary_flags() always returns non-NULL. */ static const protover_summary_flags_t zero_protover_flags = { - 0,0,0,0,0,0,0,0,0 + 0,0,0,0,0,0,0,0,0,0,0,0 }; /** Return the protover_summary_flags for a given node. */ @@ -1234,9 +1230,9 @@ node_get_protover_summary_flags(const node_t *node) * by ed25519 ID during the link handshake. If <b>compatible_with_us</b>, * it needs to be using a link authentication method that we understand. * If not, any plausible link authentication method will do. */ -MOCK_IMPL(int, +MOCK_IMPL(bool, node_supports_ed25519_link_authentication,(const node_t *node, - int compatible_with_us)) + bool compatible_with_us)) { if (! node_get_ed25519_id(node)) return 0; @@ -1251,7 +1247,7 @@ node_supports_ed25519_link_authentication,(const node_t *node, /** Return true iff <b>node</b> supports the hidden service directory version * 3 protocol (proposal 224). */ -int +bool node_supports_v3_hsdir(const node_t *node) { tor_assert(node); @@ -1261,7 +1257,7 @@ node_supports_v3_hsdir(const node_t *node) /** Return true iff <b>node</b> supports ed25519 authentication as an hidden * service introduction point.*/ -int +bool node_supports_ed25519_hs_intro(const node_t *node) { tor_assert(node); @@ -1269,9 +1265,24 @@ node_supports_ed25519_hs_intro(const node_t *node) return node_get_protover_summary_flags(node)->supports_ed25519_hs_intro; } +/** Return true iff <b>node</b> can be a rendezvous point for hidden + * service version 3 (HSRend=2). */ +bool +node_supports_v3_rendezvous_point(const node_t *node) +{ + tor_assert(node); + + /* We can't use a v3 rendezvous point without the curve25519 onion pk. */ + if (!node_get_curve25519_onion_key(node)) { + return 0; + } + + return node_get_protover_summary_flags(node)->supports_v3_rendezvous_point; +} + /** Return true iff <b>node</b> supports the DoS ESTABLISH_INTRO cell - * extenstion. */ -int + * extension. */ +bool node_supports_establish_intro_dos_extension(const node_t *node) { tor_assert(node); @@ -1280,19 +1291,54 @@ node_supports_establish_intro_dos_extension(const node_t *node) supports_establish_intro_dos_extension; } -/** Return true iff <b>node</b> supports to be a rendezvous point for hidden - * service version 3 (HSRend=2). */ -int -node_supports_v3_rendezvous_point(const node_t *node) +/** Return true iff <b>node</b> can initiate IPv6 extends (Relay=3). + * + * This check should only be performed by client path selection code. + * + * Extending relays should check their own IPv6 support using + * router_can_extend_over_ipv6(). Like other extends, they should not verify + * the link specifiers in the extend cell against the consensus, because it + * may be out of date. */ +bool +node_supports_initiating_ipv6_extends(const node_t *node) { tor_assert(node); - /* We can't use a v3 rendezvous point without the curve25519 onion pk. */ - if (!node_get_curve25519_onion_key(node)) { + /* Relays can't initiate an IPv6 extend, unless they have an IPv6 ORPort. */ + if (!node_has_ipv6_orport(node)) { return 0; } - return node_get_protover_summary_flags(node)->supports_v3_rendezvous_point; + /* Initiating relays also need to support the relevant protocol version. */ + return + node_get_protover_summary_flags(node)->supports_initiating_ipv6_extends; +} + +/** Return true iff <b>node</b> can accept IPv6 extends (Relay=2 or Relay=3) + * from other relays. If <b>need_canonical_ipv6_conn</b> is true, also check + * if the relay supports canonical IPv6 connections (Relay=3 only). + * + * This check should only be performed by client path selection code. + */ +bool +node_supports_accepting_ipv6_extends(const node_t *node, + bool need_canonical_ipv6_conn) +{ + tor_assert(node); + + /* Relays can't accept an IPv6 extend, unless they have an IPv6 ORPort. */ + if (!node_has_ipv6_orport(node)) { + return 0; + } + + /* Accepting relays also need to support the relevant protocol version. */ + if (need_canonical_ipv6_conn) { + return + node_get_protover_summary_flags(node)->supports_canonical_ipv6_conns; + } else { + return + node_get_protover_summary_flags(node)->supports_accepting_ipv6_extends; + } } /** Return the RSA ID key's SHA1 digest for the provided node. */ @@ -1567,32 +1613,14 @@ node_exit_policy_is_exact(const node_t *node, sa_family_t family) * "addr" is an IPv4 host-order address and port_field is a uint16_t. * r is typically a routerinfo_t or routerstatus_t. */ -#define SL_ADD_NEW_IPV4_AP(r, port_field, sl, valid) \ - STMT_BEGIN \ - if (tor_addr_port_is_valid_ipv4h((r)->addr, (r)->port_field, 0)) { \ - valid = 1; \ - tor_addr_port_t *ap = tor_malloc(sizeof(tor_addr_port_t)); \ - tor_addr_from_ipv4h(&ap->addr, (r)->addr); \ - ap->port = (r)->port_field; \ - smartlist_add((sl), ap); \ - } \ - STMT_END - -/* Check if the "addr" and port_field fields from r are a valid non-listening - * address/port. If so, set valid to true and add a newly allocated - * tor_addr_port_t containing "addr" and port_field to sl. - * "addr" is a tor_addr_t and port_field is a uint16_t. - * r is typically a routerinfo_t or routerstatus_t. - */ -#define SL_ADD_NEW_IPV6_AP(r, port_field, sl, valid) \ - STMT_BEGIN \ - if (tor_addr_port_is_valid(&(r)->ipv6_addr, (r)->port_field, 0)) { \ - valid = 1; \ - tor_addr_port_t *ap = tor_malloc(sizeof(tor_addr_port_t)); \ - tor_addr_copy(&ap->addr, &(r)->ipv6_addr); \ - ap->port = (r)->port_field; \ - smartlist_add((sl), ap); \ - } \ +#define SL_ADD_NEW_AP(r, addr_field, port_field, sl, valid) \ + STMT_BEGIN \ + if (tor_addr_port_is_valid(&(r)->addr_field, (r)->port_field, 0)) { \ + valid = 1; \ + tor_addr_port_t *ap = tor_addr_port_new(&(r)->addr_field, \ + (r)->port_field); \ + smartlist_add((sl), ap); \ + } \ STMT_END /** Return list of tor_addr_port_t with all OR ports (in the sense IP @@ -1611,33 +1639,32 @@ node_get_all_orports(const node_t *node) /* Find a valid IPv4 address and port */ if (node->ri != NULL) { - SL_ADD_NEW_IPV4_AP(node->ri, or_port, sl, valid); + SL_ADD_NEW_AP(node->ri, ipv4_addr, ipv4_orport, sl, valid); } /* If we didn't find a valid address/port in the ri, try the rs */ if (!valid && node->rs != NULL) { - SL_ADD_NEW_IPV4_AP(node->rs, or_port, sl, valid); + SL_ADD_NEW_AP(node->rs, ipv4_addr, ipv4_orport, sl, valid); } /* Find a valid IPv6 address and port */ valid = 0; if (node->ri != NULL) { - SL_ADD_NEW_IPV6_AP(node->ri, ipv6_orport, sl, valid); + SL_ADD_NEW_AP(node->ri, ipv6_addr, ipv6_orport, sl, valid); } if (!valid && node->rs != NULL) { - SL_ADD_NEW_IPV6_AP(node->rs, ipv6_orport, sl, valid); + SL_ADD_NEW_AP(node->rs, ipv6_addr, ipv6_orport, sl, valid); } if (!valid && node->md != NULL) { - SL_ADD_NEW_IPV6_AP(node->md, ipv6_orport, sl, valid); + SL_ADD_NEW_AP(node->md, ipv6_addr, ipv6_orport, sl, valid); } return sl; } -#undef SL_ADD_NEW_IPV4_AP -#undef SL_ADD_NEW_IPV6_AP +#undef SL_ADD_NEW_AP /** Wrapper around node_get_prim_orport for backward compatibility. */ @@ -1649,21 +1676,20 @@ node_get_addr(const node_t *node, tor_addr_t *addr_out) tor_addr_copy(addr_out, &ap.addr); } -/** Return the host-order IPv4 address for <b>node</b>, or 0 if it doesn't - * seem to have one. */ -uint32_t -node_get_prim_addr_ipv4h(const node_t *node) +/** Return the IPv4 address for <b>node</b>, or NULL if none found. */ +static const tor_addr_t * +node_get_prim_addr_ipv4(const node_t *node) { /* Don't check the ORPort or DirPort, as this function isn't port-specific, * and the node might have a valid IPv4 address, yet have a zero * ORPort or DirPort. */ - if (node->ri && tor_addr_is_valid_ipv4h(node->ri->addr, 0)) { - return node->ri->addr; - } else if (node->rs && tor_addr_is_valid_ipv4h(node->rs->addr, 0)) { - return node->rs->addr; + if (node->ri && tor_addr_is_valid(&node->ri->ipv4_addr, 0)) { + return &node->ri->ipv4_addr; + } else if (node->rs && tor_addr_is_valid(&node->rs->ipv4_addr, 0)) { + return &node->rs->ipv4_addr; } - return 0; + return NULL; } /** Copy a string representation of an IP address for <b>node</b> into @@ -1671,12 +1697,10 @@ node_get_prim_addr_ipv4h(const node_t *node) void node_get_address_string(const node_t *node, char *buf, size_t len) { - uint32_t ipv4_addr = node_get_prim_addr_ipv4h(node); + const tor_addr_t *ipv4_addr = node_get_prim_addr_ipv4(node); - if (tor_addr_is_valid_ipv4h(ipv4_addr, 0)) { - tor_addr_t addr; - tor_addr_from_ipv4h(&addr, ipv4_addr); - tor_addr_to_str(buf, &addr, len, 0); + if (ipv4_addr) { + tor_addr_to_str(buf, ipv4_addr, len, 0); } else if (len > 0) { buf[0] = '\0'; } @@ -1761,7 +1785,7 @@ node_has_ipv6_dirport(const node_t *node) * ii) the router has no IPv4 OR address. * * If you don't have a node, consider looking it up. - * If there is no node, use fascist_firewall_prefer_ipv6_orport(). + * If there is no node, use reachable_addr_prefer_ipv6_orport(). */ int node_ipv6_or_preferred(const node_t *node) @@ -1771,10 +1795,10 @@ node_ipv6_or_preferred(const node_t *node) node_assert_ok(node); /* XX/teor - node->ipv6_preferred is set from - * fascist_firewall_prefer_ipv6_orport() each time the consensus is loaded. + * reachable_addr_prefer_ipv6_orport() each time the consensus is loaded. */ node_get_prim_orport(node, &ipv4_addr); - if (!fascist_firewall_use_ipv6(options)) { + if (!reachable_addr_use_ipv6(options)) { return 0; } else if (node->ipv6_preferred || !tor_addr_port_is_valid_ap(&ipv4_addr, 0)) { @@ -1783,12 +1807,12 @@ node_ipv6_or_preferred(const node_t *node) return 0; } -#define RETURN_IPV4_AP(r, port_field, ap_out) \ - STMT_BEGIN \ - if (r && tor_addr_port_is_valid_ipv4h((r)->addr, (r)->port_field, 0)) { \ - tor_addr_from_ipv4h(&(ap_out)->addr, (r)->addr); \ - (ap_out)->port = (r)->port_field; \ - } \ +#define RETURN_IPV4_AP(r, port_field, ap_out) \ + STMT_BEGIN \ + if (r && tor_addr_port_is_valid(&(r)->ipv4_addr, (r)->port_field, 0)) { \ + tor_addr_copy(&(ap_out)->addr, &(r)->ipv4_addr); \ + (ap_out)->port = (r)->port_field; \ + } \ STMT_END /** Copy the primary (IPv4) OR port (IP address and TCP port) for <b>node</b> @@ -1807,8 +1831,8 @@ node_get_prim_orport(const node_t *node, tor_addr_port_t *ap_out) /* Check ri first, because rewrite_node_address_for_bridge() updates * node->ri with the configured bridge address. */ - RETURN_IPV4_AP(node->ri, or_port, ap_out); - RETURN_IPV4_AP(node->rs, or_port, ap_out); + RETURN_IPV4_AP(node->ri, ipv4_orport, ap_out); + RETURN_IPV4_AP(node->rs, ipv4_orport, ap_out); /* Microdescriptors only have an IPv6 address */ } @@ -1869,7 +1893,7 @@ node_get_pref_ipv6_orport(const node_t *node, tor_addr_port_t *ap_out) * or * ii) our preference is for IPv6 Dir addresses. * - * If there is no node, use fascist_firewall_prefer_ipv6_dirport(). + * If there is no node, use reachable_addr_prefer_ipv6_dirport(). */ int node_ipv6_dir_preferred(const node_t *node) @@ -1878,15 +1902,15 @@ node_ipv6_dir_preferred(const node_t *node) tor_addr_port_t ipv4_addr; node_assert_ok(node); - /* node->ipv6_preferred is set from fascist_firewall_prefer_ipv6_orport(), + /* node->ipv6_preferred is set from reachable_addr_prefer_ipv6_orport(), * so we can't use it to determine DirPort IPv6 preference. * This means that bridge clients will use IPv4 DirPorts by default. */ node_get_prim_dirport(node, &ipv4_addr); - if (!fascist_firewall_use_ipv6(options)) { + if (!reachable_addr_use_ipv6(options)) { return 0; } else if (!tor_addr_port_is_valid_ap(&ipv4_addr, 0) - || fascist_firewall_prefer_ipv6_dirport(get_options())) { + || reachable_addr_prefer_ipv6_dirport(get_options())) { return node_has_ipv6_dirport(node); } return 0; @@ -1908,8 +1932,8 @@ node_get_prim_dirport(const node_t *node, tor_addr_port_t *ap_out) /* Check ri first, because rewrite_node_address_for_bridge() updates * node->ri with the configured bridge address. */ - RETURN_IPV4_AP(node->ri, dir_port, ap_out); - RETURN_IPV4_AP(node->rs, dir_port, ap_out); + RETURN_IPV4_AP(node->ri, ipv4_dirport, ap_out); + RETURN_IPV4_AP(node->rs, ipv4_dirport, ap_out); /* Microdescriptors only have an IPv6 address */ } @@ -1946,13 +1970,13 @@ node_get_pref_ipv6_dirport(const node_t *node, tor_addr_port_t *ap_out) /* Assume IPv4 and IPv6 dirports are the same */ if (node->ri && tor_addr_port_is_valid(&node->ri->ipv6_addr, - node->ri->dir_port, 0)) { + node->ri->ipv4_dirport, 0)) { tor_addr_copy(&ap_out->addr, &node->ri->ipv6_addr); - ap_out->port = node->ri->dir_port; + ap_out->port = node->ri->ipv4_dirport; } else if (node->rs && tor_addr_port_is_valid(&node->rs->ipv6_addr, - node->rs->dir_port, 0)) { + node->rs->ipv4_dirport, 0)) { tor_addr_copy(&ap_out->addr, &node->rs->ipv6_addr); - ap_out->port = node->rs->dir_port; + ap_out->port = node->rs->ipv4_dirport; } else { tor_addr_make_null(&ap_out->addr, AF_INET6); ap_out->port = 0; @@ -2004,7 +2028,7 @@ node_get_curve25519_onion_key(const node_t *node) /* Return a newly allocacted RSA onion public key taken from the given node. * * Return NULL if node is NULL or no RSA onion public key can be found. It is - * the caller responsability to free the returned object. */ + * the caller responsibility to free the returned object. */ crypto_pk_t * node_get_rsa_onion_key(const node_t *node) { @@ -2037,15 +2061,21 @@ node_get_rsa_onion_key(const node_t *node) void node_set_country(node_t *node) { - tor_addr_t addr = TOR_ADDR_NULL; + const tor_addr_t *ipv4_addr = NULL; /* XXXXipv6 */ if (node->rs) - tor_addr_from_ipv4h(&addr, node->rs->addr); + ipv4_addr = &node->rs->ipv4_addr; else if (node->ri) - tor_addr_from_ipv4h(&addr, node->ri->addr); + ipv4_addr = &node->ri->ipv4_addr; - node->country = geoip_get_country_by_addr(&addr); + /* IPv4 is mandatory for a relay so this should not happen unless we are + * attempting to set the country code on a node without a descriptor. */ + if (BUG(!ipv4_addr)) { + node->country = -1; + return; + } + node->country = geoip_get_country_by_addr(ipv4_addr); } /** Set the country code of all routers in the routerlist. */ @@ -2060,7 +2090,7 @@ nodelist_refresh_countries(void) /** Return true iff router1 and router2 have similar enough network addresses * that we should treat them as being in the same family */ int -addrs_in_same_network_family(const tor_addr_t *a1, +router_addrs_in_same_network(const tor_addr_t *a1, const tor_addr_t *a2) { if (tor_addr_is_null(a1) || tor_addr_is_null(a2)) @@ -2176,8 +2206,8 @@ nodes_in_same_family(const node_t *node1, const node_t *node2) node_get_pref_ipv6_orport(node1, &ap6_1); node_get_pref_ipv6_orport(node2, &ap6_2); - if (addrs_in_same_network_family(&a1, &a2) || - addrs_in_same_network_family(&ap6_1.addr, &ap6_2.addr)) + if (router_addrs_in_same_network(&a1, &a2) || + router_addrs_in_same_network(&ap6_1.addr, &ap6_2.addr)) return 1; } @@ -2235,8 +2265,8 @@ nodelist_add_node_and_family(smartlist_t *sl, const node_t *node) tor_addr_port_t ap6; node_get_addr(node2, &a); node_get_pref_ipv6_orport(node2, &ap6); - if (addrs_in_same_network_family(&a, &node_addr) || - addrs_in_same_network_family(&ap6.addr, &node_ap6.addr)) + if (router_addrs_in_same_network(&a, &node_addr) || + router_addrs_in_same_network(&ap6.addr, &node_ap6.addr)) smartlist_add(sl, (void*)node2); } SMARTLIST_FOREACH_END(node2); } @@ -2276,21 +2306,18 @@ nodelist_add_node_and_family(smartlist_t *sl, const node_t *node) const node_t * router_find_exact_exit_enclave(const char *address, uint16_t port) {/*XXXX MOVE*/ - uint32_t addr; struct in_addr in; - tor_addr_t a; + tor_addr_t ipv4_addr; const or_options_t *options = get_options(); if (!tor_inet_aton(address, &in)) return NULL; /* it's not an IP already */ - addr = ntohl(in.s_addr); - - tor_addr_from_ipv4h(&a, addr); + tor_addr_from_in(&ipv4_addr, &in); SMARTLIST_FOREACH(nodelist_get_list(), const node_t *, node, { - if (node_get_addr_ipv4h(node) == addr && + if (tor_addr_eq(node_get_prim_addr_ipv4(node), &ipv4_addr) && node->is_running && - compare_tor_addr_to_node_policy(&a, port, node) == + compare_tor_addr_to_node_policy(&ipv4_addr, port, node) == ADDR_POLICY_ACCEPTED && !routerset_contains_node(options->ExcludeExitNodesUnion_, node)) return node; |