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 : }
|