LCOV - code coverage report
Current view: top level - feature/nodelist - dirlist.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 172 219 78.5 %
Date: 2021-11-24 03:28:48 Functions: 21 26 80.8 %

          Line data    Source code
       1             : /* Copyright (c) 2001 Matej Pfajfar.
       2             :  * Copyright (c) 2001-2004, Roger Dingledine.
       3             :  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
       4             :  * Copyright (c) 2007-2021, The Tor Project, Inc. */
       5             : /* See LICENSE for licensing information */
       6             : 
       7             : /**
       8             :  * \file dirlist.c
       9             :  * \brief Code to maintain our lists of directory authorities and
      10             :  *    fallback directories.
      11             :  *
      12             :  * For the directory authorities, we have a list containing the public
      13             :  * identity key, and contact points, for each authority.  The
      14             :  * authorities receive descriptors from relays, and publish consensuses,
      15             :  * descriptors, and microdescriptors.  This list is pre-configured.
      16             :  *
      17             :  * Fallback directories are well-known, stable, but untrusted directory
      18             :  * caches that clients which have not yet bootstrapped can use to get
      19             :  * their first networkstatus consensus, in order to find out where the
      20             :  * Tor network really is.  This list is pre-configured in
      21             :  * fallback_dirs.inc.  Every authority also serves as a fallback.
      22             :  *
      23             :  * Both fallback directories and directory authorities are are
      24             :  * represented by a dir_server_t.
      25             :  */
      26             : 
      27             : #include "core/or/or.h"
      28             : 
      29             : #include "app/config/config.h"
      30             : #include "app/config/resolve_addr.h"
      31             : #include "core/or/policies.h"
      32             : #include "feature/control/control_events.h"
      33             : #include "feature/dirauth/authmode.h"
      34             : #include "feature/dircommon/directory.h"
      35             : #include "feature/nodelist/dirlist.h"
      36             : #include "feature/nodelist/networkstatus.h"
      37             : #include "feature/nodelist/nodelist.h"
      38             : #include "feature/nodelist/routerlist.h"
      39             : #include "feature/nodelist/routerset.h"
      40             : #include "feature/relay/router.h"
      41             : #include "lib/net/resolve.h"
      42             : 
      43             : #include "feature/dirclient/dir_server_st.h"
      44             : #include "feature/nodelist/node_st.h"
      45             : 
      46             : /** Information about an (HTTP) dirport for a directory authority. */
      47             : struct auth_dirport_t {
      48             :   /** What is the intended usage for this dirport? One of AUTH_USAGE_* */
      49             :   auth_dirport_usage_t usage;
      50             :   /** What is the correct address/port ? */
      51             :   tor_addr_port_t dirport;
      52             : };
      53             : 
      54             : /** Global list of a dir_server_t object for each directory
      55             :  * authority. */
      56             : static smartlist_t *trusted_dir_servers = NULL;
      57             : /** Global list of dir_server_t objects for all directory authorities
      58             :  * and all fallback directory servers. */
      59             : static smartlist_t *fallback_dir_servers = NULL;
      60             : 
      61             : /** Helper: From a given trusted directory entry, add the v4 or/and v6 address
      62             :  * to the nodelist address set. */
      63             : static void
      64         280 : add_trusted_dir_to_nodelist_addr_set(const dir_server_t *dir)
      65             : {
      66         280 :   tor_assert(dir);
      67         280 :   tor_assert(dir->is_authority);
      68             : 
      69             :   /* Add IPv4 and then IPv6 if applicable. For authorities, we add the ORPort
      70             :    * and DirPort so re-entry into the network back to them is not possible. */
      71         280 :   nodelist_add_addr_to_address_set(&dir->ipv4_addr, dir->ipv4_orport,
      72         280 :                                    dir->ipv4_dirport);
      73         280 :   if (!tor_addr_is_null(&dir->ipv6_addr)) {
      74             :     /* IPv6 DirPort is not a thing yet for authorities. */
      75         140 :     nodelist_add_addr_to_address_set(&dir->ipv6_addr, dir->ipv6_orport, 0);
      76             :   }
      77         280 :   if (dir->auth_dirports) {
      78         560 :     SMARTLIST_FOREACH_BEGIN(dir->auth_dirports, const auth_dirport_t *, p) {
      79         280 :       nodelist_add_addr_to_address_set(&p->dirport.addr, 0, p->dirport.port);
      80         280 :     } SMARTLIST_FOREACH_END(p);
      81             :   }
      82         280 : }
      83             : 
      84             : /** Go over the trusted directory server list and add their address(es) to the
      85             :  * nodelist address set. This is called every time a new consensus is set. */
      86          37 : MOCK_IMPL(void,
      87             : dirlist_add_trusted_dir_addresses, (void))
      88             : {
      89          37 :   if (!trusted_dir_servers) {
      90             :     return;
      91             :   }
      92             : 
      93         313 :   SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, const dir_server_t *, ent) {
      94         280 :     if (ent->is_authority) {
      95         280 :       add_trusted_dir_to_nodelist_addr_set(ent);
      96             :     }
      97         280 :   } SMARTLIST_FOREACH_END(ent);
      98             : }
      99             : 
     100             : /** Return the number of directory authorities whose type matches some bit set
     101             :  * in <b>type</b>  */
     102             : int
     103         118 : get_n_authorities(dirinfo_type_t type)
     104             : {
     105         118 :   int n = 0;
     106         118 :   if (!trusted_dir_servers)
     107             :     return 0;
     108         439 :   SMARTLIST_FOREACH(trusted_dir_servers, dir_server_t *, ds,
     109             :                     if (ds->type & type)
     110             :                       ++n);
     111             :   return n;
     112             : }
     113             : 
     114             : /** Return a smartlist containing a list of dir_server_t * for all
     115             :  * known trusted dirservers.  Callers must not modify the list or its
     116             :  * contents.
     117             :  */
     118             : smartlist_t *
     119         579 : router_get_trusted_dir_servers_mutable(void)
     120             : {
     121         579 :   if (!trusted_dir_servers)
     122         216 :     trusted_dir_servers = smartlist_new();
     123             : 
     124         579 :   return trusted_dir_servers;
     125             : }
     126             : 
     127             : smartlist_t *
     128        4511 : router_get_fallback_dir_servers_mutable(void)
     129             : {
     130        4511 :   if (!fallback_dir_servers)
     131           1 :     fallback_dir_servers = smartlist_new();
     132             : 
     133        4511 :   return fallback_dir_servers;
     134             : }
     135             : 
     136             : const smartlist_t *
     137         579 : router_get_trusted_dir_servers(void)
     138             : {
     139         579 :   return router_get_trusted_dir_servers_mutable();
     140             : }
     141             : 
     142             : const smartlist_t *
     143        4511 : router_get_fallback_dir_servers(void)
     144             : {
     145        4511 :   return router_get_fallback_dir_servers_mutable();
     146             : }
     147             : 
     148             : /** Reset all internal variables used to count failed downloads of network
     149             :  * status objects. */
     150             : void
     151           0 : router_reset_status_download_failures(void)
     152             : {
     153           0 :   mark_all_dirservers_up(fallback_dir_servers);
     154           0 : }
     155             : 
     156             : /** Return the dir_server_t for the directory authority whose identity
     157             :  * key hashes to <b>digest</b>, or NULL if no such authority is known.
     158             :  */
     159             : dir_server_t *
     160           9 : router_get_trusteddirserver_by_digest(const char *digest)
     161             : {
     162           9 :   if (!trusted_dir_servers)
     163             :     return NULL;
     164             : 
     165           0 :   SMARTLIST_FOREACH(trusted_dir_servers, dir_server_t *, ds,
     166             :      {
     167             :        if (tor_memeq(ds->digest, digest, DIGEST_LEN))
     168             :          return ds;
     169             :      });
     170             : 
     171             :   return NULL;
     172             : }
     173             : 
     174             : /** Return the dir_server_t for the fallback dirserver whose identity
     175             :  * key hashes to <b>digest</b>, or NULL if no such fallback is in the list of
     176             :  * fallback_dir_servers. (fallback_dir_servers is affected by the FallbackDir
     177             :  * and UseDefaultFallbackDirs torrc options.)
     178             :  * The list of fallback directories includes the list of authorities.
     179             :  */
     180             : dir_server_t *
     181           0 : router_get_fallback_dirserver_by_digest(const char *digest)
     182             : {
     183           0 :   if (!fallback_dir_servers)
     184             :     return NULL;
     185             : 
     186           0 :   if (!digest)
     187             :     return NULL;
     188             : 
     189           0 :   SMARTLIST_FOREACH(fallback_dir_servers, dir_server_t *, ds,
     190             :      {
     191             :        if (tor_memeq(ds->digest, digest, DIGEST_LEN))
     192             :          return ds;
     193             :      });
     194             : 
     195             :   return NULL;
     196             : }
     197             : 
     198             : /** Return 1 if any fallback dirserver's identity key hashes to <b>digest</b>,
     199             :  * or 0 if no such fallback is in the list of fallback_dir_servers.
     200             :  * (fallback_dir_servers is affected by the FallbackDir and
     201             :  * UseDefaultFallbackDirs torrc options.)
     202             :  * The list of fallback directories includes the list of authorities.
     203             :  */
     204             : int
     205           0 : router_digest_is_fallback_dir(const char *digest)
     206             : {
     207           0 :   return (router_get_fallback_dirserver_by_digest(digest) != NULL);
     208             : }
     209             : 
     210             : /** Return the dir_server_t for the directory authority whose
     211             :  * v3 identity key hashes to <b>digest</b>, or NULL if no such authority
     212             :  * is known.
     213             :  */
     214          69 : MOCK_IMPL(dir_server_t *,
     215             : trusteddirserver_get_by_v3_auth_digest, (const char *digest))
     216             : {
     217          69 :   if (!trusted_dir_servers)
     218             :     return NULL;
     219             : 
     220          68 :   SMARTLIST_FOREACH(trusted_dir_servers, dir_server_t *, ds,
     221             :      {
     222             :        if (tor_memeq(ds->v3_identity_digest, digest, DIGEST_LEN) &&
     223             :            (ds->type & V3_DIRINFO))
     224             :          return ds;
     225             :      });
     226             : 
     227             :   return NULL;
     228             : }
     229             : 
     230             : /** Mark as running every dir_server_t in <b>server_list</b>. */
     231             : void
     232           0 : mark_all_dirservers_up(smartlist_t *server_list)
     233             : {
     234           0 :   if (server_list) {
     235           0 :     SMARTLIST_FOREACH_BEGIN(server_list, dir_server_t *, dir) {
     236           0 :       routerstatus_t *rs;
     237           0 :       node_t *node;
     238           0 :       dir->is_running = 1;
     239           0 :       node = node_get_mutable_by_id(dir->digest);
     240           0 :       if (node)
     241           0 :         node->is_running = 1;
     242           0 :       rs = router_get_mutable_consensus_status_by_id(dir->digest);
     243           0 :       if (rs) {
     244           0 :         rs->last_dir_503_at = 0;
     245           0 :         control_event_networkstatus_changed_single(rs);
     246             :       }
     247           0 :     } SMARTLIST_FOREACH_END(dir);
     248             :   }
     249           0 :   router_dir_info_changed();
     250           0 : }
     251             : 
     252             : /** Return true iff <b>digest</b> is the digest of the identity key of a
     253             :  * trusted directory matching at least one bit of <b>type</b>.  If <b>type</b>
     254             :  * is zero (NO_DIRINFO), or ALL_DIRINFO, any authority is okay. */
     255          81 : MOCK_IMPL(int, router_digest_is_trusted_dir_type,
     256             :         (const char *digest, dirinfo_type_t type))
     257             : {
     258          81 :   if (!trusted_dir_servers)
     259             :     return 0;
     260          33 :   if (authdir_mode(get_options()) && router_digest_is_me(digest))
     261             :     return 1;
     262         363 :   SMARTLIST_FOREACH(trusted_dir_servers, dir_server_t *, ent,
     263             :     if (tor_memeq(digest, ent->digest, DIGEST_LEN)) {
     264             :       return (!type) || ((type & ent->type) != 0);
     265             :     });
     266             :   return 0;
     267             : }
     268             : 
     269             : /** Return true iff the given address matches a trusted directory that matches
     270             :  * at least one bit of type.
     271             :  *
     272             :  * If type is NO_DIRINFO or ALL_DIRINFO, any authority is matched.
     273             :  *
     274             :  * Only ORPorts' addresses are considered.
     275             :  */
     276             : bool
     277           8 : router_addr_is_trusted_dir_type(const tor_addr_t *addr, dirinfo_type_t type)
     278             : {
     279           8 :   int family = tor_addr_family(addr);
     280             : 
     281           8 :   if (!trusted_dir_servers) {
     282             :     return false;
     283             :   }
     284             : 
     285          54 :   SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, dir_server_t *, ent) {
     286             :     /* Ignore entries that don't match the given type. */
     287          52 :     if (type != NO_DIRINFO && (type & ent->type) == 0) {
     288           0 :       continue;
     289             :     }
     290             :     /* Match IPv4 or IPv6 address. */
     291          52 :     if ((family == AF_INET && tor_addr_eq(addr, &ent->ipv4_addr)) ||
     292          15 :         (family == AF_INET6 && tor_addr_eq(addr, &ent->ipv6_addr))) {
     293           6 :       return true;
     294             :     }
     295          46 :   } SMARTLIST_FOREACH_END(ent);
     296             : 
     297             :   return false;
     298             : }
     299             : 
     300             : /** Return an appropriate usage value describing which authdir port to use
     301             :  * for a given directory connection purpose.
     302             :  */
     303             : auth_dirport_usage_t
     304           0 : auth_dirport_usage_for_purpose(int purpose)
     305             : {
     306           0 :   switch (purpose) {
     307             :     case DIR_PURPOSE_FETCH_SERVERDESC:
     308             :     case DIR_PURPOSE_FETCH_EXTRAINFO:
     309             :     case DIR_PURPOSE_FETCH_CONSENSUS:
     310             :     case DIR_PURPOSE_FETCH_CERTIFICATE:
     311             :     case DIR_PURPOSE_FETCH_MICRODESC:
     312             :       return AUTH_USAGE_DOWNLOAD;
     313             : 
     314           0 :     case DIR_PURPOSE_UPLOAD_DIR:
     315           0 :       return AUTH_USAGE_UPLOAD;
     316             : 
     317           0 :     case DIR_PURPOSE_UPLOAD_VOTE:
     318             :     case DIR_PURPOSE_UPLOAD_SIGNATURES:
     319             :     case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
     320             :     case DIR_PURPOSE_FETCH_STATUS_VOTE:
     321           0 :       return AUTH_USAGE_VOTING;
     322             : 
     323           0 :     case DIR_PURPOSE_SERVER:
     324             :     case DIR_PURPOSE_UPLOAD_HSDESC:
     325             :     case DIR_PURPOSE_FETCH_HSDESC:
     326             :     case DIR_PURPOSE_HAS_FETCHED_HSDESC:
     327             :     default:
     328           0 :       tor_assert_nonfatal_unreached();
     329           0 :       return AUTH_USAGE_LEGACY;
     330             :   }
     331             : }
     332             : 
     333             : /** Create a directory server at <b>address</b>:<b>port</b>, with OR identity
     334             :  * key <b>digest</b> which has DIGEST_LEN bytes.  If <b>address</b> is NULL,
     335             :  * add ourself.  If <b>is_authority</b>, this is a directory authority.  Return
     336             :  * the new directory server entry on success or NULL on failure. */
     337             : static dir_server_t *
     338       44448 : dir_server_new(int is_authority,
     339             :                const char *nickname,
     340             :                const tor_addr_t *ipv4_addr,
     341             :                const char *hostname,
     342             :                uint16_t ipv4_dirport, uint16_t ipv4_orport,
     343             :                const tor_addr_port_t *addrport_ipv6,
     344             :                const char *digest, const char *v3_auth_digest,
     345             :                dirinfo_type_t type,
     346             :                double weight)
     347             : {
     348       44448 :   dir_server_t *ent;
     349       44448 :   char *hostname_ = NULL;
     350             : 
     351       44448 :   tor_assert(digest);
     352             : 
     353       44448 :   if (weight < 0)
     354             :     return NULL;
     355             : 
     356       44448 :   if (!ipv4_addr) {
     357             :     return NULL;
     358             :   }
     359             : 
     360       44448 :   if (!hostname)
     361       42210 :     hostname_ = tor_addr_to_str_dup(ipv4_addr);
     362             :   else
     363        2238 :     hostname_ = tor_strdup(hostname);
     364             : 
     365       44448 :   ent = tor_malloc_zero(sizeof(dir_server_t));
     366       44448 :   ent->nickname = nickname ? tor_strdup(nickname) : NULL;
     367       44448 :   ent->address = hostname_;
     368       44448 :   tor_addr_copy(&ent->ipv4_addr, ipv4_addr);
     369       44448 :   ent->ipv4_dirport = ipv4_dirport;
     370       44448 :   ent->ipv4_orport = ipv4_orport;
     371       44448 :   ent->is_running = 1;
     372       44448 :   ent->is_authority = is_authority;
     373       44448 :   ent->type = type;
     374       44448 :   ent->weight = weight;
     375       44448 :   if (addrport_ipv6 && tor_addr_port_is_valid_ap(addrport_ipv6, 0)) {
     376       16089 :     if (tor_addr_family(&addrport_ipv6->addr) != AF_INET6) {
     377           0 :       log_warn(LD_BUG, "Hey, I got a non-ipv6 addr as addrport_ipv6.");
     378           0 :       tor_addr_make_unspec(&ent->ipv6_addr);
     379             :     } else {
     380       16089 :       tor_addr_copy(&ent->ipv6_addr, &addrport_ipv6->addr);
     381       16089 :       ent->ipv6_orport = addrport_ipv6->port;
     382             :     }
     383             :   } else {
     384       28359 :     tor_addr_make_unspec(&ent->ipv6_addr);
     385             :   }
     386             : 
     387       44448 :   memcpy(ent->digest, digest, DIGEST_LEN);
     388       44448 :   if (v3_auth_digest && (type & V3_DIRINFO))
     389        1998 :     memcpy(ent->v3_identity_digest, v3_auth_digest, DIGEST_LEN);
     390             : 
     391       44448 :   if (nickname)
     392        2238 :     tor_asprintf(&ent->description, "directory server \"%s\" at %s:%" PRIu16,
     393             :                  nickname, hostname_, ipv4_dirport);
     394             :   else
     395       42210 :     tor_asprintf(&ent->description, "directory server at %s:%" PRIu16,
     396             :                  hostname_, ipv4_dirport);
     397             : 
     398       44448 :   tor_addr_copy(&ent->fake_status.ipv4_addr, &ent->ipv4_addr);
     399       44448 :   tor_addr_copy(&ent->fake_status.ipv6_addr, &ent->ipv6_addr);
     400       44448 :   memcpy(ent->fake_status.identity_digest, digest, DIGEST_LEN);
     401       44448 :   if (nickname)
     402        2238 :     strlcpy(ent->fake_status.nickname, nickname,
     403             :             sizeof(ent->fake_status.nickname));
     404             :   else
     405       42210 :     ent->fake_status.nickname[0] = '\0';
     406       44448 :   ent->fake_status.ipv4_dirport = ent->ipv4_dirport;
     407       44448 :   ent->fake_status.ipv4_orport = ent->ipv4_orport;
     408       44448 :   ent->fake_status.ipv6_orport = ent->ipv6_orport;
     409       44448 :   ent->fake_status.is_authority = !! is_authority;
     410             : 
     411       44448 :   return ent;
     412             : }
     413             : 
     414             : /** Create an authoritative directory server at <b>address</b>:<b>port</b>,
     415             :  * with identity key <b>digest</b>.  If <b>ipv4_addr_str</b> is NULL, add
     416             :  * ourself.  Return the new trusted directory server entry on success or NULL
     417             :  * if we couldn't add it. */
     418             : dir_server_t *
     419        2238 : trusted_dir_server_new(const char *nickname, const char *address,
     420             :                        uint16_t ipv4_dirport, uint16_t ipv4_orport,
     421             :                        const tor_addr_port_t *ipv6_addrport,
     422             :                        const char *digest, const char *v3_auth_digest,
     423             :                        dirinfo_type_t type, double weight)
     424             : {
     425        2238 :   tor_addr_t ipv4_addr;
     426        2238 :   char *hostname=NULL;
     427        2238 :   dir_server_t *result;
     428             : 
     429        2238 :   if (!address) { /* The address is us; we should guess. */
     430           0 :     if (!find_my_address(get_options(), AF_INET, LOG_WARN, &ipv4_addr,
     431             :                          NULL, &hostname)) {
     432           0 :       log_warn(LD_CONFIG,
     433             :                "Couldn't find a suitable address when adding ourself as a "
     434             :                "trusted directory server.");
     435           0 :       return NULL;
     436             :     }
     437           0 :     if (!hostname)
     438           0 :       hostname = tor_addr_to_str_dup(&ipv4_addr);
     439             : 
     440           0 :     if (!hostname)
     441             :       return NULL;
     442             :   } else {
     443        2238 :     if (tor_addr_lookup(address, AF_INET, &ipv4_addr)) {
     444           0 :       log_warn(LD_CONFIG,
     445             :                "Unable to lookup address for directory server at '%s'",
     446             :                address);
     447           0 :       return NULL;
     448             :     }
     449        2238 :     hostname = tor_strdup(address);
     450             :   }
     451             : 
     452        2238 :   result = dir_server_new(1, nickname, &ipv4_addr, hostname,
     453             :                           ipv4_dirport, ipv4_orport,
     454             :                           ipv6_addrport,
     455             :                           digest,
     456             :                           v3_auth_digest, type, weight);
     457             : 
     458        2238 :   if (ipv4_dirport) {
     459        2238 :     tor_addr_port_t p;
     460        2238 :     memset(&p, 0, sizeof(p));
     461        2238 :     tor_addr_copy(&p.addr, &ipv4_addr);
     462        2238 :     p.port = ipv4_dirport;
     463        2238 :     trusted_dir_server_add_dirport(result, AUTH_USAGE_LEGACY, &p);
     464             :   }
     465        2238 :   tor_free(hostname);
     466        2238 :   return result;
     467             : }
     468             : 
     469             : /**
     470             :  * Add @a dirport as an HTTP DirPort contact point for the directory authority
     471             :  * @a ds, for use when contacting that authority for the given @a usage.
     472             :  *
     473             :  * Multiple ports of the same usage are allowed; if present, then only
     474             :  * the first one of each address family is currently used.
     475             :  */
     476             : void
     477        2242 : trusted_dir_server_add_dirport(dir_server_t *ds,
     478             :                                auth_dirport_usage_t usage,
     479             :                                const tor_addr_port_t *dirport)
     480             : {
     481        2242 :   tor_assert(ds);
     482        2242 :   tor_assert(dirport);
     483             : 
     484        2242 :   if (BUG(! ds->is_authority)) {
     485           0 :     return;
     486             :   }
     487             : 
     488        2242 :   if (ds->auth_dirports == NULL) {
     489        2238 :     ds->auth_dirports = smartlist_new();
     490             :   }
     491             : 
     492        2242 :   auth_dirport_t *port = tor_malloc_zero(sizeof(auth_dirport_t));
     493        2242 :   port->usage = usage;
     494        2242 :   tor_addr_port_copy(&port->dirport, dirport);
     495        2242 :   smartlist_add(ds->auth_dirports, port);
     496             : }
     497             : 
     498             : /**
     499             :  * Helper for trusted_dir_server_get_dirport: only return the exact requested
     500             :  * usage type.
     501             :  */
     502             : const tor_addr_port_t *
     503           8 : trusted_dir_server_get_dirport_exact(const dir_server_t *ds,
     504             :                                      auth_dirport_usage_t usage,
     505             :                                      int addr_family)
     506             : {
     507           8 :   tor_assert(ds);
     508           8 :   tor_assert_nonfatal(addr_family == AF_INET || addr_family == AF_INET6);
     509           8 :   if (ds->auth_dirports == NULL)
     510             :     return NULL;
     511             : 
     512          19 :   SMARTLIST_FOREACH_BEGIN(ds->auth_dirports, const auth_dirport_t *, port) {
     513          17 :     if (port->usage == usage &&
     514           6 :         tor_addr_family(&port->dirport.addr) == addr_family) {
     515           6 :       return &port->dirport;
     516             :     }
     517          11 :   } SMARTLIST_FOREACH_END(port);
     518             : 
     519             :   return NULL;
     520             : }
     521             : 
     522             : /**
     523             :  * Return the DirPort of the authority @a ds for with the usage type
     524             :  * @a usage and address family @a addr_family.  If none is found, try
     525             :  * again with an AUTH_USAGE_LEGACY dirport, if there is one.  Return NULL
     526             :  * if no port can be found.
     527             :  */
     528             : const tor_addr_port_t *
     529           6 : trusted_dir_server_get_dirport(const dir_server_t *ds,
     530             :                                auth_dirport_usage_t usage,
     531             :                                int addr_family)
     532             : {
     533           8 :   const tor_addr_port_t *port;
     534             : 
     535           8 :   while (1) {
     536           8 :     port = trusted_dir_server_get_dirport_exact(ds, usage, addr_family);
     537           8 :     if (port)
     538           6 :       return port;
     539             : 
     540             :     // If we tried LEGACY, there is no fallback from this point.
     541           2 :     if (usage == AUTH_USAGE_LEGACY)
     542             :       return NULL;
     543             : 
     544             :     // Try again with LEGACY.
     545             :     usage = AUTH_USAGE_LEGACY;
     546             :   }
     547             : }
     548             : 
     549             : /** Return a new dir_server_t for a fallback directory server at
     550             :  * <b>addr</b>:<b>or_port</b>/<b>dir_port</b>, with identity key digest
     551             :  * <b>id_digest</b> */
     552             : dir_server_t *
     553       42210 : fallback_dir_server_new(const tor_addr_t *ipv4_addr,
     554             :                         uint16_t ipv4_dirport, uint16_t ipv4_orport,
     555             :                         const tor_addr_port_t *addrport_ipv6,
     556             :                         const char *id_digest, double weight)
     557             : {
     558       42210 :   return dir_server_new(0, NULL, ipv4_addr, NULL, ipv4_dirport, ipv4_orport,
     559             :                         addrport_ipv6, id_digest, NULL, ALL_DIRINFO, weight);
     560             : }
     561             : 
     562             : /** Add a directory server to the global list(s). */
     563             : void
     564       44448 : dir_server_add(dir_server_t *ent)
     565             : {
     566       44448 :   if (!trusted_dir_servers)
     567          16 :     trusted_dir_servers = smartlist_new();
     568       44448 :   if (!fallback_dir_servers)
     569          16 :     fallback_dir_servers = smartlist_new();
     570             : 
     571       44448 :   if (ent->is_authority)
     572        2238 :     smartlist_add(trusted_dir_servers, ent);
     573             : 
     574       44448 :   smartlist_add(fallback_dir_servers, ent);
     575       44448 :   router_dir_info_changed();
     576       44448 : }
     577             : 
     578             : #define dir_server_free(val) \
     579             :   FREE_AND_NULL(dir_server_t, dir_server_free_, (val))
     580             : 
     581             : /** Free storage held in <b>ds</b>. */
     582             : static void
     583       46317 : dir_server_free_(dir_server_t *ds)
     584             : {
     585       46317 :   if (!ds)
     586             :     return;
     587             : 
     588       46317 :   if (ds->auth_dirports) {
     589        4614 :     SMARTLIST_FOREACH(ds->auth_dirports, auth_dirport_t *, p, tor_free(p));
     590        2307 :     smartlist_free(ds->auth_dirports);
     591             :   }
     592       46317 :   tor_free(ds->nickname);
     593       46317 :   tor_free(ds->description);
     594       46317 :   tor_free(ds->address);
     595       46317 :   tor_free(ds);
     596             : }
     597             : 
     598             : /** Remove all members from the list of dir servers. */
     599             : void
     600         578 : clear_dir_servers(void)
     601             : {
     602         578 :   if (fallback_dir_servers) {
     603       46617 :     SMARTLIST_FOREACH(fallback_dir_servers, dir_server_t *, ent,
     604             :                       dir_server_free(ent));
     605         300 :     smartlist_clear(fallback_dir_servers);
     606             :   } else {
     607         278 :     fallback_dir_servers = smartlist_new();
     608             :   }
     609         578 :   if (trusted_dir_servers) {
     610         510 :     smartlist_clear(trusted_dir_servers);
     611             :   } else {
     612          68 :     trusted_dir_servers = smartlist_new();
     613             :   }
     614         578 :   router_dir_info_changed();
     615         578 : }
     616             : 
     617             : void
     618         302 : dirlist_free_all(void)
     619             : {
     620         302 :   clear_dir_servers();
     621         302 :   smartlist_free(trusted_dir_servers);
     622         302 :   smartlist_free(fallback_dir_servers);
     623         302 :   trusted_dir_servers = fallback_dir_servers = NULL;
     624         302 : }

Generated by: LCOV version 1.14