mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Merge branch 'nodes'
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
o Code refactorings
|
||||
- Unified our node-listing and selecting logic. We had at least
|
||||
two major ways to look at the question of "which Tor servers do
|
||||
we know about": our list of router descriptors, and the current
|
||||
consensus. We're adding a third in microdescriptors. Having
|
||||
so many systems without an abstraction layer over them was
|
||||
hurting the codebase. Now, we have a new "node_t" abstraction
|
||||
that presents a consistent interface to a client's view of
|
||||
a Tor node, and holds (nearly) all of the mutable state
|
||||
formerly in routerinfo_t and routerstatus_t.
|
||||
@@ -0,0 +1,4 @@
|
||||
o Minor features
|
||||
- The NodeFamily option -- which let you declare that you want to
|
||||
consider nodes to be part of a family whether they list themselves
|
||||
that way or not -- now allows IP address ranges and country codes.
|
||||
+2
-1
@@ -571,7 +571,8 @@ The following options are useful only for clients (that is, if
|
||||
constitute a "family" of similar or co-administered servers, so never use
|
||||
any two of them in the same circuit. Defining a NodeFamily is only needed
|
||||
when a server doesn't list the family itself (with MyFamily). This option
|
||||
can be used multiple times.
|
||||
can be used multiple times. In addition to nodes, you can also list
|
||||
IP address and ranges and country codes in {curly braces}.
|
||||
|
||||
**EnforceDistinctSubnets** **0**|**1**::
|
||||
If 1, Tor will not put two servers whose IP addresses are "too close" on
|
||||
|
||||
@@ -311,7 +311,7 @@ tor_addr_is_internal(const tor_addr_t *addr, int for_listening)
|
||||
* brackets.
|
||||
*/
|
||||
const char *
|
||||
tor_addr_to_str(char *dest, const tor_addr_t *addr, int len, int decorate)
|
||||
tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len, int decorate)
|
||||
{
|
||||
const char *ptr;
|
||||
tor_assert(addr && dest);
|
||||
|
||||
@@ -144,7 +144,7 @@ int tor_addr_port_parse(const char *s, tor_addr_t *addr_out,
|
||||
int tor_addr_parse_mask_ports(const char *s,
|
||||
tor_addr_t *addr_out, maskbits_t *mask_out,
|
||||
uint16_t *port_min_out, uint16_t *port_max_out);
|
||||
const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, int len,
|
||||
const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len,
|
||||
int decorate);
|
||||
int tor_addr_from_str(tor_addr_t *addr, const char *src);
|
||||
void tor_addr_copy(tor_addr_t *dest, const tor_addr_t *src);
|
||||
|
||||
@@ -268,7 +268,6 @@ smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2)
|
||||
|
||||
/** Remove the <b>idx</b>th element of sl; if idx is not the last
|
||||
* element, swap the last element of sl into the <b>idx</b>th space.
|
||||
* Return the old value of the <b>idx</b>th element.
|
||||
*/
|
||||
void
|
||||
smartlist_del(smartlist_t *sl, int idx)
|
||||
|
||||
+1
-1
@@ -934,7 +934,7 @@ esc_for_log(const char *s)
|
||||
char *result, *outp;
|
||||
size_t len = 3;
|
||||
if (!s) {
|
||||
return tor_strdup("");
|
||||
return tor_strdup("(null)");
|
||||
}
|
||||
|
||||
for (cp = s; *cp; ++cp) {
|
||||
|
||||
+2
-1
@@ -21,7 +21,7 @@ libtor_a_SOURCES = buffers.c circuitbuild.c circuitlist.c \
|
||||
cpuworker.c directory.c dirserv.c dirvote.c \
|
||||
dns.c dnsserv.c geoip.c hibernate.c main.c $(tor_platform_source) \
|
||||
microdesc.c \
|
||||
networkstatus.c onion.c policies.c \
|
||||
networkstatus.c nodelist.c onion.c policies.c \
|
||||
reasons.c relay.c rendcommon.c rendclient.c rendmid.c \
|
||||
rendservice.c rephist.c router.c routerlist.c routerparse.c \
|
||||
$(evdns_source) config_codedigest.c
|
||||
@@ -56,6 +56,7 @@ noinst_HEADERS = buffers.h circuitbuild.h circuitlist.h circuituse.h \
|
||||
command.h config.h connection_edge.h connection.h connection_or.h \
|
||||
control.h cpuworker.h directory.h dirserv.h dirvote.h dns.h \
|
||||
dnsserv.h geoip.h hibernate.h main.h microdesc.h networkstatus.h \
|
||||
nodelist.h \
|
||||
ntmain.h onion.h policies.h reasons.h relay.h rendclient.h \
|
||||
rendcommon.h rendmid.h rendservice.h rephist.h router.h routerlist.h \
|
||||
routerparse.h or.h eventdns.h eventdns_tor.h micro-revision.i
|
||||
|
||||
+254
-226
File diff suppressed because it is too large
Load Diff
@@ -44,10 +44,11 @@ void onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop);
|
||||
extend_info_t *extend_info_alloc(const char *nickname, const char *digest,
|
||||
crypto_pk_env_t *onion_key,
|
||||
const tor_addr_t *addr, uint16_t port);
|
||||
extend_info_t *extend_info_from_router(routerinfo_t *r);
|
||||
extend_info_t *extend_info_from_router(const routerinfo_t *r);
|
||||
extend_info_t *extend_info_from_node(const node_t *node);
|
||||
extend_info_t *extend_info_dup(extend_info_t *info);
|
||||
void extend_info_free(extend_info_t *info);
|
||||
routerinfo_t *build_state_get_exit_router(cpath_build_state_t *state);
|
||||
const node_t *build_state_get_exit_node(cpath_build_state_t *state);
|
||||
const char *build_state_get_exit_nickname(cpath_build_state_t *state);
|
||||
|
||||
void entry_guards_compute_status(or_options_t *options, time_t now);
|
||||
@@ -55,7 +56,7 @@ int entry_guard_register_connect_status(const char *digest, int succeeded,
|
||||
int mark_relay_status, time_t now);
|
||||
void entry_nodes_should_be_added(void);
|
||||
int entry_list_is_constrained(or_options_t *options);
|
||||
routerinfo_t *choose_random_entry(cpath_build_state_t *state);
|
||||
const node_t *choose_random_entry(cpath_build_state_t *state);
|
||||
int entry_guards_parse_state(or_state_t *state, int set, char **msg);
|
||||
void entry_guards_update_state(or_state_t *state);
|
||||
int getinfo_helper_entry_guards(control_connection_t *conn,
|
||||
@@ -63,9 +64,9 @@ int getinfo_helper_entry_guards(control_connection_t *conn,
|
||||
const char **errmsg);
|
||||
|
||||
void clear_bridge_list(void);
|
||||
int routerinfo_is_a_configured_bridge(routerinfo_t *ri);
|
||||
void
|
||||
learned_router_identity(tor_addr_t *addr, uint16_t port, const char *digest);
|
||||
int routerinfo_is_a_configured_bridge(const routerinfo_t *ri);
|
||||
void learned_router_identity(tor_addr_t *addr, uint16_t port,
|
||||
const char *digest);
|
||||
void bridge_add_from_config(const tor_addr_t *addr, uint16_t port,
|
||||
char *digest);
|
||||
void retry_bridge_descriptor_fetch_directly(const char *digest);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "connection_or.h"
|
||||
#include "control.h"
|
||||
#include "networkstatus.h"
|
||||
#include "nodelist.h"
|
||||
#include "onion.h"
|
||||
#include "relay.h"
|
||||
#include "rendclient.h"
|
||||
@@ -946,15 +947,15 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
|
||||
if (info) {
|
||||
/* need to make sure we don't duplicate hops */
|
||||
crypt_path_t *hop = circ->cpath;
|
||||
routerinfo_t *ri1 = router_get_by_digest(info->identity_digest);
|
||||
const node_t *ri1 = node_get_by_id(info->identity_digest);
|
||||
do {
|
||||
routerinfo_t *ri2;
|
||||
const node_t *ri2;
|
||||
if (!memcmp(hop->extend_info->identity_digest,
|
||||
info->identity_digest, DIGEST_LEN))
|
||||
goto next;
|
||||
if (ri1 &&
|
||||
(ri2 = router_get_by_digest(hop->extend_info->identity_digest))
|
||||
&& routers_in_same_family(ri1, ri2))
|
||||
(ri2 = node_get_by_id(hop->extend_info->identity_digest))
|
||||
&& nodes_in_same_family(ri1, ri2))
|
||||
goto next;
|
||||
hop=hop->next;
|
||||
} while (hop!=circ->cpath);
|
||||
|
||||
+30
-37
@@ -17,6 +17,7 @@
|
||||
#include "connection.h"
|
||||
#include "connection_edge.h"
|
||||
#include "control.h"
|
||||
#include "nodelist.h"
|
||||
#include "policies.h"
|
||||
#include "rendclient.h"
|
||||
#include "rendcommon.h"
|
||||
@@ -43,7 +44,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
|
||||
int need_uptime, int need_internal,
|
||||
time_t now)
|
||||
{
|
||||
routerinfo_t *exitrouter;
|
||||
const node_t *exitnode;
|
||||
cpath_build_state_t *build_state;
|
||||
tor_assert(circ);
|
||||
tor_assert(conn);
|
||||
@@ -85,7 +86,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
|
||||
* of the one we meant to finish at.
|
||||
*/
|
||||
build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
|
||||
exitrouter = build_state_get_exit_router(build_state);
|
||||
exitnode = build_state_get_exit_node(build_state);
|
||||
|
||||
if (need_uptime && !build_state->need_uptime)
|
||||
return 0;
|
||||
@@ -93,7 +94,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
|
||||
return 0;
|
||||
|
||||
if (purpose == CIRCUIT_PURPOSE_C_GENERAL) {
|
||||
if (!exitrouter && !build_state->onehop_tunnel) {
|
||||
if (!exitnode && !build_state->onehop_tunnel) {
|
||||
log_debug(LD_CIRC,"Not considering circuit with unknown router.");
|
||||
return 0; /* this circuit is screwed and doesn't know it yet,
|
||||
* or is a rendezvous circuit. */
|
||||
@@ -127,7 +128,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (exitrouter && !connection_ap_can_use_exit(conn, exitrouter, 0)) {
|
||||
if (exitnode && !connection_ap_can_use_exit(conn, exitnode, 0)) {
|
||||
/* can't exit from this router */
|
||||
return 0;
|
||||
}
|
||||
@@ -473,7 +474,7 @@ circuit_stream_is_being_handled(edge_connection_t *conn,
|
||||
uint16_t port, int min)
|
||||
{
|
||||
circuit_t *circ;
|
||||
routerinfo_t *exitrouter;
|
||||
const node_t *exitnode;
|
||||
int num=0;
|
||||
time_t now = time(NULL);
|
||||
int need_uptime = smartlist_string_num_isin(get_options()->LongLivedPorts,
|
||||
@@ -489,14 +490,14 @@ circuit_stream_is_being_handled(edge_connection_t *conn,
|
||||
if (build_state->is_internal || build_state->onehop_tunnel)
|
||||
continue;
|
||||
|
||||
exitrouter = build_state_get_exit_router(build_state);
|
||||
if (exitrouter && (!need_uptime || build_state->need_uptime)) {
|
||||
exitnode = build_state_get_exit_node(build_state);
|
||||
if (exitnode && (!need_uptime || build_state->need_uptime)) {
|
||||
int ok;
|
||||
if (conn) {
|
||||
ok = connection_ap_can_use_exit(conn, exitrouter, 0);
|
||||
ok = connection_ap_can_use_exit(conn, exitnode, 0);
|
||||
} else {
|
||||
addr_policy_result_t r = compare_addr_to_addr_policy(
|
||||
0, port, exitrouter->exit_policy);
|
||||
addr_policy_result_t r;
|
||||
r = compare_addr_to_node_policy(0, port, exitnode);
|
||||
ok = r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED;
|
||||
}
|
||||
if (ok) {
|
||||
@@ -563,7 +564,7 @@ circuit_predict_and_launch_new(void)
|
||||
log_info(LD_CIRC,
|
||||
"Have %d clean circs (%d internal), need another exit circ.",
|
||||
num, num_internal);
|
||||
circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
|
||||
circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -575,7 +576,7 @@ circuit_predict_and_launch_new(void)
|
||||
"Have %d clean circs (%d internal), need another internal "
|
||||
"circ for my hidden service.",
|
||||
num, num_internal);
|
||||
circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
|
||||
circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -593,7 +594,7 @@ circuit_predict_and_launch_new(void)
|
||||
"Have %d clean circs (%d uptime-internal, %d internal), need"
|
||||
" another hidden service circ.",
|
||||
num, num_uptime_internal, num_internal);
|
||||
circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
|
||||
circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -606,7 +607,7 @@ circuit_predict_and_launch_new(void)
|
||||
flags = CIRCLAUNCH_NEED_CAPACITY;
|
||||
log_info(LD_CIRC,
|
||||
"Have %d clean circs need another buildtime test circ.", num);
|
||||
circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
|
||||
circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -644,7 +645,7 @@ circuit_build_needed_circs(time_t now)
|
||||
circ &&
|
||||
circ->timestamp_created + TESTING_CIRCUIT_INTERVAL < now) {
|
||||
log_fn(LOG_INFO,"Creating a new testing circuit.");
|
||||
circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, 0);
|
||||
circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1076,17 +1077,9 @@ static int did_circs_fail_last_period = 0;
|
||||
/** Launch a new circuit; see circuit_launch_by_extend_info() for
|
||||
* details on arguments. */
|
||||
origin_circuit_t *
|
||||
circuit_launch_by_router(uint8_t purpose,
|
||||
routerinfo_t *exit, int flags)
|
||||
circuit_launch(uint8_t purpose, int flags)
|
||||
{
|
||||
origin_circuit_t *circ;
|
||||
extend_info_t *info = NULL;
|
||||
if (exit)
|
||||
info = extend_info_from_router(exit);
|
||||
circ = circuit_launch_by_extend_info(purpose, info, flags);
|
||||
|
||||
extend_info_free(info);
|
||||
return circ;
|
||||
return circuit_launch_by_extend_info(purpose, NULL, flags);
|
||||
}
|
||||
|
||||
/** Launch a new circuit with purpose <b>purpose</b> and exit node
|
||||
@@ -1256,9 +1249,9 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
|
||||
uint32_t addr = 0;
|
||||
if (tor_inet_aton(conn->socks_request->address, &in))
|
||||
addr = ntohl(in.s_addr);
|
||||
if (router_exit_policy_all_routers_reject(addr,
|
||||
conn->socks_request->port,
|
||||
need_uptime)) {
|
||||
if (router_exit_policy_all_nodes_reject(addr,
|
||||
conn->socks_request->port,
|
||||
need_uptime)) {
|
||||
log_notice(LD_APP,
|
||||
"No Tor server allows exit to %s:%d. Rejecting.",
|
||||
safe_str_client(conn->socks_request->address),
|
||||
@@ -1267,9 +1260,9 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
|
||||
}
|
||||
} else {
|
||||
/* XXXX022 Duplicates checks in connection_ap_handshake_attach_circuit */
|
||||
routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1);
|
||||
const node_t *node = node_get_by_nickname(conn->chosen_exit_name, 1);
|
||||
int opt = conn->chosen_exit_optional;
|
||||
if (router && !connection_ap_can_use_exit(conn, router, 0)) {
|
||||
if (node && !connection_ap_can_use_exit(conn, node, 0)) {
|
||||
log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP,
|
||||
"Requested exit point '%s' would refuse request. %s.",
|
||||
conn->chosen_exit_name, opt ? "Trying others" : "Closing");
|
||||
@@ -1317,11 +1310,11 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
|
||||
*/
|
||||
if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_GENERAL) {
|
||||
if (conn->chosen_exit_name) {
|
||||
routerinfo_t *r;
|
||||
const node_t *r;
|
||||
int opt = conn->chosen_exit_optional;
|
||||
r = router_get_by_nickname(conn->chosen_exit_name, 1);
|
||||
if (r) {
|
||||
extend_info = extend_info_from_router(r);
|
||||
r = node_get_by_nickname(conn->chosen_exit_name, 1);
|
||||
if (r && node_has_descriptor(r)) {
|
||||
extend_info = extend_info_from_node(r);
|
||||
} else {
|
||||
log_debug(LD_DIR, "considering %d, %s",
|
||||
want_onehop, conn->chosen_exit_name);
|
||||
@@ -1571,9 +1564,9 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
|
||||
origin_circuit_t *circ=NULL;
|
||||
|
||||
if (conn->chosen_exit_name) {
|
||||
routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1);
|
||||
const node_t *node = node_get_by_nickname(conn->chosen_exit_name, 1);
|
||||
int opt = conn->chosen_exit_optional;
|
||||
if (!router && !want_onehop) {
|
||||
if (!node && !want_onehop) {
|
||||
/* We ran into this warning when trying to extend a circuit to a
|
||||
* hidden service directory for which we didn't have a router
|
||||
* descriptor. See flyspray task 767 for more details. We should
|
||||
@@ -1589,7 +1582,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (router && !connection_ap_can_use_exit(conn, router, 0)) {
|
||||
if (node && !connection_ap_can_use_exit(conn, node, 0)) {
|
||||
log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP,
|
||||
"Requested exit point '%s' would refuse request. %s.",
|
||||
conn->chosen_exit_name, opt ? "Trying others" : "Closing");
|
||||
|
||||
+1
-2
@@ -41,8 +41,7 @@ void circuit_build_failed(origin_circuit_t *circ);
|
||||
origin_circuit_t *circuit_launch_by_extend_info(uint8_t purpose,
|
||||
extend_info_t *info,
|
||||
int flags);
|
||||
origin_circuit_t *circuit_launch_by_router(uint8_t purpose,
|
||||
routerinfo_t *exit, int flags);
|
||||
origin_circuit_t *circuit_launch(uint8_t purpose, int flags);
|
||||
void circuit_reset_failure_count(int timeout);
|
||||
int connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn,
|
||||
origin_circuit_t *circ,
|
||||
|
||||
+7
-3
@@ -25,6 +25,7 @@
|
||||
#include "control.h"
|
||||
#include "cpuworker.h"
|
||||
#include "hibernate.h"
|
||||
#include "nodelist.h"
|
||||
#include "onion.h"
|
||||
#include "relay.h"
|
||||
#include "router.h"
|
||||
@@ -267,15 +268,18 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn)
|
||||
}
|
||||
|
||||
if (circuit_id_in_use_on_orconn(cell->circ_id, conn)) {
|
||||
routerinfo_t *router = router_get_by_digest(conn->identity_digest);
|
||||
const node_t *node = node_get_by_id(conn->identity_digest);
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Received CREATE cell (circID %d) for known circ. "
|
||||
"Dropping (age %d).",
|
||||
cell->circ_id, (int)(time(NULL) - conn->_base.timestamp_created));
|
||||
if (router)
|
||||
if (node) {
|
||||
char *p = esc_for_log(node_get_platform(node));
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Details: nickname \"%s\", platform %s.",
|
||||
router->nickname, escaped(router->platform));
|
||||
node_get_nickname(node), p);
|
||||
tor_free(p);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+22
-1
@@ -691,6 +691,11 @@ or_options_free(or_options_t *options)
|
||||
return;
|
||||
|
||||
routerset_free(options->_ExcludeExitNodesUnion);
|
||||
if (options->NodeFamilySets) {
|
||||
SMARTLIST_FOREACH(options->NodeFamilySets, routerset_t *,
|
||||
rs, routerset_free(rs));
|
||||
smartlist_free(options->NodeFamilySets);
|
||||
}
|
||||
config_free(&options_format, options);
|
||||
}
|
||||
|
||||
@@ -3084,6 +3089,18 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
||||
routerset_union(options->_ExcludeExitNodesUnion,options->ExcludeNodes);
|
||||
}
|
||||
|
||||
if (options->NodeFamilies) {
|
||||
options->NodeFamilySets = smartlist_create();
|
||||
for (cl = options->NodeFamilies; cl; cl = cl->next) {
|
||||
routerset_t *rs = routerset_new();
|
||||
if (routerset_parse(rs, cl->value, cl->key) == 0) {
|
||||
smartlist_add(options->NodeFamilySets, rs);
|
||||
} else {
|
||||
routerset_free(rs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (options->ExcludeNodes && options->StrictNodes) {
|
||||
COMPLAIN("You have asked to exclude certain relays from all positions "
|
||||
"in your circuits. Expect hidden services and other Tor "
|
||||
@@ -3549,8 +3566,12 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
||||
if (check_nickname_list(options->MyFamily, "MyFamily", msg))
|
||||
return -1;
|
||||
for (cl = options->NodeFamilies; cl; cl = cl->next) {
|
||||
if (check_nickname_list(cl->value, "NodeFamily", msg))
|
||||
routerset_t *rs = routerset_new();
|
||||
if (routerset_parse(rs, cl->value, cl->key)) {
|
||||
routerset_free(rs);
|
||||
return -1;
|
||||
}
|
||||
routerset_free(rs);
|
||||
}
|
||||
|
||||
if (validate_addr_policies(options, msg) < 0)
|
||||
|
||||
+18
-18
@@ -23,6 +23,7 @@
|
||||
#include "dirserv.h"
|
||||
#include "hibernate.h"
|
||||
#include "main.h"
|
||||
#include "nodelist.h"
|
||||
#include "policies.h"
|
||||
#include "reasons.h"
|
||||
#include "relay.h"
|
||||
@@ -586,7 +587,7 @@ void
|
||||
circuit_discard_optional_exit_enclaves(extend_info_t *info)
|
||||
{
|
||||
edge_connection_t *edge_conn;
|
||||
routerinfo_t *r1, *r2;
|
||||
const node_t *r1, *r2;
|
||||
|
||||
smartlist_t *conns = get_connection_array();
|
||||
SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
|
||||
@@ -598,8 +599,8 @@ circuit_discard_optional_exit_enclaves(extend_info_t *info)
|
||||
if (!edge_conn->chosen_exit_optional &&
|
||||
!edge_conn->chosen_exit_retries)
|
||||
continue;
|
||||
r1 = router_get_by_nickname(edge_conn->chosen_exit_name, 0);
|
||||
r2 = router_get_by_nickname(info->nickname, 0);
|
||||
r1 = node_get_by_nickname(edge_conn->chosen_exit_name, 0);
|
||||
r2 = node_get_by_nickname(info->nickname, 0);
|
||||
if (!r1 || !r2 || r1 != r2)
|
||||
continue;
|
||||
tor_assert(edge_conn->socks_request);
|
||||
@@ -1574,12 +1575,12 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
routerinfo_t *r;
|
||||
const node_t *r;
|
||||
conn->chosen_exit_name = tor_strdup(socks->address);
|
||||
r = router_get_by_nickname(conn->chosen_exit_name, 1);
|
||||
r = node_get_by_nickname(conn->chosen_exit_name, 1);
|
||||
*socks->address = 0;
|
||||
if (r) {
|
||||
strlcpy(socks->address, r->address, sizeof(socks->address));
|
||||
node_get_address_string(r, socks->address, sizeof(socks->address));
|
||||
} else {
|
||||
log_warn(LD_APP,
|
||||
"Unrecognized server in exit address '%s.exit'. Refusing.",
|
||||
@@ -1630,16 +1631,16 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
|
||||
|
||||
if (!conn->use_begindir && !conn->chosen_exit_name && !circ) {
|
||||
/* see if we can find a suitable enclave exit */
|
||||
routerinfo_t *r =
|
||||
const node_t *r =
|
||||
router_find_exact_exit_enclave(socks->address, socks->port);
|
||||
if (r) {
|
||||
log_info(LD_APP,
|
||||
"Redirecting address %s to exit at enclave router %s",
|
||||
safe_str_client(socks->address), r->nickname);
|
||||
safe_str_client(socks->address), node_get_nickname(r));
|
||||
/* use the hex digest, not nickname, in case there are two
|
||||
routers with this nickname */
|
||||
conn->chosen_exit_name =
|
||||
tor_strdup(hex_str(r->cache_info.identity_digest, DIGEST_LEN));
|
||||
tor_strdup(hex_str(r->identity, DIGEST_LEN));
|
||||
conn->chosen_exit_optional = 1;
|
||||
}
|
||||
}
|
||||
@@ -2895,7 +2896,7 @@ connection_edge_is_rendezvous_stream(edge_connection_t *conn)
|
||||
* this relay, return 0.
|
||||
*/
|
||||
int
|
||||
connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit,
|
||||
connection_ap_can_use_exit(edge_connection_t *conn, const node_t *exit,
|
||||
int excluded_means_no)
|
||||
{
|
||||
or_options_t *options = get_options();
|
||||
@@ -2909,10 +2910,10 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit,
|
||||
* make sure the exit node of the existing circuit matches exactly.
|
||||
*/
|
||||
if (conn->chosen_exit_name) {
|
||||
routerinfo_t *chosen_exit =
|
||||
router_get_by_nickname(conn->chosen_exit_name, 1);
|
||||
if (!chosen_exit || memcmp(chosen_exit->cache_info.identity_digest,
|
||||
exit->cache_info.identity_digest, DIGEST_LEN)) {
|
||||
const node_t *chosen_exit =
|
||||
node_get_by_nickname(conn->chosen_exit_name, 1);
|
||||
if (!chosen_exit || memcmp(chosen_exit->identity,
|
||||
exit->identity, DIGEST_LEN)) {
|
||||
/* doesn't match */
|
||||
// log_debug(LD_APP,"Requested node '%s', considering node '%s'. No.",
|
||||
// conn->chosen_exit_name, exit->nickname);
|
||||
@@ -2927,8 +2928,7 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit,
|
||||
addr_policy_result_t r;
|
||||
if (tor_inet_aton(conn->socks_request->address, &in))
|
||||
addr = ntohl(in.s_addr);
|
||||
r = compare_addr_to_addr_policy(addr, conn->socks_request->port,
|
||||
exit->exit_policy);
|
||||
r = compare_addr_to_node_policy(addr, conn->socks_request->port, exit);
|
||||
if (r == ADDR_POLICY_REJECTED)
|
||||
return 0; /* We know the address, and the exit policy rejects it. */
|
||||
if (r == ADDR_POLICY_PROBABLY_REJECTED && !conn->chosen_exit_name)
|
||||
@@ -2937,12 +2937,12 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit,
|
||||
* this node, err on the side of caution. */
|
||||
} else if (SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)) {
|
||||
/* Don't send DNS requests to non-exit servers by default. */
|
||||
if (!conn->chosen_exit_name && policy_is_reject_star(exit->exit_policy))
|
||||
if (!conn->chosen_exit_name && node_exit_policy_rejects_all(exit))
|
||||
return 0;
|
||||
}
|
||||
if (options->_ExcludeExitNodesUnion &&
|
||||
(options->StrictNodes || excluded_means_no) &&
|
||||
routerset_contains_router(options->_ExcludeExitNodesUnion, exit)) {
|
||||
routerset_contains_node(options->_ExcludeExitNodesUnion, exit)) {
|
||||
/* If we are trying to avoid this node as exit, and we have StrictNodes
|
||||
* set, then this is not a suitable exit. Refuse it.
|
||||
*
|
||||
|
||||
@@ -47,7 +47,8 @@ int connection_exit_begin_conn(cell_t *cell, circuit_t *circ);
|
||||
int connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ);
|
||||
void connection_exit_connect(edge_connection_t *conn);
|
||||
int connection_edge_is_rendezvous_stream(edge_connection_t *conn);
|
||||
int connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit,
|
||||
int connection_ap_can_use_exit(edge_connection_t *conn,
|
||||
const node_t *exit,
|
||||
int excluded_means_no);
|
||||
void connection_ap_expire_beginning(void);
|
||||
void connection_ap_attach_pending(void);
|
||||
|
||||
+10
-7
@@ -22,6 +22,7 @@
|
||||
#include "geoip.h"
|
||||
#include "main.h"
|
||||
#include "networkstatus.h"
|
||||
#include "nodelist.h"
|
||||
#include "reasons.h"
|
||||
#include "relay.h"
|
||||
#include "rephist.h"
|
||||
@@ -446,7 +447,7 @@ connection_or_init_conn_from_address(or_connection_t *conn,
|
||||
const char *id_digest,
|
||||
int started_here)
|
||||
{
|
||||
routerinfo_t *r = router_get_by_digest(id_digest);
|
||||
const node_t *r = node_get_by_id(id_digest);
|
||||
connection_or_set_identity_digest(conn, id_digest);
|
||||
connection_or_update_token_buckets_helper(conn, 1, get_options());
|
||||
|
||||
@@ -454,8 +455,10 @@ connection_or_init_conn_from_address(or_connection_t *conn,
|
||||
tor_addr_copy(&conn->_base.addr, addr);
|
||||
tor_addr_copy(&conn->real_addr, addr);
|
||||
if (r) {
|
||||
tor_addr_t node_addr;
|
||||
node_get_addr(r, &node_addr);
|
||||
/* XXXX proposal 118 will make this more complex. */
|
||||
if (tor_addr_eq_ipv4h(&conn->_base.addr, r->addr))
|
||||
if (tor_addr_eq(&conn->_base.addr, &node_addr))
|
||||
conn->is_canonical = 1;
|
||||
if (!started_here) {
|
||||
/* Override the addr/port, so our log messages will make sense.
|
||||
@@ -468,12 +471,12 @@ connection_or_init_conn_from_address(or_connection_t *conn,
|
||||
* right IP address and port 56244, that wouldn't be as helpful. now we
|
||||
* log the "right" port too, so we know if it's moria1 or moria2.
|
||||
*/
|
||||
tor_addr_from_ipv4h(&conn->_base.addr, r->addr);
|
||||
conn->_base.port = r->or_port;
|
||||
tor_addr_copy(&conn->_base.addr, &node_addr);
|
||||
conn->_base.port = node_get_orport(r);
|
||||
}
|
||||
conn->nickname = tor_strdup(r->nickname);
|
||||
conn->nickname = tor_strdup(node_get_nickname(r));
|
||||
tor_free(conn->_base.address);
|
||||
conn->_base.address = tor_strdup(r->address);
|
||||
conn->_base.address = tor_dup_addr(&node_addr);
|
||||
} else {
|
||||
const char *n;
|
||||
/* If we're an authoritative directory server, we may know a
|
||||
@@ -1527,7 +1530,7 @@ connection_or_send_netinfo(or_connection_t *conn)
|
||||
{
|
||||
cell_t cell;
|
||||
time_t now = time(NULL);
|
||||
routerinfo_t *me;
|
||||
const routerinfo_t *me;
|
||||
int len;
|
||||
char *out;
|
||||
|
||||
|
||||
+41
-33
@@ -26,6 +26,7 @@
|
||||
#include "hibernate.h"
|
||||
#include "main.h"
|
||||
#include "networkstatus.h"
|
||||
#include "nodelist.h"
|
||||
#include "policies.h"
|
||||
#include "reasons.h"
|
||||
#include "router.h"
|
||||
@@ -1344,7 +1345,7 @@ getinfo_helper_misc(control_connection_t *conn, const char *question,
|
||||
} else if (!strcmp(question, "dir-usage")) {
|
||||
*answer = directory_dump_request_log();
|
||||
} else if (!strcmp(question, "fingerprint")) {
|
||||
routerinfo_t *me = router_get_my_routerinfo();
|
||||
const routerinfo_t *me = router_get_my_routerinfo();
|
||||
if (!me) {
|
||||
*errmsg = "No routerdesc known; am I really a server?";
|
||||
return -1;
|
||||
@@ -1366,8 +1367,9 @@ getinfo_helper_misc(control_connection_t *conn, const char *question,
|
||||
* NOTE: <b>ri_body</b> is as returned by signed_descriptor_get_body: it might
|
||||
* not be NUL-terminated. */
|
||||
static char *
|
||||
munge_extrainfo_into_routerinfo(const char *ri_body, signed_descriptor_t *ri,
|
||||
signed_descriptor_t *ei)
|
||||
munge_extrainfo_into_routerinfo(const char *ri_body,
|
||||
const signed_descriptor_t *ri,
|
||||
const signed_descriptor_t *ei)
|
||||
{
|
||||
char *out = NULL, *outp;
|
||||
int i;
|
||||
@@ -1412,16 +1414,17 @@ getinfo_helper_dir(control_connection_t *control_conn,
|
||||
const char *question, char **answer,
|
||||
const char **errmsg)
|
||||
{
|
||||
const routerinfo_t *ri;
|
||||
(void) control_conn;
|
||||
if (!strcmpstart(question, "desc/id/")) {
|
||||
routerinfo_t *ri = router_get_by_hexdigest(question+strlen("desc/id/"));
|
||||
ri = router_get_by_hexdigest(question+strlen("desc/id/"));
|
||||
if (ri) {
|
||||
const char *body = signed_descriptor_get_body(&ri->cache_info);
|
||||
if (body)
|
||||
*answer = tor_strndup(body, ri->cache_info.signed_descriptor_len);
|
||||
}
|
||||
} else if (!strcmpstart(question, "desc/name/")) {
|
||||
routerinfo_t *ri = router_get_by_nickname(question+strlen("desc/name/"),1);
|
||||
ri = router_get_by_nickname(question+strlen("desc/name/"),1);
|
||||
if (ri) {
|
||||
const char *body = signed_descriptor_get_body(&ri->cache_info);
|
||||
if (body)
|
||||
@@ -1431,7 +1434,7 @@ getinfo_helper_dir(control_connection_t *control_conn,
|
||||
routerlist_t *routerlist = router_get_routerlist();
|
||||
smartlist_t *sl = smartlist_create();
|
||||
if (routerlist && routerlist->routers) {
|
||||
SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, ri,
|
||||
SMARTLIST_FOREACH(routerlist->routers, const routerinfo_t *, ri,
|
||||
{
|
||||
const char *body = signed_descriptor_get_body(&ri->cache_info);
|
||||
if (body)
|
||||
@@ -1447,7 +1450,7 @@ getinfo_helper_dir(control_connection_t *control_conn,
|
||||
routerlist_t *routerlist = router_get_routerlist();
|
||||
smartlist_t *sl = smartlist_create();
|
||||
if (routerlist && routerlist->routers) {
|
||||
SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, ri,
|
||||
SMARTLIST_FOREACH(routerlist->routers, const routerinfo_t *, ri,
|
||||
{
|
||||
const char *body = signed_descriptor_get_body(&ri->cache_info);
|
||||
signed_descriptor_t *ei = extrainfo_get_by_descriptor_digest(
|
||||
@@ -1465,8 +1468,8 @@ getinfo_helper_dir(control_connection_t *control_conn,
|
||||
SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
|
||||
smartlist_free(sl);
|
||||
} else if (!strcmpstart(question, "desc-annotations/id/")) {
|
||||
routerinfo_t *ri = router_get_by_hexdigest(question+
|
||||
strlen("desc-annotations/id/"));
|
||||
ri = router_get_by_hexdigest(question+
|
||||
strlen("desc-annotations/id/"));
|
||||
if (ri) {
|
||||
const char *annotations =
|
||||
signed_descriptor_get_annotations(&ri->cache_info);
|
||||
@@ -2105,7 +2108,7 @@ static int
|
||||
handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
|
||||
const char *body)
|
||||
{
|
||||
smartlist_t *router_nicknames=NULL, *routers=NULL;
|
||||
smartlist_t *router_nicknames=NULL, *nodes=NULL;
|
||||
origin_circuit_t *circ = NULL;
|
||||
int zero_circ;
|
||||
uint8_t intended_purpose = CIRCUIT_PURPOSE_C_GENERAL;
|
||||
@@ -2136,8 +2139,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
|
||||
if ((smartlist_len(args) == 1) ||
|
||||
(smartlist_len(args) >= 2 && is_keyval_pair(smartlist_get(args, 1)))) {
|
||||
// "EXTENDCIRCUIT 0" || EXTENDCIRCUIT 0 foo=bar"
|
||||
circ = circuit_launch_by_router(intended_purpose, NULL,
|
||||
CIRCLAUNCH_NEED_CAPACITY);
|
||||
circ = circuit_launch(intended_purpose, CIRCLAUNCH_NEED_CAPACITY);
|
||||
if (!circ) {
|
||||
connection_write_str_to_buf("551 Couldn't start circuit\r\n", conn);
|
||||
} else {
|
||||
@@ -2165,17 +2167,21 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
|
||||
SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
|
||||
smartlist_free(args);
|
||||
|
||||
routers = smartlist_create();
|
||||
nodes = smartlist_create();
|
||||
SMARTLIST_FOREACH(router_nicknames, const char *, n,
|
||||
{
|
||||
routerinfo_t *r = router_get_by_nickname(n, 1);
|
||||
if (!r) {
|
||||
const node_t *node = node_get_by_nickname(n, 1);
|
||||
if (!node) {
|
||||
connection_printf_to_buf(conn, "552 No such router \"%s\"\r\n", n);
|
||||
goto done;
|
||||
}
|
||||
smartlist_add(routers, r);
|
||||
if (!node_has_descriptor(node)) {
|
||||
connection_printf_to_buf(conn, "552 descriptor for \"%s\"\r\n", n);
|
||||
goto done;
|
||||
}
|
||||
smartlist_add(nodes, (void*)node);
|
||||
});
|
||||
if (!smartlist_len(routers)) {
|
||||
if (!smartlist_len(nodes)) {
|
||||
connection_write_str_to_buf("512 No router names provided\r\n", conn);
|
||||
goto done;
|
||||
}
|
||||
@@ -2186,9 +2192,10 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
|
||||
}
|
||||
|
||||
/* now circ refers to something that is ready to be extended */
|
||||
SMARTLIST_FOREACH(routers, routerinfo_t *, r,
|
||||
SMARTLIST_FOREACH(nodes, const node_t *, node,
|
||||
{
|
||||
extend_info_t *info = extend_info_from_router(r);
|
||||
extend_info_t *info = extend_info_from_node(node);
|
||||
tor_assert(info); /* True, since node_has_descriptor(node) == true */
|
||||
circuit_append_new_exit(circ, info);
|
||||
extend_info_free(info);
|
||||
});
|
||||
@@ -2222,7 +2229,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
|
||||
done:
|
||||
SMARTLIST_FOREACH(router_nicknames, char *, n, tor_free(n));
|
||||
smartlist_free(router_nicknames);
|
||||
smartlist_free(routers);
|
||||
smartlist_free(nodes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2338,16 +2345,17 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len,
|
||||
}
|
||||
/* Is this a single hop circuit? */
|
||||
if (circ && (circuit_get_cpath_len(circ)<2 || hop==1)) {
|
||||
routerinfo_t *r = NULL;
|
||||
char* exit_digest;
|
||||
const node_t *node = NULL;
|
||||
char *exit_digest;
|
||||
if (circ->build_state &&
|
||||
circ->build_state->chosen_exit &&
|
||||
!tor_digest_is_zero(circ->build_state->chosen_exit->identity_digest)) {
|
||||
exit_digest = circ->build_state->chosen_exit->identity_digest;
|
||||
r = router_get_by_digest(exit_digest);
|
||||
node = node_get_by_id(exit_digest);
|
||||
}
|
||||
/* Do both the client and relay allow one-hop exit circuits? */
|
||||
if (!r || !r->allow_single_hop_exits ||
|
||||
if (!node ||
|
||||
!node_allows_single_hop_exits(node) ||
|
||||
!get_options()->AllowSingleHopCircuits) {
|
||||
connection_write_str_to_buf(
|
||||
"551 Can't attach stream to this one-hop circuit.\r\n", conn);
|
||||
@@ -3173,10 +3181,10 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp,
|
||||
static void
|
||||
orconn_target_get_name(char *name, size_t len, or_connection_t *conn)
|
||||
{
|
||||
routerinfo_t *ri = router_get_by_digest(conn->identity_digest);
|
||||
if (ri) {
|
||||
const node_t *node = node_get_by_id(conn->identity_digest);
|
||||
if (node) {
|
||||
tor_assert(len > MAX_VERBOSE_NICKNAME_LEN);
|
||||
router_get_verbose_nickname(name, ri);
|
||||
node_get_verbose_nickname(node, name);
|
||||
} else if (! tor_digest_is_zero(conn->identity_digest)) {
|
||||
name[0] = '$';
|
||||
base16_encode(name+1, len-1, conn->identity_digest,
|
||||
@@ -3493,7 +3501,7 @@ control_event_networkstatus_changed_helper(smartlist_t *statuses,
|
||||
smartlist_add(strs, tor_strdup("650+"));
|
||||
smartlist_add(strs, tor_strdup(event_string));
|
||||
smartlist_add(strs, tor_strdup("\r\n"));
|
||||
SMARTLIST_FOREACH(statuses, routerstatus_t *, rs,
|
||||
SMARTLIST_FOREACH(statuses, const routerstatus_t *, rs,
|
||||
{
|
||||
s = networkstatus_getinfo_helper_single(rs);
|
||||
if (!s) continue;
|
||||
@@ -3584,7 +3592,7 @@ control_event_buildtimeout_set(const circuit_build_times_t *cbt,
|
||||
/** Called when a single local_routerstatus_t has changed: Sends an NS event
|
||||
* to any controller that cares. */
|
||||
int
|
||||
control_event_networkstatus_changed_single(routerstatus_t *rs)
|
||||
control_event_networkstatus_changed_single(const routerstatus_t *rs)
|
||||
{
|
||||
smartlist_t *statuses;
|
||||
int r;
|
||||
@@ -3593,7 +3601,7 @@ control_event_networkstatus_changed_single(routerstatus_t *rs)
|
||||
return 0;
|
||||
|
||||
statuses = smartlist_create();
|
||||
smartlist_add(statuses, rs);
|
||||
smartlist_add(statuses, (void*)rs);
|
||||
r = control_event_networkstatus_changed(statuses);
|
||||
smartlist_free(statuses);
|
||||
return r;
|
||||
@@ -3718,9 +3726,9 @@ control_event_guard(const char *nickname, const char *digest,
|
||||
|
||||
{
|
||||
char buf[MAX_VERBOSE_NICKNAME_LEN+1];
|
||||
routerinfo_t *ri = router_get_by_digest(digest);
|
||||
if (ri) {
|
||||
router_get_verbose_nickname(buf, ri);
|
||||
const node_t *node = node_get_by_id(digest);
|
||||
if (node) {
|
||||
node_get_verbose_nickname(node, buf);
|
||||
} else {
|
||||
tor_snprintf(buf, sizeof(buf), "$%s~%s", hbuf, nickname);
|
||||
}
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ int control_event_my_descriptor_changed(void);
|
||||
int control_event_networkstatus_changed(smartlist_t *statuses);
|
||||
|
||||
int control_event_newconsensus(const networkstatus_t *consensus);
|
||||
int control_event_networkstatus_changed_single(routerstatus_t *rs);
|
||||
int control_event_networkstatus_changed_single(const routerstatus_t *rs);
|
||||
int control_event_general_status(int severity, const char *format, ...)
|
||||
CHECK_PRINTF(2,3);
|
||||
int control_event_client_status(int severity, const char *format, ...)
|
||||
|
||||
+27
-20
@@ -17,6 +17,7 @@
|
||||
#include "main.h"
|
||||
#include "microdesc.h"
|
||||
#include "networkstatus.h"
|
||||
#include "nodelist.h"
|
||||
#include "policies.h"
|
||||
#include "rendclient.h"
|
||||
#include "rendcommon.h"
|
||||
@@ -219,17 +220,19 @@ dir_conn_purpose_to_string(int purpose)
|
||||
int
|
||||
router_supports_extrainfo(const char *identity_digest, int is_authority)
|
||||
{
|
||||
routerinfo_t *ri = router_get_by_digest(identity_digest);
|
||||
const node_t *node = node_get_by_id(identity_digest);
|
||||
|
||||
if (ri) {
|
||||
if (ri->caches_extra_info)
|
||||
if (node && node->ri) {
|
||||
if (node->ri->caches_extra_info)
|
||||
return 1;
|
||||
if (is_authority && ri->platform &&
|
||||
tor_version_as_new_as(ri->platform, "Tor 0.2.0.0-alpha-dev (r10070)"))
|
||||
if (is_authority && node->ri->platform &&
|
||||
tor_version_as_new_as(node->ri->platform,
|
||||
"Tor 0.2.0.0-alpha-dev (r10070)"))
|
||||
return 1;
|
||||
}
|
||||
if (is_authority) {
|
||||
routerstatus_t *rs = router_get_consensus_status_by_id(identity_digest);
|
||||
const routerstatus_t *rs =
|
||||
router_get_consensus_status_by_id(identity_digest);
|
||||
if (rs && rs->version_supports_extrainfo_upload)
|
||||
return 1;
|
||||
}
|
||||
@@ -328,7 +331,7 @@ void
|
||||
directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
|
||||
const char *resource, int pds_flags)
|
||||
{
|
||||
routerstatus_t *rs = NULL;
|
||||
const routerstatus_t *rs = NULL;
|
||||
or_options_t *options = get_options();
|
||||
int prefer_authority = directory_fetches_from_authorities(options);
|
||||
int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose);
|
||||
@@ -400,10 +403,12 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
|
||||
* possible directory question. This won't be true forever. -RD */
|
||||
/* It certainly is not true with conditional consensus downloading,
|
||||
* so, for now, never assume the server supports that. */
|
||||
routerinfo_t *ri = choose_random_entry(NULL);
|
||||
if (ri) {
|
||||
const node_t *node = choose_random_entry(NULL);
|
||||
if (node && node->ri) {
|
||||
/* every bridge has a routerinfo. */
|
||||
tor_addr_t addr;
|
||||
tor_addr_from_ipv4h(&addr, ri->addr);
|
||||
routerinfo_t *ri = node->ri;
|
||||
node_get_addr(node, &addr);
|
||||
directory_initiate_command(ri->address, &addr,
|
||||
ri->or_port, 0,
|
||||
0, /* don't use conditional consensus url */
|
||||
@@ -512,7 +517,7 @@ directory_get_from_all_authorities(uint8_t dir_purpose,
|
||||
/** Same as directory_initiate_command_routerstatus(), but accepts
|
||||
* rendezvous data to fetch a hidden service descriptor. */
|
||||
void
|
||||
directory_initiate_command_routerstatus_rend(routerstatus_t *status,
|
||||
directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
|
||||
uint8_t dir_purpose,
|
||||
uint8_t router_purpose,
|
||||
int anonymized_connection,
|
||||
@@ -522,18 +527,19 @@ directory_initiate_command_routerstatus_rend(routerstatus_t *status,
|
||||
time_t if_modified_since,
|
||||
const rend_data_t *rend_query)
|
||||
{
|
||||
routerinfo_t *router;
|
||||
const node_t *node;
|
||||
char address_buf[INET_NTOA_BUF_LEN+1];
|
||||
struct in_addr in;
|
||||
const char *address;
|
||||
tor_addr_t addr;
|
||||
router = router_get_by_digest(status->identity_digest);
|
||||
if (!router && anonymized_connection) {
|
||||
node = node_get_by_id(status->identity_digest);
|
||||
if (!node && anonymized_connection) {
|
||||
log_info(LD_DIR, "Not sending anonymized request to directory '%s'; we "
|
||||
"don't have its router descriptor.", status->nickname);
|
||||
return;
|
||||
} else if (router) {
|
||||
address = router->address;
|
||||
} else if (node) {
|
||||
node_get_address_string(node, address_buf, sizeof(address_buf));
|
||||
address = address_buf;
|
||||
} else {
|
||||
in.s_addr = htonl(status->addr);
|
||||
tor_inet_ntoa(&in, address_buf, sizeof(address_buf));
|
||||
@@ -566,7 +572,7 @@ directory_initiate_command_routerstatus_rend(routerstatus_t *status,
|
||||
* want to fetch.
|
||||
*/
|
||||
void
|
||||
directory_initiate_command_routerstatus(routerstatus_t *status,
|
||||
directory_initiate_command_routerstatus(const routerstatus_t *status,
|
||||
uint8_t dir_purpose,
|
||||
uint8_t router_purpose,
|
||||
int anonymized_connection,
|
||||
@@ -590,7 +596,7 @@ directory_conn_is_self_reachability_test(dir_connection_t *conn)
|
||||
{
|
||||
if (conn->requested_resource &&
|
||||
!strcmpstart(conn->requested_resource,"authority")) {
|
||||
routerinfo_t *me = router_get_my_routerinfo();
|
||||
const routerinfo_t *me = router_get_my_routerinfo();
|
||||
if (me &&
|
||||
router_digest_is_me(conn->identity_digest) &&
|
||||
tor_addr_eq_ipv4h(&conn->_base.addr, me->addr) && /*XXXX prop 118*/
|
||||
@@ -1597,7 +1603,8 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
|
||||
"'%s:%d'. I'll try again soon.",
|
||||
status_code, escaped(reason), conn->_base.address,
|
||||
conn->_base.port);
|
||||
if ((rs = router_get_consensus_status_by_id(conn->identity_digest)))
|
||||
rs = router_get_mutable_consensus_status_by_id(conn->identity_digest);
|
||||
if (rs)
|
||||
rs->last_dir_503_at = now;
|
||||
if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest)))
|
||||
ds->fake_status.last_dir_503_at = now;
|
||||
@@ -3692,7 +3699,7 @@ dir_microdesc_download_failed(smartlist_t *failed,
|
||||
if (! consensus)
|
||||
return;
|
||||
SMARTLIST_FOREACH_BEGIN(failed, const char *, d) {
|
||||
rs = router_get_consensus_status_by_descriptor_digest(consensus, d);
|
||||
rs = router_get_mutable_consensus_status_by_descriptor_digest(consensus,d);
|
||||
if (!rs)
|
||||
continue;
|
||||
dls = &rs->dl_status;
|
||||
|
||||
+2
-2
@@ -23,7 +23,7 @@ void directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
|
||||
void directory_get_from_all_authorities(uint8_t dir_purpose,
|
||||
uint8_t router_purpose,
|
||||
const char *resource);
|
||||
void directory_initiate_command_routerstatus(routerstatus_t *status,
|
||||
void directory_initiate_command_routerstatus(const routerstatus_t *status,
|
||||
uint8_t dir_purpose,
|
||||
uint8_t router_purpose,
|
||||
int anonymized_connection,
|
||||
@@ -31,7 +31,7 @@ void directory_initiate_command_routerstatus(routerstatus_t *status,
|
||||
const char *payload,
|
||||
size_t payload_len,
|
||||
time_t if_modified_since);
|
||||
void directory_initiate_command_routerstatus_rend(routerstatus_t *status,
|
||||
void directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
|
||||
uint8_t dir_purpose,
|
||||
uint8_t router_purpose,
|
||||
int anonymized_connection,
|
||||
|
||||
+144
-109
@@ -16,6 +16,7 @@
|
||||
#include "hibernate.h"
|
||||
#include "microdesc.h"
|
||||
#include "networkstatus.h"
|
||||
#include "nodelist.h"
|
||||
#include "policies.h"
|
||||
#include "rephist.h"
|
||||
#include "router.h"
|
||||
@@ -65,8 +66,6 @@ static char *format_versions_list(config_line_t *ln);
|
||||
struct authdir_config_t;
|
||||
static int add_fingerprint_to_dir(const char *nickname, const char *fp,
|
||||
struct authdir_config_t *list);
|
||||
static uint32_t dirserv_router_get_status(const routerinfo_t *router,
|
||||
const char **msg);
|
||||
static uint32_t
|
||||
dirserv_get_status_impl(const char *fp, const char *nickname,
|
||||
const char *address,
|
||||
@@ -74,7 +73,8 @@ dirserv_get_status_impl(const char *fp, const char *nickname,
|
||||
const char *platform, const char *contact,
|
||||
const char **msg, int should_log);
|
||||
static void clear_cached_dir(cached_dir_t *d);
|
||||
static signed_descriptor_t *get_signed_descriptor_by_fp(const char *fp,
|
||||
static const signed_descriptor_t *get_signed_descriptor_by_fp(
|
||||
const char *fp,
|
||||
int extrainfo,
|
||||
time_t publish_cutoff);
|
||||
static int dirserv_add_extrainfo(extrainfo_t *ei, const char **msg);
|
||||
@@ -303,7 +303,7 @@ dirserv_load_fingerprint_file(void)
|
||||
*
|
||||
* If the status is 'FP_REJECT' and <b>msg</b> is provided, set
|
||||
* *<b>msg</b> to an explanation of why. */
|
||||
static uint32_t
|
||||
uint32_t
|
||||
dirserv_router_get_status(const routerinfo_t *router, const char **msg)
|
||||
{
|
||||
char d[DIGEST_LEN];
|
||||
@@ -325,7 +325,7 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg)
|
||||
/** Return true if there is no point in downloading the router described by
|
||||
* <b>rs</b> because this directory would reject it. */
|
||||
int
|
||||
dirserv_would_reject_router(routerstatus_t *rs)
|
||||
dirserv_would_reject_router(const routerstatus_t *rs)
|
||||
{
|
||||
uint32_t res;
|
||||
|
||||
@@ -360,7 +360,7 @@ dirserv_get_name_status(const char *id_digest, const char *nickname)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Helper: As dirserv_get_router_status, but takes the router fingerprint
|
||||
/** Helper: As dirserv_router_get_status, but takes the router fingerprint
|
||||
* (hex, no spaces), nickname, address (used for logging only), IP address, OR
|
||||
* port, platform (logging only) and contact info (logging only) as arguments.
|
||||
*
|
||||
@@ -375,7 +375,7 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname,
|
||||
const char **msg, int should_log)
|
||||
{
|
||||
int reject_unlisted = get_options()->AuthDirRejectUnlisted;
|
||||
uint32_t result = 0;
|
||||
uint32_t result;
|
||||
router_status_t *status_by_digest;
|
||||
|
||||
if (!fingerprint_list)
|
||||
@@ -533,7 +533,7 @@ dirserv_router_has_valid_address(routerinfo_t *ri)
|
||||
*/
|
||||
int
|
||||
authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
|
||||
int complain)
|
||||
int complain, int *valid_out)
|
||||
{
|
||||
/* Okay. Now check whether the fingerprint is recognized. */
|
||||
uint32_t status = dirserv_router_get_status(ri, msg);
|
||||
@@ -574,15 +574,24 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
|
||||
*msg = "Rejected: Address is not an IP, or IP is a private address.";
|
||||
return -1;
|
||||
}
|
||||
/* Okay, looks like we're willing to accept this one. */
|
||||
ri->is_named = (status & FP_NAMED) ? 1 : 0;
|
||||
ri->is_valid = (status & FP_INVALID) ? 0 : 1;
|
||||
ri->is_bad_directory = (status & FP_BADDIR) ? 1 : 0;
|
||||
ri->is_bad_exit = (status & FP_BADEXIT) ? 1 : 0;
|
||||
|
||||
*valid_out = ! (status & FP_INVALID);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Update the relevant flags of <b>node</b> based on our opinion as a
|
||||
* directory authority in <b>authstatus</b>, as returned by
|
||||
* dirserv_router_get_status or equivalent. */
|
||||
void
|
||||
dirserv_set_node_flags_from_authoritative_status(node_t *node,
|
||||
uint32_t authstatus)
|
||||
{
|
||||
node->is_valid = (authstatus & FP_INVALID) ? 0 : 1;
|
||||
node->is_bad_directory = (authstatus & FP_BADDIR) ? 1 : 0;
|
||||
node->is_bad_exit = (authstatus & FP_BADEXIT) ? 1 : 0;
|
||||
}
|
||||
|
||||
/** True iff <b>a</b> is more severe than <b>b</b>. */
|
||||
static int
|
||||
WRA_MORE_SEVERE(was_router_added_t a, was_router_added_t b)
|
||||
@@ -707,7 +716,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
|
||||
* from this server. (We do this here and not in router_add_to_routerlist
|
||||
* because we want to be able to accept the newest router descriptor that
|
||||
* another authority has, so we all converge on the same one.) */
|
||||
ri_old = router_get_by_digest(ri->cache_info.identity_digest);
|
||||
ri_old = router_get_mutable_by_digest(ri->cache_info.identity_digest);
|
||||
if (ri_old && ri_old->cache_info.published_on < ri->cache_info.published_on
|
||||
&& router_differences_are_cosmetic(ri_old, ri)
|
||||
&& !router_is_me(ri)) {
|
||||
@@ -751,8 +760,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
|
||||
routerlist_descriptors_added(changed, 0);
|
||||
smartlist_free(changed);
|
||||
if (!*msg) {
|
||||
*msg = ri->is_valid ? "Descriptor for valid server accepted" :
|
||||
"Descriptor for invalid server accepted";
|
||||
*msg = "Descriptor accepted";
|
||||
}
|
||||
log_info(LD_DIRSERV,
|
||||
"Added descriptor from '%s' (source: %s): %s.",
|
||||
@@ -767,7 +775,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
|
||||
static was_router_added_t
|
||||
dirserv_add_extrainfo(extrainfo_t *ei, const char **msg)
|
||||
{
|
||||
routerinfo_t *ri;
|
||||
const routerinfo_t *ri;
|
||||
int r;
|
||||
tor_assert(msg);
|
||||
*msg = NULL;
|
||||
@@ -807,50 +815,60 @@ dirserv_add_extrainfo(extrainfo_t *ei, const char **msg)
|
||||
static void
|
||||
directory_remove_invalid(void)
|
||||
{
|
||||
int i;
|
||||
int changed = 0;
|
||||
routerlist_t *rl = router_get_routerlist();
|
||||
smartlist_t *nodes = smartlist_create();
|
||||
smartlist_add_all(nodes, nodelist_get_list());
|
||||
|
||||
routerlist_assert_ok(rl);
|
||||
|
||||
for (i = 0; i < smartlist_len(rl->routers); ++i) {
|
||||
SMARTLIST_FOREACH_BEGIN(nodes, node_t *, node) {
|
||||
const char *msg;
|
||||
routerinfo_t *ent = smartlist_get(rl->routers, i);
|
||||
uint32_t r = dirserv_router_get_status(ent, &msg);
|
||||
routerinfo_t *ent = node->ri;
|
||||
uint32_t r;
|
||||
if (!ent)
|
||||
continue;
|
||||
r = dirserv_router_get_status(ent, &msg);
|
||||
if (r & FP_REJECT) {
|
||||
log_info(LD_DIRSERV, "Router '%s' is now rejected: %s",
|
||||
ent->nickname, msg?msg:"");
|
||||
routerlist_remove(rl, ent, 0, time(NULL));
|
||||
i--;
|
||||
changed = 1;
|
||||
continue;
|
||||
}
|
||||
if (bool_neq((r & FP_NAMED), ent->is_named)) {
|
||||
#if 0
|
||||
if (bool_neq((r & FP_NAMED), ent->auth_says_is_named)) {
|
||||
log_info(LD_DIRSERV,
|
||||
"Router '%s' is now %snamed.", ent->nickname,
|
||||
(r&FP_NAMED)?"":"un");
|
||||
ent->is_named = (r&FP_NAMED)?1:0;
|
||||
changed = 1;
|
||||
}
|
||||
if (bool_neq((r & FP_INVALID), !ent->is_valid)) {
|
||||
if (bool_neq((r & FP_UNNAMED), ent->auth_says_is_unnamed)) {
|
||||
log_info(LD_DIRSERV,
|
||||
"Router '%s' is now %snamed. (FP_UNNAMED)", ent->nickname,
|
||||
(r&FP_NAMED)?"":"un");
|
||||
ent->is_named = (r&FP_NUNAMED)?0:1;
|
||||
changed = 1;
|
||||
}
|
||||
#endif
|
||||
if (bool_neq((r & FP_INVALID), !node->is_valid)) {
|
||||
log_info(LD_DIRSERV, "Router '%s' is now %svalid.", ent->nickname,
|
||||
(r&FP_INVALID) ? "in" : "");
|
||||
ent->is_valid = (r&FP_INVALID)?0:1;
|
||||
node->is_valid = (r&FP_INVALID)?0:1;
|
||||
changed = 1;
|
||||
}
|
||||
if (bool_neq((r & FP_BADDIR), ent->is_bad_directory)) {
|
||||
if (bool_neq((r & FP_BADDIR), node->is_bad_directory)) {
|
||||
log_info(LD_DIRSERV, "Router '%s' is now a %s directory", ent->nickname,
|
||||
(r & FP_BADDIR) ? "bad" : "good");
|
||||
ent->is_bad_directory = (r&FP_BADDIR) ? 1: 0;
|
||||
node->is_bad_directory = (r&FP_BADDIR) ? 1: 0;
|
||||
changed = 1;
|
||||
}
|
||||
if (bool_neq((r & FP_BADEXIT), ent->is_bad_exit)) {
|
||||
if (bool_neq((r & FP_BADEXIT), node->is_bad_exit)) {
|
||||
log_info(LD_DIRSERV, "Router '%s' is now a %s exit", ent->nickname,
|
||||
(r & FP_BADEXIT) ? "bad" : "good");
|
||||
ent->is_bad_exit = (r&FP_BADEXIT) ? 1: 0;
|
||||
node->is_bad_exit = (r&FP_BADEXIT) ? 1: 0;
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(node);
|
||||
if (changed)
|
||||
directory_set_dirty();
|
||||
|
||||
@@ -893,10 +911,11 @@ directory_set_dirty(void)
|
||||
* as running iff <b>is_live</b> is true.
|
||||
*/
|
||||
static char *
|
||||
list_single_server_status(routerinfo_t *desc, int is_live)
|
||||
list_single_server_status(const routerinfo_t *desc, int is_live)
|
||||
{
|
||||
char buf[MAX_NICKNAME_LEN+HEX_DIGEST_LEN+4]; /* !nickname=$hexdigest\0 */
|
||||
char *cp;
|
||||
const node_t *node;
|
||||
|
||||
tor_assert(desc);
|
||||
|
||||
@@ -904,7 +923,8 @@ list_single_server_status(routerinfo_t *desc, int is_live)
|
||||
if (!is_live) {
|
||||
*cp++ = '!';
|
||||
}
|
||||
if (desc->is_valid) {
|
||||
node = node_get_by_id(desc->cache_info.identity_digest);
|
||||
if (node && node->is_valid) {
|
||||
strlcpy(cp, desc->nickname, sizeof(buf)-(cp-buf));
|
||||
cp += strlen(cp);
|
||||
*cp++ = '=';
|
||||
@@ -943,6 +963,8 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
|
||||
unreachable.
|
||||
*/
|
||||
int answer;
|
||||
node_t *node = node_get_mutable_by_id(router->cache_info.identity_digest);
|
||||
tor_assert(node);
|
||||
|
||||
if (router_is_me(router)) {
|
||||
/* We always know if we are down ourselves. */
|
||||
@@ -967,7 +989,7 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
|
||||
rep_hist_note_router_unreachable(router->cache_info.identity_digest, now);
|
||||
}
|
||||
|
||||
router->is_running = answer;
|
||||
node->is_running = answer;
|
||||
}
|
||||
|
||||
/** Based on the routerinfo_ts in <b>routers</b>, allocate the
|
||||
@@ -995,6 +1017,8 @@ list_server_status_v1(smartlist_t *routers, char **router_status_out,
|
||||
rs_entries = smartlist_create();
|
||||
|
||||
SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) {
|
||||
const node_t *node = node_get_by_id(ri->cache_info.identity_digest);
|
||||
tor_assert(node);
|
||||
if (authdir) {
|
||||
/* Update router status in routerinfo_t. */
|
||||
dirserv_set_router_is_running(ri, now);
|
||||
@@ -1002,12 +1026,13 @@ list_server_status_v1(smartlist_t *routers, char **router_status_out,
|
||||
if (for_controller) {
|
||||
char name_buf[MAX_VERBOSE_NICKNAME_LEN+2];
|
||||
char *cp = name_buf;
|
||||
if (!ri->is_running)
|
||||
if (!node->is_running)
|
||||
*cp++ = '!';
|
||||
router_get_verbose_nickname(cp, ri);
|
||||
smartlist_add(rs_entries, tor_strdup(name_buf));
|
||||
} else if (ri->cache_info.published_on >= cutoff) {
|
||||
smartlist_add(rs_entries, list_single_server_status(ri, ri->is_running));
|
||||
smartlist_add(rs_entries, list_single_server_status(ri,
|
||||
node->is_running));
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(ri);
|
||||
|
||||
@@ -1045,12 +1070,12 @@ format_versions_list(config_line_t *ln)
|
||||
* not hibernating, and not too old. Else return 0.
|
||||
*/
|
||||
static int
|
||||
router_is_active(routerinfo_t *ri, time_t now)
|
||||
router_is_active(const routerinfo_t *ri, const node_t *node, time_t now)
|
||||
{
|
||||
time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
|
||||
if (ri->cache_info.published_on < cutoff)
|
||||
return 0;
|
||||
if (!ri->is_running || !ri->is_valid || ri->is_hibernating)
|
||||
if (!node->is_running || !node->is_valid || ri->is_hibernating)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -1151,7 +1176,7 @@ dirserv_dump_directory_to_string(char **dir_out,
|
||||
int
|
||||
directory_fetches_from_authorities(or_options_t *options)
|
||||
{
|
||||
routerinfo_t *me;
|
||||
const routerinfo_t *me;
|
||||
uint32_t addr;
|
||||
int refuseunknown;
|
||||
if (options->FetchDirInfoEarly)
|
||||
@@ -1716,7 +1741,7 @@ static uint64_t total_exit_bandwidth = 0;
|
||||
/** Helper: estimate the uptime of a router given its stated uptime and the
|
||||
* amount of time since it last stated its stated uptime. */
|
||||
static INLINE long
|
||||
real_uptime(routerinfo_t *router, time_t now)
|
||||
real_uptime(const routerinfo_t *router, time_t now)
|
||||
{
|
||||
if (now < router->cache_info.published_on)
|
||||
return router->uptime;
|
||||
@@ -1767,7 +1792,8 @@ dirserv_thinks_router_is_unreliable(time_t now,
|
||||
* been set.
|
||||
*/
|
||||
static int
|
||||
dirserv_thinks_router_is_hs_dir(routerinfo_t *router, time_t now)
|
||||
dirserv_thinks_router_is_hs_dir(const routerinfo_t *router,
|
||||
const node_t *node, time_t now)
|
||||
{
|
||||
long uptime = real_uptime(router, now);
|
||||
|
||||
@@ -1777,7 +1803,7 @@ dirserv_thinks_router_is_hs_dir(routerinfo_t *router, time_t now)
|
||||
* version is too old. */
|
||||
return (router->wants_to_be_hs_dir && router->dir_port &&
|
||||
uptime > get_options()->MinUptimeHidServDirectoryV2 &&
|
||||
router->is_running);
|
||||
node->is_running);
|
||||
}
|
||||
|
||||
/** Look through the routerlist, the Mean Time Between Failure history, and
|
||||
@@ -1825,19 +1851,22 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
|
||||
/* Weighted fractional uptime for each active router. */
|
||||
wfus = tor_malloc(sizeof(double)*smartlist_len(rl->routers));
|
||||
|
||||
nodelist_assert_ok();
|
||||
|
||||
/* Now, fill in the arrays. */
|
||||
SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
|
||||
if (router_is_active(ri, now)) {
|
||||
SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) {
|
||||
routerinfo_t *ri = node->ri;
|
||||
if (ri && router_is_active(ri, node, now)) {
|
||||
const char *id = ri->cache_info.identity_digest;
|
||||
uint32_t bw;
|
||||
ri->is_exit = (!router_exit_policy_rejects_all(ri) &&
|
||||
exit_policy_is_general_exit(ri->exit_policy));
|
||||
node->is_exit = (!router_exit_policy_rejects_all(ri) &&
|
||||
exit_policy_is_general_exit(ri->exit_policy));
|
||||
uptimes[n_active] = (uint32_t)real_uptime(ri, now);
|
||||
mtbfs[n_active] = rep_hist_get_stability(id, now);
|
||||
tks [n_active] = rep_hist_get_weighted_time_known(id, now);
|
||||
bandwidths[n_active] = bw = router_get_advertised_bandwidth(ri);
|
||||
total_bandwidth += bw;
|
||||
if (ri->is_exit && !ri->is_bad_exit) {
|
||||
if (node->is_exit && !node->is_bad_exit) {
|
||||
total_exit_bandwidth += bw;
|
||||
} else {
|
||||
bandwidths_excluding_exits[n_active_nonexit] = bw;
|
||||
@@ -1845,7 +1874,7 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
|
||||
}
|
||||
++n_active;
|
||||
}
|
||||
});
|
||||
} SMARTLIST_FOREACH_END(node);
|
||||
|
||||
/* Now, compute thresholds. */
|
||||
if (n_active) {
|
||||
@@ -1871,15 +1900,17 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
|
||||
/* Now that we have a time-known that 7/8 routers are known longer than,
|
||||
* fill wfus with the wfu of every such "familiar" router. */
|
||||
n_familiar = 0;
|
||||
SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
|
||||
if (router_is_active(ri, now)) {
|
||||
|
||||
SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) {
|
||||
routerinfo_t *ri = node->ri;
|
||||
if (ri && router_is_active(ri, node, now)) {
|
||||
const char *id = ri->cache_info.identity_digest;
|
||||
long tk = rep_hist_get_weighted_time_known(id, now);
|
||||
if (tk < guard_tk)
|
||||
continue;
|
||||
wfus[n_familiar++] = rep_hist_get_weighted_fractional_uptime(id, now);
|
||||
}
|
||||
});
|
||||
} SMARTLIST_FOREACH_END(node);
|
||||
if (n_familiar)
|
||||
guard_wfu = median_double(wfus, n_familiar);
|
||||
if (guard_wfu > WFU_TO_GUARANTEE_GUARD)
|
||||
@@ -1950,7 +1981,7 @@ version_from_platform(const char *platform)
|
||||
*/
|
||||
int
|
||||
routerstatus_format_entry(char *buf, size_t buf_len,
|
||||
routerstatus_t *rs, const char *version,
|
||||
const routerstatus_t *rs, const char *version,
|
||||
routerstatus_format_type_t format)
|
||||
{
|
||||
int r;
|
||||
@@ -2004,7 +2035,7 @@ routerstatus_format_entry(char *buf, size_t buf_len,
|
||||
rs->is_possible_guard?" Guard":"",
|
||||
rs->is_hs_dir?" HSDir":"",
|
||||
rs->is_named?" Named":"",
|
||||
rs->is_running?" Running":"",
|
||||
rs->is_flagged_running?" Running":"",
|
||||
rs->is_stable?" Stable":"",
|
||||
rs->is_unnamed?" Unnamed":"",
|
||||
rs->is_v2_dir?" V2Dir":"",
|
||||
@@ -2026,7 +2057,7 @@ routerstatus_format_entry(char *buf, size_t buf_len,
|
||||
}
|
||||
|
||||
if (format != NS_V2) {
|
||||
routerinfo_t* desc = router_get_by_digest(rs->identity_digest);
|
||||
const routerinfo_t* desc = router_get_by_digest(rs->identity_digest);
|
||||
uint32_t bw;
|
||||
|
||||
if (format != NS_CONTROL_PORT) {
|
||||
@@ -2122,6 +2153,8 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b)
|
||||
routerinfo_t *first = *(routerinfo_t **)a, *second = *(routerinfo_t **)b;
|
||||
int first_is_auth, second_is_auth;
|
||||
uint32_t bw_first, bw_second;
|
||||
const node_t *node_first, *node_second;
|
||||
int first_is_running, second_is_running;
|
||||
|
||||
/* we return -1 if first should appear before second... that is,
|
||||
* if first is a better router. */
|
||||
@@ -2144,9 +2177,14 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b)
|
||||
else if (!first_is_auth && second_is_auth)
|
||||
return 1;
|
||||
|
||||
else if (first->is_running && !second->is_running)
|
||||
node_first = node_get_by_id(first->cache_info.identity_digest);
|
||||
node_second = node_get_by_id(second->cache_info.identity_digest);
|
||||
first_is_running = node_first && node_first->is_running;
|
||||
second_is_running = node_second && node_second->is_running;
|
||||
|
||||
if (first_is_running && !second_is_running)
|
||||
return -1;
|
||||
else if (!first->is_running && second->is_running)
|
||||
else if (!first_is_running && second_is_running)
|
||||
return 1;
|
||||
|
||||
bw_first = router_get_advertised_bandwidth(first);
|
||||
@@ -2215,7 +2253,9 @@ get_possible_sybil_list(const smartlist_t *routers)
|
||||
*/
|
||||
void
|
||||
set_routerstatus_from_routerinfo(routerstatus_t *rs,
|
||||
routerinfo_t *ri, time_t now,
|
||||
node_t *node,
|
||||
routerinfo_t *ri,
|
||||
time_t now,
|
||||
int naming, int listbadexits,
|
||||
int listbaddirs)
|
||||
{
|
||||
@@ -2227,48 +2267,46 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs,
|
||||
router_digest_is_trusted_dir(ri->cache_info.identity_digest);
|
||||
|
||||
/* Already set by compute_performance_thresholds. */
|
||||
rs->is_exit = ri->is_exit;
|
||||
rs->is_stable = ri->is_stable =
|
||||
router_is_active(ri, now) &&
|
||||
rs->is_exit = node->is_exit;
|
||||
rs->is_stable = node->is_stable =
|
||||
router_is_active(ri, node, now) &&
|
||||
!dirserv_thinks_router_is_unreliable(now, ri, 1, 0) &&
|
||||
!unstable_version;
|
||||
rs->is_fast = ri->is_fast =
|
||||
router_is_active(ri, now) &&
|
||||
rs->is_fast = node->is_fast =
|
||||
router_is_active(ri, node, now) &&
|
||||
!dirserv_thinks_router_is_unreliable(now, ri, 0, 1);
|
||||
rs->is_running = ri->is_running; /* computed above */
|
||||
rs->is_flagged_running = node->is_running; /* computed above */
|
||||
|
||||
if (naming) {
|
||||
uint32_t name_status = dirserv_get_name_status(
|
||||
ri->cache_info.identity_digest, ri->nickname);
|
||||
node->identity, ri->nickname);
|
||||
rs->is_named = (naming && (name_status & FP_NAMED)) ? 1 : 0;
|
||||
rs->is_unnamed = (naming && (name_status & FP_UNNAMED)) ? 1 : 0;
|
||||
}
|
||||
rs->is_valid = ri->is_valid;
|
||||
rs->is_valid = node->is_valid;
|
||||
|
||||
if (rs->is_fast &&
|
||||
if (node->is_fast &&
|
||||
(router_get_advertised_bandwidth(ri) >= BANDWIDTH_TO_GUARANTEE_GUARD ||
|
||||
router_get_advertised_bandwidth(ri) >=
|
||||
MIN(guard_bandwidth_including_exits,
|
||||
guard_bandwidth_excluding_exits))) {
|
||||
long tk = rep_hist_get_weighted_time_known(
|
||||
ri->cache_info.identity_digest, now);
|
||||
double wfu = rep_hist_get_weighted_fractional_uptime(
|
||||
ri->cache_info.identity_digest, now);
|
||||
long tk = rep_hist_get_weighted_time_known(node->identity, now);
|
||||
double wfu = rep_hist_get_weighted_fractional_uptime(node->identity, now);
|
||||
rs->is_possible_guard = (wfu >= guard_wfu && tk >= guard_tk) ? 1 : 0;
|
||||
} else {
|
||||
rs->is_possible_guard = 0;
|
||||
}
|
||||
rs->is_bad_directory = listbaddirs && ri->is_bad_directory;
|
||||
rs->is_bad_exit = listbadexits && ri->is_bad_exit;
|
||||
ri->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, now);
|
||||
rs->is_hs_dir = ri->is_hs_dir;
|
||||
rs->is_bad_directory = listbaddirs && node->is_bad_directory;
|
||||
rs->is_bad_exit = listbadexits && node->is_bad_exit;
|
||||
node->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, node, now);
|
||||
rs->is_hs_dir = node->is_hs_dir;
|
||||
rs->is_v2_dir = ri->dir_port != 0;
|
||||
|
||||
if (!strcasecmp(ri->nickname, UNNAMED_ROUTER_NICKNAME))
|
||||
rs->is_named = rs->is_unnamed = 0;
|
||||
|
||||
rs->published_on = ri->cache_info.published_on;
|
||||
memcpy(rs->identity_digest, ri->cache_info.identity_digest, DIGEST_LEN);
|
||||
memcpy(rs->identity_digest, node->identity, DIGEST_LEN);
|
||||
memcpy(rs->descriptor_digest, ri->cache_info.signed_descriptor_digest,
|
||||
DIGEST_LEN);
|
||||
rs->addr = ri->addr;
|
||||
@@ -2285,7 +2323,7 @@ static void
|
||||
clear_status_flags_on_sybil(routerstatus_t *rs)
|
||||
{
|
||||
rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast =
|
||||
rs->is_running = rs->is_named = rs->is_valid = rs->is_v2_dir =
|
||||
rs->is_flagged_running = rs->is_named = rs->is_valid = rs->is_v2_dir =
|
||||
rs->is_hs_dir = rs->is_possible_guard = rs->is_bad_exit =
|
||||
rs->is_bad_directory = 0;
|
||||
/* FFFF we might want some mechanism to check later on if we
|
||||
@@ -2293,18 +2331,6 @@ clear_status_flags_on_sybil(routerstatus_t *rs)
|
||||
* forget to add it to this clause. */
|
||||
}
|
||||
|
||||
/** Clear all the status flags in routerinfo <b>router</b>. We put this
|
||||
* function here because it's eerily similar to
|
||||
* clear_status_flags_on_sybil() above. One day we should merge them. */
|
||||
void
|
||||
router_clear_status_flags(routerinfo_t *router)
|
||||
{
|
||||
router->is_valid = router->is_running = router->is_hs_dir =
|
||||
router->is_fast = router->is_stable =
|
||||
router->is_possible_guard = router->is_exit =
|
||||
router->is_bad_exit = router->is_bad_directory = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to parse out a line in the measured bandwidth file
|
||||
* into a measured_bw_line_t output structure. Returns -1 on failure
|
||||
@@ -2552,17 +2578,20 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
|
||||
routerstatus_t *rs;
|
||||
vote_routerstatus_t *vrs;
|
||||
microdesc_t *md;
|
||||
node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
|
||||
if (!node)
|
||||
continue;
|
||||
|
||||
vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
|
||||
rs = &vrs->status;
|
||||
set_routerstatus_from_routerinfo(rs, ri, now,
|
||||
set_routerstatus_from_routerinfo(rs, node, ri, now,
|
||||
naming, listbadexits, listbaddirs);
|
||||
|
||||
if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest))
|
||||
clear_status_flags_on_sybil(rs);
|
||||
|
||||
if (!vote_on_reachability)
|
||||
rs->is_running = 0;
|
||||
rs->is_flagged_running = 0;
|
||||
|
||||
vrs->version = version_from_platform(ri->platform);
|
||||
md = dirvote_create_microdescriptor(ri);
|
||||
@@ -2795,8 +2824,12 @@ generate_v2_networkstatus_opinion(void)
|
||||
if (ri->cache_info.published_on >= cutoff) {
|
||||
routerstatus_t rs;
|
||||
char *version = version_from_platform(ri->platform);
|
||||
|
||||
set_routerstatus_from_routerinfo(&rs, ri, now,
|
||||
node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
|
||||
if (!node) {
|
||||
tor_free(version);
|
||||
continue;
|
||||
}
|
||||
set_routerstatus_from_routerinfo(&rs, node, ri, now,
|
||||
naming, listbadexits, listbaddirs);
|
||||
|
||||
if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest))
|
||||
@@ -2879,7 +2912,7 @@ dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result,
|
||||
|
||||
if (!strcmp(key,"authority")) {
|
||||
if (authdir_mode_v2(get_options())) {
|
||||
routerinfo_t *me = router_get_my_routerinfo();
|
||||
const routerinfo_t *me = router_get_my_routerinfo();
|
||||
if (me)
|
||||
smartlist_add(result,
|
||||
tor_memdup(me->cache_info.identity_digest, DIGEST_LEN));
|
||||
@@ -2965,7 +2998,7 @@ dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key,
|
||||
smartlist_add(fps_out,
|
||||
tor_memdup(r->cache_info.identity_digest, DIGEST_LEN)));
|
||||
} else if (!strcmp(key, "authority")) {
|
||||
routerinfo_t *ri = router_get_my_routerinfo();
|
||||
const routerinfo_t *ri = router_get_my_routerinfo();
|
||||
if (ri)
|
||||
smartlist_add(fps_out,
|
||||
tor_memdup(ri->cache_info.identity_digest, DIGEST_LEN));
|
||||
@@ -2985,8 +3018,8 @@ dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key,
|
||||
|
||||
if (for_unencrypted_conn) {
|
||||
/* Remove anything that insists it not be sent unencrypted. */
|
||||
SMARTLIST_FOREACH(fps_out, char *, cp, {
|
||||
signed_descriptor_t *sd;
|
||||
SMARTLIST_FOREACH_BEGIN(fps_out, char *, cp) {
|
||||
const signed_descriptor_t *sd;
|
||||
if (by_id)
|
||||
sd = get_signed_descriptor_by_fp(cp,is_extrainfo,0);
|
||||
else if (is_extrainfo)
|
||||
@@ -2997,7 +3030,7 @@ dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key,
|
||||
tor_free(cp);
|
||||
SMARTLIST_DEL_CURRENT(fps_out, cp);
|
||||
}
|
||||
});
|
||||
} SMARTLIST_FOREACH_END(cp);
|
||||
}
|
||||
|
||||
if (!smartlist_len(fps_out)) {
|
||||
@@ -3036,9 +3069,9 @@ dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
|
||||
SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
|
||||
smartlist_add(descs_out, &(r->cache_info)));
|
||||
} else if (!strcmp(key, "/tor/server/authority")) {
|
||||
routerinfo_t *ri = router_get_my_routerinfo();
|
||||
const routerinfo_t *ri = router_get_my_routerinfo();
|
||||
if (ri)
|
||||
smartlist_add(descs_out, &(ri->cache_info));
|
||||
smartlist_add(descs_out, (void*) &(ri->cache_info));
|
||||
} else if (!strcmpstart(key, "/tor/server/d/")) {
|
||||
smartlist_t *digests = smartlist_create();
|
||||
key += strlen("/tor/server/d/");
|
||||
@@ -3062,17 +3095,17 @@ dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
|
||||
{
|
||||
if (router_digest_is_me(d)) {
|
||||
/* make sure desc_routerinfo exists */
|
||||
routerinfo_t *ri = router_get_my_routerinfo();
|
||||
const routerinfo_t *ri = router_get_my_routerinfo();
|
||||
if (ri)
|
||||
smartlist_add(descs_out, &(ri->cache_info));
|
||||
smartlist_add(descs_out, (void*) &(ri->cache_info));
|
||||
} else {
|
||||
routerinfo_t *ri = router_get_by_digest(d);
|
||||
const routerinfo_t *ri = router_get_by_digest(d);
|
||||
/* Don't actually serve a descriptor that everyone will think is
|
||||
* expired. This is an (ugly) workaround to keep buggy 0.1.1.10
|
||||
* Tors from downloading descriptors that they will throw away.
|
||||
*/
|
||||
if (ri && ri->cache_info.published_on > cutoff)
|
||||
smartlist_add(descs_out, &(ri->cache_info));
|
||||
smartlist_add(descs_out, (void*) &(ri->cache_info));
|
||||
}
|
||||
});
|
||||
SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
|
||||
@@ -3121,6 +3154,7 @@ dirserv_orconn_tls_done(const char *address,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* FFFF Maybe we should reinstate the code that dumps routers with the same
|
||||
* addr/port but with nonmatching keys, but instead of dumping, we should
|
||||
* skip testing. */
|
||||
@@ -3130,7 +3164,8 @@ dirserv_orconn_tls_done(const char *address,
|
||||
* an upload or a download. Used to decide whether to relaunch reachability
|
||||
* testing for the server. */
|
||||
int
|
||||
dirserv_should_launch_reachability_test(routerinfo_t *ri, routerinfo_t *ri_old)
|
||||
dirserv_should_launch_reachability_test(const routerinfo_t *ri,
|
||||
const routerinfo_t *ri_old)
|
||||
{
|
||||
if (!authdir_mode_handles_descs(get_options(), ri->purpose))
|
||||
return 0;
|
||||
@@ -3254,7 +3289,7 @@ dirserv_remove_old_statuses(smartlist_t *fps, time_t cutoff)
|
||||
* its extra-info document if <b>extrainfo</b> is true. Return
|
||||
* NULL if not found or if the descriptor is older than
|
||||
* <b>publish_cutoff</b>. */
|
||||
static signed_descriptor_t *
|
||||
static const signed_descriptor_t *
|
||||
get_signed_descriptor_by_fp(const char *fp, int extrainfo,
|
||||
time_t publish_cutoff)
|
||||
{
|
||||
@@ -3264,7 +3299,7 @@ get_signed_descriptor_by_fp(const char *fp, int extrainfo,
|
||||
else
|
||||
return &(router_get_my_routerinfo()->cache_info);
|
||||
} else {
|
||||
routerinfo_t *ri = router_get_by_digest(fp);
|
||||
const routerinfo_t *ri = router_get_by_digest(fp);
|
||||
if (ri &&
|
||||
ri->cache_info.published_on > publish_cutoff) {
|
||||
if (extrainfo)
|
||||
@@ -3332,7 +3367,7 @@ dirserv_estimate_data_size(smartlist_t *fps, int is_serverdescs,
|
||||
tor_assert(fps);
|
||||
if (is_serverdescs) {
|
||||
int n = smartlist_len(fps);
|
||||
routerinfo_t *me = router_get_my_routerinfo();
|
||||
const routerinfo_t *me = router_get_my_routerinfo();
|
||||
result = (me?me->cache_info.signed_descriptor_len:2048) * n;
|
||||
if (compressed)
|
||||
result /= 2; /* observed compressibility is between 35 and 55%. */
|
||||
@@ -3399,7 +3434,7 @@ connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn)
|
||||
connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN) {
|
||||
const char *body;
|
||||
char *fp = smartlist_pop_last(conn->fingerprint_stack);
|
||||
signed_descriptor_t *sd = NULL;
|
||||
const signed_descriptor_t *sd = NULL;
|
||||
if (by_fp) {
|
||||
sd = get_signed_descriptor_by_fp(fp, extra, publish_cutoff);
|
||||
} else {
|
||||
|
||||
+11
-7
@@ -40,8 +40,6 @@
|
||||
MAX_V_LINE_LEN \
|
||||
)
|
||||
|
||||
#define UNNAMED_ROUTER_NICKNAME "Unnamed"
|
||||
|
||||
int connection_dirserv_flushed_some(dir_connection_t *conn);
|
||||
|
||||
int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk);
|
||||
@@ -99,13 +97,19 @@ void dirserv_orconn_tls_done(const char *address,
|
||||
uint16_t or_port,
|
||||
const char *digest_rcvd,
|
||||
int as_advertised);
|
||||
int dirserv_should_launch_reachability_test(routerinfo_t *ri,
|
||||
routerinfo_t *ri_old);
|
||||
int dirserv_should_launch_reachability_test(const routerinfo_t *ri,
|
||||
const routerinfo_t *ri_old);
|
||||
void dirserv_single_reachability_test(time_t now, routerinfo_t *router);
|
||||
void dirserv_test_reachability(time_t now);
|
||||
int authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
|
||||
int complain);
|
||||
int dirserv_would_reject_router(routerstatus_t *rs);
|
||||
int complain,
|
||||
int *valid_out);
|
||||
uint32_t dirserv_router_get_status(const routerinfo_t *router,
|
||||
const char **msg);
|
||||
void dirserv_set_node_flags_from_authoritative_status(node_t *node,
|
||||
uint32_t authstatus);
|
||||
|
||||
int dirserv_would_reject_router(const routerstatus_t *rs);
|
||||
int dirserv_remove_old_statuses(smartlist_t *fps, time_t cutoff);
|
||||
int dirserv_have_any_serverdesc(smartlist_t *fps, int spool_src);
|
||||
int dirserv_have_any_microdesc(const smartlist_t *fps);
|
||||
@@ -114,7 +118,7 @@ size_t dirserv_estimate_data_size(smartlist_t *fps, int is_serverdescs,
|
||||
size_t dirserv_estimate_microdesc_size(const smartlist_t *fps, int compressed);
|
||||
|
||||
int routerstatus_format_entry(char *buf, size_t buf_len,
|
||||
routerstatus_t *rs, const char *platform,
|
||||
const routerstatus_t *rs, const char *platform,
|
||||
routerstatus_format_type_t format);
|
||||
void dirserv_free_all(void);
|
||||
void cached_dir_decref(cached_dir_t *d);
|
||||
|
||||
@@ -63,6 +63,7 @@ const char *dirvote_get_pending_detached_signatures(void);
|
||||
#define DGV_INCLUDE_PREVIOUS 4
|
||||
const cached_dir_t *dirvote_get_vote(const char *fp, int flags);
|
||||
void set_routerstatus_from_routerinfo(routerstatus_t *rs,
|
||||
node_t *node,
|
||||
routerinfo_t *ri, time_t now,
|
||||
int naming, int listbadexits,
|
||||
int listbaddirs);
|
||||
|
||||
+1
-1
@@ -668,7 +668,7 @@ dns_resolve_impl(edge_connection_t *exitconn, int is_resolve,
|
||||
cached_resolve_t *resolve;
|
||||
cached_resolve_t search;
|
||||
pending_connection_t *pending_connection;
|
||||
routerinfo_t *me;
|
||||
const routerinfo_t *me;
|
||||
tor_addr_t addr;
|
||||
time_t now = time(NULL);
|
||||
uint8_t is_reverse = 0;
|
||||
|
||||
+13
-2
@@ -33,6 +33,7 @@
|
||||
#include "main.h"
|
||||
#include "microdesc.h"
|
||||
#include "networkstatus.h"
|
||||
#include "nodelist.h"
|
||||
#include "ntmain.h"
|
||||
#include "onion.h"
|
||||
#include "policies.h"
|
||||
@@ -1043,6 +1044,15 @@ run_scheduled_events(time_t now)
|
||||
*/
|
||||
consider_hibernation(now);
|
||||
|
||||
/* XXXX NM REMOVE THIS. XXXX NM XXXX NM XXXX NM*/
|
||||
{
|
||||
static time_t nl_check_time = 0;
|
||||
if (nl_check_time <= now) {
|
||||
nodelist_assert_ok();
|
||||
nl_check_time = now + 30;
|
||||
}
|
||||
}
|
||||
|
||||
/* 0b. If we've deferred a signewnym, make sure it gets handled
|
||||
* eventually. */
|
||||
if (signewnym_is_pending &&
|
||||
@@ -1267,7 +1277,7 @@ run_scheduled_events(time_t now)
|
||||
/* If we haven't checked for 12 hours and our bandwidth estimate is
|
||||
* low, do another bandwidth test. This is especially important for
|
||||
* bridges, since they might go long periods without much use. */
|
||||
routerinfo_t *me = router_get_my_routerinfo();
|
||||
const routerinfo_t *me = router_get_my_routerinfo();
|
||||
if (time_to_recheck_bandwidth && me &&
|
||||
me->bandwidthcapacity < me->bandwidthrate &&
|
||||
me->bandwidthcapacity < 51200) {
|
||||
@@ -1468,7 +1478,7 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg)
|
||||
(stats_n_seconds_working+seconds_elapsed) /
|
||||
TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT) {
|
||||
/* every 20 minutes, check and complain if necessary */
|
||||
routerinfo_t *me = router_get_my_routerinfo();
|
||||
const routerinfo_t *me = router_get_my_routerinfo();
|
||||
if (me && !check_whether_orport_reachable()) {
|
||||
log_warn(LD_CONFIG,"Your server (%s:%d) has not managed to confirm that "
|
||||
"its ORPort is reachable. Please check your firewalls, ports, "
|
||||
@@ -2209,6 +2219,7 @@ tor_free_all(int postfork)
|
||||
connection_free_all();
|
||||
buf_shrink_freelists(1);
|
||||
memarea_clear_freelist();
|
||||
nodelist_free_all();
|
||||
microdesc_free_all();
|
||||
if (!postfork) {
|
||||
config_free_all();
|
||||
|
||||
+14
-5
@@ -4,11 +4,13 @@
|
||||
#include "or.h"
|
||||
#include "config.h"
|
||||
#include "directory.h"
|
||||
#include "microdesc.h"
|
||||
#include "routerparse.h"
|
||||
#include "networkstatus.h"
|
||||
#include "routerlist.h"
|
||||
#include "dirserv.h"
|
||||
#include "microdesc.h"
|
||||
#include "networkstatus.h"
|
||||
#include "nodelist.h"
|
||||
#include "policies.h"
|
||||
#include "routerlist.h"
|
||||
#include "routerparse.h"
|
||||
|
||||
/** A data structure to hold a bunch of cached microdescriptors. There are
|
||||
* two active files in the cache: a "cache file" that we mmap, and a "journal
|
||||
@@ -249,6 +251,12 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache,
|
||||
microdesc_cache_rebuild(cache);
|
||||
}
|
||||
|
||||
{
|
||||
networkstatus_t *ns = networkstatus_get_latest_consensus();
|
||||
if (ns && ns->flavor == FLAV_MICRODESC)
|
||||
SMARTLIST_FOREACH(added, microdesc_t *, md, nodelist_add_microdesc(md));
|
||||
}
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
@@ -474,7 +482,7 @@ microdesc_free(microdesc_t *md)
|
||||
SMARTLIST_FOREACH(md->family, char *, cp, tor_free(cp));
|
||||
smartlist_free(md->family);
|
||||
}
|
||||
tor_free(md->exitsummary);
|
||||
short_policy_free(md->exit_policy);
|
||||
|
||||
tor_free(md);
|
||||
}
|
||||
@@ -612,3 +620,4 @@ update_microdescs_from_networkstatus(time_t now)
|
||||
md->last_listed = ns->valid_after;
|
||||
} SMARTLIST_FOREACH_END(rs);
|
||||
}
|
||||
|
||||
|
||||
+80
-141
@@ -22,6 +22,7 @@
|
||||
#include "main.h"
|
||||
#include "microdesc.h"
|
||||
#include "networkstatus.h"
|
||||
#include "nodelist.h"
|
||||
#include "relay.h"
|
||||
#include "router.h"
|
||||
#include "routerlist.h"
|
||||
@@ -106,9 +107,8 @@ void
|
||||
networkstatus_reset_warnings(void)
|
||||
{
|
||||
if (current_consensus) {
|
||||
SMARTLIST_FOREACH(current_consensus->routerstatus_list,
|
||||
routerstatus_t *, rs,
|
||||
rs->name_lookup_warned = 0);
|
||||
SMARTLIST_FOREACH(nodelist_get_list(), node_t *, node,
|
||||
node->name_lookup_warned = 0);
|
||||
}
|
||||
|
||||
have_warned_about_old_version = 0;
|
||||
@@ -939,10 +939,9 @@ compare_digest_to_routerstatus_entry(const void *_key, const void **_member)
|
||||
return memcmp(key, rs->identity_digest, DIGEST_LEN);
|
||||
}
|
||||
|
||||
/** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or
|
||||
* NULL if none was found. */
|
||||
/** As networkstatus_v2_find_entry, but do not return a const pointer */
|
||||
routerstatus_t *
|
||||
networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest)
|
||||
networkstatus_v2_find_mutable_entry(networkstatus_v2_t *ns, const char *digest)
|
||||
{
|
||||
return smartlist_bsearch(ns->entries, digest,
|
||||
compare_digest_to_routerstatus_entry);
|
||||
@@ -950,13 +949,28 @@ networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest)
|
||||
|
||||
/** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or
|
||||
* NULL if none was found. */
|
||||
const routerstatus_t *
|
||||
networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest)
|
||||
{
|
||||
return networkstatus_v2_find_mutable_entry(ns, digest);
|
||||
}
|
||||
|
||||
/** As networkstatus_find_entry, but do not return a const pointer */
|
||||
routerstatus_t *
|
||||
networkstatus_vote_find_entry(networkstatus_t *ns, const char *digest)
|
||||
networkstatus_vote_find_mutable_entry(networkstatus_t *ns, const char *digest)
|
||||
{
|
||||
return smartlist_bsearch(ns->routerstatus_list, digest,
|
||||
compare_digest_to_routerstatus_entry);
|
||||
}
|
||||
|
||||
/** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or
|
||||
* NULL if none was found. */
|
||||
const routerstatus_t *
|
||||
networkstatus_vote_find_entry(networkstatus_t *ns, const char *digest)
|
||||
{
|
||||
return networkstatus_vote_find_mutable_entry(ns, digest);
|
||||
}
|
||||
|
||||
/*XXXX make this static once functions are moved into this file. */
|
||||
/** Search the routerstatuses in <b>ns</b> for one whose identity digest is
|
||||
* <b>digest</b>. Return value and set *<b>found_out</b> as for
|
||||
@@ -979,11 +993,11 @@ networkstatus_get_v2_list(void)
|
||||
return networkstatus_v2_list;
|
||||
}
|
||||
|
||||
/** Return the consensus view of the status of the router whose current
|
||||
* <i>descriptor</i> digest in <b>consensus</b> is <b>digest</b>, or NULL if
|
||||
* no such router is known. */
|
||||
/* As router_get_consensus_status_by_descriptor_digest, but does not return
|
||||
* a const pointer */
|
||||
routerstatus_t *
|
||||
router_get_consensus_status_by_descriptor_digest(networkstatus_t *consensus,
|
||||
router_get_mutable_consensus_status_by_descriptor_digest(
|
||||
networkstatus_t *consensus,
|
||||
const char *digest)
|
||||
{
|
||||
if (!consensus)
|
||||
@@ -1001,6 +1015,17 @@ router_get_consensus_status_by_descriptor_digest(networkstatus_t *consensus,
|
||||
return digestmap_get(consensus->desc_digest_map, digest);
|
||||
}
|
||||
|
||||
/** Return the consensus view of the status of the router whose current
|
||||
* <i>descriptor</i> digest in <b>consensus</b> is <b>digest</b>, or NULL if
|
||||
* no such router is known. */
|
||||
const routerstatus_t *
|
||||
router_get_consensus_status_by_descriptor_digest(networkstatus_t *consensus,
|
||||
const char *digest)
|
||||
{
|
||||
return router_get_mutable_consensus_status_by_descriptor_digest(
|
||||
consensus, digest);
|
||||
}
|
||||
|
||||
/** Given the digest of a router descriptor, return its current download
|
||||
* status, or NULL if the digest is unrecognized. */
|
||||
download_status_t *
|
||||
@@ -1009,8 +1034,8 @@ router_get_dl_status_by_descriptor_digest(const char *d)
|
||||
routerstatus_t *rs;
|
||||
if (!current_ns_consensus)
|
||||
return NULL;
|
||||
if ((rs = router_get_consensus_status_by_descriptor_digest(
|
||||
current_ns_consensus, d)))
|
||||
if ((rs = router_get_mutable_consensus_status_by_descriptor_digest(
|
||||
current_ns_consensus, d)))
|
||||
return &rs->dl_status;
|
||||
if (v2_download_status_map)
|
||||
return digestmap_get(v2_download_status_map, d);
|
||||
@@ -1018,10 +1043,9 @@ router_get_dl_status_by_descriptor_digest(const char *d)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Return the consensus view of the status of the router whose identity
|
||||
* digest is <b>digest</b>, or NULL if we don't know about any such router. */
|
||||
/** As router_get_consensus_status_by_id, but do not return a const pointer */
|
||||
routerstatus_t *
|
||||
router_get_consensus_status_by_id(const char *digest)
|
||||
router_get_mutable_consensus_status_by_id(const char *digest)
|
||||
{
|
||||
if (!current_consensus)
|
||||
return NULL;
|
||||
@@ -1029,100 +1053,27 @@ router_get_consensus_status_by_id(const char *digest)
|
||||
compare_digest_to_routerstatus_entry);
|
||||
}
|
||||
|
||||
/** Return the consensus view of the status of the router whose identity
|
||||
* digest is <b>digest</b>, or NULL if we don't know about any such router. */
|
||||
const routerstatus_t *
|
||||
router_get_consensus_status_by_id(const char *digest)
|
||||
{
|
||||
return router_get_mutable_consensus_status_by_id(digest);
|
||||
}
|
||||
|
||||
/** Given a nickname (possibly verbose, possibly a hexadecimal digest), return
|
||||
* the corresponding routerstatus_t, or NULL if none exists. Warn the
|
||||
* user if <b>warn_if_unnamed</b> is set, and they have specified a router by
|
||||
* nickname, but the Named flag isn't set for that router. */
|
||||
routerstatus_t *
|
||||
const routerstatus_t *
|
||||
router_get_consensus_status_by_nickname(const char *nickname,
|
||||
int warn_if_unnamed)
|
||||
{
|
||||
char digest[DIGEST_LEN];
|
||||
routerstatus_t *best=NULL;
|
||||
smartlist_t *matches=NULL;
|
||||
const char *named_id=NULL;
|
||||
|
||||
if (!current_consensus || !nickname)
|
||||
const node_t *node = node_get_by_nickname(nickname, warn_if_unnamed);
|
||||
if (node)
|
||||
return node->rs;
|
||||
else
|
||||
return NULL;
|
||||
|
||||
/* Is this name really a hexadecimal identity digest? */
|
||||
if (nickname[0] == '$') {
|
||||
if (base16_decode(digest, DIGEST_LEN, nickname+1, strlen(nickname+1))<0)
|
||||
return NULL;
|
||||
return networkstatus_vote_find_entry(current_consensus, digest);
|
||||
} else if (strlen(nickname) == HEX_DIGEST_LEN &&
|
||||
(base16_decode(digest, DIGEST_LEN, nickname, strlen(nickname))==0)) {
|
||||
return networkstatus_vote_find_entry(current_consensus, digest);
|
||||
}
|
||||
|
||||
/* Is there a server that is Named with this name? */
|
||||
if (named_server_map)
|
||||
named_id = strmap_get_lc(named_server_map, nickname);
|
||||
if (named_id)
|
||||
return networkstatus_vote_find_entry(current_consensus, named_id);
|
||||
|
||||
/* Okay; is this name listed as Unnamed? */
|
||||
if (unnamed_server_map &&
|
||||
strmap_get_lc(unnamed_server_map, nickname)) {
|
||||
log_info(LD_GENERAL, "The name %s is listed as Unnamed; it is not the "
|
||||
"canonical name of any server we know.", escaped(nickname));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This name is not canonical for any server; go through the list and
|
||||
* see who it matches. */
|
||||
/*XXXX This is inefficient; optimize it if it matters. */
|
||||
matches = smartlist_create();
|
||||
SMARTLIST_FOREACH(current_consensus->routerstatus_list,
|
||||
routerstatus_t *, lrs,
|
||||
{
|
||||
if (!strcasecmp(lrs->nickname, nickname)) {
|
||||
if (lrs->is_named) {
|
||||
tor_fragile_assert() /* This should never happen. */
|
||||
smartlist_free(matches);
|
||||
return lrs;
|
||||
} else {
|
||||
if (lrs->is_unnamed) {
|
||||
tor_fragile_assert(); /* nor should this. */
|
||||
smartlist_clear(matches);
|
||||
best=NULL;
|
||||
break;
|
||||
}
|
||||
smartlist_add(matches, lrs);
|
||||
best = lrs;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (smartlist_len(matches)>1 && warn_if_unnamed) {
|
||||
int any_unwarned=0;
|
||||
SMARTLIST_FOREACH(matches, routerstatus_t *, lrs,
|
||||
{
|
||||
if (! lrs->name_lookup_warned) {
|
||||
lrs->name_lookup_warned=1;
|
||||
any_unwarned=1;
|
||||
}
|
||||
});
|
||||
if (any_unwarned) {
|
||||
log_warn(LD_CONFIG,"There are multiple matches for the nickname \"%s\","
|
||||
" but none is listed as named by the directory authorities. "
|
||||
"Choosing one arbitrarily.", nickname);
|
||||
}
|
||||
} else if (warn_if_unnamed && best && !best->name_lookup_warned) {
|
||||
char fp[HEX_DIGEST_LEN+1];
|
||||
base16_encode(fp, sizeof(fp),
|
||||
best->identity_digest, DIGEST_LEN);
|
||||
log_warn(LD_CONFIG,
|
||||
"When looking up a status, you specified a server \"%s\" by name, "
|
||||
"but the directory authorities do not have any key registered for "
|
||||
"this nickname -- so it could be used by any server, "
|
||||
"not just the one you meant. "
|
||||
"To make sure you get the same server in the future, refer to "
|
||||
"it by key, as \"$%s\".", nickname, fp);
|
||||
best->name_lookup_warned = 1;
|
||||
}
|
||||
smartlist_free(matches);
|
||||
return best;
|
||||
}
|
||||
|
||||
/** Return the identity digest that's mapped to officially by
|
||||
@@ -1524,7 +1475,7 @@ routerstatus_has_changed(const routerstatus_t *a, const routerstatus_t *b)
|
||||
a->is_exit != b->is_exit ||
|
||||
a->is_stable != b->is_stable ||
|
||||
a->is_fast != b->is_fast ||
|
||||
a->is_running != b->is_running ||
|
||||
a->is_flagged_running != b->is_flagged_running ||
|
||||
a->is_named != b->is_named ||
|
||||
a->is_unnamed != b->is_unnamed ||
|
||||
a->is_valid != b->is_valid ||
|
||||
@@ -1565,13 +1516,14 @@ notify_control_networkstatus_changed(const networkstatus_t *old_c,
|
||||
}
|
||||
changed = smartlist_create();
|
||||
|
||||
SMARTLIST_FOREACH_JOIN(old_c->routerstatus_list, routerstatus_t *, rs_old,
|
||||
new_c->routerstatus_list, routerstatus_t *, rs_new,
|
||||
memcmp(rs_old->identity_digest,
|
||||
rs_new->identity_digest, DIGEST_LEN),
|
||||
smartlist_add(changed, rs_new)) {
|
||||
SMARTLIST_FOREACH_JOIN(
|
||||
old_c->routerstatus_list, const routerstatus_t *, rs_old,
|
||||
new_c->routerstatus_list, const routerstatus_t *, rs_new,
|
||||
memcmp(rs_old->identity_digest,
|
||||
rs_new->identity_digest, DIGEST_LEN),
|
||||
smartlist_add(changed, (void*) rs_new)) {
|
||||
if (routerstatus_has_changed(rs_old, rs_new))
|
||||
smartlist_add(changed, rs_new);
|
||||
smartlist_add(changed, (void*)rs_new);
|
||||
} SMARTLIST_FOREACH_JOIN_END(rs_old, rs_new);
|
||||
|
||||
control_event_networkstatus_changed(changed);
|
||||
@@ -1595,7 +1547,6 @@ networkstatus_copy_old_consensus_info(networkstatus_t *new_c,
|
||||
rs_new->identity_digest, DIGEST_LEN),
|
||||
STMT_NIL) {
|
||||
/* Okay, so we're looking at the same identity. */
|
||||
rs_new->name_lookup_warned = rs_old->name_lookup_warned;
|
||||
rs_new->last_dir_503_at = rs_old->last_dir_503_at;
|
||||
|
||||
if (!memcmp(rs_old->descriptor_digest, rs_new->descriptor_digest,
|
||||
@@ -1833,6 +1784,8 @@ networkstatus_set_current_consensus(const char *consensus,
|
||||
/* XXXXNM Microdescs: needs a non-ns variant. */
|
||||
update_consensus_networkstatus_fetch_time(now);
|
||||
|
||||
nodelist_set_consensus(current_consensus);
|
||||
|
||||
dirvote_recalculate_timing(options, now);
|
||||
routerstatus_list_update_named_server_map();
|
||||
cell_ewma_set_scale_factor(options, current_consensus);
|
||||
@@ -1975,7 +1928,7 @@ download_status_map_update_from_v2_networkstatus(void)
|
||||
|
||||
dl_status = digestmap_new();
|
||||
SMARTLIST_FOREACH_BEGIN(networkstatus_v2_list, networkstatus_v2_t *, ns) {
|
||||
SMARTLIST_FOREACH_BEGIN(ns->entries, routerstatus_t *, rs) {
|
||||
SMARTLIST_FOREACH_BEGIN(ns->entries, const routerstatus_t *, rs) {
|
||||
const char *d = rs->descriptor_digest;
|
||||
download_status_t *s;
|
||||
if (digestmap_get(dl_status, d))
|
||||
@@ -2003,7 +1956,8 @@ routerstatus_list_update_named_server_map(void)
|
||||
named_server_map = strmap_new();
|
||||
strmap_free(unnamed_server_map, NULL);
|
||||
unnamed_server_map = strmap_new();
|
||||
SMARTLIST_FOREACH(current_consensus->routerstatus_list, routerstatus_t *, rs,
|
||||
SMARTLIST_FOREACH(current_consensus->routerstatus_list,
|
||||
const routerstatus_t *, rs,
|
||||
{
|
||||
if (rs->is_named) {
|
||||
strmap_set_lc(named_server_map, rs->nickname,
|
||||
@@ -2025,7 +1979,6 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
|
||||
trusted_dir_server_t *ds;
|
||||
or_options_t *options = get_options();
|
||||
int authdir = authdir_mode_v2(options) || authdir_mode_v3(options);
|
||||
int namingdir = authdir && options->NamingAuthoritativeDir;
|
||||
networkstatus_t *ns = current_consensus;
|
||||
if (!ns || !smartlist_len(ns->routerstatus_list))
|
||||
return;
|
||||
@@ -2039,25 +1992,19 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
|
||||
memcmp(rs->identity_digest,
|
||||
router->cache_info.identity_digest, DIGEST_LEN),
|
||||
{
|
||||
#if 0
|
||||
/* We have no routerstatus for this router. Clear flags and skip it. */
|
||||
if (!namingdir)
|
||||
router->is_named = 0;
|
||||
if (!authdir) {
|
||||
if (router->purpose == ROUTER_PURPOSE_GENERAL)
|
||||
router_clear_status_flags(router);
|
||||
}
|
||||
#endif
|
||||
}) {
|
||||
/* We have a routerstatus for this router. */
|
||||
const char *digest = router->cache_info.identity_digest;
|
||||
|
||||
ds = router_get_trusteddirserver_by_digest(digest);
|
||||
|
||||
if (!namingdir) {
|
||||
if (rs->is_named && !strcasecmp(router->nickname, rs->nickname))
|
||||
router->is_named = 1;
|
||||
else
|
||||
router->is_named = 0;
|
||||
}
|
||||
/* Is it the same descriptor, or only the same identity? */
|
||||
if (!memcmp(router->cache_info.signed_descriptor_digest,
|
||||
rs->descriptor_digest, DIGEST_LEN)) {
|
||||
@@ -2065,28 +2012,17 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
|
||||
router->cache_info.last_listed_as_valid_until = ns->valid_until;
|
||||
}
|
||||
|
||||
if (!authdir) {
|
||||
/* If we're not an authdir, believe others. */
|
||||
router->is_valid = rs->is_valid;
|
||||
router->is_running = rs->is_running;
|
||||
router->is_fast = rs->is_fast;
|
||||
router->is_stable = rs->is_stable;
|
||||
router->is_possible_guard = rs->is_possible_guard;
|
||||
router->is_exit = rs->is_exit;
|
||||
router->is_bad_directory = rs->is_bad_directory;
|
||||
router->is_bad_exit = rs->is_bad_exit;
|
||||
router->is_hs_dir = rs->is_hs_dir;
|
||||
} else {
|
||||
if (authdir) {
|
||||
/* If we _are_ an authority, we should check whether this router
|
||||
* is one that will cause us to need a reachability test. */
|
||||
routerinfo_t *old_router =
|
||||
router_get_by_digest(router->cache_info.identity_digest);
|
||||
router_get_mutable_by_digest(router->cache_info.identity_digest);
|
||||
if (old_router != router) {
|
||||
router->needs_retest_if_added =
|
||||
dirserv_should_launch_reachability_test(router, old_router);
|
||||
}
|
||||
}
|
||||
if (router->is_running && ds) {
|
||||
if (rs->is_flagged_running && ds) {
|
||||
download_status_reset(&ds->v2_ns_dl_status);
|
||||
}
|
||||
if (reset_failures) {
|
||||
@@ -2098,7 +2034,7 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
|
||||
/* XXXX If this is slow, we need to rethink the code. */
|
||||
SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns, {
|
||||
time_t live_until = ns->published_on + V2_NETWORKSTATUS_ROUTER_LIFETIME;
|
||||
SMARTLIST_FOREACH_JOIN(ns->entries, routerstatus_t *, rs,
|
||||
SMARTLIST_FOREACH_JOIN(ns->entries, const routerstatus_t *, rs,
|
||||
routers, routerinfo_t *, ri,
|
||||
memcmp(rs->identity_digest,
|
||||
ri->cache_info.identity_digest, DIGEST_LEN),
|
||||
@@ -2131,7 +2067,7 @@ signed_descs_update_status_from_consensus_networkstatus(smartlist_t *descs)
|
||||
}
|
||||
SMARTLIST_FOREACH(descs, signed_descriptor_t *, d,
|
||||
{
|
||||
routerstatus_t *rs = digestmap_get(ns->desc_digest_map,
|
||||
const routerstatus_t *rs = digestmap_get(ns->desc_digest_map,
|
||||
d->signed_descriptor_digest);
|
||||
if (rs) {
|
||||
if (ns->valid_until > d->last_listed_as_valid_until)
|
||||
@@ -2144,7 +2080,7 @@ signed_descs_update_status_from_consensus_networkstatus(smartlist_t *descs)
|
||||
* return the result in a newly allocated string. Used only by controller
|
||||
* interface (for now.) */
|
||||
char *
|
||||
networkstatus_getinfo_helper_single(routerstatus_t *rs)
|
||||
networkstatus_getinfo_helper_single(const routerstatus_t *rs)
|
||||
{
|
||||
char buf[RS_ENTRY_LEN+1];
|
||||
routerstatus_format_entry(buf, sizeof(buf), rs, NULL, NS_CONTROL_PORT);
|
||||
@@ -2177,6 +2113,9 @@ networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now)
|
||||
|
||||
statuses = smartlist_create();
|
||||
SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
|
||||
node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
|
||||
if (!node)
|
||||
continue;
|
||||
if (ri->cache_info.published_on < cutoff)
|
||||
continue;
|
||||
if (ri->purpose != purpose)
|
||||
@@ -2184,7 +2123,7 @@ networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now)
|
||||
if (bridge_auth && ri->purpose == ROUTER_PURPOSE_BRIDGE)
|
||||
dirserv_set_router_is_running(ri, now);
|
||||
/* then generate and write out status lines for each of them */
|
||||
set_routerstatus_from_routerinfo(&rs, ri, now, 0, 0, 0);
|
||||
set_routerstatus_from_routerinfo(&rs, node, ri, now, 0, 0, 0);
|
||||
smartlist_add(statuses, networkstatus_getinfo_helper_single(&rs));
|
||||
});
|
||||
|
||||
@@ -2300,7 +2239,7 @@ getinfo_helper_networkstatus(control_connection_t *conn,
|
||||
const char *question, char **answer,
|
||||
const char **errmsg)
|
||||
{
|
||||
routerstatus_t *status;
|
||||
const routerstatus_t *status;
|
||||
(void) conn;
|
||||
|
||||
if (!current_consensus) {
|
||||
@@ -2311,7 +2250,7 @@ getinfo_helper_networkstatus(control_connection_t *conn,
|
||||
if (!strcmp(question, "ns/all")) {
|
||||
smartlist_t *statuses = smartlist_create();
|
||||
SMARTLIST_FOREACH(current_consensus->routerstatus_list,
|
||||
routerstatus_t *, rs,
|
||||
const routerstatus_t *, rs,
|
||||
{
|
||||
smartlist_add(statuses, networkstatus_getinfo_helper_single(rs));
|
||||
});
|
||||
|
||||
+17
-7
@@ -38,20 +38,30 @@ int router_set_networkstatus_v2(const char *s, time_t arrived_at,
|
||||
void networkstatus_v2_list_clean(time_t now);
|
||||
int compare_digest_to_routerstatus_entry(const void *_key,
|
||||
const void **_member);
|
||||
routerstatus_t *networkstatus_v2_find_entry(networkstatus_v2_t *ns,
|
||||
const routerstatus_t *networkstatus_v2_find_entry(networkstatus_v2_t *ns,
|
||||
const char *digest);
|
||||
routerstatus_t *networkstatus_vote_find_entry(networkstatus_t *ns,
|
||||
const routerstatus_t *networkstatus_vote_find_entry(networkstatus_t *ns,
|
||||
const char *digest);
|
||||
routerstatus_t *networkstatus_v2_find_mutable_entry(networkstatus_v2_t *ns,
|
||||
const char *digest);
|
||||
routerstatus_t *networkstatus_vote_find_mutable_entry(networkstatus_t *ns,
|
||||
const char *digest);
|
||||
int networkstatus_vote_find_entry_idx(networkstatus_t *ns,
|
||||
const char *digest, int *found_out);
|
||||
const smartlist_t *networkstatus_get_v2_list(void);
|
||||
download_status_t *router_get_dl_status_by_descriptor_digest(const char *d);
|
||||
routerstatus_t *router_get_consensus_status_by_id(const char *digest);
|
||||
routerstatus_t *router_get_consensus_status_by_descriptor_digest(
|
||||
const routerstatus_t *router_get_consensus_status_by_id(const char *digest);
|
||||
routerstatus_t *router_get_mutable_consensus_status_by_id(
|
||||
const char *digest);
|
||||
const routerstatus_t *router_get_consensus_status_by_descriptor_digest(
|
||||
networkstatus_t *consensus,
|
||||
const char *digest);
|
||||
routerstatus_t *router_get_consensus_status_by_nickname(const char *nickname,
|
||||
int warn_if_unnamed);
|
||||
routerstatus_t *router_get_mutable_consensus_status_by_descriptor_digest(
|
||||
networkstatus_t *consensus,
|
||||
const char *digest);
|
||||
const routerstatus_t *router_get_consensus_status_by_nickname(
|
||||
const char *nickname,
|
||||
int warn_if_unnamed);
|
||||
const char *networkstatus_get_router_digest_by_nickname(const char *nickname);
|
||||
int networkstatus_nickname_is_unnamed(const char *nickname);
|
||||
void networkstatus_consensus_download_failed(int status_code,
|
||||
@@ -83,7 +93,7 @@ void routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
|
||||
void signed_descs_update_status_from_consensus_networkstatus(
|
||||
smartlist_t *descs);
|
||||
|
||||
char *networkstatus_getinfo_helper_single(routerstatus_t *rs);
|
||||
char *networkstatus_getinfo_helper_single(const routerstatus_t *rs);
|
||||
char *networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now);
|
||||
void networkstatus_dump_bridge_status_to_file(time_t now);
|
||||
int32_t get_net_param_from_list(smartlist_t *net_params, const char *name,
|
||||
|
||||
@@ -0,0 +1,730 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2010, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
#include "or.h"
|
||||
#include "config.h"
|
||||
#include "dirserv.h"
|
||||
#include "microdesc.h"
|
||||
#include "networkstatus.h"
|
||||
#include "nodelist.h"
|
||||
#include "policies.h"
|
||||
#include "router.h"
|
||||
#include "routerlist.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static void nodelist_drop_node(node_t *node, int remove_from_ht);
|
||||
static void node_free(node_t *node);
|
||||
|
||||
/** A nodelist_t holds a node_t object for every router we're "willing to use
|
||||
* for something". Specifically, it should hold a node_t for every node that
|
||||
* is currently in the routerlist, or currently in the consensus we're using.
|
||||
*/
|
||||
typedef struct nodelist_t {
|
||||
/* A list of all the nodes. */
|
||||
smartlist_t *nodes;
|
||||
/* Hash table to map from node ID digest to node. */
|
||||
HT_HEAD(nodelist_map, node_t) nodes_by_id;
|
||||
|
||||
} nodelist_t;
|
||||
|
||||
static INLINE unsigned int
|
||||
node_id_hash(const node_t *node)
|
||||
{
|
||||
#if SIZEOF_INT == 4
|
||||
const uint32_t *p = (const uint32_t*)node->identity;
|
||||
return p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4];
|
||||
#elif SIZEOF_INT == 8
|
||||
const uint64_t *p = (const uint32_t*)node->identity;
|
||||
const uint32_t *p32 = (const uint32_t*)node->identity;
|
||||
return p[0] ^ p[1] ^ p32[4];
|
||||
#endif
|
||||
}
|
||||
|
||||
static INLINE unsigned int
|
||||
node_id_eq(const node_t *node1, const node_t *node2)
|
||||
{
|
||||
return 0 == memcmp(node1->identity, node2->identity, DIGEST_LEN);
|
||||
}
|
||||
|
||||
HT_PROTOTYPE(nodelist_map, node_t, ht_ent, node_id_hash, node_id_eq);
|
||||
HT_GENERATE(nodelist_map, node_t, ht_ent, node_id_hash, node_id_eq,
|
||||
0.6, malloc, realloc, free);
|
||||
|
||||
/** The global nodelist. */
|
||||
static nodelist_t *the_nodelist=NULL;
|
||||
|
||||
/** Create an empty nodelist if we haven't done so already. */
|
||||
static void
|
||||
init_nodelist(void)
|
||||
{
|
||||
if (PREDICT_UNLIKELY(the_nodelist == NULL)) {
|
||||
the_nodelist = tor_malloc_zero(sizeof(nodelist_t));
|
||||
HT_INIT(nodelist_map, &the_nodelist->nodes_by_id);
|
||||
the_nodelist->nodes = smartlist_create();
|
||||
}
|
||||
}
|
||||
|
||||
/** As node_get_by_id, but returns a non-const pointer */
|
||||
node_t *
|
||||
node_get_mutable_by_id(const char *identity_digest)
|
||||
{
|
||||
node_t search, *node;
|
||||
if (PREDICT_UNLIKELY(the_nodelist == NULL))
|
||||
return NULL;
|
||||
|
||||
memcpy(&search.identity, identity_digest, DIGEST_LEN);
|
||||
node = HT_FIND(nodelist_map, &the_nodelist->nodes_by_id, &search);
|
||||
return node;
|
||||
}
|
||||
|
||||
/** Return the node_t whose identity is <b>identity_digest</b>, or NULL
|
||||
* if no such node exists. */
|
||||
const node_t *
|
||||
node_get_by_id(const char *identity_digest)
|
||||
{
|
||||
return node_get_mutable_by_id(identity_digest);
|
||||
}
|
||||
|
||||
/** Internal: return the node_t whose identity_digest is
|
||||
* <b>identity_digest</b>. If none exists, create a new one, add it to the
|
||||
* nodelist, and return it.
|
||||
*
|
||||
* Requires that the nodelist be initialized.
|
||||
*/
|
||||
static node_t *
|
||||
node_get_or_create(const char *identity_digest)
|
||||
{
|
||||
node_t *node;
|
||||
|
||||
if ((node = node_get_mutable_by_id(identity_digest)))
|
||||
return node;
|
||||
|
||||
node = tor_malloc_zero(sizeof(node_t));
|
||||
memcpy(node->identity, identity_digest, DIGEST_LEN);
|
||||
HT_INSERT(nodelist_map, &the_nodelist->nodes_by_id, node);
|
||||
|
||||
smartlist_add(the_nodelist->nodes, node);
|
||||
node->nodelist_idx = smartlist_len(the_nodelist->nodes) - 1;
|
||||
|
||||
node->country = -1;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/** Add <b>ri</b> to the nodelist. */
|
||||
node_t *
|
||||
nodelist_add_routerinfo(routerinfo_t *ri)
|
||||
{
|
||||
node_t *node;
|
||||
init_nodelist();
|
||||
node = node_get_or_create(ri->cache_info.identity_digest);
|
||||
node->ri = ri;
|
||||
|
||||
if (node->country == -1)
|
||||
node_set_country(node);
|
||||
|
||||
if (authdir_mode(get_options())) {
|
||||
const char *discard=NULL;
|
||||
uint32_t status = dirserv_router_get_status(ri, &discard);
|
||||
dirserv_set_node_flags_from_authoritative_status(node, status);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/** Set the appropriate node_t to use <b>md</b> as its microdescriptor.
|
||||
*
|
||||
* Called when a new microdesc has arrived and the usable consensus flavor
|
||||
* is "microdesc".
|
||||
**/
|
||||
node_t *
|
||||
nodelist_add_microdesc(microdesc_t *md)
|
||||
{
|
||||
networkstatus_t *ns =
|
||||
networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC);
|
||||
const routerstatus_t *rs;
|
||||
node_t *node;
|
||||
if (ns == NULL)
|
||||
return NULL;
|
||||
init_nodelist();
|
||||
|
||||
/* Microdescriptors don't carry an identity digest, so we need to figure
|
||||
* it out by looking up the routerstatus. */
|
||||
rs = router_get_consensus_status_by_descriptor_digest(ns, md->digest);
|
||||
if (rs == NULL)
|
||||
return NULL;
|
||||
node = node_get_mutable_by_id(rs->identity_digest);
|
||||
if (node)
|
||||
node->md = md;
|
||||
return node;
|
||||
}
|
||||
|
||||
/** Tell the nodelist that the current usable consensus to <b>ns</b>.
|
||||
* This makes the nodelist change all of the routerstatus entries for
|
||||
* the nodes, drop nodes that no longer have enough info to get used,
|
||||
* and grab microdescriptors into nodes as appropriate.
|
||||
*/
|
||||
void
|
||||
nodelist_set_consensus(networkstatus_t *ns)
|
||||
{
|
||||
or_options_t *options = get_options();
|
||||
int authdir = authdir_mode_v2(options) || authdir_mode_v3(options);
|
||||
init_nodelist();
|
||||
|
||||
SMARTLIST_FOREACH(the_nodelist->nodes, node_t *, node,
|
||||
node->rs = NULL);
|
||||
|
||||
SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) {
|
||||
node_t *node = node_get_or_create(rs->identity_digest);
|
||||
node->rs = rs;
|
||||
if (ns->flavor == FLAV_MICRODESC) {
|
||||
if (node->md == NULL ||
|
||||
0!=memcmp(node->md->digest,rs->descriptor_digest,DIGEST256_LEN)) {
|
||||
node->md = microdesc_cache_lookup_by_digest256(NULL,
|
||||
rs->descriptor_digest);
|
||||
}
|
||||
}
|
||||
|
||||
node_set_country(node);
|
||||
|
||||
/* If we're not an authdir, believe others. */
|
||||
if (!authdir) {
|
||||
node->is_valid = rs->is_valid;
|
||||
node->is_running = rs->is_flagged_running;
|
||||
node->is_fast = rs->is_fast;
|
||||
node->is_stable = rs->is_stable;
|
||||
node->is_possible_guard = rs->is_possible_guard;
|
||||
node->is_exit = rs->is_exit;
|
||||
node->is_bad_directory = rs->is_bad_directory;
|
||||
node->is_bad_exit = rs->is_bad_exit;
|
||||
node->is_hs_dir = rs->is_hs_dir;
|
||||
}
|
||||
|
||||
} SMARTLIST_FOREACH_END(rs);
|
||||
|
||||
nodelist_purge();
|
||||
|
||||
if (! authdir) {
|
||||
SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) {
|
||||
/* We have no routerstatus for this router. Clear flags so we can skip
|
||||
* it, maybe.*/
|
||||
if (!node->rs) {
|
||||
tor_assert(node->ri); /* if it had only an md, or nothing, purge
|
||||
* would have removed it. */
|
||||
if (node->ri->purpose == ROUTER_PURPOSE_GENERAL) {
|
||||
/* Clear all flags. */
|
||||
node->is_valid = node->is_running = node->is_hs_dir =
|
||||
node->is_fast = node->is_stable =
|
||||
node->is_possible_guard = node->is_exit =
|
||||
node->is_bad_exit = node->is_bad_directory = 0;
|
||||
}
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(node);
|
||||
}
|
||||
}
|
||||
|
||||
/** Helper: return true iff a node has a usable amount of information*/
|
||||
static INLINE int
|
||||
node_is_usable(const node_t *node)
|
||||
{
|
||||
return (node->rs) || (node->ri);
|
||||
}
|
||||
|
||||
/** Tell the nodelist that <b>md</b> is no longer a microdescriptor for the
|
||||
* node with <b>identity_digest</b>. */
|
||||
void
|
||||
nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md)
|
||||
{
|
||||
node_t *node = node_get_mutable_by_id(identity_digest);
|
||||
if (node && node->md == md)
|
||||
node->md = NULL;
|
||||
}
|
||||
|
||||
/** Tell the nodelist that <b>ri</b> is no longer in the routerlist. */
|
||||
void
|
||||
nodelist_remove_routerinfo(routerinfo_t *ri)
|
||||
{
|
||||
node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
|
||||
if (node && node->ri == ri) {
|
||||
node->ri = NULL;
|
||||
if (! node_is_usable(node)) {
|
||||
nodelist_drop_node(node, 1);
|
||||
node_free(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Remove <b>node</b> from the nodelist. (Asserts that it was there to begin
|
||||
* with.) */
|
||||
static void
|
||||
nodelist_drop_node(node_t *node, int remove_from_ht)
|
||||
{
|
||||
node_t *tmp;
|
||||
int idx;
|
||||
if (remove_from_ht) {
|
||||
tmp = HT_REMOVE(nodelist_map, &the_nodelist->nodes_by_id, node);
|
||||
tor_assert(tmp == node);
|
||||
}
|
||||
|
||||
idx = node->nodelist_idx;
|
||||
tor_assert(idx >= 0);
|
||||
|
||||
tor_assert(node == smartlist_get(the_nodelist->nodes, idx));
|
||||
smartlist_del(the_nodelist->nodes, idx);
|
||||
if (idx < smartlist_len(the_nodelist->nodes)) {
|
||||
tmp = smartlist_get(the_nodelist->nodes, idx);
|
||||
tmp->nodelist_idx = idx;
|
||||
}
|
||||
node->nodelist_idx = -1;
|
||||
}
|
||||
|
||||
/** Release storage held by <b>node</b> */
|
||||
static void
|
||||
node_free(node_t *node)
|
||||
{
|
||||
if (!node)
|
||||
return;
|
||||
tor_assert(node->nodelist_idx == -1);
|
||||
tor_free(node);
|
||||
}
|
||||
|
||||
/** Remove all entries from the nodelist that don't have enough info to be
|
||||
* usable for anything. */
|
||||
void
|
||||
nodelist_purge(void)
|
||||
{
|
||||
node_t **iter;
|
||||
if (PREDICT_UNLIKELY(the_nodelist == NULL))
|
||||
return;
|
||||
|
||||
/* Remove the non-usable nodes. */
|
||||
for (iter = HT_START(nodelist_map, &the_nodelist->nodes_by_id); iter; ) {
|
||||
node_t *node = *iter;
|
||||
|
||||
if (node_is_usable(node)) {
|
||||
iter = HT_NEXT(nodelist_map, &the_nodelist->nodes_by_id, iter);
|
||||
} else {
|
||||
iter = HT_NEXT_RMV(nodelist_map, &the_nodelist->nodes_by_id, iter);
|
||||
nodelist_drop_node(node, 0);
|
||||
node_free(node);
|
||||
}
|
||||
}
|
||||
nodelist_assert_ok();
|
||||
}
|
||||
|
||||
/** Release all storage held by the nodelist. */
|
||||
void
|
||||
nodelist_free_all(void)
|
||||
{
|
||||
if (PREDICT_UNLIKELY(the_nodelist == NULL))
|
||||
return;
|
||||
|
||||
HT_CLEAR(nodelist_map, &the_nodelist->nodes_by_id);
|
||||
SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) {
|
||||
node->nodelist_idx = -1;
|
||||
node_free(node);
|
||||
} SMARTLIST_FOREACH_END(node);
|
||||
|
||||
smartlist_free(the_nodelist->nodes);
|
||||
|
||||
tor_free(the_nodelist);
|
||||
}
|
||||
|
||||
/** Check that the nodelist is internally consistent, and consistent with
|
||||
* the directory info it's derived from.
|
||||
*/
|
||||
void
|
||||
nodelist_assert_ok(void)
|
||||
{
|
||||
routerlist_t *rl = router_get_routerlist();
|
||||
networkstatus_t *ns = networkstatus_get_latest_consensus();
|
||||
digestmap_t *dm = digestmap_new();
|
||||
|
||||
if (!the_nodelist)
|
||||
return;
|
||||
|
||||
/* every routerinfo in rl->routers should be in the nodelist. */
|
||||
if (rl) {
|
||||
SMARTLIST_FOREACH_BEGIN(rl->routers, routerinfo_t *, ri) {
|
||||
const node_t *node = node_get_by_id(ri->cache_info.identity_digest);
|
||||
tor_assert(node && node->ri == ri);
|
||||
tor_assert(0 == memcmp(ri->cache_info.identity_digest,
|
||||
node->identity, DIGEST_LEN));
|
||||
tor_assert(! digestmap_get(dm, node->identity));
|
||||
digestmap_set(dm, node->identity, (void*)node);
|
||||
} SMARTLIST_FOREACH_END(ri);
|
||||
}
|
||||
|
||||
/* every routerstatus in ns should be in the nodelist */
|
||||
if (ns) {
|
||||
SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) {
|
||||
const node_t *node = node_get_by_id(rs->identity_digest);
|
||||
tor_assert(node && node->rs == rs);
|
||||
tor_assert(0 == memcmp(rs->identity_digest, node->identity, DIGEST_LEN));
|
||||
digestmap_set(dm, node->identity, (void*)node);
|
||||
if (ns->flavor == FLAV_MICRODESC) {
|
||||
/* If it's a microdesc consensus, every entry that has a
|
||||
* microdescriptor should be in the nodelist.
|
||||
*/
|
||||
microdesc_t *md =
|
||||
microdesc_cache_lookup_by_digest256(NULL, rs->descriptor_digest);
|
||||
tor_assert(md == node->md);
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(rs);
|
||||
}
|
||||
|
||||
/* The nodelist should have no other entries, and its entries should be
|
||||
* well-formed. */
|
||||
SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) {
|
||||
tor_assert(digestmap_get(dm, node->identity) != NULL);
|
||||
tor_assert(node_sl_idx == node->nodelist_idx);
|
||||
} SMARTLIST_FOREACH_END(node);
|
||||
|
||||
tor_assert((long)smartlist_len(the_nodelist->nodes) ==
|
||||
(long)HT_SIZE(&the_nodelist->nodes_by_id));
|
||||
|
||||
digestmap_free(dm, NULL);
|
||||
}
|
||||
|
||||
/** Return a list of a node_t * for every node we know about. The caller
|
||||
* MUST NOT modify the list. (You can set and clear flags in the nodes if
|
||||
* you must, but you must not add or remove nodes.) */
|
||||
smartlist_t *
|
||||
nodelist_get_list(void)
|
||||
{
|
||||
init_nodelist();
|
||||
return the_nodelist->nodes;
|
||||
}
|
||||
|
||||
/** Given a nickname (possibly verbose, possibly a hexadecimal digest), return
|
||||
* the corresponding node_t, or NULL if none exists. Warn the user if
|
||||
* <b>warn_if_unnamed</b> is set, and they have specified a router by
|
||||
* nickname, but the Named flag isn't set for that router. */
|
||||
const node_t *
|
||||
node_get_by_nickname(const char *nickname, int warn_if_unnamed)
|
||||
{
|
||||
char digest_buf[DIGEST_LEN];
|
||||
char nn_buf[MAX_NICKNAME_LEN+1];
|
||||
char nn_char='\0';
|
||||
|
||||
if (!the_nodelist)
|
||||
return NULL;
|
||||
|
||||
/* ???? NM Naming authorities had an additional weird behavior here where
|
||||
they would treat their own namings as slightly authoritative in a
|
||||
strange and inconsistent way. I think that this way is better, but we
|
||||
could get the old behavior back if we wanted to by adding a function
|
||||
to look in the fp_by_name table in fingerprint_list, and using this
|
||||
function to override the name-to-digest lookup below if we are a
|
||||
naming server. -NM
|
||||
*/
|
||||
|
||||
/* Handle these cases: DIGEST, $DIGEST, $DIGEST=name, $DIGEST~name. */
|
||||
if (hex_digest_nickname_decode(nickname, digest_buf, &nn_char, nn_buf)==0) {
|
||||
const node_t *node = node_get_by_id(digest_buf);
|
||||
if (!node)
|
||||
return NULL;
|
||||
if (nn_char) {
|
||||
const char *real_name = node_get_nickname(node);
|
||||
if (!real_name || strcasecmp(real_name, nn_buf))
|
||||
return NULL;
|
||||
if (nn_char == '=') {
|
||||
const char *named_id =
|
||||
networkstatus_get_router_digest_by_nickname(nn_buf);
|
||||
if (!named_id || memcmp(named_id, digest_buf, DIGEST_LEN))
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
if (!strcasecmp(nickname, UNNAMED_ROUTER_NICKNAME))
|
||||
return NULL;
|
||||
|
||||
/* Okay, so if we get here, the nickname is just a nickname. Is there
|
||||
* a binding for it in the consensus? */
|
||||
{
|
||||
const char *named_id =
|
||||
networkstatus_get_router_digest_by_nickname(nickname);
|
||||
if (named_id)
|
||||
return node_get_by_id(named_id);
|
||||
}
|
||||
|
||||
/* Is it marked as owned-by-someone-else? */
|
||||
if (networkstatus_nickname_is_unnamed(nickname)) {
|
||||
log_info(LD_GENERAL, "The name %s is listed as Unnamed: there is some "
|
||||
"router that holds it, but not one listed in the current "
|
||||
"consensus.", escaped(nickname));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Okay, so the name is not canonical for anybody. */
|
||||
{
|
||||
smartlist_t *matches = smartlist_create();
|
||||
const node_t *choice = NULL;
|
||||
|
||||
SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) {
|
||||
if (!strcasecmp(node_get_nickname(node), nickname))
|
||||
smartlist_add(matches, node);
|
||||
} SMARTLIST_FOREACH_END(node);
|
||||
|
||||
if (smartlist_len(matches)>1 && warn_if_unnamed) {
|
||||
int any_unwarned = 0;
|
||||
SMARTLIST_FOREACH_BEGIN(matches, node_t *, node) {
|
||||
if (!node->name_lookup_warned) {
|
||||
node->name_lookup_warned = 1;
|
||||
any_unwarned = 1;
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(node);
|
||||
|
||||
if (any_unwarned) {
|
||||
log_warn(LD_CONFIG, "There are multiple matches for the name %s, "
|
||||
"but none is listed as Named in the directory consensus. "
|
||||
"Choosing one arbitrarily.", nickname);
|
||||
}
|
||||
} else if (smartlist_len(matches)>1 && warn_if_unnamed) {
|
||||
char fp[HEX_DIGEST_LEN+1];
|
||||
node_t *node = smartlist_get(matches, 0);
|
||||
if (node->name_lookup_warned) {
|
||||
base16_encode(fp, sizeof(fp), node->identity, DIGEST_LEN);
|
||||
log_warn(LD_CONFIG,
|
||||
"You specified a server \"%s\" by name, but the directory "
|
||||
"authorities do not have any key registered for this "
|
||||
"nickname -- so it could be used by any server, not just "
|
||||
"the one you meant. "
|
||||
"To make sure you get the same server in the future, refer "
|
||||
"to it by key, as \"$%s\".", nickname, fp);
|
||||
node->name_lookup_warned = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (smartlist_len(matches))
|
||||
choice = smartlist_get(matches, 0);
|
||||
|
||||
smartlist_free(matches);
|
||||
return choice;
|
||||
}
|
||||
}
|
||||
|
||||
/** Return the nickname of <b>node</b>, or NULL if we can't find one. */
|
||||
const char *
|
||||
node_get_nickname(const node_t *node)
|
||||
{
|
||||
tor_assert(node);
|
||||
if (node->rs)
|
||||
return node->rs->nickname;
|
||||
else if (node->ri)
|
||||
return node->ri->nickname;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Return true iff the nickname of <b>node</b> is canonical, based on the
|
||||
* latest consensus. */
|
||||
int
|
||||
node_is_named(const node_t *node)
|
||||
{
|
||||
const char *named_id;
|
||||
const char *nickname = node_get_nickname(node);
|
||||
if (!nickname)
|
||||
return 0;
|
||||
named_id = networkstatus_get_router_digest_by_nickname(nickname);
|
||||
if (!named_id)
|
||||
return 0;
|
||||
return !memcmp(named_id, node->identity, DIGEST_LEN);
|
||||
}
|
||||
|
||||
/** Return true iff <b>node</b> appears to be a directory authority or
|
||||
* directory cache */
|
||||
int
|
||||
node_is_dir(const node_t *node)
|
||||
{
|
||||
if (node->rs)
|
||||
return node->rs->dir_port != 0;
|
||||
else if (node->ri)
|
||||
return node->ri->dir_port != 0;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** Return true iff <b>node</b> has either kind of usable descriptor -- that
|
||||
* is, a routerdecriptor or a microdescriptor. */
|
||||
int
|
||||
node_has_descriptor(const node_t *node)
|
||||
{
|
||||
return (node->ri ||
|
||||
(node->rs && node->md));
|
||||
}
|
||||
|
||||
/** Return the router_purpose of <b>node</b>. */
|
||||
int
|
||||
node_get_purpose(const node_t *node)
|
||||
{
|
||||
if (node->ri)
|
||||
return node->ri->purpose;
|
||||
else
|
||||
return ROUTER_PURPOSE_GENERAL;
|
||||
}
|
||||
|
||||
/** Compute the verbose ("extended") nickname of <b>node</b> and store it
|
||||
* into the MAX_VERBOSE_NICKNAME_LEN+1 character buffer at
|
||||
* <b>verbose_nickname_out</b> */
|
||||
void
|
||||
node_get_verbose_nickname(const node_t *node,
|
||||
char *verbose_name_out)
|
||||
{
|
||||
const char *nickname = node_get_nickname(node);
|
||||
int is_named = node_is_named(node);
|
||||
verbose_name_out[0] = '$';
|
||||
base16_encode(verbose_name_out+1, HEX_DIGEST_LEN+1, node->identity,
|
||||
DIGEST_LEN);
|
||||
if (!nickname)
|
||||
return;
|
||||
verbose_name_out[1+HEX_DIGEST_LEN] = is_named ? '=' : '~';
|
||||
strlcpy(verbose_name_out+1+HEX_DIGEST_LEN+1, nickname, MAX_NICKNAME_LEN+1);
|
||||
}
|
||||
|
||||
/** Return true iff it seems that <b>node</b> allows circuits to exit
|
||||
* through it directlry from the client. */
|
||||
int
|
||||
node_allows_single_hop_exits(const node_t *node)
|
||||
{
|
||||
if (node && node->ri)
|
||||
return node->ri->allow_single_hop_exits;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Return true iff it seems that <b>node</b> has an exit policy that doesn't
|
||||
* actually permit anything to exit, or we don't know its exit policy */
|
||||
int
|
||||
node_exit_policy_rejects_all(const node_t *node)
|
||||
{
|
||||
if (node->ri)
|
||||
return node->ri->policy_is_reject_star;
|
||||
else if (node->md)
|
||||
return node->md->exit_policy == NULL ||
|
||||
short_policy_is_reject_star(node->md->exit_policy);
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Copy the address for <b>node</b> into *<b>addr_out</b>. */
|
||||
int
|
||||
node_get_addr(const node_t *node, tor_addr_t *addr_out)
|
||||
{
|
||||
if (node->ri) {
|
||||
tor_addr_from_ipv4h(addr_out, node->ri->addr);
|
||||
return 0;
|
||||
} else if (node->rs) {
|
||||
tor_addr_from_ipv4h(addr_out, node->rs->addr);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Return the host-order IPv4 address for <b>node</b>, or 0 if it doesn't
|
||||
* seem to have one. */
|
||||
uint32_t
|
||||
node_get_addr_ipv4h(const node_t *node)
|
||||
{
|
||||
if (node->ri) {
|
||||
return node->ri->addr;
|
||||
} else if (node->rs) {
|
||||
return node->rs->addr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Copy a string representation of the IP address for <b>node</b> into the
|
||||
* <b>len</b>-byte buffer at <b>buf</b>.
|
||||
*/
|
||||
void
|
||||
node_get_address_string(const node_t *node, char *buf, size_t len)
|
||||
{
|
||||
if (node->ri) {
|
||||
strlcpy(buf, node->ri->address, len);
|
||||
} else if (node->rs) {
|
||||
tor_addr_t addr;
|
||||
tor_addr_from_ipv4h(&addr, node->rs->addr);
|
||||
tor_addr_to_str(buf, &addr, len, 0);
|
||||
} else {
|
||||
buf[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/** Return <b>node</b>'s declared uptime, or -1 if it doesn't seem to have
|
||||
* one. */
|
||||
long
|
||||
node_get_declared_uptime(const node_t *node)
|
||||
{
|
||||
if (node->ri)
|
||||
return node->ri->uptime;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Return <b>node</b>'s declared or_port */
|
||||
uint16_t
|
||||
node_get_orport(const node_t *node)
|
||||
{
|
||||
if (node->ri)
|
||||
return node->ri->or_port;
|
||||
else if (node->rs)
|
||||
return node->rs->or_port;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Return <b>node</b>'s platform string, or NULL if we don't know it. */
|
||||
const char *
|
||||
node_get_platform(const node_t *node)
|
||||
{
|
||||
/* If we wanted, we could record the version in the routerstatus_t, since
|
||||
* the consensus lists it. We don't, though, so this function just won't
|
||||
* work with microdescriptors. */
|
||||
if (node->ri)
|
||||
return node->ri->platform;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Return <b>node</b>'s time of publication, or 0 if we don't have one. */
|
||||
time_t
|
||||
node_get_published_on(const node_t *node)
|
||||
{
|
||||
if (node->ri)
|
||||
return node->ri->cache_info.published_on;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Return true iff <b>node</b> is one representing this router. */
|
||||
int
|
||||
node_is_me(const node_t *node)
|
||||
{
|
||||
return router_digest_is_me(node->identity);
|
||||
}
|
||||
|
||||
/** Return <b>node</b> declared family (as a list of names), or NULL if
|
||||
* the node didn't declare a family. */
|
||||
const smartlist_t *
|
||||
node_get_declared_family(const node_t *node)
|
||||
{
|
||||
if (node->ri && node->ri->declared_family)
|
||||
return node->ri->declared_family;
|
||||
else if (node->md && node->md->family)
|
||||
return node->md->family;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* KILLTHIS XXXX NM -- it's a dummy to keep UNIMPLEMENTED_NODELIST()
|
||||
* working */
|
||||
int unimplemented_nodelist_truth = 1;
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2010, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file microdesc.h
|
||||
* \brief Header file for microdesc.c.
|
||||
**/
|
||||
|
||||
#ifndef _TOR_NODELIST_H
|
||||
#define _TOR_NODELIST_H
|
||||
|
||||
node_t *node_get_mutable_by_id(const char *identity_digest);
|
||||
const node_t *node_get_by_id(const char *identity_digest);
|
||||
node_t *nodelist_add_routerinfo(routerinfo_t *ri);
|
||||
node_t *nodelist_add_microdesc(microdesc_t *md);
|
||||
void nodelist_set_consensus(networkstatus_t *ns);
|
||||
|
||||
void nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md);
|
||||
void nodelist_remove_routerinfo(routerinfo_t *ri);
|
||||
void nodelist_purge(void);
|
||||
|
||||
void nodelist_free_all(void);
|
||||
void nodelist_assert_ok(void);
|
||||
|
||||
const node_t *node_get_by_nickname(const char *nickname, int warn_if_unnamed);
|
||||
void node_get_verbose_nickname(const node_t *node,
|
||||
char *verbose_name_out);
|
||||
int node_is_named(const node_t *node);
|
||||
int node_is_dir(const node_t *node);
|
||||
int node_has_descriptor(const node_t *node);
|
||||
int node_get_purpose(const node_t *node);
|
||||
#define node_is_bridge(node) \
|
||||
(node_get_purpose((node)) == ROUTER_PURPOSE_BRIDGE)
|
||||
int node_is_me(const node_t *node);
|
||||
int node_exit_policy_rejects_all(const node_t *node);
|
||||
int node_get_addr(const node_t *node, tor_addr_t *addr_out);
|
||||
uint32_t node_get_addr_ipv4h(const node_t *node);
|
||||
int node_allows_single_hop_exits(const node_t *node);
|
||||
uint16_t node_get_orport(const node_t *node);
|
||||
const char *node_get_nickname(const node_t *node);
|
||||
const char *node_get_platform(const node_t *node);
|
||||
void node_get_address_string(const node_t *node, char *cp, size_t len);
|
||||
long node_get_declared_uptime(const node_t *node);
|
||||
time_t node_get_published_on(const node_t *node);
|
||||
const smartlist_t *node_get_declared_family(const node_t *node);
|
||||
|
||||
smartlist_t *nodelist_get_list(void);
|
||||
|
||||
/* XXXX These need to move out of routerlist.c */
|
||||
void nodelist_refresh_countries(void);
|
||||
void node_set_country(node_t *node);
|
||||
void nodelist_add_node_family(smartlist_t *nodes, const node_t *node);
|
||||
int nodes_in_same_family(const node_t *node1, const node_t *node2);
|
||||
|
||||
/* This means: implement this code or function or thing, nick! */
|
||||
#define UNIMPLEMENTED_NODELIST() \
|
||||
while (unimplemented_nodelist_truth) { \
|
||||
tor_assert(0); \
|
||||
}
|
||||
extern int unimplemented_nodelist_truth;
|
||||
|
||||
#endif
|
||||
|
||||
+112
-34
@@ -809,6 +809,9 @@ typedef enum {
|
||||
* Tor 0.1.2.x is obsolete, we can remove this. */
|
||||
#define DEFAULT_CLIENT_NICKNAME "client"
|
||||
|
||||
/** Name chosen by routers that don't configure nicknames */
|
||||
#define UNNAMED_ROUTER_NICKNAME "Unnamed"
|
||||
|
||||
/** Number of bytes in a SOCKS4 header. */
|
||||
#define SOCKS4_NETWORK_LEN 8
|
||||
|
||||
@@ -1510,52 +1513,44 @@ typedef struct {
|
||||
unsigned int allow_single_hop_exits:1; /**< Whether the router says
|
||||
* it allows single hop exits. */
|
||||
|
||||
/* local info */
|
||||
unsigned int is_running:1; /**< As far as we know, is this OR currently
|
||||
* running? */
|
||||
unsigned int is_valid:1; /**< Has a trusted dirserver validated this OR?
|
||||
* (For Authdir: Have we validated this OR?)
|
||||
*/
|
||||
unsigned int is_named:1; /**< Do we believe the nickname that this OR gives
|
||||
* us? */
|
||||
unsigned int is_fast:1; /** Do we think this is a fast OR? */
|
||||
unsigned int is_stable:1; /** Do we think this is a stable OR? */
|
||||
unsigned int is_possible_guard:1; /**< Do we think this is an OK guard? */
|
||||
unsigned int is_exit:1; /**< Do we think this is an OK exit? */
|
||||
unsigned int is_bad_exit:1; /**< Do we think this exit is censored, borked,
|
||||
* or otherwise nasty? */
|
||||
unsigned int is_bad_directory:1; /**< Do we think this directory is junky,
|
||||
* underpowered, or otherwise useless? */
|
||||
unsigned int wants_to_be_hs_dir:1; /**< True iff this router claims to be
|
||||
* a hidden service directory. */
|
||||
unsigned int is_hs_dir:1; /**< True iff this router is a hidden service
|
||||
* directory according to the authorities. */
|
||||
unsigned int policy_is_reject_star:1; /**< True iff the exit policy for this
|
||||
* router rejects everything. */
|
||||
/** True if, after we have added this router, we should re-launch
|
||||
* tests for it. */
|
||||
unsigned int needs_retest_if_added:1;
|
||||
|
||||
/** Tor can use this router for general positions in circuits. */
|
||||
/** Tor can use this router for general positions in circuits; we got it
|
||||
* from a directory server as usual, or we're an authority and a server
|
||||
* uploaded it. */
|
||||
#define ROUTER_PURPOSE_GENERAL 0
|
||||
/** Tor should avoid using this router for circuit-building. */
|
||||
/** Tor should avoid using this router for circuit-building: we got it
|
||||
* from a crontroller. If the controller wants to use it, it'll have to
|
||||
* ask for it by identity. */
|
||||
#define ROUTER_PURPOSE_CONTROLLER 1
|
||||
/** Tor should use this router only for bridge positions in circuits. */
|
||||
/** Tor should use this router only for bridge positions in circuits: we got
|
||||
* it via a directory request from the bridge itself, or a bridge
|
||||
* authority. x*/
|
||||
#define ROUTER_PURPOSE_BRIDGE 2
|
||||
/** Tor should not use this router; it was marked in cached-descriptors with
|
||||
* a purpose we didn't recognize. */
|
||||
#define ROUTER_PURPOSE_UNKNOWN 255
|
||||
|
||||
uint8_t purpose; /** What positions in a circuit is this router good for? */
|
||||
/* In what way did we find out about this router? One of ROUTER_PURPOSE_*.
|
||||
* Routers of different purposes are kept segregated and used for different
|
||||
* things; see notes on ROUTER_PURPOSE_* macros above.
|
||||
*/
|
||||
uint8_t purpose;
|
||||
|
||||
/* The below items are used only by authdirservers for
|
||||
* reachability testing. */
|
||||
|
||||
/** When was the last time we could reach this OR? */
|
||||
time_t last_reachable;
|
||||
/** When did we start testing reachability for this OR? */
|
||||
time_t testing_since;
|
||||
/** According to the geoip db what country is this router in? */
|
||||
country_t country;
|
||||
|
||||
} routerinfo_t;
|
||||
|
||||
/** Information needed to keep and cache a signed extra-info document. */
|
||||
@@ -1591,7 +1586,11 @@ typedef struct routerstatus_t {
|
||||
unsigned int is_exit:1; /**< True iff this router is a good exit. */
|
||||
unsigned int is_stable:1; /**< True iff this router stays up a long time. */
|
||||
unsigned int is_fast:1; /**< True iff this router has good bandwidth. */
|
||||
unsigned int is_running:1; /**< True iff this router is up. */
|
||||
/** True iff this router is called 'running' in the consensus. We give it
|
||||
* this funny name so that we don't accidentally use this bit as a view of
|
||||
* whether we think the router is *currently* running. If that's what you
|
||||
* want to know, look at is_running in node_t. */
|
||||
unsigned int is_flagged_running:1;
|
||||
unsigned int is_named:1; /**< True iff "nickname" belongs to this router. */
|
||||
unsigned int is_unnamed:1; /**< True iff "nickname" belongs to another
|
||||
* router. */
|
||||
@@ -1643,15 +1642,31 @@ typedef struct routerstatus_t {
|
||||
* from this authority.) Applies in v2 networkstatus document only.
|
||||
*/
|
||||
unsigned int need_to_mirror:1;
|
||||
unsigned int name_lookup_warned:1; /**< Have we warned the user for referring
|
||||
* to this (unnamed) router by nickname?
|
||||
*/
|
||||
time_t last_dir_503_at; /**< When did this router last tell us that it
|
||||
* was too busy to serve directory info? */
|
||||
download_status_t dl_status;
|
||||
|
||||
} routerstatus_t;
|
||||
|
||||
/** A single entry in a parsed policy summary, describing a range of ports. */
|
||||
typedef struct short_policy_entry_t {
|
||||
uint16_t min_port, max_port;
|
||||
} short_policy_entry_t;
|
||||
|
||||
/** A short_poliy_t is the parsed version of a policy summary. */
|
||||
typedef struct short_policy_t {
|
||||
/** True if the members of 'entries' are port ranges to accept; false if
|
||||
* they are port ranges to reject */
|
||||
unsigned int is_accept : 1;
|
||||
/** The actual number of values in 'entries'. */
|
||||
unsigned int n_entries : 31;
|
||||
/** An array of (probably more than 1!) short_policy_entry_t values,
|
||||
* each descriping a range of ports that this policy accepts or rejects
|
||||
* (depending on the value of is_accept).
|
||||
*/
|
||||
short_policy_entry_t entries[1];
|
||||
} short_policy_t;
|
||||
|
||||
/** A microdescriptor is the smallest amount of information needed to build a
|
||||
* circuit through a router. They are generated by the directory authorities,
|
||||
* using information from the uploaded routerinfo documents. They are not
|
||||
@@ -1693,11 +1708,72 @@ typedef struct microdesc_t {
|
||||
crypto_pk_env_t *onion_pkey;
|
||||
/** As routerinfo_t.family */
|
||||
smartlist_t *family;
|
||||
/** Encoded exit policy summary */
|
||||
char *exitsummary; /**< exit policy summary -
|
||||
* XXX this probably should not stay a string. */
|
||||
/** Exit policy summary */
|
||||
short_policy_t *exit_policy;
|
||||
} microdesc_t;
|
||||
|
||||
/** A node_t represents a Tor router.
|
||||
*
|
||||
* Specifically, a node_t is a Tor router as we are using it: a router that
|
||||
* we are considering for circuits, connections, and so on. A node_t is a
|
||||
* thin wrapper around the routerstatus, routerinfo, and microdesc for a
|
||||
* single wrapper, and provides a consistent interface for all of them.
|
||||
*
|
||||
* Also, a node_t has mutable state. While a routerinfo, a routerstatus,
|
||||
* and a microdesc have[*] only the information read from a router
|
||||
* descriptor, a consensus entry, and a microdescriptor (respectively)...
|
||||
* a node_t has flags based on *our own current opinion* of the node.
|
||||
*
|
||||
* [*] Actually, there is some leftover information in each that is mutable.
|
||||
* We should try to excise that.
|
||||
*/
|
||||
typedef struct node_t {
|
||||
/* Indexing information */
|
||||
|
||||
/** Used to look up the node_t by its identity digest. */
|
||||
HT_ENTRY(node_t) ht_ent;
|
||||
/** Position of the node within the list of nodes */
|
||||
int nodelist_idx;
|
||||
|
||||
/** The identity digest of this node_t. No more than one node_t per
|
||||
* identity may exist at a time. */
|
||||
char identity[DIGEST_LEN];
|
||||
|
||||
microdesc_t *md;
|
||||
routerinfo_t *ri;
|
||||
routerstatus_t *rs;
|
||||
|
||||
/* local info: copied from routerstatus, then possibly frobbed based
|
||||
* on experience. Authorities set this stuff directly. */
|
||||
|
||||
unsigned int is_running:1; /**< As far as we know, is this OR currently
|
||||
* running? */
|
||||
unsigned int is_valid:1; /**< Has a trusted dirserver validated this OR?
|
||||
* (For Authdir: Have we validated this OR?)
|
||||
*/
|
||||
unsigned int is_fast:1; /** Do we think this is a fast OR? */
|
||||
unsigned int is_stable:1; /** Do we think this is a stable OR? */
|
||||
unsigned int is_possible_guard:1; /**< Do we think this is an OK guard? */
|
||||
unsigned int is_exit:1; /**< Do we think this is an OK exit? */
|
||||
unsigned int is_bad_exit:1; /**< Do we think this exit is censored, borked,
|
||||
* or otherwise nasty? */
|
||||
unsigned int is_bad_directory:1; /**< Do we think this directory is junky,
|
||||
* underpowered, or otherwise useless? */
|
||||
unsigned int is_hs_dir:1; /**< True iff this router is a hidden service
|
||||
* directory according to the authorities. */
|
||||
|
||||
/* Local info: warning state. */
|
||||
|
||||
unsigned int name_lookup_warned:1; /**< Have we warned the user for referring
|
||||
* to this (unnamed) router by nickname?
|
||||
*/
|
||||
|
||||
/* Local info: derived. */
|
||||
|
||||
/** According to the geoip db what country is this router in? */
|
||||
country_t country;
|
||||
} node_t;
|
||||
|
||||
/** How many times will we try to download a router's descriptor before giving
|
||||
* up? */
|
||||
#define MAX_ROUTERDESC_DOWNLOAD_FAILURES 8
|
||||
@@ -2667,7 +2743,8 @@ typedef struct {
|
||||
|
||||
char *MyFamily; /**< Declared family for this OR. */
|
||||
config_line_t *NodeFamilies; /**< List of config lines for
|
||||
* node families */
|
||||
* node families */
|
||||
smartlist_t *NodeFamilySets; /**< List of parsed NodeFamilies values. */
|
||||
config_line_t *AuthDirBadDir; /**< Address policy for descriptors to
|
||||
* mark as bad dir mirrors. */
|
||||
config_line_t *AuthDirBadExit; /**< Address policy for descriptors to
|
||||
@@ -3385,7 +3462,7 @@ typedef enum {
|
||||
ADDR_POLICY_PROBABLY_ACCEPTED=1,
|
||||
/** Part of the address was unknown, but as far as we can tell, it was
|
||||
* rejected. */
|
||||
ADDR_POLICY_PROBABLY_REJECTED=2
|
||||
ADDR_POLICY_PROBABLY_REJECTED=2,
|
||||
} addr_policy_result_t;
|
||||
|
||||
/********************************* rephist.c ***************************/
|
||||
@@ -3535,7 +3612,8 @@ typedef enum {
|
||||
CRN_NEED_GUARD = 1<<2,
|
||||
CRN_ALLOW_INVALID = 1<<3,
|
||||
/* XXXX not used, apparently. */
|
||||
CRN_WEIGHT_AS_EXIT = 1<<5
|
||||
CRN_WEIGHT_AS_EXIT = 1<<5,
|
||||
CRN_NEED_DESC = 1<<6
|
||||
} router_crn_flags_t;
|
||||
|
||||
/** Return value for router_add_to_routerlist() and dirserv_add_descriptor() */
|
||||
|
||||
+213
-1
@@ -11,6 +11,7 @@
|
||||
#include "or.h"
|
||||
#include "config.h"
|
||||
#include "dirserv.h"
|
||||
#include "nodelist.h"
|
||||
#include "policies.h"
|
||||
#include "routerparse.h"
|
||||
#include "ht.h"
|
||||
@@ -261,7 +262,7 @@ fascist_firewall_allows_address_or(const tor_addr_t *addr, uint16_t port)
|
||||
/** Return true iff we think our firewall will let us make an OR connection to
|
||||
* <b>ri</b>. */
|
||||
int
|
||||
fascist_firewall_allows_or(routerinfo_t *ri)
|
||||
fascist_firewall_allows_or(const routerinfo_t *ri)
|
||||
{
|
||||
/* XXXX proposal 118 */
|
||||
tor_addr_t addr;
|
||||
@@ -269,6 +270,22 @@ fascist_firewall_allows_or(routerinfo_t *ri)
|
||||
return fascist_firewall_allows_address_or(&addr, ri->or_port);
|
||||
}
|
||||
|
||||
/** Return true iff we think our firewall will let us make an OR connection to
|
||||
* <b>node</b>. */
|
||||
int
|
||||
fascist_firewall_allows_node(const node_t *node)
|
||||
{
|
||||
if (node->ri) {
|
||||
return fascist_firewall_allows_or(node->ri);
|
||||
} else if (node->rs) {
|
||||
tor_addr_t addr;
|
||||
tor_addr_from_ipv4h(&addr, node->rs->addr);
|
||||
return fascist_firewall_allows_address_or(&addr, node->rs->or_port);
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Return true iff we think our firewall will let us make a directory
|
||||
* connection to addr:port. */
|
||||
int
|
||||
@@ -858,6 +875,7 @@ policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/** Replace the exit policy of <b>r</b> with reject *:*. */
|
||||
void
|
||||
policies_set_router_exitpolicy_to_reject_all(routerinfo_t *r)
|
||||
@@ -868,6 +886,15 @@ policies_set_router_exitpolicy_to_reject_all(routerinfo_t *r)
|
||||
item = router_parse_addr_policy_item_from_string("reject *:*", -1);
|
||||
smartlist_add(r->exit_policy, item);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Replace the exit policy of <b>node</b> with reject *:* */
|
||||
void
|
||||
policies_set_node_exitpolicy_to_reject_all(node_t *node)
|
||||
{
|
||||
(void)node;
|
||||
UNIMPLEMENTED_NODELIST();
|
||||
}
|
||||
|
||||
/** Return 1 if there is at least one /8 subnet in <b>policy</b> that
|
||||
* allows exiting to <b>port</b>. Otherwise, return 0. */
|
||||
@@ -1288,6 +1315,191 @@ policy_summarize(smartlist_t *policy)
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Convert a summarized policy string into a short_policy_t. Return NULL
|
||||
* if the string is not well-formed. */
|
||||
short_policy_t *
|
||||
parse_short_policy(const char *summary)
|
||||
{
|
||||
const char *orig_summary = summary;
|
||||
short_policy_t *result;
|
||||
int is_accept;
|
||||
int n_entries;
|
||||
short_policy_entry_t entries[MAX_EXITPOLICY_SUMMARY_LEN]; /* overkill */
|
||||
const char *next;
|
||||
|
||||
if (!strcmpstart(summary, "accept ")) {
|
||||
is_accept = 1;
|
||||
summary += strlen("accept ");
|
||||
} else if (!strcmpstart(summary, "reject ")) {
|
||||
is_accept = 0;
|
||||
summary += strlen("reject ");
|
||||
} else {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Unrecognized policy summary keyword");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
n_entries = 0;
|
||||
for ( ; *summary; summary = next) {
|
||||
const char *comma = strchr(summary, ',');
|
||||
unsigned low, high;
|
||||
char dummy;
|
||||
char ent_buf[32];
|
||||
|
||||
next = comma ? comma+1 : strchr(summary, '\0');
|
||||
|
||||
if (n_entries == MAX_EXITPOLICY_SUMMARY_LEN) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Impossibly long policy summary %s",
|
||||
escaped(orig_summary));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (! TOR_ISDIGIT(*summary) || next-summary > (int)(sizeof(ent_buf)-1)) {
|
||||
/* unrecognized entry format. skip it. */
|
||||
continue;
|
||||
}
|
||||
if (next-summary < 2) {
|
||||
/* empty; skip it. */
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(ent_buf, summary, next-summary-1);
|
||||
ent_buf[next-summary-1] = '\0';
|
||||
|
||||
if (tor_sscanf(ent_buf, "%u-%u%c", &low, &high, &dummy) == 2) {
|
||||
if (low<1 || low>65535 || high<1 || high>65535) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_DIR,"Found bad entry in policy summary %s",
|
||||
escaped(orig_summary));
|
||||
return NULL;
|
||||
}
|
||||
} else if (tor_sscanf(ent_buf, "%u%c", &low, &dummy) == 1) {
|
||||
if (low<1 || low>65535) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_DIR,"Found bad entry in policy summary %s",
|
||||
escaped(orig_summary));
|
||||
return NULL;
|
||||
}
|
||||
high = low;
|
||||
} else {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_DIR,"Found bad entry in policy summary %s",
|
||||
escaped(orig_summary));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
entries[n_entries].min_port = low;
|
||||
entries[n_entries].max_port = high;
|
||||
n_entries++;
|
||||
}
|
||||
|
||||
if (n_entries == 0) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_DIR,
|
||||
"Found no port-range entries in summary %s", escaped(orig_summary));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
{
|
||||
size_t size = sizeof(short_policy_t) +
|
||||
sizeof(short_policy_entry_t)*(n_entries-1);
|
||||
result = tor_malloc_zero(size);
|
||||
|
||||
tor_assert( (char*)&result->entries[n_entries-1] < ((char*)result)+size);
|
||||
}
|
||||
|
||||
result->is_accept = is_accept;
|
||||
result->n_entries = n_entries;
|
||||
memcpy(result->entries, entries, sizeof(short_policy_entry_t)*n_entries);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Release all storage held in <b>policy</b>. */
|
||||
void
|
||||
short_policy_free(short_policy_t *policy)
|
||||
{
|
||||
tor_free(policy);
|
||||
}
|
||||
|
||||
/** See whether the <b>addr</b>:<b>port</b> address is likely to be accepted
|
||||
* or rejected by the summarized policy <b>policy</b>. Return values are as
|
||||
* for compare_tor_addr_to_addr_policy. Unlike the regular addr_policy
|
||||
* functions, requires the <b>port</b> be specified. */
|
||||
addr_policy_result_t
|
||||
compare_tor_addr_to_short_policy(const tor_addr_t *addr, uint16_t port,
|
||||
const short_policy_t *policy)
|
||||
{
|
||||
int i;
|
||||
int found_match = 0;
|
||||
int accept;
|
||||
(void)addr;
|
||||
|
||||
tor_assert(port != 0);
|
||||
|
||||
if (addr && (tor_addr_is_internal(addr, 0) ||
|
||||
tor_addr_is_null(addr) ||
|
||||
tor_addr_is_loopback(addr)))
|
||||
return ADDR_POLICY_REJECTED;
|
||||
|
||||
for (i=0; i < policy->n_entries; ++i) {
|
||||
const short_policy_entry_t *e = &policy->entries[i];
|
||||
if (e->min_port <= port && port <= e->max_port) {
|
||||
found_match = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_match)
|
||||
accept = policy->is_accept;
|
||||
else
|
||||
accept = ! policy->is_accept;
|
||||
|
||||
/* ???? are these right? */
|
||||
if (accept)
|
||||
return ADDR_POLICY_PROBABLY_ACCEPTED;
|
||||
else
|
||||
return ADDR_POLICY_REJECTED;
|
||||
}
|
||||
|
||||
/** Return true iff <b>policy</b> seems reject all ports */
|
||||
int
|
||||
short_policy_is_reject_star(const short_policy_t *policy)
|
||||
{
|
||||
/* This doesn't need to be as much on the lookout as policy_is_reject_star,
|
||||
* since policy summaries are from the consensus or from consensus microdescs.
|
||||
*/
|
||||
tor_assert(policy);
|
||||
/* Check for an exact match of "reject 1-65535". */
|
||||
return (policy->is_accept == 0 && policy->n_entries == 1 &&
|
||||
policy->entries[0].min_port == 1 &&
|
||||
policy->entries[0].max_port == 65535);
|
||||
}
|
||||
|
||||
/** Decides whether addr:port is probably or definitely accepted or rejcted by
|
||||
* <b>node</b>. See compare_tor_addr_to_addr_policy for details on addr/port
|
||||
* interpretation. */
|
||||
addr_policy_result_t
|
||||
compare_addr_to_node_policy(uint32_t addr, uint16_t port, const node_t *node)
|
||||
{
|
||||
tor_addr_t a;
|
||||
tor_addr_from_ipv4h(&a, addr);
|
||||
return compare_tor_addr_to_node_policy(&a, port, node);
|
||||
}
|
||||
|
||||
/** Decides whether addr:port is probably or definitely accepted or rejcted by
|
||||
* <b>node</b>. See compare_tor_addr_to_addr_policy for details on addr/port
|
||||
* interpretation. */
|
||||
addr_policy_result_t
|
||||
compare_tor_addr_to_node_policy(const tor_addr_t *addr, uint16_t port,
|
||||
const node_t *node)
|
||||
{
|
||||
if (node->ri)
|
||||
return compare_tor_addr_to_addr_policy(addr, port, node->ri->exit_policy);
|
||||
else if (node->md && node->md) {
|
||||
if (node->md->exit_policy == NULL)
|
||||
return ADDR_POLICY_REJECTED;
|
||||
else
|
||||
return compare_tor_addr_to_short_policy(addr, port,
|
||||
node->md->exit_policy);
|
||||
} else
|
||||
return ADDR_POLICY_PROBABLY_REJECTED;
|
||||
}
|
||||
|
||||
/** Implementation for GETINFO control command: knows the answer for questions
|
||||
* about "exit-policy/..." */
|
||||
int
|
||||
|
||||
+16
-2
@@ -19,7 +19,8 @@
|
||||
|
||||
int firewall_is_fascist_or(void);
|
||||
int fascist_firewall_allows_address_or(const tor_addr_t *addr, uint16_t port);
|
||||
int fascist_firewall_allows_or(routerinfo_t *ri);
|
||||
int fascist_firewall_allows_or(const routerinfo_t *ri);
|
||||
int fascist_firewall_allows_node(const node_t *node);
|
||||
int fascist_firewall_allows_address_dir(const tor_addr_t *addr, uint16_t port);
|
||||
int dir_policy_permits_address(const tor_addr_t *addr);
|
||||
int socks_policy_permits_address(const tor_addr_t *addr);
|
||||
@@ -38,10 +39,16 @@ addr_policy_result_t compare_tor_addr_to_addr_policy(const tor_addr_t *addr,
|
||||
uint16_t port, const smartlist_t *policy);
|
||||
addr_policy_result_t compare_addr_to_addr_policy(uint32_t addr,
|
||||
uint16_t port, const smartlist_t *policy);
|
||||
|
||||
addr_policy_result_t compare_addr_to_node_policy(uint32_t addr,
|
||||
uint16_t port, const node_t *node);
|
||||
addr_policy_result_t compare_tor_addr_to_node_policy(const tor_addr_t *addr,
|
||||
uint16_t port, const node_t *node);
|
||||
|
||||
int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
|
||||
int rejectprivate, const char *local_address,
|
||||
int add_default_policy);
|
||||
void policies_set_router_exitpolicy_to_reject_all(routerinfo_t *exitrouter);
|
||||
void policies_set_node_exitpolicy_to_reject_all(node_t *exitrouter);
|
||||
int exit_policy_is_general_exit(smartlist_t *policy);
|
||||
int policy_is_reject_star(const smartlist_t *policy);
|
||||
int getinfo_helper_policies(control_connection_t *conn,
|
||||
@@ -56,5 +63,12 @@ void policies_free_all(void);
|
||||
|
||||
char *policy_summarize(smartlist_t *policy);
|
||||
|
||||
short_policy_t *parse_short_policy(const char *summary);
|
||||
void short_policy_free(short_policy_t *policy);
|
||||
int short_policy_is_reject_star(const short_policy_t *policy);
|
||||
addr_policy_result_t compare_tor_addr_to_short_policy(
|
||||
const tor_addr_t *addr, uint16_t port,
|
||||
const short_policy_t *policy);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+8
-6
@@ -24,6 +24,7 @@
|
||||
#include "main.h"
|
||||
#include "mempool.h"
|
||||
#include "networkstatus.h"
|
||||
#include "nodelist.h"
|
||||
#include "policies.h"
|
||||
#include "reasons.h"
|
||||
#include "relay.h"
|
||||
@@ -712,7 +713,7 @@ connection_ap_process_end_not_open(
|
||||
edge_connection_t *conn, crypt_path_t *layer_hint)
|
||||
{
|
||||
struct in_addr in;
|
||||
routerinfo_t *exitrouter;
|
||||
node_t *exitrouter;
|
||||
int reason = *(cell->payload+RELAY_HEADER_SIZE);
|
||||
int control_reason = reason | END_STREAM_REASON_FLAG_REMOTE;
|
||||
(void) layer_hint; /* unused */
|
||||
@@ -720,11 +721,12 @@ connection_ap_process_end_not_open(
|
||||
if (rh->length > 0 && edge_reason_is_retriable(reason) &&
|
||||
!connection_edge_is_rendezvous_stream(conn) /* avoid retry if rend */
|
||||
) {
|
||||
const char *chosen_exit_digest =
|
||||
circ->build_state->chosen_exit->identity_digest;
|
||||
log_info(LD_APP,"Address '%s' refused due to '%s'. Considering retrying.",
|
||||
safe_str(conn->socks_request->address),
|
||||
stream_end_reason_to_string(reason));
|
||||
exitrouter =
|
||||
router_get_by_digest(circ->build_state->chosen_exit->identity_digest);
|
||||
exitrouter = node_get_mutable_by_id(chosen_exit_digest);
|
||||
switch (reason) {
|
||||
case END_STREAM_REASON_EXITPOLICY:
|
||||
if (rh->length >= 5) {
|
||||
@@ -759,8 +761,8 @@ connection_ap_process_end_not_open(
|
||||
log_info(LD_APP,
|
||||
"Exitrouter '%s' seems to be more restrictive than its exit "
|
||||
"policy. Not using this router as exit for now.",
|
||||
exitrouter->nickname);
|
||||
policies_set_router_exitpolicy_to_reject_all(exitrouter);
|
||||
node_get_nickname(exitrouter));
|
||||
policies_set_node_exitpolicy_to_reject_all(exitrouter);
|
||||
}
|
||||
/* rewrite it to an IP if we learned one. */
|
||||
if (addressmap_rewrite(conn->socks_request->address,
|
||||
@@ -823,7 +825,7 @@ connection_ap_process_end_not_open(
|
||||
case END_STREAM_REASON_HIBERNATING:
|
||||
case END_STREAM_REASON_RESOURCELIMIT:
|
||||
if (exitrouter) {
|
||||
policies_set_router_exitpolicy_to_reject_all(exitrouter);
|
||||
policies_set_node_exitpolicy_to_reject_all(exitrouter);
|
||||
}
|
||||
if (conn->chosen_exit_optional) {
|
||||
/* stop wanting a specific exit */
|
||||
|
||||
+4
-4
@@ -16,6 +16,7 @@
|
||||
#include "connection_edge.h"
|
||||
#include "directory.h"
|
||||
#include "main.h"
|
||||
#include "nodelist.h"
|
||||
#include "relay.h"
|
||||
#include "rendclient.h"
|
||||
#include "rendcommon.h"
|
||||
@@ -738,7 +739,6 @@ rend_client_get_random_intro(const rend_data_t *rend_query)
|
||||
int i;
|
||||
rend_cache_entry_t *entry;
|
||||
rend_intro_point_t *intro;
|
||||
routerinfo_t *router;
|
||||
|
||||
if (rend_cache_lookup_entry(rend_query->onion_address, -1, &entry) < 1) {
|
||||
log_warn(LD_REND,
|
||||
@@ -755,8 +755,8 @@ rend_client_get_random_intro(const rend_data_t *rend_query)
|
||||
intro = smartlist_get(entry->parsed->intro_nodes, i);
|
||||
/* Do we need to look up the router or is the extend info complete? */
|
||||
if (!intro->extend_info->onion_key) {
|
||||
router = router_get_by_nickname(intro->extend_info->nickname, 0);
|
||||
if (!router) {
|
||||
const node_t *node = node_get_by_nickname(intro->extend_info->nickname, 0);
|
||||
if (!node) {
|
||||
log_info(LD_REND, "Unknown router with nickname '%s'; trying another.",
|
||||
intro->extend_info->nickname);
|
||||
rend_intro_point_free(intro);
|
||||
@@ -764,7 +764,7 @@ rend_client_get_random_intro(const rend_data_t *rend_query)
|
||||
goto again;
|
||||
}
|
||||
extend_info_free(intro->extend_info);
|
||||
intro->extend_info = extend_info_from_router(router);
|
||||
intro->extend_info = extend_info_from_node(node);
|
||||
}
|
||||
return extend_info_dup(intro->extend_info);
|
||||
}
|
||||
|
||||
+21
-20
@@ -14,6 +14,7 @@
|
||||
#include "config.h"
|
||||
#include "directory.h"
|
||||
#include "networkstatus.h"
|
||||
#include "nodelist.h"
|
||||
#include "rendclient.h"
|
||||
#include "rendcommon.h"
|
||||
#include "rendservice.h"
|
||||
@@ -1001,7 +1002,7 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request,
|
||||
} else {
|
||||
char *rp_nickname;
|
||||
size_t nickname_field_len;
|
||||
routerinfo_t *router;
|
||||
const node_t *node;
|
||||
int version;
|
||||
if (*buf == 1) {
|
||||
rp_nickname = buf+1;
|
||||
@@ -1028,8 +1029,8 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request,
|
||||
len -= nickname_field_len;
|
||||
len -= rp_nickname - buf; /* also remove header space used by version, if
|
||||
* any */
|
||||
router = router_get_by_nickname(rp_nickname, 0);
|
||||
if (!router) {
|
||||
node = node_get_by_nickname(rp_nickname, 0);
|
||||
if (!node) {
|
||||
log_info(LD_REND, "Couldn't find router %s named in introduce2 cell.",
|
||||
escaped_safe_str_client(rp_nickname));
|
||||
/* XXXX Add a no-such-router reason? */
|
||||
@@ -1037,7 +1038,7 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request,
|
||||
goto err;
|
||||
}
|
||||
|
||||
extend_info = extend_info_from_router(router);
|
||||
extend_info = extend_info_from_node(node);
|
||||
}
|
||||
|
||||
if (len != REND_COOKIE_LEN+DH_KEY_LEN) {
|
||||
@@ -1754,19 +1755,19 @@ void
|
||||
rend_services_introduce(void)
|
||||
{
|
||||
int i,j,r;
|
||||
routerinfo_t *router;
|
||||
const node_t *node;
|
||||
rend_service_t *service;
|
||||
rend_intro_point_t *intro;
|
||||
int changed, prev_intro_nodes;
|
||||
smartlist_t *intro_routers;
|
||||
smartlist_t *intro_nodes;
|
||||
time_t now;
|
||||
or_options_t *options = get_options();
|
||||
|
||||
intro_routers = smartlist_create();
|
||||
intro_nodes = smartlist_create();
|
||||
now = time(NULL);
|
||||
|
||||
for (i=0; i < smartlist_len(rend_service_list); ++i) {
|
||||
smartlist_clear(intro_routers);
|
||||
smartlist_clear(intro_nodes);
|
||||
service = smartlist_get(rend_service_list, i);
|
||||
|
||||
tor_assert(service);
|
||||
@@ -1786,8 +1787,8 @@ rend_services_introduce(void)
|
||||
service. */
|
||||
for (j=0; j < smartlist_len(service->intro_nodes); ++j) {
|
||||
intro = smartlist_get(service->intro_nodes, j);
|
||||
router = router_get_by_digest(intro->extend_info->identity_digest);
|
||||
if (!router || !find_intro_circuit(intro, service->pk_digest)) {
|
||||
node = node_get_by_id(intro->extend_info->identity_digest);
|
||||
if (!node || !find_intro_circuit(intro, service->pk_digest)) {
|
||||
log_info(LD_REND,"Giving up on %s as intro point for %s.",
|
||||
intro->extend_info->nickname, service->service_id);
|
||||
if (service->desc) {
|
||||
@@ -1806,8 +1807,8 @@ rend_services_introduce(void)
|
||||
smartlist_del(service->intro_nodes,j--);
|
||||
changed = 1;
|
||||
}
|
||||
if (router)
|
||||
smartlist_add(intro_routers, router);
|
||||
if (node)
|
||||
smartlist_add(intro_nodes, (void*)node);
|
||||
}
|
||||
|
||||
/* We have enough intro points, and the intro points we thought we had were
|
||||
@@ -1836,26 +1837,26 @@ rend_services_introduce(void)
|
||||
#define NUM_INTRO_POINTS_INIT (NUM_INTRO_POINTS + 2)
|
||||
for (j=prev_intro_nodes; j < (prev_intro_nodes == 0 ?
|
||||
NUM_INTRO_POINTS_INIT : NUM_INTRO_POINTS); ++j) {
|
||||
router_crn_flags_t flags = CRN_NEED_UPTIME;
|
||||
router_crn_flags_t flags = CRN_NEED_UPTIME|CRN_NEED_DESC;
|
||||
if (get_options()->_AllowInvalid & ALLOW_INVALID_INTRODUCTION)
|
||||
flags |= CRN_ALLOW_INVALID;
|
||||
router = router_choose_random_node(intro_routers,
|
||||
options->ExcludeNodes, flags);
|
||||
if (!router) {
|
||||
node = router_choose_random_node(intro_nodes,
|
||||
options->ExcludeNodes, flags);
|
||||
if (!node) {
|
||||
log_warn(LD_REND,
|
||||
"Could only establish %d introduction points for %s.",
|
||||
smartlist_len(service->intro_nodes), service->service_id);
|
||||
break;
|
||||
}
|
||||
changed = 1;
|
||||
smartlist_add(intro_routers, router);
|
||||
smartlist_add(intro_nodes, (void*)node);
|
||||
intro = tor_malloc_zero(sizeof(rend_intro_point_t));
|
||||
intro->extend_info = extend_info_from_router(router);
|
||||
intro->extend_info = extend_info_from_node(node);
|
||||
intro->intro_key = crypto_new_pk_env();
|
||||
tor_assert(!crypto_pk_generate_key(intro->intro_key));
|
||||
smartlist_add(service->intro_nodes, intro);
|
||||
log_info(LD_REND, "Picked router %s as an intro point for %s.",
|
||||
router->nickname, service->service_id);
|
||||
node_get_nickname(node), service->service_id);
|
||||
}
|
||||
|
||||
/* If there's no need to launch new circuits, stop here. */
|
||||
@@ -1872,7 +1873,7 @@ rend_services_introduce(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
smartlist_free(intro_routers);
|
||||
smartlist_free(intro_nodes);
|
||||
}
|
||||
|
||||
/** Regenerate and upload rendezvous service descriptors for all
|
||||
|
||||
+21
-16
@@ -14,6 +14,7 @@
|
||||
#include "circuitlist.h"
|
||||
#include "circuituse.h"
|
||||
#include "config.h"
|
||||
#include "nodelist.h"
|
||||
#include "rephist.h"
|
||||
#include "router.h"
|
||||
#include "routerlist.h"
|
||||
@@ -579,7 +580,7 @@ rep_hist_dump_stats(time_t now, int severity)
|
||||
size_t len;
|
||||
int ret;
|
||||
unsigned long upt, downt;
|
||||
routerinfo_t *r;
|
||||
const node_t *node;
|
||||
|
||||
rep_history_clean(now - get_options()->RephistTrackTime);
|
||||
|
||||
@@ -593,8 +594,8 @@ rep_hist_dump_stats(time_t now, int severity)
|
||||
digestmap_iter_get(orhist_it, &digest1, &or_history_p);
|
||||
or_history = (or_history_t*) or_history_p;
|
||||
|
||||
if ((r = router_get_by_digest(digest1)))
|
||||
name1 = r->nickname;
|
||||
if ((node = node_get_by_id(digest1)) && node_get_nickname(node))
|
||||
name1 = node_get_nickname(node);
|
||||
else
|
||||
name1 = "(unknown)";
|
||||
base16_encode(hexdigest1, sizeof(hexdigest1), digest1, DIGEST_LEN);
|
||||
@@ -624,8 +625,8 @@ rep_hist_dump_stats(time_t now, int severity)
|
||||
lhist_it = digestmap_iter_next(or_history->link_history_map,
|
||||
lhist_it)) {
|
||||
digestmap_iter_get(lhist_it, &digest2, &link_history_p);
|
||||
if ((r = router_get_by_digest(digest2)))
|
||||
name2 = r->nickname;
|
||||
if ((node = node_get_by_id(digest2)) && node_get_nickname(node))
|
||||
name2 = node_get_nickname(node);
|
||||
else
|
||||
name2 = "(unknown)";
|
||||
|
||||
@@ -871,28 +872,32 @@ rep_hist_get_router_stability_doc(time_t now)
|
||||
}
|
||||
|
||||
DIGESTMAP_FOREACH(history_map, id, or_history_t *, hist) {
|
||||
routerinfo_t *ri;
|
||||
const node_t *node;
|
||||
char dbuf[BASE64_DIGEST_LEN+1];
|
||||
char header_buf[512];
|
||||
char *info;
|
||||
digest_to_base64(dbuf, id);
|
||||
ri = router_get_by_digest(id);
|
||||
if (ri) {
|
||||
char *ip = tor_dup_ip(ri->addr);
|
||||
node = node_get_by_id(id);
|
||||
if (node) {
|
||||
char ip[INET_NTOA_BUF_LEN+1];
|
||||
char tbuf[ISO_TIME_LEN+1];
|
||||
format_iso_time(tbuf, ri->cache_info.published_on);
|
||||
time_t published = node_get_published_on(node);
|
||||
node_get_address_string(node,ip,sizeof(ip));
|
||||
if (published > 0)
|
||||
format_iso_time(tbuf, published);
|
||||
else
|
||||
strlcpy(tbuf, "???", sizeof(tbuf));
|
||||
tor_snprintf(header_buf, sizeof(header_buf),
|
||||
"router %s %s %s\n"
|
||||
"published %s\n"
|
||||
"relevant-flags %s%s%s\n"
|
||||
"declared-uptime %ld\n",
|
||||
dbuf, ri->nickname, ip,
|
||||
dbuf, node_get_nickname(node), ip,
|
||||
tbuf,
|
||||
ri->is_running ? "Running " : "",
|
||||
ri->is_valid ? "Valid " : "",
|
||||
ri->is_hibernating ? "Hibernating " : "",
|
||||
ri->uptime);
|
||||
tor_free(ip);
|
||||
node->is_running ? "Running " : "",
|
||||
node->is_valid ? "Valid " : "",
|
||||
node->ri && node->ri->is_hibernating ? "Hibernating " : "",
|
||||
node_get_declared_uptime(node));
|
||||
} else {
|
||||
tor_snprintf(header_buf, sizeof(header_buf),
|
||||
"router %s {no descriptor}\n", dbuf);
|
||||
|
||||
+32
-24
@@ -7,6 +7,7 @@
|
||||
#define ROUTER_PRIVATE
|
||||
|
||||
#include "or.h"
|
||||
#include "circuitbuild.h"
|
||||
#include "circuitlist.h"
|
||||
#include "circuituse.h"
|
||||
#include "config.h"
|
||||
@@ -19,6 +20,7 @@
|
||||
#include "hibernate.h"
|
||||
#include "main.h"
|
||||
#include "networkstatus.h"
|
||||
#include "nodelist.h"
|
||||
#include "policies.h"
|
||||
#include "relay.h"
|
||||
#include "rephist.h"
|
||||
@@ -773,18 +775,21 @@ decide_to_advertise_dirport(or_options_t *options, uint16_t dir_port)
|
||||
void
|
||||
consider_testing_reachability(int test_or, int test_dir)
|
||||
{
|
||||
routerinfo_t *me = router_get_my_routerinfo();
|
||||
const routerinfo_t *me = router_get_my_routerinfo();
|
||||
int orport_reachable = check_whether_orport_reachable();
|
||||
tor_addr_t addr;
|
||||
if (!me)
|
||||
return;
|
||||
|
||||
if (test_or && (!orport_reachable || !circuit_enough_testing_circs())) {
|
||||
extend_info_t *ei;
|
||||
log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.",
|
||||
!orport_reachable ? "reachability" : "bandwidth",
|
||||
me->address, me->or_port);
|
||||
circuit_launch_by_router(CIRCUIT_PURPOSE_TESTING, me,
|
||||
CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
|
||||
ei = extend_info_from_router(me);
|
||||
circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei,
|
||||
CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
|
||||
extend_info_free(ei);
|
||||
}
|
||||
|
||||
tor_addr_from_ipv4h(&addr, me->addr);
|
||||
@@ -808,7 +813,7 @@ void
|
||||
router_orport_found_reachable(void)
|
||||
{
|
||||
if (!can_reach_or_port) {
|
||||
routerinfo_t *me = router_get_my_routerinfo();
|
||||
const routerinfo_t *me = router_get_my_routerinfo();
|
||||
log_notice(LD_OR,"Self-testing indicates your ORPort is reachable from "
|
||||
"the outside. Excellent.%s",
|
||||
get_options()->_PublishServerDescriptor != NO_AUTHORITY ?
|
||||
@@ -831,7 +836,7 @@ void
|
||||
router_dirport_found_reachable(void)
|
||||
{
|
||||
if (!can_reach_dir_port) {
|
||||
routerinfo_t *me = router_get_my_routerinfo();
|
||||
const routerinfo_t *me = router_get_my_routerinfo();
|
||||
log_notice(LD_DIRSERV,"Self-testing indicates your DirPort is reachable "
|
||||
"from the outside. Excellent.");
|
||||
can_reach_dir_port = 1;
|
||||
@@ -1093,7 +1098,7 @@ static int desc_needs_upload = 0;
|
||||
void
|
||||
router_upload_dir_desc_to_dirservers(int force)
|
||||
{
|
||||
routerinfo_t *ri;
|
||||
const routerinfo_t *ri;
|
||||
extrainfo_t *ei;
|
||||
char *msg;
|
||||
size_t desc_len, extra_len = 0, total_len;
|
||||
@@ -1186,7 +1191,7 @@ router_extrainfo_digest_is_me(const char *digest)
|
||||
|
||||
/** A wrapper around router_digest_is_me(). */
|
||||
int
|
||||
router_is_me(routerinfo_t *router)
|
||||
router_is_me(const routerinfo_t *router)
|
||||
{
|
||||
return router_digest_is_me(router->cache_info.identity_digest);
|
||||
}
|
||||
@@ -1205,7 +1210,7 @@ router_fingerprint_is_me(const char *fp)
|
||||
|
||||
/** Return a routerinfo for this OR, rebuilding a fresh one if
|
||||
* necessary. Return NULL on error, or if called on an OP. */
|
||||
routerinfo_t *
|
||||
const routerinfo_t *
|
||||
router_get_my_routerinfo(void)
|
||||
{
|
||||
if (!server_mode(get_options()))
|
||||
@@ -1333,13 +1338,12 @@ router_rebuild_descriptor(int force)
|
||||
ri->policy_is_reject_star =
|
||||
policy_is_reject_star(ri->exit_policy);
|
||||
|
||||
if (desc_routerinfo) { /* inherit values */
|
||||
ri->is_valid = desc_routerinfo->is_valid;
|
||||
ri->is_running = desc_routerinfo->is_running;
|
||||
ri->is_named = desc_routerinfo->is_named;
|
||||
}
|
||||
#if 0
|
||||
/* XXXX NM NM I belive this is safe to remove */
|
||||
if (authdir_mode(options))
|
||||
ri->is_valid = ri->is_named = 1; /* believe in yourself */
|
||||
#endif
|
||||
|
||||
if (options->MyFamily) {
|
||||
smartlist_t *family;
|
||||
if (!warned_nonexistent_family)
|
||||
@@ -1348,13 +1352,12 @@ router_rebuild_descriptor(int force)
|
||||
ri->declared_family = smartlist_create();
|
||||
smartlist_split_string(family, options->MyFamily, ",",
|
||||
SPLIT_SKIP_SPACE|SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
|
||||
SMARTLIST_FOREACH(family, char *, name,
|
||||
{
|
||||
routerinfo_t *member;
|
||||
SMARTLIST_FOREACH_BEGIN(family, char *, name) {
|
||||
const node_t *member;
|
||||
if (!strcasecmp(name, options->Nickname))
|
||||
member = ri;
|
||||
goto skip; /* Don't list ourself, that's redundant */
|
||||
else
|
||||
member = router_get_by_nickname(name, 1);
|
||||
member = node_get_by_nickname(name, 1);
|
||||
if (!member) {
|
||||
int is_legal = is_legal_nickname_or_hexdigest(name);
|
||||
if (!smartlist_string_isin(warned_nonexistent_family, name) &&
|
||||
@@ -1374,19 +1377,21 @@ router_rebuild_descriptor(int force)
|
||||
smartlist_add(ri->declared_family, name);
|
||||
name = NULL;
|
||||
}
|
||||
} else if (router_is_me(member)) {
|
||||
} else if (router_digest_is_me(member->identity)) {
|
||||
/* Don't list ourself in our own family; that's redundant */
|
||||
/* XXX shouldn't be possible */
|
||||
} else {
|
||||
char *fp = tor_malloc(HEX_DIGEST_LEN+2);
|
||||
fp[0] = '$';
|
||||
base16_encode(fp+1,HEX_DIGEST_LEN+1,
|
||||
member->cache_info.identity_digest, DIGEST_LEN);
|
||||
member->identity, DIGEST_LEN);
|
||||
smartlist_add(ri->declared_family, fp);
|
||||
if (smartlist_string_isin(warned_nonexistent_family, name))
|
||||
smartlist_string_remove(warned_nonexistent_family, name);
|
||||
}
|
||||
skip:
|
||||
tor_free(name);
|
||||
});
|
||||
} SMARTLIST_FOREACH_END(name);
|
||||
|
||||
/* remove duplicates from the list */
|
||||
smartlist_sort_strings(ri->declared_family);
|
||||
@@ -1444,8 +1449,6 @@ router_rebuild_descriptor(int force)
|
||||
strlen(ri->cache_info.signed_descriptor_body),
|
||||
ri->cache_info.signed_descriptor_digest);
|
||||
|
||||
routerinfo_set_country(ri);
|
||||
|
||||
tor_assert(! routerinfo_incompatible_with_extrainfo(ri, ei, NULL, NULL));
|
||||
|
||||
routerinfo_free(desc_routerinfo);
|
||||
@@ -2099,10 +2102,15 @@ is_legal_hexdigest(const char *s)
|
||||
void
|
||||
router_get_verbose_nickname(char *buf, const routerinfo_t *router)
|
||||
{
|
||||
const char *good_digest = networkstatus_get_router_digest_by_nickname(
|
||||
router->nickname);
|
||||
int is_named = good_digest && !memcmp(good_digest,
|
||||
router->cache_info.identity_digest,
|
||||
DIGEST_LEN);
|
||||
buf[0] = '$';
|
||||
base16_encode(buf+1, HEX_DIGEST_LEN+1, router->cache_info.identity_digest,
|
||||
DIGEST_LEN);
|
||||
buf[1+HEX_DIGEST_LEN] = router->is_named ? '=' : '~';
|
||||
buf[1+HEX_DIGEST_LEN] = is_named ? '=' : '~';
|
||||
strlcpy(buf+1+HEX_DIGEST_LEN+1, router->nickname, MAX_NICKNAME_LEN+1);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -62,12 +62,12 @@ void router_new_address_suggestion(const char *suggestion,
|
||||
const dir_connection_t *d_conn);
|
||||
int router_compare_to_my_exit_policy(edge_connection_t *conn);
|
||||
int router_my_exit_policy_is_reject_star(void);
|
||||
routerinfo_t *router_get_my_routerinfo(void);
|
||||
const routerinfo_t *router_get_my_routerinfo(void);
|
||||
extrainfo_t *router_get_my_extrainfo(void);
|
||||
const char *router_get_my_descriptor(void);
|
||||
int router_digest_is_me(const char *digest);
|
||||
int router_extrainfo_digest_is_me(const char *digest);
|
||||
int router_is_me(routerinfo_t *router);
|
||||
int router_is_me(const routerinfo_t *router);
|
||||
int router_fingerprint_is_me(const char *fp);
|
||||
int router_pick_published_address(or_options_t *options, uint32_t *addr);
|
||||
int router_rebuild_descriptor(int force);
|
||||
|
||||
+534
-430
File diff suppressed because it is too large
Load Diff
+48
-40
@@ -27,37 +27,34 @@ int router_reload_router_list(void);
|
||||
int authority_cert_dl_looks_uncertain(const char *id_digest);
|
||||
smartlist_t *router_get_trusted_dir_servers(void);
|
||||
|
||||
routerstatus_t *router_pick_directory_server(authority_type_t type, int flags);
|
||||
const routerstatus_t *router_pick_directory_server(authority_type_t type,
|
||||
int flags);
|
||||
trusted_dir_server_t *router_get_trusteddirserver_by_digest(const char *d);
|
||||
trusted_dir_server_t *trusteddirserver_get_by_v3_auth_digest(const char *d);
|
||||
routerstatus_t *router_pick_trusteddirserver(authority_type_t type, int flags);
|
||||
const routerstatus_t *router_pick_trusteddirserver(authority_type_t type,
|
||||
int flags);
|
||||
int router_get_my_share_of_directory_requests(double *v2_share_out,
|
||||
double *v3_share_out);
|
||||
void router_reset_status_download_failures(void);
|
||||
void routerlist_add_family(smartlist_t *sl, routerinfo_t *router);
|
||||
int routers_in_same_family(routerinfo_t *r1, routerinfo_t *r2);
|
||||
void routerlist_add_family(smartlist_t *sl, const routerinfo_t *router);
|
||||
int routers_have_same_or_addr(const routerinfo_t *r1, const routerinfo_t *r2);
|
||||
void add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
|
||||
int must_be_running);
|
||||
int router_nickname_is_in_list(routerinfo_t *router, const char *list);
|
||||
routerinfo_t *routerlist_find_my_routerinfo(void);
|
||||
routerinfo_t *router_find_exact_exit_enclave(const char *address,
|
||||
int router_nickname_is_in_list(const routerinfo_t *router, const char *list);
|
||||
const routerinfo_t *routerlist_find_my_routerinfo(void);
|
||||
const node_t *router_find_exact_exit_enclave(const char *address,
|
||||
uint16_t port);
|
||||
int router_is_unreliable(routerinfo_t *router, int need_uptime,
|
||||
int node_is_unreliable(const node_t *router, int need_uptime,
|
||||
int need_capacity, int need_guard);
|
||||
uint32_t router_get_advertised_bandwidth(routerinfo_t *router);
|
||||
uint32_t router_get_advertised_bandwidth_capped(routerinfo_t *router);
|
||||
uint32_t router_get_advertised_bandwidth(const routerinfo_t *router);
|
||||
uint32_t router_get_advertised_bandwidth_capped(const routerinfo_t *router);
|
||||
|
||||
routerinfo_t *routerlist_sl_choose_by_bandwidth(smartlist_t *sl,
|
||||
bandwidth_weight_rule_t rule);
|
||||
routerstatus_t *routerstatus_sl_choose_by_bandwidth(smartlist_t *sl,
|
||||
bandwidth_weight_rule_t rule);
|
||||
const node_t *node_sl_choose_by_bandwidth(smartlist_t *sl,
|
||||
bandwidth_weight_rule_t rule);
|
||||
|
||||
routerinfo_t *router_choose_random_node(smartlist_t *excludedsmartlist,
|
||||
const node_t *router_choose_random_node(smartlist_t *excludedsmartlist,
|
||||
struct routerset_t *excludedset,
|
||||
router_crn_flags_t flags);
|
||||
|
||||
routerinfo_t *router_get_by_nickname(const char *nickname,
|
||||
const routerinfo_t *router_get_by_nickname(const char *nickname,
|
||||
int warn_if_unnamed);
|
||||
int router_digest_version_as_new_as(const char *digest, const char *cutoff);
|
||||
int router_digest_is_trusted_dir_type(const char *digest,
|
||||
@@ -67,13 +64,14 @@ int router_digest_is_trusted_dir_type(const char *digest,
|
||||
|
||||
int router_addr_is_trusted_dir(uint32_t addr);
|
||||
int hexdigest_to_digest(const char *hexdigest, char *digest);
|
||||
routerinfo_t *router_get_by_hexdigest(const char *hexdigest);
|
||||
routerinfo_t *router_get_by_digest(const char *digest);
|
||||
const routerinfo_t *router_get_by_hexdigest(const char *hexdigest);
|
||||
const routerinfo_t *router_get_by_digest(const char *digest);
|
||||
routerinfo_t *router_get_mutable_by_digest(const char *digest);
|
||||
signed_descriptor_t *router_get_by_descriptor_digest(const char *digest);
|
||||
signed_descriptor_t *router_get_by_extrainfo_digest(const char *digest);
|
||||
signed_descriptor_t *extrainfo_get_by_descriptor_digest(const char *digest);
|
||||
const char *signed_descriptor_get_body(signed_descriptor_t *desc);
|
||||
const char *signed_descriptor_get_annotations(signed_descriptor_t *desc);
|
||||
const char *signed_descriptor_get_body(const signed_descriptor_t *desc);
|
||||
const char *signed_descriptor_get_annotations(const signed_descriptor_t *desc);
|
||||
routerlist_t *router_get_routerlist(void);
|
||||
void routerinfo_free(routerinfo_t *router);
|
||||
void extrainfo_free(extrainfo_t *extrainfo);
|
||||
@@ -132,9 +130,10 @@ void router_load_extrainfo_from_string(const char *s, const char *eos,
|
||||
int descriptor_digests);
|
||||
|
||||
void routerlist_retry_directory_downloads(time_t now);
|
||||
int router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port,
|
||||
int need_uptime);
|
||||
int router_exit_policy_rejects_all(routerinfo_t *router);
|
||||
int router_exit_policy_all_nodes_reject(uint32_t addr, uint16_t port,
|
||||
int need_uptime);
|
||||
|
||||
int router_exit_policy_rejects_all(const routerinfo_t *router);
|
||||
trusted_dir_server_t *add_trusted_dir_server(const char *nickname,
|
||||
const char *address,
|
||||
uint16_t dir_port, uint16_t or_port,
|
||||
@@ -152,39 +151,43 @@ void router_dir_info_changed(void);
|
||||
const char *get_dir_info_status_string(void);
|
||||
int count_loading_descriptors_progress(void);
|
||||
void router_reset_descriptor_download_failures(void);
|
||||
int router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2);
|
||||
int routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei,
|
||||
int router_differences_are_cosmetic(const routerinfo_t *r1,
|
||||
const routerinfo_t *r2);
|
||||
int routerinfo_incompatible_with_extrainfo(const routerinfo_t *ri,
|
||||
extrainfo_t *ei,
|
||||
signed_descriptor_t *sd,
|
||||
const char **msg);
|
||||
|
||||
void routerlist_assert_ok(routerlist_t *rl);
|
||||
const char *esc_router_info(routerinfo_t *router);
|
||||
void routerlist_assert_ok(const routerlist_t *rl);
|
||||
const char *esc_router_info(const routerinfo_t *router);
|
||||
void routers_sort_by_identity(smartlist_t *routers);
|
||||
|
||||
routerset_t *routerset_new(void);
|
||||
void routerset_refresh_countries(routerset_t *rs);
|
||||
int routerset_parse(routerset_t *target, const char *s,
|
||||
const char *description);
|
||||
void routerset_union(routerset_t *target, const routerset_t *source);
|
||||
int routerset_is_list(const routerset_t *set);
|
||||
int routerset_needs_geoip(const routerset_t *set);
|
||||
int routerset_contains_router(const routerset_t *set, routerinfo_t *ri);
|
||||
int routerset_contains_router(const routerset_t *set, const routerinfo_t *ri,
|
||||
country_t country);
|
||||
int routerset_contains_routerstatus(const routerset_t *set,
|
||||
routerstatus_t *rs);
|
||||
const routerstatus_t *rs,
|
||||
country_t country);
|
||||
int routerset_contains_extendinfo(const routerset_t *set,
|
||||
const extend_info_t *ei);
|
||||
void routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset,
|
||||
int running_only);
|
||||
void routersets_get_disjunction(smartlist_t *target, const smartlist_t *source,
|
||||
int routerset_contains_node(const routerset_t *set, const node_t *node);
|
||||
void routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset,
|
||||
int running_only);
|
||||
void routersets_get_node_disjunction(smartlist_t *target,
|
||||
const smartlist_t *source,
|
||||
const routerset_t *include,
|
||||
const routerset_t *exclude, int running_only);
|
||||
void routerset_subtract_routers(smartlist_t *out,
|
||||
const routerset_t *routerset);
|
||||
void routerset_subtract_nodes(smartlist_t *out,
|
||||
const routerset_t *routerset);
|
||||
char *routerset_to_string(const routerset_t *routerset);
|
||||
void routerset_refresh_countries(routerset_t *target);
|
||||
int routerset_equal(const routerset_t *old, const routerset_t *new);
|
||||
void routerset_free(routerset_t *routerset);
|
||||
void routerinfo_set_country(routerinfo_t *ri);
|
||||
void routerlist_refresh_countries(void);
|
||||
void refresh_all_country_info(void);
|
||||
|
||||
int hid_serv_get_responsible_directories(smartlist_t *responsible_dirs,
|
||||
@@ -195,8 +198,13 @@ int hid_serv_responsible_for_desc_id(const char *id);
|
||||
void list_pending_microdesc_downloads(digestmap_t *result);
|
||||
void launch_descriptor_downloads(int purpose,
|
||||
smartlist_t *downloadable,
|
||||
routerstatus_t *source,
|
||||
const routerstatus_t *source,
|
||||
time_t now);
|
||||
|
||||
int hex_digest_nickname_decode(const char *hexdigest,
|
||||
char *digest_out,
|
||||
char *nickname_qualifier_out,
|
||||
char *nickname_out);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1344,7 +1344,6 @@ router_parse_entry_from_string(const char *s, const char *end,
|
||||
tor_assert(tok->n_args >= 5);
|
||||
|
||||
router = tor_malloc_zero(sizeof(routerinfo_t));
|
||||
router->country = -1;
|
||||
router->cache_info.routerlist_index = -1;
|
||||
router->cache_info.annotations_len = s-start_of_annotations + prepend_len;
|
||||
router->cache_info.signed_descriptor_len = end-s;
|
||||
@@ -1543,8 +1542,6 @@ router_parse_entry_from_string(const char *s, const char *end,
|
||||
"router descriptor") < 0)
|
||||
goto err;
|
||||
|
||||
routerinfo_set_country(router);
|
||||
|
||||
if (!router->or_port) {
|
||||
log_warn(LD_DIR,"or_port unreadable or 0. Failing.");
|
||||
goto err;
|
||||
@@ -2030,7 +2027,7 @@ routerstatus_parse_entry_from_string(memarea_t *area,
|
||||
else if (!strcmp(tok->args[i], "Fast"))
|
||||
rs->is_fast = 1;
|
||||
else if (!strcmp(tok->args[i], "Running"))
|
||||
rs->is_running = 1;
|
||||
rs->is_flagged_running = 1;
|
||||
else if (!strcmp(tok->args[i], "Named"))
|
||||
rs->is_named = 1;
|
||||
else if (!strcmp(tok->args[i], "Valid"))
|
||||
@@ -4305,7 +4302,7 @@ microdescs_parse_from_string(const char *s, const char *eos,
|
||||
}
|
||||
|
||||
if ((tok = find_opt_by_keyword(tokens, K_P))) {
|
||||
md->exitsummary = tor_strdup(tok->args[0]);
|
||||
md->exit_policy = parse_short_policy(tok->args[0]);
|
||||
}
|
||||
|
||||
crypto_digest256(md->digest, md->body, md->bodylen, DIGEST_SHA256);
|
||||
|
||||
@@ -576,6 +576,7 @@ test_policy_summary_helper(const char *policy_str,
|
||||
smartlist_t *policy = smartlist_create();
|
||||
char *summary = NULL;
|
||||
int r;
|
||||
short_policy_t *short_policy = NULL;
|
||||
|
||||
line.key = (char*)"foo";
|
||||
line.value = (char *)policy_str;
|
||||
@@ -588,10 +589,14 @@ test_policy_summary_helper(const char *policy_str,
|
||||
test_assert(summary != NULL);
|
||||
test_streq(summary, expected_summary);
|
||||
|
||||
short_policy = parse_short_policy(summary);
|
||||
tt_assert(short_policy);
|
||||
|
||||
done:
|
||||
tor_free(summary);
|
||||
if (policy)
|
||||
addr_policy_list_free(policy);
|
||||
short_policy_free(short_policy);
|
||||
}
|
||||
|
||||
/** Run unit tests for generating summary lines of exit policies */
|
||||
|
||||
+7
-5
@@ -801,7 +801,7 @@ test_dir_v3_networkstatus(void)
|
||||
rs->or_port = 443;
|
||||
rs->dir_port = 8000;
|
||||
/* all flags but running cleared */
|
||||
rs->is_running = 1;
|
||||
rs->is_flagged_running = 1;
|
||||
smartlist_add(vote->routerstatus_list, vrs);
|
||||
test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0);
|
||||
|
||||
@@ -816,7 +816,7 @@ test_dir_v3_networkstatus(void)
|
||||
rs->addr = 0x99009901;
|
||||
rs->or_port = 443;
|
||||
rs->dir_port = 0;
|
||||
rs->is_exit = rs->is_stable = rs->is_fast = rs->is_running =
|
||||
rs->is_exit = rs->is_stable = rs->is_fast = rs->is_flagged_running =
|
||||
rs->is_valid = rs->is_v2_dir = rs->is_possible_guard = 1;
|
||||
smartlist_add(vote->routerstatus_list, vrs);
|
||||
test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0);
|
||||
@@ -833,7 +833,8 @@ test_dir_v3_networkstatus(void)
|
||||
rs->or_port = 400;
|
||||
rs->dir_port = 9999;
|
||||
rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast =
|
||||
rs->is_running = rs->is_valid = rs->is_v2_dir = rs->is_possible_guard = 1;
|
||||
rs->is_flagged_running = rs->is_valid = rs->is_v2_dir =
|
||||
rs->is_possible_guard = 1;
|
||||
smartlist_add(vote->routerstatus_list, vrs);
|
||||
test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0);
|
||||
|
||||
@@ -1073,7 +1074,8 @@ test_dir_v3_networkstatus(void)
|
||||
test_assert(!rs->is_fast);
|
||||
test_assert(!rs->is_possible_guard);
|
||||
test_assert(!rs->is_stable);
|
||||
test_assert(rs->is_running); /* If it wasn't running it wouldn't be here */
|
||||
/* (If it wasn't running it wouldn't be here) */
|
||||
test_assert(rs->is_flagged_running);
|
||||
test_assert(!rs->is_v2_dir);
|
||||
test_assert(!rs->is_valid);
|
||||
test_assert(!rs->is_named);
|
||||
@@ -1095,7 +1097,7 @@ test_dir_v3_networkstatus(void)
|
||||
test_assert(rs->is_fast);
|
||||
test_assert(rs->is_possible_guard);
|
||||
test_assert(rs->is_stable);
|
||||
test_assert(rs->is_running);
|
||||
test_assert(rs->is_flagged_running);
|
||||
test_assert(rs->is_v2_dir);
|
||||
test_assert(rs->is_valid);
|
||||
test_assert(!rs->is_named);
|
||||
|
||||
Reference in New Issue
Block a user