mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Finish implementing config's EntryNodes and StrictEntryNodes option.
The logging is way verbose for now. svn:r5683
This commit is contained in:
+127
-45
@@ -109,7 +109,7 @@ circuit_list_path(circuit_t *circ, int verbose)
|
||||
|
||||
if (verbose) {
|
||||
const char *nickname = build_state_get_exit_nickname(circ->build_state);
|
||||
tor_snprintf(buf, sizeof(buf)-1, "%s%s circ (length %d%s%s):",
|
||||
tor_snprintf(buf, sizeof(buf), "%s%s circ (length %d%s%s):",
|
||||
circ->build_state->is_internal ? "internal" : "exit",
|
||||
circ->build_state->need_uptime ? " (high-uptime)" : "",
|
||||
circ->build_state->desired_path_len,
|
||||
@@ -1115,14 +1115,10 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
|
||||
int n_connections;
|
||||
int best_support = -1;
|
||||
int n_best_support=0;
|
||||
smartlist_t *sl, *preferredexits, *preferredentries, *excludedexits;
|
||||
smartlist_t *sl, *preferredexits, *excludedexits;
|
||||
routerinfo_t *router;
|
||||
or_options_t *options = get_options();
|
||||
|
||||
//XXX
|
||||
preferredentries = smartlist_create();
|
||||
add_nickname_list_to_smartlist(preferredentries,options->EntryNodes,1,1);
|
||||
|
||||
get_connection_array(&carray, &n_connections);
|
||||
|
||||
/* Count how many connections are waiting for a circuit to be built.
|
||||
@@ -1176,13 +1172,6 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
|
||||
// router->nickname, i);
|
||||
continue; /* skip routers that reject all */
|
||||
}
|
||||
if (smartlist_len(preferredentries)==1 &&
|
||||
router == (routerinfo_t*)smartlist_get(preferredentries, 0)) {
|
||||
n_supported[i] = -1;
|
||||
// log_fn(LOG_DEBUG, "Skipping node %s (index %d) -- it's our only "
|
||||
// "preferred entry node.", router->nickname, i);
|
||||
continue;
|
||||
}
|
||||
n_supported[i] = 0;
|
||||
for (j = 0; j < n_connections; ++j) { /* iterate over connections */
|
||||
if (!ap_stream_wants_exit_attention(carray[j]))
|
||||
@@ -1213,10 +1202,10 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
|
||||
n_best_support, best_support, n_pending_connections);
|
||||
|
||||
preferredexits = smartlist_create();
|
||||
add_nickname_list_to_smartlist(preferredexits,options->ExitNodes,1,1);
|
||||
add_nickname_list_to_smartlist(preferredexits,options->ExitNodes,1,1,1);
|
||||
|
||||
excludedexits = smartlist_create();
|
||||
add_nickname_list_to_smartlist(excludedexits,options->ExcludeNodes,0,1);
|
||||
add_nickname_list_to_smartlist(excludedexits,options->ExcludeNodes,0,0,1);
|
||||
|
||||
sl = smartlist_create();
|
||||
|
||||
@@ -1277,7 +1266,6 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
|
||||
}
|
||||
|
||||
smartlist_free(preferredexits);
|
||||
smartlist_free(preferredentries);
|
||||
smartlist_free(excludedexits);
|
||||
smartlist_free(sl);
|
||||
tor_free(n_supported);
|
||||
@@ -1741,7 +1729,7 @@ num_live_entry_nodes(void)
|
||||
/** Return 1 if <b>digest</b> matches the identity of any node
|
||||
* in the entry_nodes list. Else return 0. */
|
||||
static INLINE int
|
||||
is_an_entry(char *digest)
|
||||
is_an_entry_node(char *digest)
|
||||
{
|
||||
SMARTLIST_FOREACH(entry_nodes, entry_node_t *, entry,
|
||||
if(!memcmp(digest, entry->identity, DIGEST_LEN))
|
||||
@@ -1750,22 +1738,47 @@ is_an_entry(char *digest)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
log_entry_nodes(int severity)
|
||||
{
|
||||
smartlist_t *elements = smartlist_create();
|
||||
char buf[1024];
|
||||
char *s;
|
||||
|
||||
SMARTLIST_FOREACH(entry_nodes, entry_node_t *, e,
|
||||
{
|
||||
tor_snprintf(buf, sizeof(buf), "%s (%s%s%s)",
|
||||
e->nickname,
|
||||
e->down_since ? "down " : "up ",
|
||||
e->unlisted_since ? "unlisted " : "listed ",
|
||||
e->made_contact ? "made-contact" : "never-contacted");
|
||||
smartlist_add(elements, tor_strdup(buf));
|
||||
});
|
||||
|
||||
s = smartlist_join_strings(elements, ",", 0, NULL);
|
||||
SMARTLIST_FOREACH(elements, char*, cp, tor_free(cp));
|
||||
smartlist_free(elements);
|
||||
log_fn(severity,LD_CIRC,"%s",s);
|
||||
tor_free(s);
|
||||
}
|
||||
|
||||
#define NUM_ENTRY_PICK_TRIES 100
|
||||
|
||||
/** Add a new (preferably stable and fast) entry to our
|
||||
* entry_nodes list. Return a pointer to the router if we succeed,
|
||||
* or NULL if we can't find any more suitable entries. If
|
||||
* <b>tries_left</b> is <= 1, that means you should fail.
|
||||
* or NULL if we can't find any more suitable entries.
|
||||
*
|
||||
* [not implemented yet]
|
||||
* If <b>chosen</b> is defined, use that one, and put it at
|
||||
* the *beginning* of our entry_nodes list. Else, put the one
|
||||
* we pick at the end of the list. */
|
||||
* If <b>chosen</b> is defined, use that one, and if it's not
|
||||
* already in our entry_nodes list, put it at the *beginning*.
|
||||
* Else, put the one we pick at the end of the list. */
|
||||
static routerinfo_t *
|
||||
add_an_entry(routerinfo_t *chosen, int tries_left)
|
||||
add_an_entry_node(routerinfo_t *chosen)
|
||||
{
|
||||
routerinfo_t *router;
|
||||
entry_node_t *entry;
|
||||
int tries_left = NUM_ENTRY_PICK_TRIES;
|
||||
|
||||
again:
|
||||
if (--tries_left <= 0) {
|
||||
warn(LD_CIRC, "Tried finding a new entry, but failed. Bad news. XXX.");
|
||||
return NULL;
|
||||
@@ -1777,14 +1790,21 @@ add_an_entry(routerinfo_t *chosen, int tries_left)
|
||||
if (!router)
|
||||
return NULL;
|
||||
/* make sure it's not already an entry */
|
||||
if (is_an_entry(router->cache_info.identity_digest))
|
||||
return chosen ? NULL : add_an_entry(NULL, tries_left); /* recurse */
|
||||
if (is_an_entry_node(router->cache_info.identity_digest)) {
|
||||
if (chosen)
|
||||
return NULL;
|
||||
goto again;
|
||||
}
|
||||
entry = tor_malloc_zero(sizeof(entry_node_t));
|
||||
/* XXXX Downgrade this to info before release. NM */
|
||||
notice(LD_CIRC, "Chose '%s' as new entry node.", router->nickname);
|
||||
strlcpy(entry->nickname, router->nickname, sizeof(entry->nickname));
|
||||
memcpy(entry->identity, router->cache_info.identity_digest, DIGEST_LEN);
|
||||
smartlist_add(entry_nodes, entry);
|
||||
if (chosen)
|
||||
smartlist_insert(entry_nodes, 0, entry);
|
||||
else
|
||||
smartlist_add(entry_nodes, entry);
|
||||
log_entry_nodes(LOG_NOTICE);
|
||||
return router;
|
||||
}
|
||||
|
||||
@@ -1796,13 +1816,10 @@ pick_entry_nodes(void)
|
||||
or_options_t *options = get_options();
|
||||
int changed = 0;
|
||||
|
||||
if (!entry_nodes)
|
||||
entry_nodes = smartlist_create();
|
||||
|
||||
/* XXX this is where we prepend options->EntryNodes? */
|
||||
tor_assert(entry_nodes);
|
||||
|
||||
while (num_live_entry_nodes() < options->NumEntryNodes) {
|
||||
if (!add_an_entry(NULL, NUM_ENTRY_PICK_TRIES))
|
||||
if (!add_an_entry_node(NULL))
|
||||
break;
|
||||
changed = 1;
|
||||
}
|
||||
@@ -1862,6 +1879,7 @@ remove_dead_entries(void)
|
||||
entry->nickname, dbuf, why, tbuf);
|
||||
tor_free(entry);
|
||||
smartlist_del_keeporder(entry_nodes, i);
|
||||
log_entry_nodes(LOG_NOTICE);
|
||||
changed = 1;
|
||||
} else
|
||||
++i;
|
||||
@@ -1941,6 +1959,7 @@ entry_nodes_set_status_from_directory(void)
|
||||
if (changed) {
|
||||
log_fn(severity, LD_CIRC, " (%d/%d entries are usable/new)",
|
||||
num_live_entry_nodes(), smartlist_len(entry_nodes));
|
||||
log_entry_nodes(severity);
|
||||
entry_nodes_changed();
|
||||
}
|
||||
}
|
||||
@@ -1987,6 +2006,7 @@ entry_node_set_status(const char *digest, int succeeded)
|
||||
"Connected to new entry node '%s'. Marking earlier "
|
||||
"entries up. %d/%d entries usable/new.", entry->nickname,
|
||||
num_live_entry_nodes(), smartlist_len(entry_nodes));
|
||||
log_entry_nodes(LOG_NOTICE);
|
||||
changed = 1;
|
||||
}
|
||||
if (entry->down_since) {
|
||||
@@ -1996,6 +2016,7 @@ entry_node_set_status(const char *digest, int succeeded)
|
||||
"%d/%d entry nodes usable/new.", entry->nickname,
|
||||
num_live_entry_nodes(), smartlist_len(entry_nodes));
|
||||
entry->down_since = 0;
|
||||
log_entry_nodes(LOG_NOTICE);
|
||||
changed = 1;
|
||||
}
|
||||
} else {
|
||||
@@ -2007,6 +2028,7 @@ entry_node_set_status(const char *digest, int succeeded)
|
||||
num_live_entry_nodes()-1, smartlist_len(entry_nodes)-1);
|
||||
tor_free(entry);
|
||||
smartlist_del_keeporder(entry_nodes, entry_sl_idx);
|
||||
log_entry_nodes(LOG_NOTICE);
|
||||
changed = 1;
|
||||
} else if (!entry->down_since) {
|
||||
entry->down_since = time(NULL);
|
||||
@@ -2014,6 +2036,7 @@ entry_node_set_status(const char *digest, int succeeded)
|
||||
" %d/%d entry nodes usable/new.",
|
||||
entry->nickname,
|
||||
num_live_entry_nodes(), smartlist_len(entry_nodes));
|
||||
log_entry_nodes(LOG_NOTICE);
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
@@ -2025,20 +2048,78 @@ entry_node_set_status(const char *digest, int succeeded)
|
||||
return refuse_conn ? -1 : 0;
|
||||
}
|
||||
|
||||
/** When we try to choose an entry node, should we parse and add
|
||||
* config's EntryNodes first? */
|
||||
static int should_add_entry_nodes = 0;
|
||||
|
||||
void
|
||||
entry_nodes_should_be_added(void)
|
||||
{
|
||||
notice(LD_CIRC, "New EntryNodes config option detected. Will use.");
|
||||
should_add_entry_nodes = 1;
|
||||
}
|
||||
|
||||
void
|
||||
entry_nodes_prepend_from_config(void)
|
||||
{
|
||||
int missed_some = 0;
|
||||
int idx;
|
||||
or_options_t *options = get_options();
|
||||
smartlist_t *routers = smartlist_create();
|
||||
|
||||
tor_assert(entry_nodes);
|
||||
|
||||
add_nickname_list_to_smartlist(routers, options->EntryNodes,
|
||||
0, 1, 1);
|
||||
|
||||
/* take a moment first to notice whether we got them all */
|
||||
if (options->EntryNodes) {
|
||||
notice(LD_CIRC,"Adding configured EntryNodes '%s'.",
|
||||
options->EntryNodes);
|
||||
smartlist_t *tmp = smartlist_create();
|
||||
smartlist_split_string(tmp, options->EntryNodes, ",",
|
||||
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
|
||||
missed_some = smartlist_len(routers) != smartlist_len(tmp);
|
||||
SMARTLIST_FOREACH(tmp, char *, nick, tor_free(nick));
|
||||
smartlist_free(tmp);
|
||||
}
|
||||
|
||||
for (idx = smartlist_len(routers)-1 ; idx >= 0; idx--) {
|
||||
/* pick off the last one, turn it into a router, prepend it
|
||||
* to our entry_nodes list. If we can't find it, set missed_some
|
||||
* to 1. */
|
||||
routerinfo_t *r = smartlist_get(routers, idx);
|
||||
add_an_entry_node(r);
|
||||
}
|
||||
|
||||
if (!missed_some)
|
||||
should_add_entry_nodes = 0; /* whew, we're done */
|
||||
|
||||
smartlist_free(routers);
|
||||
}
|
||||
|
||||
/** Pick a live (up and listed) entry node from entry_nodes, and
|
||||
* make sure not to pick this circuit's exit. */
|
||||
static routerinfo_t *
|
||||
choose_random_entry(cpath_build_state_t *state)
|
||||
{
|
||||
or_options_t *options = get_options();
|
||||
smartlist_t *live_entry_nodes = smartlist_create();
|
||||
routerinfo_t *chosen_exit = build_state_get_exit_router(state);
|
||||
routerinfo_t *r;
|
||||
routerinfo_t *r = NULL;
|
||||
int need_uptime = state->need_uptime;
|
||||
int need_capacity = state->need_capacity;
|
||||
|
||||
if (!entry_nodes)
|
||||
entry_nodes = smartlist_create();
|
||||
|
||||
if (should_add_entry_nodes)
|
||||
entry_nodes_prepend_from_config();
|
||||
|
||||
if (! entry_nodes ||
|
||||
smartlist_len(entry_nodes) < get_options()->NumEntryNodes)
|
||||
pick_entry_nodes();
|
||||
smartlist_len(entry_nodes) < options->NumEntryNodes)
|
||||
if (!options->StrictEntryNodes)
|
||||
pick_entry_nodes();
|
||||
|
||||
retry:
|
||||
smartlist_clear(live_entry_nodes);
|
||||
@@ -2047,7 +2128,7 @@ choose_random_entry(cpath_build_state_t *state)
|
||||
r = entry_is_live(entry, need_uptime, need_capacity);
|
||||
if (r && r != chosen_exit) {
|
||||
smartlist_add(live_entry_nodes, r);
|
||||
if (smartlist_len(live_entry_nodes) >= get_options()->NumEntryNodes)
|
||||
if (smartlist_len(live_entry_nodes) >= options->NumEntryNodes)
|
||||
break; /* we have enough */
|
||||
}
|
||||
});
|
||||
@@ -2061,19 +2142,20 @@ choose_random_entry(cpath_build_state_t *state)
|
||||
need_uptime = 0; /* try without that requirement */
|
||||
goto retry;
|
||||
}
|
||||
/* still no? try adding a new entry then */
|
||||
r = add_an_entry(NULL, NUM_ENTRY_PICK_TRIES);
|
||||
if (r) {
|
||||
smartlist_add(live_entry_nodes, r);
|
||||
entry_nodes_changed();
|
||||
} else {
|
||||
if (need_capacity) {
|
||||
if (!options->StrictEntryNodes) {
|
||||
/* still no? try adding a new entry then */
|
||||
r = add_an_entry_node(NULL);
|
||||
if (r) {
|
||||
smartlist_add(live_entry_nodes, r);
|
||||
entry_nodes_changed();
|
||||
}
|
||||
}
|
||||
if (!r && need_capacity) {
|
||||
/* still no? last attempt, try without requiring capacity */
|
||||
need_capacity = 0;
|
||||
goto retry;
|
||||
}
|
||||
/* live_entry_nodes will be empty below. Oh well, we tried. */
|
||||
}
|
||||
/* live_entry_nodes will be empty below. Oh well, we tried. */
|
||||
}
|
||||
|
||||
r = smartlist_choose(live_entry_nodes);
|
||||
|
||||
@@ -701,6 +701,11 @@ options_act(or_options_t *old_options)
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we need to parse and add the EntryNodes config option. */
|
||||
if (!old_options ||
|
||||
!opt_streq(old_options->EntryNodes, options->EntryNodes))
|
||||
entry_nodes_should_be_added();
|
||||
|
||||
/* Since our options changed, we might need to regenerate and upload our
|
||||
* server descriptor.
|
||||
*/
|
||||
|
||||
+4
-1
@@ -1469,8 +1469,10 @@ void extend_info_free(extend_info_t *info);
|
||||
routerinfo_t *build_state_get_exit_router(cpath_build_state_t *state);
|
||||
const char *build_state_get_exit_nickname(cpath_build_state_t *state);
|
||||
|
||||
int entry_node_set_status(const char *digest, int succeeded);
|
||||
void entry_nodes_set_status_from_directory(void);
|
||||
int entry_node_set_status(const char *digest, int succeeded);
|
||||
void entry_nodes_should_be_added(void);
|
||||
void entry_nodes_prepend_from_config(void);
|
||||
void entry_nodes_update_state(or_state_t *state);
|
||||
int entry_nodes_parse_state(or_state_t *state, int set, const char **err);
|
||||
int entry_nodes_getinfo(const char *question, char **answer);
|
||||
@@ -2235,6 +2237,7 @@ trusted_dir_server_t *router_get_trusteddirserver_by_digest(
|
||||
int all_trusted_directory_servers_down(void);
|
||||
void routerlist_add_family(smartlist_t *sl, routerinfo_t *router);
|
||||
void add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
|
||||
int must_be_running,
|
||||
int warn_if_down, int warn_if_unnamed);
|
||||
routerinfo_t *routerlist_find_my_routerinfo(void);
|
||||
int exit_policy_implicitly_allows_local_networks(addr_policy_t *policy,
|
||||
|
||||
+6
-5
@@ -559,7 +559,7 @@ routerlist_add_family(smartlist_t *sl, routerinfo_t *router)
|
||||
/* If the user declared any families locally, honor those too. */
|
||||
for (cl = get_options()->NodeFamilies; cl; cl = cl->next) {
|
||||
if (router_nickname_is_in_list(router, cl->value)) {
|
||||
add_nickname_list_to_smartlist(sl, cl->value, 1, 1);
|
||||
add_nickname_list_to_smartlist(sl, cl->value, 0, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -570,6 +570,7 @@ routerlist_add_family(smartlist_t *sl, routerinfo_t *router)
|
||||
*/
|
||||
void
|
||||
add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
|
||||
int must_be_running,
|
||||
int warn_if_down, int warn_if_unnamed)
|
||||
{
|
||||
routerinfo_t *router;
|
||||
@@ -590,13 +591,13 @@ add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
|
||||
SMARTLIST_FOREACH(nickname_list, const char *, nick, {
|
||||
int warned;
|
||||
if (!is_legal_nickname_or_hexdigest(nick)) {
|
||||
warn(LD_CONFIG, "Nickname %s is misformed; skipping", nick);
|
||||
warn(LD_CONFIG, "Nickname '%s' is misformed; skipping", nick);
|
||||
continue;
|
||||
}
|
||||
router = router_get_by_nickname(nick, warn_if_unnamed);
|
||||
warned = smartlist_string_isin(warned_nicknames, nick);
|
||||
if (router) {
|
||||
if (router->is_running) {
|
||||
if (!must_be_running || router->is_running) {
|
||||
smartlist_add(sl,router);
|
||||
if (warned)
|
||||
smartlist_string_remove(warned_nicknames, nick);
|
||||
@@ -811,12 +812,12 @@ router_choose_random_node(const char *preferred,
|
||||
routerinfo_t *choice;
|
||||
|
||||
excludednodes = smartlist_create();
|
||||
add_nickname_list_to_smartlist(excludednodes,excluded,0,1);
|
||||
add_nickname_list_to_smartlist(excludednodes,excluded,0,0,1);
|
||||
|
||||
/* Try the preferred nodes first. Ignore need_uptime and need_capacity,
|
||||
* since the user explicitly asked for these nodes. */
|
||||
sl = smartlist_create();
|
||||
add_nickname_list_to_smartlist(sl,preferred,1,1);
|
||||
add_nickname_list_to_smartlist(sl,preferred,1,1,1);
|
||||
smartlist_subtract(sl,excludednodes);
|
||||
if (excludedsmartlist)
|
||||
smartlist_subtract(sl,excludedsmartlist);
|
||||
|
||||
Reference in New Issue
Block a user