diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/compat.c | 66 | ||||
-rw-r--r-- | src/common/compat.h | 2 | ||||
-rw-r--r-- | src/or/connection.c | 28 | ||||
-rw-r--r-- | src/or/dirserv.c | 40 | ||||
-rw-r--r-- | src/or/dirserv.h | 3 | ||||
-rw-r--r-- | src/or/microdesc.c | 27 | ||||
-rw-r--r-- | src/or/nodelist.c | 2 | ||||
-rw-r--r-- | src/test/test_util.c | 25 | ||||
-rw-r--r-- | src/tools/tor-fw-helper/README | 2 |
9 files changed, 133 insertions, 62 deletions
diff --git a/src/common/compat.c b/src/common/compat.c index 306081754e..76f9bcb97e 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -68,6 +68,9 @@ #ifdef HAVE_CRT_EXTERNS_H #include <crt_externs.h> #endif +#ifdef HAVE_SYS_STATVFS_H +#include <sys/statvfs.h> +#endif #ifdef _WIN32 #include <conio.h> @@ -1600,15 +1603,23 @@ get_max_sockets(void) * tell Tor it's allowed to use. */ #define ULIMIT_BUFFER 32 /* keep 32 extra fd's beyond ConnLimit_ */ -/** Learn the maximum allowed number of file descriptors, and tell the system - * we want to use up to that number. (Some systems have a low soft limit, and - * let us set it higher.) +/** Learn the maximum allowed number of file descriptors, and tell the + * system we want to use up to that number. (Some systems have a low soft + * limit, and let us set it higher.) We compute this by finding the largest + * number that we can use. + * + * If the limit is below the reserved file descriptor value (ULIMIT_BUFFER), + * return -1 and <b>max_out</b> is untouched. + * + * If we can't find a number greater than or equal to <b>limit</b>, then we + * fail by returning -1 and <b>max_out</b> is untouched. * - * We compute this by finding the largest number that we can use. - * If we can't find a number greater than or equal to <b>limit</b>, - * then we fail: return -1. + * If we are unable to set the limit value because of setrlimit() failing, + * return -1 and <b>max_out</b> is set to the current maximum value returned + * by getrlimit(). * - * Otherwise, return 0 and store the maximum we found inside <b>max_out</b>.*/ + * Otherwise, return 0 and store the maximum we found inside <b>max_out</b> + * and set <b>max_sockets</b> with that value as well.*/ int set_max_file_descriptors(rlim_t limit, int *max_out) { @@ -1665,7 +1676,7 @@ set_max_file_descriptors(rlim_t limit, int *max_out) } /* Set the current limit value so if the attempt to set the limit to the * max fails at least we'll have a valid value of maximum sockets. */ - max_sockets = (int)rlim.rlim_cur - ULIMIT_BUFFER; + *max_out = max_sockets = (int)rlim.rlim_cur - ULIMIT_BUFFER; rlim.rlim_cur = rlim.rlim_max; if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) { @@ -3374,3 +3385,42 @@ tor_getpass(const char *prompt, char *output, size_t buflen) #endif } +/** Return the amount of free disk space we have permission to use, in + * bytes. Return -1 if the amount of free space can't be determined. */ +int64_t +tor_get_avail_disk_space(const char *path) +{ +#ifdef HAVE_STATVFS + struct statvfs st; + int r; + memset(&st, 0, sizeof(st)); + + r = statvfs(path, &st); + if (r < 0) + return -1; + + int64_t result = st.f_bavail; + if (st.f_frsize) { + result *= st.f_frsize; + } else if (st.f_bsize) { + result *= st.f_bsize; + } else { + return -1; + } + + return result; +#elif defined(_WIN32) + ULARGE_INTEGER freeBytesAvail; + BOOL ok; + + ok = GetDiskFreeSpaceEx(path, &freeBytesAvail, NULL, NULL); + if (!ok) { + return -1; + } + return (int64_t)freeBytesAvail.QuadPart; +#else + (void)path; + errno = ENOSYS; + return -1; +#endif +} diff --git a/src/common/compat.h b/src/common/compat.h index 3247a59878..d3b18eba92 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -405,6 +405,8 @@ int tor_fd_setpos(int fd, off_t pos); int tor_fd_seekend(int fd); int tor_ftruncate(int fd); +int64_t tor_get_avail_disk_space(const char *path); + #ifdef _WIN32 #define PATH_SEPARATOR "\\" #else diff --git a/src/or/connection.c b/src/or/connection.c index 2cca6e4cf9..ac36578069 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -4206,34 +4206,6 @@ connection_write_to_buf_impl_,(const char *string, size_t len, conn->outbuf_flushlen += buf_datalen(conn->outbuf) - old_datalen; } else { conn->outbuf_flushlen += len; - - /* Should we try flushing the outbuf now? */ - if (conn->in_flushed_some) { - /* Don't flush the outbuf when the reason we're writing more stuff is - * _because_ we flushed the outbuf. That's unfair. */ - return; - } - - if (conn->type == CONN_TYPE_CONTROL && - !connection_is_rate_limited(conn) && - conn->outbuf_flushlen-len < 1<<16 && - conn->outbuf_flushlen >= 1<<16) { - /* just try to flush all of it */ - } else - return; /* no need to try flushing */ - - if (connection_handle_write(conn, 0) < 0) { - if (!conn->marked_for_close) { - /* this connection is broken. remove it. */ - log_warn(LD_BUG, "unhandled error on write for " - "conn (type %d, fd %d); removing", - conn->type, (int)conn->s); - tor_fragile_assert(); - /* do a close-immediate here, so we don't try to flush */ - connection_close_immediate(conn); - } - return; - } } } diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 0a15332163..e70b1b422d 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -244,7 +244,8 @@ 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. */ uint32_t -dirserv_router_get_status(const routerinfo_t *router, const char **msg) +dirserv_router_get_status(const routerinfo_t *router, const char **msg, + int severity) { char d[DIGEST_LEN]; @@ -263,7 +264,8 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg) if (msg) { *msg = "Ed25519 identity key or RSA identity key has changed."; } - log_warn(LD_DIR, "Router %s uploaded a descriptor with a Ed25519 key " + log_fn(severity, LD_DIR, + "Descriptor from router %s has an Ed25519 key, " "but the <rsa,ed25519> keys don't match what they were before.", router_describe(router)); return FP_REJECT; @@ -272,7 +274,8 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg) /* No ed25519 key */ if (KEYPIN_MISMATCH == keypin_check_lone_rsa( (const uint8_t*)router->cache_info.identity_digest)) { - log_warn(LD_DIR, "Router %s uploaded a descriptor with no Ed25519 key, " + log_fn(severity, LD_DIR, + "Descriptor from router %s has no Ed25519 key, " "when we previously knew an Ed25519 for it. Ignoring for now, " "since Tor 0.2.6 is under development.", router_describe(router)); @@ -299,7 +302,7 @@ dirserv_would_reject_router(const routerstatus_t *rs) res = dirserv_get_status_impl(rs->identity_digest, rs->nickname, rs->addr, rs->or_port, - NULL, NULL, 0); + NULL, NULL, LOG_DEBUG); return (res & FP_REJECT) != 0; } @@ -308,13 +311,13 @@ dirserv_would_reject_router(const routerstatus_t *rs) * (hex, no spaces), nickname, address (used for logging only), IP address, OR * port and platform (logging only) as arguments. * - * If should_log is false, do not log messages. (There's not much point in + * Log messages at 'severity'. (There's not much point in * logging that we're rejecting servers we'll not download.) */ static uint32_t dirserv_get_status_impl(const char *id_digest, const char *nickname, uint32_t addr, uint16_t or_port, - const char *platform, const char **msg, int should_log) + const char *platform, const char **msg, int severity) { uint32_t result = 0; router_status_t *status_by_digest; @@ -322,10 +325,9 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname, if (!fingerprint_list) fingerprint_list = authdir_config_new(); - if (should_log) - log_debug(LD_DIRSERV, "%d fingerprints, %d digests known.", - strmap_size(fingerprint_list->fp_by_name), - digestmap_size(fingerprint_list->status_by_digest)); + log_debug(LD_DIRSERV, "%d fingerprints, %d digests known.", + strmap_size(fingerprint_list->fp_by_name), + digestmap_size(fingerprint_list->status_by_digest)); /* Versions before Tor 0.2.4.18-rc are too old to support, and are * missing some important security fixes too. Disable them. */ @@ -350,23 +352,22 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname, } if (authdir_policy_badexit_address(addr, or_port)) { - if (should_log) - log_info(LD_DIRSERV, "Marking '%s' as bad exit because of address '%s'", + log_fn(severity, LD_DIRSERV, + "Marking '%s' as bad exit because of address '%s'", nickname, fmt_addr32(addr)); result |= FP_BADEXIT; } if (!authdir_policy_permits_address(addr, or_port)) { - if (should_log) - log_info(LD_DIRSERV, "Rejecting '%s' because of address '%s'", + log_fn(severity, LD_DIRSERV, "Rejecting '%s' because of address '%s'", nickname, fmt_addr32(addr)); if (msg) *msg = "Authdir is rejecting routers in this range."; return FP_REJECT; } if (!authdir_policy_valid_address(addr, or_port)) { - if (should_log) - log_info(LD_DIRSERV, "Not marking '%s' valid because of address '%s'", + log_fn(severity, LD_DIRSERV, + "Not marking '%s' valid because of address '%s'", nickname, fmt_addr32(addr)); result |= FP_INVALID; } @@ -422,9 +423,9 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg, int complain, int *valid_out) { /* Okay. Now check whether the fingerprint is recognized. */ - uint32_t status = dirserv_router_get_status(ri, msg); time_t now; int severity = (complain && ri->contact_info) ? LOG_NOTICE : LOG_INFO; + uint32_t status = dirserv_router_get_status(ri, msg, severity); tor_assert(msg); if (status & FP_REJECT) return -1; /* msg is already set. */ @@ -734,7 +735,7 @@ directory_remove_invalid(void) uint32_t r; if (!ent) continue; - r = dirserv_router_get_status(ent, &msg); + r = dirserv_router_get_status(ent, &msg, LOG_INFO); router_get_description(description, ent); if (r & FP_REJECT) { log_info(LD_DIRSERV, "Router %s is now rejected: %s", @@ -1372,7 +1373,8 @@ dirserv_thinks_router_is_hs_dir(const routerinfo_t *router, return (router->wants_to_be_hs_dir && router->dir_port && node->is_stable && - uptime >= get_options()->MinUptimeHidServDirectoryV2); + uptime >= get_options()->MinUptimeHidServDirectoryV2 && + router_is_active(router, node, now)); } /** Don't consider routers with less bandwidth than this when computing diff --git a/src/or/dirserv.h b/src/or/dirserv.h index 311a513dbe..8a4e68dcf5 100644 --- a/src/or/dirserv.h +++ b/src/or/dirserv.h @@ -84,7 +84,8 @@ int authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg, int complain, int *valid_out); uint32_t dirserv_router_get_status(const routerinfo_t *router, - const char **msg); + const char **msg, + int severity); void dirserv_set_node_flags_from_authoritative_status(node_t *node, uint32_t authstatus); diff --git a/src/or/microdesc.c b/src/or/microdesc.c index ee48f6a419..051603d327 100644 --- a/src/or/microdesc.c +++ b/src/or/microdesc.c @@ -39,8 +39,13 @@ struct microdesc_cache_t { uint64_t total_len_seen; /** Total number of microdescriptors we have added to this cache */ unsigned n_seen; + + /** True iff we have loaded this cache from disk ever. */ + int is_loaded; }; +static microdesc_cache_t *get_microdesc_cache_noload(void); + /** Helper: computes a hash of <b>md</b> to place it in a hash table. */ static INLINE unsigned int microdesc_hash_(microdesc_t *md) @@ -113,12 +118,24 @@ static microdesc_cache_t *the_microdesc_cache = NULL; microdesc_cache_t * get_microdesc_cache(void) { + microdesc_cache_t *cache = get_microdesc_cache_noload(); + if (PREDICT_UNLIKELY(cache->is_loaded == 0)) { + microdesc_cache_reload(cache); + } + return cache; +} + +/** Return a pointer to the microdescriptor cache, creating (but not loading) + * it if necessary. */ +static microdesc_cache_t * +get_microdesc_cache_noload(void) +{ if (PREDICT_UNLIKELY(the_microdesc_cache==NULL)) { - microdesc_cache_t *cache = tor_malloc_zero(sizeof(microdesc_cache_t)); + microdesc_cache_t *cache = tor_malloc_zero(sizeof(*cache)); + tor_malloc_zero(sizeof(microdesc_cache_t)); HT_INIT(microdesc_map, &cache->map); cache->cache_fname = get_datadir_fname("cached-microdescs"); cache->journal_fname = get_datadir_fname("cached-microdescs.new"); - microdesc_cache_reload(cache); the_microdesc_cache = cache; } return the_microdesc_cache; @@ -353,6 +370,8 @@ microdesc_cache_reload(microdesc_cache_t *cache) microdesc_cache_clear(cache); + cache->is_loaded = 1; + mm = cache->cache_content = tor_mmap_file(cache->cache_fname); if (mm) { added = microdescs_add_to_cache(cache, mm->data, mm->data+mm->size, @@ -697,7 +716,7 @@ microdesc_free_(microdesc_t *md, const char *fname, int lineno) /* Make sure that the microdesc was really removed from the appropriate data structures. */ if (md->held_in_map) { - microdesc_cache_t *cache = get_microdesc_cache(); + microdesc_cache_t *cache = get_microdesc_cache_noload(); microdesc_t *md2 = HT_FIND(microdesc_map, &cache->map, md); if (md2 == md) { log_warn(LD_BUG, "microdesc_free() called from %s:%d, but md was still " @@ -710,7 +729,7 @@ microdesc_free_(microdesc_t *md, const char *fname, int lineno) tor_fragile_assert(); } if (md->held_by_nodes) { - microdesc_cache_t *cache = get_microdesc_cache(); + microdesc_cache_t *cache = get_microdesc_cache_noload(); int found=0; const smartlist_t *nodes = nodelist_get_list(); const int ht_badness = HT_REP_IS_BAD_(microdesc_map, &cache->map); diff --git a/src/or/nodelist.c b/src/or/nodelist.c index 8f8adb42b5..2f272a1d56 100644 --- a/src/or/nodelist.c +++ b/src/or/nodelist.c @@ -176,7 +176,7 @@ nodelist_set_routerinfo(routerinfo_t *ri, routerinfo_t **ri_old_out) if (authdir_mode(get_options()) && !had_router) { const char *discard=NULL; - uint32_t status = dirserv_router_get_status(ri, &discard); + uint32_t status = dirserv_router_get_status(ri, &discard, LOG_INFO); dirserv_set_node_flags_from_authoritative_status(node, status); } diff --git a/src/test/test_util.c b/src/test/test_util.c index 2bffb17bfd..a6c423dcdf 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -4347,6 +4347,30 @@ test_util_writepid(void *arg) tor_free(contents); } +static void +test_util_get_avail_disk_space(void *arg) +{ + (void) arg; + int64_t val; + + /* No answer for nonexistent directory */ + val = tor_get_avail_disk_space("/akljasdfklsajdklasjkldjsa"); + tt_i64_op(val, OP_EQ, -1); + + /* Try the current directory */ + val = tor_get_avail_disk_space("."); + +#if !defined(HAVE_STATVFS) && !defined(_WIN32) + tt_i64_op(val, OP_EQ, -1); /* You don't have an implementation for this */ +#else + tt_i64_op(val, OP_GT, 0); /* You have some space. */ + tt_i64_op(val, OP_LT, ((int64_t)1)<<56); /* You don't have a zebibyte */ +#endif + + done: + ; +} + struct testcase_t util_tests[] = { UTIL_LEGACY(time), UTIL_TEST(parse_http_time, 0), @@ -4414,6 +4438,7 @@ struct testcase_t util_tests[] = { UTIL_TEST(hostname_validation, 0), UTIL_TEST(ipv4_validation, 0), UTIL_TEST(writepid, 0), + UTIL_TEST(get_avail_disk_space, 0), END_OF_TESTCASES }; diff --git a/src/tools/tor-fw-helper/README b/src/tools/tor-fw-helper/README index 3868cc2e4d..6a1ecaa1e4 100644 --- a/src/tools/tor-fw-helper/README +++ b/src/tools/tor-fw-helper/README @@ -1,7 +1,7 @@ We no longer recommend the use of this tool. Instead, please use the pure-Go version of tor-fw-helper available at - https://github.com/Yawning/tor-fw-helper + https://gitweb.torproject.org/tor-fw-helper.git Why? |