Commit dc7951a5 authored by Roger Dingledine's avatar Roger Dingledine
Browse files

a whole swath of fixes

introduce an authdir_mode() macro to match the others.
don't initialize uptime to the number of seconds since 1970.
non-authoritative dirservers don't cache their directory on disk.
make only authdirservers use clique_mode.
only read approved-routers file if you're an authdirserver.
even authdirservers fetch a new directory in do_hup.
retry_all_connections() is now called retry_all_listeners().
router_parse_list_from_string() correctly reports the router number
  it's working on.
only call dirserv_add_own_fingerprint() and
   dirserv_add_descriptor() on startup if we're an authdirserver.
if AuthDir and !ORPort then fail.
if AuthDir and ClientOnly then fail.


svn:r2061
parent 63b476a6
......@@ -726,9 +726,15 @@ int getconfig(int argc, char **argv, or_options_t *options) {
result = -1;
}
/* XXX008 if AuthDir and !ORPort then fail */
if(options->AuthoritativeDir && !options->ORPort) {
log(LOG_WARN,"Running as authoritative directory, but no ORPort set.");
result = -1;
}
/* XXX008 if AuthDir and ClientOnly then fail */
if(options->AuthoritativeDir && options->ClientOnly) {
log(LOG_WARN,"Running as authoritative directory, but ClientOnly also set.");
result = -1;
}
if(options->SocksPort >= 1 &&
(options->PathlenCoinWeight < 0.0 || options->PathlenCoinWeight >= 1.0)) {
......
......@@ -540,14 +540,9 @@ static int retry_listeners(int type, struct config_line_t *cfg,
return 0;
}
/** Start all connections that should be up but aren't.
* - Connect to all ORs if you're an OR.
* - Relaunch listeners for each port you have open.
/** (Re)launch listeners for each port you should have open.
*/
int retry_all_connections(void) {
if(clique_mode()) {
router_retry_connections();
}
int retry_all_listeners(void) {
if (retry_listeners(CONN_TYPE_OR_LISTENER, options.ORBindAddress,
options.ORPort, "0.0.0.0")<0)
......
......@@ -619,7 +619,6 @@ static int cached_directory_len = -1;
void dirserv_set_cached_directory(const char *directory, time_t when)
{
time_t now;
char filename[512];
tor_assert(!options.AuthoritativeDir);
now = time(NULL);
if (when>cached_directory_published &&
......@@ -628,10 +627,6 @@ void dirserv_set_cached_directory(const char *directory, time_t when)
cached_directory = tor_strdup(directory);
cached_directory_len = strlen(cached_directory);
cached_directory_published = when;
sprintf(filename,"%s/cached-directory", get_data_directory(&options));
if(write_str_to_file(filename,cached_directory) < 0) {
log_fn(LOG_WARN, "Couldn't write cached directory to disk. Ignoring.");
}
}
}
......
......@@ -361,7 +361,7 @@ static void run_connection_housekeeping(int i, time_t now) {
if(conn->type == CONN_TYPE_DIR &&
!conn->marked_for_close &&
conn->timestamp_lastwritten + 5*60 < now) {
log_fn(LOG_WARN,"Expiring wedged directory conn (fd %d, purpose %d)", conn->s, conn->purpose);
log_fn(LOG_INFO,"Expiring wedged directory conn (fd %d, purpose %d)", conn->s, conn->purpose);
connection_mark_for_close(conn);
return;
}
......@@ -403,28 +403,49 @@ static void run_connection_housekeeping(int i, time_t now) {
* - We believe we are reachable from the outside.
*/
static int decide_if_publishable_server(time_t now) {
int r;
if(options.AuthoritativeDir)
return 1;
if(options.ClientOnly)
return 0;
if(!options.ORPort)
return 0;
/* XXX008 for now, you're only a server if you're a server */
return server_mode();
/* here, determine if we're reachable */
if(0) { /* we've recently failed to reach our IP/ORPort from the outside */
return 0;
}
if(stats_n_seconds_uptime < MIN_UPTIME_TO_PUBLISH_DESC)
r = rep_hist_bandwidth_assess(now);
// set_advertised_bandwidth(r);
if(r < MIN_BW_TO_PUBLISH_DESC)
return 0;
if(rep_hist_bandwidth_assess(now) < MIN_BW_TO_PUBLISH_DESC)
if(options.AuthoritativeDir)
return 1;
if(stats_n_seconds_uptime < MIN_UPTIME_TO_PUBLISH_DESC)
return 0;
return 1;
}
/** Return true iff we try to stay connected to all ORs at once. This
* option should go away as Tor becomes more P2P.
/** Return true iff we believe ourselves to be an authoritative
* directory server.
*/
int authdir_mode(void) {
return (options.AuthoritativeDir != 0);
}
/** Return true iff we try to stay connected to all ORs at once.
*/
int clique_mode(void) {
return (options.ORPort != 0);
return authdir_mode();
}
/** Return true iff we are trying to be a server.
......@@ -495,10 +516,10 @@ static void run_scheduled_events(time_t now) {
routerlist_remove_old_routers(); /* purge obsolete entries */
if(options.AuthoritativeDir) {
if(authdir_mode()) {
/* We're a directory; dump any old descriptors. */
dirserv_remove_old_servers();
/* dirservers try to reconnect too, in case connections have failed */
/* dirservers try to reconnect, in case connections have failed */
router_retry_connections();
}
......@@ -582,7 +603,8 @@ static int prepare_for_poll(void) {
if(now.tv_sec > current_second) { /* the second has rolled over. check more stuff. */
stats_n_seconds_uptime += (now.tv_sec - current_second);
if(current_second)
stats_n_seconds_uptime += (now.tv_sec - current_second);
assert_all_pending_dns_resolves_ok();
run_scheduled_events(now.tv_sec);
assert_all_pending_dns_resolves_ok();
......@@ -674,11 +696,11 @@ static int do_hup(void) {
log_fn(LOG_ERR,"Error reloading rendezvous service keys");
exit(1);
}
if(retry_all_connections() < 0) {
if(retry_all_listeners() < 0) {
log_fn(LOG_ERR,"Failed to bind one of the listener ports.");
return -1;
}
if(options.DirPort) {
if(authdir_mode()) {
/* reload the approved-routers file */
sprintf(keydir,"%s/approved-routers", get_data_directory(&options));
log_fn(LOG_INFO,"Reloading approved fingerprints from %s...",keydir);
......@@ -688,10 +710,9 @@ static int do_hup(void) {
/* Since we aren't fetching a directory, we won't retry rendezvous points
* when it gets in. Try again now. */
rend_services_introduce();
} else {
/* fetch a new directory */
directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR, NULL, 0);
}
/* Fetch a new directory. Even authdirservers do this. */
directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR, NULL, 0);
if(server_mode()) {
/* Restart cpuworker and dnsworker processes, so they get up-to-date
* configuration options. */
......@@ -736,20 +757,18 @@ static int do_main_loop(void) {
}
}
if(options.DirPort) { /* the directory is already here, run startup things */
has_fetched_directory = 1;
if(authdir_mode()) {
/* the directory is already here, run startup things */
directory_has_arrived();
}
if(server_mode()) {
cpu_init(); /* launch cpuworkers. Need to do this *after* we've read the onion key. */
/* launch cpuworkers. Need to do this *after* we've read the onion key. */
cpu_init();
}
/* start up the necessary connections based on which ports are
* non-zero. This is where we try to connect to all the other ORs,
* and start the listeners.
*/
if(retry_all_connections() < 0) {
/* start up the necessary listeners based on which ports are non-zero. */
if(retry_all_listeners() < 0) {
log_fn(LOG_ERR,"Failed to bind one of the listener ports.");
return -1;
}
......
......@@ -1043,7 +1043,7 @@ int _connection_mark_for_close(connection_t *conn);
void connection_expire_held_open(void);
int connection_connect(connection_t *conn, char *address, uint32_t addr, uint16_t port);
int retry_all_connections(void);
int retry_all_listeners(void);
void connection_bucket_init(void);
void connection_bucket_refill(struct timeval *now);
......@@ -1194,6 +1194,7 @@ void connection_stop_writing(connection_t *conn);
void connection_start_writing(connection_t *conn);
void directory_has_arrived(void);
int authdir_mode(void);
int clique_mode(void);
int server_mode(void);
int exit_server_mode(void);
......
......@@ -280,20 +280,23 @@ int init_keys(void) {
}
/* 4. Dump router descriptor to 'router.desc' */
/* Must be called after keys are initialized. */
if (!(router_get_my_descriptor())) {
tmp = mydesc = router_get_my_descriptor();
if (!mydesc) {
log_fn(LOG_ERR, "Error initializing descriptor.");
return -1;
}
/* We need to add our own fingerprint so it gets recognized. */
if (dirserv_add_own_fingerprint(options.Nickname, get_identity_key())) {
log_fn(LOG_ERR, "Error adding own fingerprint to approved set");
return -1;
}
tmp = mydesc = router_get_my_descriptor();
if (dirserv_add_descriptor(&tmp) != 1) {
log(LOG_ERR, "Unable to add own descriptor to directory.");
return -1;
if(authdir_mode()) {
/* We need to add our own fingerprint so it gets recognized. */
if (dirserv_add_own_fingerprint(options.Nickname, get_identity_key())) {
log_fn(LOG_ERR, "Error adding own fingerprint to approved set");
return -1;
}
if (dirserv_add_descriptor(&tmp) != 1) {
log(LOG_ERR, "Unable to add own descriptor to directory.");
return -1;
}
}
sprintf(keydir,"%s/router.desc", datadir);
log_fn(LOG_INFO,"Dumping descriptor to %s...",keydir);
if (write_str_to_file(keydir, mydesc)) {
......@@ -313,31 +316,26 @@ int init_keys(void) {
strcat(fingerprint, "\n");
if (write_str_to_file(keydir, fingerprint))
return -1;
if(!options.DirPort)
if(!authdir_mode())
return 0;
/* 6. [dirserver only] load approved-routers file */
/* 6. [authdirserver only] load approved-routers file */
sprintf(keydir,"%s/approved-routers", datadir);
log_fn(LOG_INFO,"Loading approved fingerprints from %s...",keydir);
if(dirserv_parse_fingerprint_file(keydir) < 0) {
log_fn(LOG_ERR, "Error loading fingerprints");
return -1;
}
/* 7. [dirserver only] load old directory, if it's there */
/* 7. [authdirserver only] load old directory, if it's there */
sprintf(keydir,"%s/cached-directory", datadir);
log_fn(LOG_INFO,"Loading cached directory from %s...",keydir);
cp = read_file_to_str(keydir);
if(!cp) {
log_fn(LOG_INFO,"Cached directory %s not present. Ok.",keydir);
} else {
if(options.AuthoritativeDir) {
if(dirserv_load_from_directory_string(cp) < 0){
log_fn(LOG_ERR, "Cached directory %s is corrupt", keydir);
tor_free(cp);
return -1;
}
} else {
/* set time to 1 so it will be replaced on first download. */
dirserv_set_cached_directory(cp, 1);
if(dirserv_load_from_directory_string(cp) < 0){
log_fn(LOG_ERR, "Cached directory %s is corrupt", keydir);
tor_free(cp);
return -1;
}
tor_free(cp);
}
......@@ -510,6 +508,10 @@ int router_rebuild_descriptor(void) {
log_fn(LOG_WARN, "Couldn't dump router to string.");
return -1;
}
/* XXX008 NM: no, we shouldn't just blindly assume we're an
* authdirserver just because our dir_port is set. We should
* take these next two lines out, and then set our is_trusted_dir
* variable if we find ourselves in the dirservers file. Yes/no? */
if (ri->dir_port)
ri->is_trusted_dir = 1;
return 0;
......
......@@ -330,7 +330,7 @@ router_parse_routerlist_from_directory(const char *str,
log_fn(LOG_WARN, "Unable to compute digest of directory");
goto err;
}
log(LOG_DEBUG,"Received directory hashes to %s",hex_str(digest,4));
log_fn(LOG_DEBUG,"Received directory hashes to %s",hex_str(digest,4));
if ((end = strstr(str,"\nrouter "))) {
++end;
......@@ -573,7 +573,6 @@ router_parse_list_from_string(const char **s, routerlist_t **dest,
{
routerinfo_t *router;
smartlist_t *routers;
int rarray_len = 0;
const char *end;
tor_assert(s && *s);
......@@ -609,7 +608,7 @@ router_parse_list_from_string(const char **s, routerlist_t **dest,
router->status_set_at = time(NULL);
}
smartlist_add(routers, router);
log_fn(LOG_DEBUG,"just added router #%d.",rarray_len);
log_fn(LOG_DEBUG,"just added router #%d.",smartlist_len(routers));
}
if (*dest)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment