diff --git a/src/core/or/policies.c b/src/core/or/policies.c index f59894ea8f..26a053821a 100644 --- a/src/core/or/policies.c +++ b/src/core/or/policies.c @@ -31,6 +31,7 @@ #include "ht.h" #include "lib/crypt_ops/crypto_rand.h" #include "lib/encoding/confline.h" +#include "trunnel/ed25519_cert.h" #include "core/or/addr_policy_st.h" #include "feature/dirclient/dir_server_st.h" @@ -1015,6 +1016,60 @@ fascist_firewall_choose_address_rs(const routerstatus_t *rs, } } +/** Like fascist_firewall_choose_address_base(), but takes in a smartlist + * lspecs consisting of one or more link specifiers. + */ +void +fascist_firewall_choose_address_ls(const smartlist_t *lspecs, + int pref_only, tor_addr_port_t* ap, + int direct_conn) +{ + int have_v4 = 0, have_v6 = 0; + uint16_t port_v4 = 0, port_v6 = 0; + tor_addr_t addr_v4, addr_v6; + + SMARTLIST_FOREACH_BEGIN(lspecs, const link_specifier_t *, ls) { + switch (link_specifier_get_ls_type(ls)) { + case LS_IPV4: + /* Skip if we already seen a v4. */ + if (have_v4) continue; + tor_addr_from_ipv4h(&addr_v4, + link_specifier_get_un_ipv4_addr(ls)); + port_v4 = link_specifier_get_un_ipv4_port(ls); + have_v4 = 1; + break; + case LS_IPV6: + /* Skip if we already seen a v6, or deliberately skip it if we're not a + * direct connection. */ + if (have_v6 || !direct_conn) continue; + tor_addr_from_ipv6_bytes(&addr_v6, + (const char *) link_specifier_getconstarray_un_ipv6_addr(ls)); + port_v6 = link_specifier_get_un_ipv6_port(ls); + have_v6 = 1; + break; + default: + /* Ignore unknown. */ + break; + } + } SMARTLIST_FOREACH_END(ls); + + tor_assert(ap); + + tor_addr_make_null(&ap->addr, AF_UNSPEC); + ap->port = 0; + + /* Here, don't check for DirPorts as link specifiers are only used for + * ORPorts. */ + const or_options_t *options = get_options(); + int pref_ipv6 = fascist_firewall_prefer_ipv6_orport(options); + /* Assume that the DirPorts are zero as link specifiers only use ORPorts. */ + fascist_firewall_choose_address_base(&addr_v4, port_v4, 0, + &addr_v6, port_v6, 0, + FIREWALL_OR_CONNECTION, + pref_only, pref_ipv6, + ap); +} + /** Like fascist_firewall_choose_address_base(), but takes node, and * looks up the node's IPv6 preference rather than taking an argument * for pref_ipv6. */ diff --git a/src/core/or/policies.h b/src/core/or/policies.h index 324c1c2dd1..f4c68fd952 100644 --- a/src/core/or/policies.h +++ b/src/core/or/policies.h @@ -92,6 +92,9 @@ int fascist_firewall_allows_dir_server(const dir_server_t *ds, void fascist_firewall_choose_address_rs(const routerstatus_t *rs, firewall_connection_t fw_connection, int pref_only, tor_addr_port_t* ap); +void fascist_firewall_choose_address_ls(const smartlist_t *lspecs, + int pref_only, tor_addr_port_t* ap, + int direct_conn); void fascist_firewall_choose_address_node(const node_t *node, firewall_connection_t fw_connection, int pref_only, tor_addr_port_t* ap);