aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRoger Dingledine <arma@torproject.org>2005-12-31 06:32:57 +0000
committerRoger Dingledine <arma@torproject.org>2005-12-31 06:32:57 +0000
commit5947388968fc43f6963e4bb0d1caa59f2a0d3d77 (patch)
treeaa86cc21bbb7467e366b17cd6b0b213150a8c382 /src
parent6005e110b9c8c3c9cf0afdcccf83cdbdc834e3d4 (diff)
downloadtor-5947388968fc43f6963e4bb0d1caa59f2a0d3d77.tar.gz
tor-5947388968fc43f6963e4bb0d1caa59f2a0d3d77.zip
Finish implementing config's EntryNodes and StrictEntryNodes option.
The logging is way verbose for now. svn:r5683
Diffstat (limited to 'src')
-rw-r--r--src/or/circuitbuild.c172
-rw-r--r--src/or/config.c5
-rw-r--r--src/or/or.h5
-rw-r--r--src/or/routerlist.c11
4 files changed, 142 insertions, 51 deletions
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 8926bcf475..10bd72c240 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -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);
diff --git a/src/or/config.c b/src/or/config.c
index 7d8626b548..a0d2eaab9a 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -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.
*/
diff --git a/src/or/or.h b/src/or/or.h
index 6157545044..ed0f178011 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -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,
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index c449edc07b..daf07a11fe 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -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);