summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/TODO6
-rw-r--r--src/or/circuitbuild.c8
-rw-r--r--src/or/circuituse.c6
-rw-r--r--src/or/connection_edge.c4
-rw-r--r--src/or/connection_or.c4
-rw-r--r--src/or/control.c4
-rw-r--r--src/or/dirserv.c14
-rw-r--r--src/or/or.h12
-rw-r--r--src/or/rendclient.c2
-rw-r--r--src/or/rendservice.c8
-rw-r--r--src/or/router.c26
-rw-r--r--src/or/routerlist.c85
12 files changed, 135 insertions, 44 deletions
diff --git a/doc/TODO b/doc/TODO
index 37047c5551..a5e8d21e75 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -186,7 +186,7 @@ N . Routerdesc download changes
connections over last N seconds.
o Call dirport_is_reachable from somewhere else.
o Networkstatus should list who's an authority.
- - Add nickname element to dirserver line. Log this along with IP:Port.
+ o Add nickname element to dirserver line. Log this along with IP:Port.
o Warn when using non-default directory servers.
- When giving up on a non-finished dir request, log how many bytes
dropped, to see whether it's worthwhile to use partial info.
@@ -206,8 +206,8 @@ N . Naming and validation:
o Not all authdirs name.
o Change naming rule: N->K iff any naming authdir says N->K,
and none says N->K' or N'->K.
- - Clients choose names based on network-status options.
- - Names are remembered in client state (?)
+ o Clients choose names based on network-status options.
+ o Names are remembered in client state (?)
- Okay to have two valid servers with same nickname, but not
two named servers with same nickname. Update logic.
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index fd84306b72..e88a5a10f3 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -1053,7 +1053,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
or_options_t *options = get_options();
preferredentries = smartlist_create();
- add_nickname_list_to_smartlist(preferredentries,options->EntryNodes,1);
+ add_nickname_list_to_smartlist(preferredentries,options->EntryNodes,1,1);
get_connection_array(&carray, &n_connections);
@@ -1142,10 +1142,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);
+ add_nickname_list_to_smartlist(preferredexits,options->ExitNodes,1,1);
excludedexits = smartlist_create();
- add_nickname_list_to_smartlist(excludedexits,options->ExcludeNodes,0);
+ add_nickname_list_to_smartlist(excludedexits,options->ExcludeNodes,0,1);
sl = smartlist_create();
@@ -1506,7 +1506,7 @@ onion_extend_cpath(uint8_t purpose, crypt_path_t **head_ptr,
state->desired_path_len);
excludednodes = smartlist_create();
- add_nickname_list_to_smartlist(excludednodes,get_options()->ExcludeNodes,0);
+ add_nickname_list_to_smartlist(excludednodes,get_options()->ExcludeNodes,0,1);
if (cur_len == state->desired_path_len - 1) { /* Picking last node */
info = extend_info_dup(state->chosen_exit);
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index d9b2f7a591..d88db4ee01 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -806,7 +806,7 @@ circuit_launch_by_nickname(uint8_t purpose, const char *exit_nickname,
routerinfo_t *router = NULL;
if (exit_nickname) {
- router = router_get_by_nickname(exit_nickname);
+ router = router_get_by_nickname(exit_nickname, 1);
if (!router) {
log_fn(LOG_WARN, "No such OR as '%s'", exit_nickname);
return NULL;
@@ -923,7 +923,7 @@ circuit_get_open_circ_or_launch(connection_t *conn,
if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_GENERAL) {
if (conn->chosen_exit_name) {
routerinfo_t *r;
- if (!(r = router_get_by_nickname(conn->chosen_exit_name))) {
+ if (!(r = router_get_by_nickname(conn->chosen_exit_name, 1))) {
log_fn(LOG_NOTICE,"Requested exit point '%s' is not known. Closing.",
conn->chosen_exit_name);
return -1;
@@ -1097,7 +1097,7 @@ connection_ap_handshake_attach_circuit(connection_t *conn)
circuit_t *circ=NULL;
if (conn->chosen_exit_name) {
- routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name);
+ routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1);
if (!router) {
log_fn(LOG_WARN,"Requested exit point '%s' is not known. Closing.",
conn->chosen_exit_name);
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index bf51b126fe..0cefe5d694 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -996,7 +996,7 @@ connection_ap_handshake_process_socks(connection_t *conn)
}
} else {
struct in_addr in;
- routerinfo_t *r = router_get_by_nickname(socks->address);
+ routerinfo_t *r = router_get_by_nickname(socks->address, 1);
if (r) {
conn->chosen_exit_name = tor_strdup(socks->address);
/* XXXX Should this use server->address instead? */
@@ -1703,7 +1703,7 @@ connection_ap_can_use_exit(connection_t *conn, routerinfo_t *exit)
* make sure the exit node of the existing circuit matches exactly.
*/
if (conn->chosen_exit_name) {
- if (router_get_by_nickname(conn->chosen_exit_name) != exit) {
+ if (router_get_by_nickname(conn->chosen_exit_name, 1) != exit) {
/* doesn't match */
log_fn(LOG_DEBUG,"Requested node '%s', considering node '%s'. No.",
conn->chosen_exit_name, exit->nickname);
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index b69301df9f..6d3fad21d0 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -497,9 +497,9 @@ connection_or_check_valid_handshake(connection_t *conn, char *digest_rcvd)
}
crypto_free_pk_env(identity_rcvd);
- router = router_get_by_nickname(nickname);
+ router = router_get_by_nickname(nickname, 0);
if (router && /* we know this nickname */
- router->is_verified && /* make sure it's the right guy */
+ router->is_named && /* make sure it's the right guy */
memcmp(digest_rcvd, router->identity_digest, DIGEST_LEN) != 0) {
log_fn(severity,
"Identity key not as expected for router claiming to be '%s' (%s:%d)",
diff --git a/src/or/control.c b/src/or/control.c
index dccb2d55a5..f522f79acd 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -1226,7 +1226,7 @@ handle_getinfo_helper(const char *question, char **answer)
if (ri && ri->signed_descriptor)
*answer = tor_strdup(ri->signed_descriptor);
} else if (!strcmpstart(question, "desc/name/")) {
- routerinfo_t *ri = router_get_by_nickname(question+strlen("desc/name/"));
+ routerinfo_t *ri = router_get_by_nickname(question+strlen("desc/name/"),1);
if (ri && ri->signed_descriptor)
*answer = tor_strdup(ri->signed_descriptor);
} else if (!strcmpstart(question, "unregistered-servers-")) {
@@ -1513,7 +1513,7 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len,
routers = smartlist_create();
SMARTLIST_FOREACH(router_nicknames, const char *, n,
{
- routerinfo_t *r = router_get_by_nickname(n);
+ routerinfo_t *r = router_get_by_nickname(n, 1);
if (!r) {
if (v0)
send_control0_error(conn, ERR_NO_ROUTER, n);
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index d60560ce41..3a1c6eb079 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -105,12 +105,14 @@ add_fingerprint_to_dir(const char *nickname, const char *fp, smartlist_t *list)
fingerprint = tor_strdup(fp);
tor_strstrip(fingerprint, " ");
- for (i = 0; i < smartlist_len(list); ++i) {
- ent = smartlist_get(list, i);
- if (!strcasecmp(ent->nickname,nickname)) {
- tor_free(ent->fingerprint);
- ent->fingerprint = fingerprint;
- return 1;
+ if (nickname[0] != '!') {
+ for (i = 0; i < smartlist_len(list); ++i) {
+ ent = smartlist_get(list, i);
+ if (!strcasecmp(ent->nickname,nickname)) {
+ tor_free(ent->fingerprint);
+ ent->fingerprint = fingerprint;
+ return 1;
+ }
}
}
ent = tor_malloc(sizeof(fingerprint_entry_t));
diff --git a/src/or/or.h b/src/or/or.h
index c1e3203010..b5286178d6 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -775,8 +775,8 @@ typedef struct {
unsigned int is_verified:1; /**< Has a trusted dirserver validated this OR?
* (For Authdir: Have we validated this OR?)
*/
- /*XXXX Make this get used once we think we do naming right. NM */
- unsigned int is_named:1; /* Do we believe the nickname that this OR gives us? */
+ unsigned int is_named:1; /**< Do we believe the nickname that this OR gives
+ * us? */
/* The below items are used only by authdirservers for
* reachability testing. */
@@ -815,6 +815,9 @@ typedef struct local_routerstatus_t {
uint8_t n_download_failures; /**< Number of failures trying to download the
* most recent descriptor. */
unsigned int should_download:1; /**< DOCDOC */
+ unsigned int name_lookup_warned:1; /*< Have we warned the user for referring
+ * to this (unnamed) router by nickname?
+ */
} local_routerstatus_t;
/*XXXX011 make this configurable? */
@@ -2091,7 +2094,7 @@ trusted_dir_server_t *router_get_trusteddirserver_by_digest(
const char *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 warn_if_down);
+void add_nickname_list_to_smartlist(smartlist_t *sl, const char *list, 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,
int warn);
@@ -2110,7 +2113,8 @@ routerinfo_t *router_choose_random_node(const char *preferred,
smartlist_t *excludedsmartlist,
int need_uptime, int need_bandwidth,
int allow_unverified, int strict);
-routerinfo_t *router_get_by_nickname(const char *nickname);
+routerinfo_t *router_get_by_nickname(const char *nickname,
+ int warn_if_unnamed);
routerinfo_t *router_get_by_hexdigest(const char *hexdigest);
routerinfo_t *router_get_by_digest(const char *digest);
int router_digest_is_trusted_dir(const char *digest);
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index 8b191b4187..b4e8f171af 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -467,7 +467,7 @@ rend_client_get_random_intro(const char *query)
} else {
/* add the intro point nicknames */
char *choice = entry->parsed->intro_points[i];
- routerinfo_t *router = router_get_by_nickname(choice);
+ routerinfo_t *router = router_get_by_nickname(choice, 0);
if (!router) {
log_fn(LOG_INFO, "Unknown router with nickname '%s'; trying another.",choice);
tor_free(choice);
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index e101e9a7b2..b33776bf8c 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -292,7 +292,7 @@ rend_service_update_descriptor(rend_service_t *service)
d->intro_point_extend_info = tor_malloc_zero(sizeof(extend_info_t*)*n);
d->protocols = (1<<2) | (1<<0); /* We support protocol 2 and protocol 0. */
for (i=0; i < n; ++i) {
- router = router_get_by_nickname(smartlist_get(service->intro_nodes, i));
+ router = router_get_by_nickname(smartlist_get(service->intro_nodes, i),1);
if (!router) {
log_fn(LOG_INFO,"Router '%s' not found. Skipping.",
(char*)smartlist_get(service->intro_nodes, i));
@@ -512,7 +512,7 @@ rend_service_introduce(circuit_t *circuit, const char *request, size_t request_l
ptr = rp_nickname+nickname_field_len;
len -= nickname_field_len;
len -= rp_nickname - buf; /* also remove header space used by version, if any */
- router = router_get_by_nickname(rp_nickname);
+ router = router_get_by_nickname(rp_nickname, 0);
if (!router) {
log_fn(LOG_INFO, "Couldn't find router '%s' named in rendezvous cell.",
rp_nickname);
@@ -934,7 +934,7 @@ rend_services_introduce(void)
/* Find out which introduction points we have in progress for this service. */
for (j=0; j < smartlist_len(service->intro_nodes); ++j) {
intro = smartlist_get(service->intro_nodes, j);
- router = router_get_by_nickname(intro);
+ router = router_get_by_nickname(intro, 1);
if (!router || !find_intro_circuit(router,service->pk_digest)) {
log_fn(LOG_INFO,"Giving up on %s as intro point for %s.",
intro, service->service_id);
@@ -1052,7 +1052,7 @@ rend_service_dump_stats(int severity)
log(severity, "Service configured in \"%s\":", service->directory);
for (j=0; j < smartlist_len(service->intro_nodes); ++j) {
nickname = smartlist_get(service->intro_nodes, j);
- router = router_get_by_nickname(smartlist_get(service->intro_nodes,j));
+ router = router_get_by_nickname(smartlist_get(service->intro_nodes,j),1);
if (!router) {
log(severity, " Intro point at %s: unrecognized router",nickname);
continue;
diff --git a/src/or/router.c b/src/or/router.c
index 3db797ffd2..5835c38aed 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -810,9 +810,33 @@ router_rebuild_descriptor(int force)
if (authdir_mode(options))
ri->is_verified = ri->is_named = 1; /* believe in yourself */
if (options->MyFamily) {
+ smartlist_t *family = smartlist_create();
ri->declared_family = smartlist_create();
- smartlist_split_string(ri->declared_family, options->MyFamily, ",",
+ smartlist_split_string(family, options->MyFamily, ",",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+ SMARTLIST_FOREACH(family, char *, name,
+ {
+ routerinfo_t *member;
+ if (!strcasecmp(name, options->Nickname))
+ member = ri;
+ else
+ member = router_get_by_nickname(name, 1);
+ if (!member) {
+ log_fn(LOG_WARN, "I have no descriptor for the router named \"%s\" "
+ "in my declared family; I'll use the nickname verbatim, but "
+ "this may confuse clients.", name);
+ smartlist_add(ri->declared_family, name);
+ name = NULL;
+ } else {
+ char *fp = tor_malloc(HEX_DIGEST_LEN+2);
+ fp[0] = '$';
+ base16_encode(fp+1,HEX_DIGEST_LEN+1,
+ member->identity_digest, DIGEST_LEN);
+ smartlist_add(ri->declared_family, fp);
+ }
+ tor_free(name);
+ });
+ smartlist_free(family);
}
ri->signed_descriptor = tor_malloc(8192);
if (router_dump_router_to_string(ri->signed_descriptor, 8192,
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 435d4dfd55..fef8427acf 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -502,7 +502,7 @@ routerlist_add_family(smartlist_t *sl, routerinfo_t *router)
* declares familyhood with router. */
SMARTLIST_FOREACH(router->declared_family, const char *, n,
{
- if (!(r = router_get_by_nickname(n)))
+ if (!(r = router_get_by_nickname(n, 0)))
continue;
if (!r->declared_family)
continue;
@@ -516,7 +516,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, 0);
+ add_nickname_list_to_smartlist(sl, cl->value, 1, 1);
}
}
}
@@ -530,7 +530,7 @@ static smartlist_t *warned_nicknames = NULL;
* currently running. Add the routerinfos for those routers to <b>sl</b>.
*/
void
-add_nickname_list_to_smartlist(smartlist_t *sl, const char *list, int warn_if_down)
+add_nickname_list_to_smartlist(smartlist_t *sl, const char *list, int warn_if_down, int warn_if_unnamed)
{
routerinfo_t *router;
smartlist_t *nickname_list;
@@ -552,7 +552,7 @@ add_nickname_list_to_smartlist(smartlist_t *sl, const char *list, int warn_if_do
log_fn(LOG_WARN,"Nickname %s is misformed; skipping", nick);
continue;
}
- router = router_get_by_nickname(nick);
+ router = router_get_by_nickname(nick, warn_if_unnamed);
warned = smartlist_string_isin(warned_nicknames, nick);
if (router) {
if (router->is_running) {
@@ -770,12 +770,12 @@ router_choose_random_node(const char *preferred,
routerinfo_t *choice;
excludednodes = smartlist_create();
- add_nickname_list_to_smartlist(excludednodes,excluded,0);
+ add_nickname_list_to_smartlist(excludednodes,excluded,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);
+ add_nickname_list_to_smartlist(sl,preferred,1,1);
smartlist_subtract(sl,excludednodes);
if (excludedsmartlist)
smartlist_subtract(sl,excludedsmartlist);
@@ -839,10 +839,12 @@ router_nickname_matches(routerinfo_t *router, const char *nickname)
* <b>nickname</b>. Return NULL if no such router is known.
*/
routerinfo_t *
-router_get_by_nickname(const char *nickname)
+router_get_by_nickname(const char *nickname, int warn_if_unnamed)
{
int maybedigest;
char digest[DIGEST_LEN];
+ routerinfo_t *best_match=NULL;
+ int n_matches = 0;
tor_assert(nickname);
if (!routerlist)
@@ -860,12 +862,69 @@ router_get_by_nickname(const char *nickname)
{
/* XXXX011 NM Should this restrict by Named rouers, or warn on
* non-named routers, or something? */
- if (0 == strcasecmp(router->nickname, nickname) ||
- (maybedigest && 0 == memcmp(digest, router->identity_digest,
- DIGEST_LEN)))
+ if (!strcasecmp(router->nickname, nickname)) {
+ if (router->is_named)
+ return router;
+ else {
+ ++n_matches;
+ best_match = router;
+ }
+ } else if (maybedigest &&
+ !memcmp(digest, router->identity_digest, DIGEST_LEN)) {
return router;
+ }
});
+ if (best_match) {
+ if (n_matches>1) {
+ smartlist_t *fps = smartlist_create();
+ int any_unwarned = 0;
+ SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
+ {
+ local_routerstatus_t *rs;
+ char *desc;
+ size_t dlen;
+ char fp[HEX_DIGEST_LEN+1];
+ if (strcasecmp(router->nickname, nickname))
+ continue;
+ rs=router_get_combined_status_by_digest(router->identity_digest);
+ if (!rs->name_lookup_warned) {
+ rs->name_lookup_warned = 1;
+ any_unwarned = 1;
+ }
+ base16_encode(fp, sizeof(fp), router->identity_digest, DIGEST_LEN);
+ dlen = 32 + HEX_DIGEST_LEN + strlen(router->address);
+ desc = tor_malloc(dlen);
+ tor_snprintf(desc, dlen, "\"$%s\" for the one at %s:%d",
+ fp, router->address, router->or_port);
+ smartlist_add(fps, desc);
+ });
+ if (any_unwarned) {
+ char *alternatives = smartlist_join_strings(fps, "; ",0,NULL);
+ log_fn(LOG_WARN, "There are multiple matches for the nickname \"%s\","
+ " but none is listed as named by the directory authories. "
+ "Choosing one arbitrarily. If you meant one in particular, "
+ "you should say %s.", nickname, alternatives);
+ tor_free(alternatives);
+ }
+ SMARTLIST_FOREACH(fps, char *, cp, tor_free(cp));
+ smartlist_free(fps);
+ } else if (warn_if_unnamed) {
+ local_routerstatus_t *rs =
+ router_get_combined_status_by_digest(best_match->identity_digest);
+ if (rs && !rs->name_lookup_warned) {
+ char fp[HEX_DIGEST_LEN+1];
+ base16_encode(fp, sizeof(fp), best_match->identity_digest, DIGEST_LEN);
+ log_fn(LOG_WARN, "You specified a server \"%s\" by name, but the "
+ "directory authorities do not have a listing for this name. "
+ "To make sure you get the same server in the future, refer to "
+ "it by key, as \"$%s\".", nickname, fp);
+ rs->name_lookup_warned = 1;
+ }
+ }
+ return best_match;
+ }
+
return NULL;
}
@@ -2313,6 +2372,7 @@ routerstatus_list_update_from_networkstatus(time_t now)
if ((rs_old = router_get_combined_status_by_digest(lowest))) {
rs_out->n_download_failures = rs_old->n_download_failures;
rs_out->next_attempt_at = rs_old->next_attempt_at;
+ rs_out->name_lookup_warned = rs_old->name_lookup_warned;
}
smartlist_add(result, rs_out);
log_fn(LOG_DEBUG, "Router '%s' is listed by %d/%d directories, "
@@ -2356,7 +2416,8 @@ routers_update_status_from_networkstatus(smartlist_t *routers, int reset_failure
local_routerstatus_t *rs;
or_options_t *options = get_options();
int authdir = options->AuthoritativeDir;
- int namingdir = options->NamingAuthoritativeDir;
+ int namingdir = options->AuthoritativeDir &&
+ options->NamingAuthoritativeDir;
if (!routerstatus_list)
return;
@@ -2600,9 +2661,9 @@ update_router_descriptor_downloads(time_t now)
*cp++ = '+';
}
memcpy(cp-1, ".z", 3);
- last_download_attempted = now;
directory_get_from_dirserver(DIR_PURPOSE_FETCH_SERVERDESC,resource,1);
}
+ last_download_attempted = now;
tor_free(resource);
}
SMARTLIST_FOREACH(downloadable, char *, c, tor_free(c));