diff options
Diffstat (limited to 'src')
38 files changed, 466 insertions, 212 deletions
diff --git a/src/common/address.c b/src/common/address.c index 69049fa0af..cc3e31f65f 100644 --- a/src/common/address.c +++ b/src/common/address.c @@ -182,7 +182,7 @@ tor_addr_make_unspec(tor_addr_t *a) a->family = AF_UNSPEC; } -/** Set address <a>a</b> to the null address in address family <b>family</b>. +/** Set address <b>a</b> to the null address in address family <b>family</b>. * The null address for AF_INET is 0.0.0.0. The null address for AF_INET6 is * [::]. AF_UNSPEC is all null. */ void @@ -1445,26 +1445,13 @@ get_interface_address6(int severity, sa_family_t family, tor_addr_t *addr) * XXXX024 IPv6 deprecate some of these. */ -/** Return true iff <b>ip</b> (in host order) is an IP reserved to localhost, - * or reserved for local networks by RFC 1918. - */ -int -is_internal_IP(uint32_t ip, int for_listening) -{ - tor_addr_t myaddr; - myaddr.family = AF_INET; - myaddr.addr.in_addr.s_addr = htonl(ip); - - return tor_addr_is_internal(&myaddr, for_listening); -} - /** Given an address of the form "ip:port", try to divide it into its * ip and port portions, setting *<b>address_out</b> to a newly * allocated string holding the address portion and *<b>port_out</b> * to the port. * - * Don't do DNS lookups and don't allow domain names in the <ip> field. - * Don't accept <b>addrport</b> of the form "<ip>" or "<ip>:0". + * Don't do DNS lookups and don't allow domain names in the "ip" field. + * Don't accept <b>addrport</b> of the form "ip" or "ip:0". * * Return 0 on success, -1 on failure. */ int @@ -1585,7 +1572,7 @@ addr_mask_get_bits(uint32_t mask) return 0; if (mask == 0xFFFFFFFFu) return 32; - for (i=0; i<=32; ++i) { + for (i=1; i<=32; ++i) { if (mask == (uint32_t) ~((1u<<(32-i))-1)) { return i; } diff --git a/src/common/address.h b/src/common/address.h index d41c2f570f..61de3d2d96 100644 --- a/src/common/address.h +++ b/src/common/address.h @@ -215,7 +215,6 @@ int tor_addr_port_parse(int severity, const char *addrport, int tor_addr_hostname_is_local(const char *name); /* IPv4 helpers */ -int is_internal_IP(uint32_t ip, int for_listening); int addr_port_lookup(int severity, const char *addrport, char **address, uint32_t *addr, uint16_t *port_out); int parse_port_range(const char *port, uint16_t *port_min_out, diff --git a/src/common/compat.c b/src/common/compat.c index 8e2619f846..135f2c9af6 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -35,6 +35,12 @@ #ifdef HAVE_UNAME #include <sys/utsname.h> #endif +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif #ifdef HAVE_UNISTD_H #include <unistd.h> #endif @@ -178,9 +184,10 @@ tor_mmap_file(const char *filename) { int fd; /* router file */ char *string; - int page_size; + int page_size, result; tor_mmap_t *res; size_t size, filesize; + struct stat st; tor_assert(filename); @@ -194,9 +201,22 @@ tor_mmap_file(const char *filename) return NULL; } - /* XXXX why not just do fstat here? */ - size = filesize = (size_t) lseek(fd, 0, SEEK_END); - lseek(fd, 0, SEEK_SET); + /* Get the size of the file */ + result = fstat(fd, &st); + if (result != 0) { + int save_errno = errno; + log_warn(LD_FS, + "Couldn't fstat opened descriptor for \"%s\" during mmap: %s", + filename, strerror(errno)); + close(fd); + errno = save_errno; + return NULL; + } + size = filesize = (size_t)(st.st_size); + /* + * Should we check for weird crap like mmapping a named pipe here, + * or just wait for if (!size) below to fail? + */ /* ensure page alignment */ page_size = getpagesize(); size += (size%page_size) ? page_size-(size%page_size) : 0; @@ -227,12 +247,27 @@ tor_mmap_file(const char *filename) return res; } -/** Release storage held for a memory mapping. */ -void +/** Release storage held for a memory mapping; returns 0 on success, + * or -1 on failure (and logs a warning). */ +int tor_munmap_file(tor_mmap_t *handle) { - munmap((char*)handle->data, handle->mapping_size); - tor_free(handle); + int res; + + if (handle == NULL) + return 0; + + res = munmap((char*)handle->data, handle->mapping_size); + if (res == 0) { + /* munmap() succeeded */ + tor_free(handle); + } else { + log_warn(LD_FS, "Failed to munmap() in tor_munmap_file(): %s", + strerror(errno)); + res = -1; + } + + return res; } #elif defined(_WIN32) tor_mmap_t * @@ -314,17 +349,29 @@ tor_mmap_file(const char *filename) tor_munmap_file(res); return NULL; } -void + +/* Unmap the file, and return 0 for success or -1 for failure */ +int tor_munmap_file(tor_mmap_t *handle) { - if (handle->data) + if (handle == NULL) + return 0; + + if (handle->data) { /* This is an ugly cast, but without it, "data" in struct tor_mmap_t would have to be redefined as non-const. */ - UnmapViewOfFile( (LPVOID) handle->data); + BOOL ok = UnmapViewOfFile( (LPVOID) handle->data); + if (!ok) { + log_warn(LD_FS, "Failed to UnmapViewOfFile() in tor_munmap_file(): %d", + (int)GetLastError()); + } + } if (handle->mmap_handle != NULL) CloseHandle(handle->mmap_handle); tor_free(handle); + + return 0; } #else tor_mmap_t * @@ -340,13 +387,25 @@ tor_mmap_file(const char *filename) handle->size = st.st_size; return handle; } -void + +/** Unmap the file mapped with tor_mmap_file(), and return 0 for success + * or -1 for failure. + */ + +int tor_munmap_file(tor_mmap_t *handle) { - char *d = (char*)handle->data; + char *d = NULL; + if (handle == NULL) + return 0; + + d = (char*)handle->data; tor_free(d); memwipe(handle, 0, sizeof(tor_mmap_t)); tor_free(handle); + + /* Can't fail in this mmap()/munmap()-free case */ + return 0; } #endif diff --git a/src/common/compat.h b/src/common/compat.h index 32effa5c74..bb88818d82 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -292,7 +292,7 @@ typedef struct tor_mmap_t { } tor_mmap_t; tor_mmap_t *tor_mmap_file(const char *filename) ATTR_NONNULL((1)); -void tor_munmap_file(tor_mmap_t *handle) ATTR_NONNULL((1)); +int tor_munmap_file(tor_mmap_t *handle) ATTR_NONNULL((1)); int tor_snprintf(char *str, size_t size, const char *format, ...) CHECK_PRINTF(3,4) ATTR_NONNULL((1,3)); @@ -321,7 +321,7 @@ tor_memstr(const void *haystack, size_t hlen, const char *needle) extern const uint32_t TOR_##name##_TABLE[]; \ static INLINE int TOR_##name(char c) { \ uint8_t u = c; \ - return !!(TOR_##name##_TABLE[(u >> 5) & 7] & (1 << (u & 31))); \ + return !!(TOR_##name##_TABLE[(u >> 5) & 7] & (1u << (u & 31))); \ } DECLARE_CTYPE_FN(ISALPHA) DECLARE_CTYPE_FN(ISALNUM) diff --git a/src/common/crypto.c b/src/common/crypto.c index f357934ac9..8a4ffb6948 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1594,7 +1594,7 @@ struct crypto_digest_t { SHA256_CTX sha2; /**< state for SHA256 */ } d; /**< State for the digest we're using. Only one member of the * union is usable, depending on the value of <b>algorithm</b>. */ - ENUM_BF(digest_algorithm_t) algorithm : 8; /**< Which algorithm is in use? */ + digest_algorithm_bitfield_t algorithm : 8; /**< Which algorithm is in use? */ }; /** Allocate and return a new digest object to compute SHA1 digests. diff --git a/src/common/crypto.h b/src/common/crypto.h index 4f0f1c10c3..aa4271aa33 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -89,6 +89,7 @@ typedef enum { DIGEST_SHA256 = 1, } digest_algorithm_t; #define N_DIGEST_ALGORITHMS (DIGEST_SHA256+1) +#define digest_algorithm_bitfield_t ENUM_BF(digest_algorithm_t) /** A set of all the digests we know how to compute, taken on a single * string. Any digests that are shorter than 256 bits are right-padded diff --git a/src/common/memarea.c b/src/common/memarea.c index 0ae0ccca1d..e2d07fca9e 100644 --- a/src/common/memarea.c +++ b/src/common/memarea.c @@ -29,6 +29,13 @@ #error "void* is neither 4 nor 8 bytes long. I don't know how to align stuff." #endif +#if defined(__GNUC__) && defined(FLEXIBLE_ARRAY_MEMBER) +#define USE_ALIGNED_ATTRIBUTE +#define U_MEM mem +#else +#define U_MEM u.mem +#endif + #ifdef USE_SENTINELS /** Magic value that we stick at the end of a memarea so we can make sure * there are no run-off-the-end bugs. */ @@ -39,12 +46,12 @@ * end, set those bytes. */ #define SET_SENTINEL(chunk) \ STMT_BEGIN \ - set_uint32( &(chunk)->u.mem[chunk->mem_size], SENTINEL_VAL ); \ + set_uint32( &(chunk)->U_MEM[chunk->mem_size], SENTINEL_VAL ); \ STMT_END /** Assert that the sentinel on a memarea is set correctly. */ #define CHECK_SENTINEL(chunk) \ STMT_BEGIN \ - uint32_t sent_val = get_uint32(&(chunk)->u.mem[chunk->mem_size]); \ + uint32_t sent_val = get_uint32(&(chunk)->U_MEM[chunk->mem_size]); \ tor_assert(sent_val == SENTINEL_VAL); \ STMT_END #else @@ -71,19 +78,23 @@ realign_pointer(void *ptr) typedef struct memarea_chunk_t { /** Next chunk in this area. Only kept around so we can free it. */ struct memarea_chunk_t *next_chunk; - size_t mem_size; /**< How much RAM is available in u.mem, total? */ - char *next_mem; /**< Next position in u.mem to allocate data at. If it's + size_t mem_size; /**< How much RAM is available in mem, total? */ + char *next_mem; /**< Next position in mem to allocate data at. If it's * greater than or equal to mem+mem_size, this chunk is * full. */ +#ifdef USE_ALIGNED_ATTRIBUTE + char mem[FLEXIBLE_ARRAY_MEMBER] __attribute__((aligned(MEMAREA_ALIGN))); +#else union { char mem[1]; /**< Memory space in this chunk. */ void *void_for_alignment_; /**< Dummy; used to make sure mem is aligned. */ } u; +#endif } memarea_chunk_t; /** How many bytes are needed for overhead before we get to the memory part * of a chunk? */ -#define CHUNK_HEADER_SIZE STRUCT_OFFSET(memarea_chunk_t, u) +#define CHUNK_HEADER_SIZE STRUCT_OFFSET(memarea_chunk_t, U_MEM) /** What's the smallest that we'll allocate a chunk? */ #define CHUNK_SIZE 4096 @@ -121,7 +132,7 @@ alloc_chunk(size_t sz, int freelist_ok) res = tor_malloc(chunk_size); res->next_chunk = NULL; res->mem_size = chunk_size - CHUNK_HEADER_SIZE - SENTINEL_LEN; - res->next_mem = res->u.mem; + res->next_mem = res->U_MEM; tor_assert(res->next_mem+res->mem_size+SENTINEL_LEN == ((char*)res)+chunk_size); tor_assert(realign_pointer(res->next_mem) == res->next_mem); @@ -140,7 +151,7 @@ chunk_free_unchecked(memarea_chunk_t *chunk) ++freelist_len; chunk->next_chunk = freelist; freelist = chunk; - chunk->next_mem = chunk->u.mem; + chunk->next_mem = chunk->U_MEM; } else { tor_free(chunk); } @@ -183,7 +194,7 @@ memarea_clear(memarea_t *area) } area->first->next_chunk = NULL; } - area->first->next_mem = area->first->u.mem; + area->first->next_mem = area->first->U_MEM; } /** Remove all unused memarea chunks from the internal freelist. */ @@ -207,7 +218,7 @@ memarea_owns_ptr(const memarea_t *area, const void *p) memarea_chunk_t *chunk; const char *ptr = p; for (chunk = area->first; chunk; chunk = chunk->next_chunk) { - if (ptr >= chunk->u.mem && ptr < chunk->next_mem) + if (ptr >= chunk->U_MEM && ptr < chunk->next_mem) return 1; } return 0; @@ -226,7 +237,7 @@ memarea_alloc(memarea_t *area, size_t sz) tor_assert(sz < SIZE_T_CEILING); if (sz == 0) sz = 1; - if (chunk->next_mem+sz > chunk->u.mem+chunk->mem_size) { + if (chunk->next_mem+sz > chunk->U_MEM+chunk->mem_size) { if (sz+CHUNK_HEADER_SIZE >= CHUNK_SIZE) { /* This allocation is too big. Stick it in a special chunk, and put * that chunk second in the list. */ @@ -244,8 +255,8 @@ memarea_alloc(memarea_t *area, size_t sz) result = chunk->next_mem; chunk->next_mem = chunk->next_mem + sz; /* Reinstate these if bug 930 ever comes back - tor_assert(chunk->next_mem >= chunk->u.mem); - tor_assert(chunk->next_mem <= chunk->u.mem+chunk->mem_size); + tor_assert(chunk->next_mem >= chunk->U_MEM); + tor_assert(chunk->next_mem <= chunk->U_MEM+chunk->mem_size); */ chunk->next_mem = realign_pointer(chunk->next_mem); return result; @@ -304,8 +315,8 @@ memarea_get_stats(memarea_t *area, size_t *allocated_out, size_t *used_out) for (chunk = area->first; chunk; chunk = chunk->next_chunk) { CHECK_SENTINEL(chunk); a += CHUNK_HEADER_SIZE + chunk->mem_size; - tor_assert(chunk->next_mem >= chunk->u.mem); - u += CHUNK_HEADER_SIZE + (chunk->next_mem - chunk->u.mem); + tor_assert(chunk->next_mem >= chunk->U_MEM); + u += CHUNK_HEADER_SIZE + (chunk->next_mem - chunk->U_MEM); } *allocated_out = a; *used_out = u; @@ -320,9 +331,9 @@ memarea_assert_ok(memarea_t *area) for (chunk = area->first; chunk; chunk = chunk->next_chunk) { CHECK_SENTINEL(chunk); - tor_assert(chunk->next_mem >= chunk->u.mem); + tor_assert(chunk->next_mem >= chunk->U_MEM); tor_assert(chunk->next_mem <= - (char*) realign_pointer(chunk->u.mem+chunk->mem_size)); + (char*) realign_pointer(chunk->U_MEM+chunk->mem_size)); } } diff --git a/src/common/tortls.c b/src/common/tortls.c index 315a767e9e..9ba8fd683e 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -149,6 +149,7 @@ typedef enum { TOR_TLS_ST_SENTCLOSE, TOR_TLS_ST_CLOSED, TOR_TLS_ST_RENEGOTIATE, TOR_TLS_ST_BUFFEREVENT } tor_tls_state_t; +#define tor_tls_state_bitfield_t ENUM_BF(tor_tls_state_t) /** Holds a SSL object and its associated data. Members are only * accessed from within tortls.c. @@ -159,7 +160,7 @@ struct tor_tls_t { SSL *ssl; /**< An OpenSSL SSL object. */ int socket; /**< The underlying file descriptor for this TLS connection. */ char *address; /**< An address to log when describing this connection. */ - ENUM_BF(tor_tls_state_t) state : 3; /**< The current SSL state, + tor_tls_state_bitfield_t state : 3; /**< The current SSL state, * depending on which operations * have completed successfully. */ unsigned int isServer:1; /**< True iff this is a server-side connection */ @@ -2311,6 +2312,7 @@ log_cert_lifetime(int severity, const X509 *cert, const char *problem) char mytime[33]; time_t now = time(NULL); struct tm tm; + size_t n; if (problem) tor_log(severity, LD_GENERAL, @@ -2336,11 +2338,17 @@ log_cert_lifetime(int severity, const X509 *cert, const char *problem) BIO_get_mem_ptr(bio, &buf); s2 = tor_strndup(buf->data, buf->length); - strftime(mytime, 32, "%b %d %H:%M:%S %Y UTC", tor_gmtime_r(&now, &tm)); - - tor_log(severity, LD_GENERAL, - "(certificate lifetime runs from %s through %s. Your time is %s.)", - s1,s2,mytime); + n = strftime(mytime, 32, "%b %d %H:%M:%S %Y UTC", tor_gmtime_r(&now, &tm)); + if (n > 0) { + tor_log(severity, LD_GENERAL, + "(certificate lifetime runs from %s through %s. Your time is %s.)", + s1,s2,mytime); + } else { + tor_log(severity, LD_GENERAL, + "(certificate lifetime runs from %s through %s. " + "Couldn't get your time.)", + s1, s2); + } end: /* Not expected to get invoked */ diff --git a/src/common/util.c b/src/common/util.c index 3c2f6643ad..a50f2566db 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -898,8 +898,8 @@ tor_digest_is_zero(const char *digest) return tor_memeq(digest, ZERO_DIGEST, DIGEST_LEN); } -/** Return true if <b>string</b> is a valid '<key>=[<value>]' string. - * <value> is optional, to indicate the empty string. Log at logging +/** Return true if <b>string</b> is a valid 'key=[value]' string. + * "value" is optional, to indicate the empty string. Log at logging * <b>severity</b> if something ugly happens. */ int string_is_key_value(int severity, const char *string) @@ -2141,6 +2141,7 @@ static int finish_writing_to_file_impl(open_file_t *file_data, int abort_write) { int r = 0; + tor_assert(file_data && file_data->filename); if (file_data->stdio_file) { if (fclose(file_data->stdio_file)) { @@ -2157,7 +2158,13 @@ finish_writing_to_file_impl(open_file_t *file_data, int abort_write) if (file_data->rename_on_close) { tor_assert(file_data->tempname && file_data->filename); if (abort_write) { - unlink(file_data->tempname); + int res = unlink(file_data->tempname); + if (res != 0) { + /* We couldn't unlink and we'll leave a mess behind */ + log_warn(LD_FS, "Failed to unlink %s: %s", + file_data->tempname, strerror(errno)); + r = -1; + } } else { tor_assert(strcmp(file_data->filename, file_data->tempname)); if (replace_file(file_data->tempname, file_data->filename)) { @@ -3026,7 +3033,7 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap) /** Minimal sscanf replacement: parse <b>buf</b> according to <b>pattern</b> * and store the results in the corresponding argument fields. Differs from * sscanf in that: - * <ul><li>It only handles %u, %lu, %x, %lx, %<NUM>s, %d, %ld, %lf, and %c. + * <ul><li>It only handles %u, %lu, %x, %lx, %[NUM]s, %d, %ld, %lf, and %c. * <li>It only handles decimal inputs for %lf. (12.3, not 1.23e1) * <li>It does not handle arbitrarily long widths. * <li>Numbers do not consume any space characters. diff --git a/src/ext/csiphash.c b/src/ext/csiphash.c index 4f58c4a141..2a96f28815 100644 --- a/src/ext/csiphash.c +++ b/src/ext/csiphash.c @@ -81,11 +81,16 @@ HALF_ROUND(v0,v1,v2,v3,13,16); \ HALF_ROUND(v2,v1,v0,v3,17,21); +#if 0 +/* This does not seem to save very much runtime in the fast case, and it's + * potentially a big loss in the slow case where we're misaligned and we cross + * a cache line. */ #if (defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ defined(__x86_64) || defined(__x86_64__) || \ defined(_M_AMD64) || defined(_M_X64) || defined(__INTEL__)) # define UNALIGNED_OK 1 #endif +#endif uint64_t siphash24(const void *src, unsigned long src_sz, const struct sipkey *key) { uint64_t k0 = key->k0; diff --git a/src/or/addressmap.c b/src/or/addressmap.c index 9bc79bd84b..998770a3db 100644 --- a/src/or/addressmap.c +++ b/src/or/addressmap.c @@ -45,7 +45,7 @@ typedef struct { char *new_address; time_t expires; - ENUM_BF(addressmap_entry_source_t) source:3; + addressmap_entry_source_bitfield_t source:3; unsigned src_wildcard:1; unsigned dst_wildcard:1; short num_resolve_failures; diff --git a/src/or/channel.h b/src/or/channel.h index 7e3f5ad075..7ec222df0f 100644 --- a/src/or/channel.h +++ b/src/or/channel.h @@ -21,7 +21,7 @@ struct cell_queue_entry_s; TOR_SIMPLEQ_HEAD(chan_cell_queue, cell_queue_entry_s) incoming_queue; typedef struct chan_cell_queue chan_cell_queue_t; -/* +/** * Channel struct; see the channel_t typedef in or.h. A channel is an * abstract interface for the OR-to-OR connection, similar to connection_or_t, * but without the strong coupling to the underlying TLS implementation. They @@ -31,18 +31,18 @@ typedef struct chan_cell_queue chan_cell_queue_t; */ struct channel_s { - /* Magic number for type-checking cast macros */ + /** Magic number for type-checking cast macros */ uint32_t magic; - /* Current channel state */ + /** Current channel state */ channel_state_t state; - /* Globally unique ID number for a channel over the lifetime of a Tor + /** Globally unique ID number for a channel over the lifetime of a Tor * process. */ uint64_t global_identifier; - /* Should we expect to see this channel in the channel lists? */ + /** Should we expect to see this channel in the channel lists? */ unsigned char registered:1; /** has this channel ever been open? */ @@ -57,28 +57,28 @@ struct channel_s { CHANNEL_CLOSE_FOR_ERROR } reason_for_closing; - /* Timestamps for both cell channels and listeners */ + /** Timestamps for both cell channels and listeners */ time_t timestamp_created; /* Channel created */ time_t timestamp_active; /* Any activity */ /* Methods implemented by the lower layer */ - /* Free a channel */ + /** Free a channel */ void (*free)(channel_t *); - /* Close an open channel */ + /** Close an open channel */ void (*close)(channel_t *); - /* Describe the transport subclass for this channel */ + /** Describe the transport subclass for this channel */ const char * (*describe_transport)(channel_t *); - /* Optional method to dump transport-specific statistics on the channel */ + /** Optional method to dump transport-specific statistics on the channel */ void (*dumpstats)(channel_t *, int); - /* Registered handlers for incoming cells */ + /** Registered handlers for incoming cells */ channel_cell_handler_fn_ptr cell_handler; channel_var_cell_handler_fn_ptr var_cell_handler; /* Methods implemented by the lower layer */ - /* + /** * Ask the underlying transport what the remote endpoint address is, in * a tor_addr_t. This is optional and subclasses may leave this NULL. * If they implement it, they should write the address out to the @@ -90,75 +90,75 @@ struct channel_s { #define GRD_FLAG_ORIGINAL 1 #define GRD_FLAG_ADDR_ONLY 2 - /* + /** * Get a text description of the remote endpoint; canonicalized if the flag * GRD_FLAG_ORIGINAL is not set, or the one we originally connected * to/received from if it is. If GRD_FLAG_ADDR_ONLY is set, we return only * the original address. */ const char * (*get_remote_descr)(channel_t *, int); - /* Check if the lower layer has queued writes */ + /** Check if the lower layer has queued writes */ int (*has_queued_writes)(channel_t *); - /* + /** * If the second param is zero, ask the lower layer if this is * 'canonical', for a transport-specific definition of canonical; if * it is 1, ask if the answer to the preceding query is safe to rely * on. */ int (*is_canonical)(channel_t *, int); - /* Check if this channel matches a specified extend_info_t */ + /** Check if this channel matches a specified extend_info_t */ int (*matches_extend_info)(channel_t *, extend_info_t *); - /* Check if this channel matches a target address when extending */ + /** Check if this channel matches a target address when extending */ int (*matches_target)(channel_t *, const tor_addr_t *); - /* Write a cell to an open channel */ + /** Write a cell to an open channel */ int (*write_cell)(channel_t *, cell_t *); - /* Write a packed cell to an open channel */ + /** Write a packed cell to an open channel */ int (*write_packed_cell)(channel_t *, packed_cell_t *); - /* Write a variable-length cell to an open channel */ + /** Write a variable-length cell to an open channel */ int (*write_var_cell)(channel_t *, var_cell_t *); - /* + /** * Hash of the public RSA key for the other side's identity key, or * zeroes if the other side hasn't shown us a valid identity key. */ char identity_digest[DIGEST_LEN]; - /* Nickname of the OR on the other side, or NULL if none. */ + /** Nickname of the OR on the other side, or NULL if none. */ char *nickname; - /* + /** * Linked list of channels with the same identity digest, for the * digest->channel map */ TOR_LIST_ENTRY(channel_s) next_with_same_id; - /* List of incoming cells to handle */ + /** List of incoming cells to handle */ chan_cell_queue_t incoming_queue; - /* List of queued outgoing cells */ + /** List of queued outgoing cells */ chan_cell_queue_t outgoing_queue; - /* Circuit mux for circuits sending on this channel */ + /** Circuit mux for circuits sending on this channel */ circuitmux_t *cmux; - /* Circuit ID generation stuff for use by circuitbuild.c */ + /** Circuit ID generation stuff for use by circuitbuild.c */ - /* + /** * When we send CREATE cells along this connection, which half of the * space should we use? */ - ENUM_BF(circ_id_type_t) circ_id_type:2; + circ_id_type_bitfield_t circ_id_type:2; /** DOCDOC*/ unsigned wide_circ_ids:1; - /* + /** * Which circ_id do we try to use next on this connection? This is * always in the range 0..1<<15-1. */ circid_t next_circ_id; - /* For how many circuits are we n_chan? What about p_chan? */ + /** For how many circuits are we n_chan? What about p_chan? */ unsigned int num_n_circuits, num_p_circuits; - /* + /** * True iff this channel shouldn't get any new circs attached to it, * because the connection is too old, or because there's a better one. * More generally, this flag is used to note an unhealthy connection; @@ -210,7 +210,7 @@ struct channel_listener_s { */ uint64_t global_identifier; - /* Should we expect to see this channel in the channel lists? */ + /** Should we expect to see this channel in the channel lists? */ unsigned char registered:1; /** Why did we close? @@ -222,31 +222,31 @@ struct channel_listener_s { CHANNEL_LISTENER_CLOSE_FOR_ERROR } reason_for_closing; - /* Timestamps for both cell channels and listeners */ + /** Timestamps for both cell channels and listeners */ time_t timestamp_created; /* Channel created */ time_t timestamp_active; /* Any activity */ /* Methods implemented by the lower layer */ - /* Free a channel */ + /** Free a channel */ void (*free)(channel_listener_t *); - /* Close an open channel */ + /** Close an open channel */ void (*close)(channel_listener_t *); - /* Describe the transport subclass for this channel */ + /** Describe the transport subclass for this channel */ const char * (*describe_transport)(channel_listener_t *); - /* Optional method to dump transport-specific statistics on the channel */ + /** Optional method to dump transport-specific statistics on the channel */ void (*dumpstats)(channel_listener_t *, int); - /* Registered listen handler to call on incoming connection */ + /** Registered listen handler to call on incoming connection */ channel_listener_fn_ptr listener; - /* List of pending incoming connections */ + /** List of pending incoming connections */ smartlist_t *incoming_list; - /* Timestamps for listeners */ + /** Timestamps for listeners */ time_t timestamp_accepted; - /* Counters for listeners */ + /** Counters for listeners */ uint64_t n_accepted; }; diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 5b8225a36e..b03b590aa5 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -1089,15 +1089,15 @@ circuit_get_by_edge_conn(edge_connection_t *conn) void circuit_unlink_all_from_channel(channel_t *chan, int reason) { - circuit_t *circ; smartlist_t *detached = smartlist_new(); -#define DEBUG_CIRCUIT_UNLINK_ALL +/* #define DEBUG_CIRCUIT_UNLINK_ALL */ channel_unlink_all_circuits(chan, detached); #ifdef DEBUG_CIRCUIT_UNLINK_ALL { + circuit_t *circ; smartlist_t *detached_2 = smartlist_new(); int mismatch = 0, badlen = 0; diff --git a/src/or/config.c b/src/or/config.c index da6aec0c16..4a6b30172c 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -1149,12 +1149,31 @@ options_act_reversible(const or_options_t *old_options, char **msg) tor_free(severity); tor_log_update_sigsafe_err_fds(); } - if (get_min_log_level() >= LOG_INFO && - get_min_log_level() != old_min_log_level) { - log_warn(LD_GENERAL, "Your log may contain sensitive information: you're " - "logging more than \"notice\". Please log safely. Don't log " - "unless it serves an important reason, and overwrite the log " - "afterwards."); + + { + const char *badness = NULL; + int bad_safelog = 0, bad_severity = 0, new_badness = 0; + if (options->SafeLogging_ != SAFELOG_SCRUB_ALL) { + bad_safelog = 1; + if (!old_options || old_options->SafeLogging_ != options->SafeLogging_) + new_badness = 1; + } + if (get_min_log_level() >= LOG_INFO) { + bad_severity = 1; + if (get_min_log_level() != old_min_log_level) + new_badness = 1; + } + if (bad_safelog && bad_severity) + badness = "you disabled SafeLogging, and " + "you're logging more than \"notice\""; + else if (bad_safelog) + badness = "you disabled SafeLogging"; + else + badness = "you're logging more than \"notice\""; + if (new_badness) + log_warn(LD_GENERAL, "Your log may contain sensitive information - %s. " + "Don't log unless it serves an important reason. " + "Overwrite the log afterwards.", badness); } SMARTLIST_FOREACH(replaced_listeners, connection_t *, conn, @@ -1355,13 +1374,6 @@ options_act(const or_options_t *old_options) "(e.g. set 'ExtORPort auto')."); } - if (options->SafeLogging_ != SAFELOG_SCRUB_ALL && - (!old_options || old_options->SafeLogging_ != options->SafeLogging_)) { - log_warn(LD_GENERAL, "Your log may contain sensitive information - you " - "disabled SafeLogging. Please log safely. Don't log unless it " - "serves an important reason. Overwrite the log afterwards."); - } - if (options->Bridges) { mark_bridge_list(); for (cl = options->Bridges; cl; cl = cl->next) { @@ -2060,6 +2072,7 @@ resolve_my_address(int warn_severity, const or_options_t *options, int notice_severity = warn_severity <= LOG_NOTICE ? LOG_NOTICE : warn_severity; + tor_addr_t myaddr; tor_assert(addr_out); /* @@ -2110,24 +2123,26 @@ resolve_my_address(int warn_severity, const or_options_t *options, "local interface. Using that.", fmt_addr32(addr)); strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname)); } else { /* resolved hostname into addr */ + tor_addr_from_ipv4h(&myaddr, addr); + if (!explicit_hostname && - is_internal_IP(addr, 0)) { - uint32_t interface_ip; + tor_addr_is_internal(&myaddr, 0)) { + tor_addr_t interface_ip; log_fn(notice_severity, LD_CONFIG, "Guessed local hostname '%s' " "resolves to a private IP address (%s). Trying something " "else.", hostname, fmt_addr32(addr)); - if (get_interface_address(warn_severity, &interface_ip)) { + if (get_interface_address6(warn_severity, AF_INET, &interface_ip)<0) { log_fn(warn_severity, LD_CONFIG, "Could not get local interface IP address. Too bad."); - } else if (is_internal_IP(interface_ip, 0)) { + } else if (tor_addr_is_internal(&interface_ip, 0)) { log_fn(notice_severity, LD_CONFIG, "Interface IP address '%s' is a private address too. " - "Ignoring.", fmt_addr32(interface_ip)); + "Ignoring.", fmt_addr(&interface_ip)); } else { from_interface = 1; - addr = interface_ip; + addr = tor_addr_to_ipv4h(&interface_ip); log_fn(notice_severity, LD_CONFIG, "Learned IP address '%s' for local interface." " Using that.", fmt_addr32(addr)); @@ -2145,8 +2160,10 @@ resolve_my_address(int warn_severity, const or_options_t *options, * out if it is and we don't want that. */ + tor_addr_from_ipv4h(&myaddr,addr); + addr_string = tor_dup_ip(addr); - if (is_internal_IP(addr, 0)) { + if (tor_addr_is_internal(&myaddr, 0)) { /* make sure we're ok with publishing an internal IP */ if (!options->DirAuthorities && !options->AlternateDirAuthority) { /* if they are using the default authorities, disallow internal IPs @@ -2252,7 +2269,7 @@ is_local_addr(const tor_addr_t *addr) * resolve_my_address will never be called at all). In those cases, * last_resolved_addr will be 0, and so checking to see whether ip is on * the same /24 as last_resolved_addr will be the same as checking whether - * it was on net 0, which is already done by is_internal_IP. + * it was on net 0, which is already done by tor_addr_is_internal. */ if ((last_resolved_addr & (uint32_t)0xffffff00ul) == (ip & (uint32_t)0xffffff00ul)) @@ -6458,7 +6475,10 @@ remove_file_if_very_old(const char *fname, time_t now) format_local_iso_time(buf, st.st_mtime); log_notice(LD_GENERAL, "Obsolete file %s hasn't been modified since %s. " "Removing it.", fname, buf); - unlink(fname); + if (unlink(fname) != 0) { + log_warn(LD_FS, "Failed to unlink %s: %s", + fname, strerror(errno)); + } } } diff --git a/src/or/connection_or.c b/src/or/connection_or.c index f7a48ecbe5..04ad2cc008 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -215,7 +215,7 @@ connection_or_clear_ext_or_id_map(void) orconn_ext_or_id_map = NULL; } -/** Creates an Extended ORPort identifier for <b>conn<b/> and deposits +/** Creates an Extended ORPort identifier for <b>conn</b> and deposits * it into the global list of identifiers. */ void connection_or_set_ext_or_identifier(or_connection_t *conn) diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c index ecf0d2035d..209274da64 100644 --- a/src/or/cpuworker.c +++ b/src/or/cpuworker.c @@ -686,7 +686,7 @@ assign_onionskin_to_cpuworker(connection_t *cpuworker, } if (connection_or_digest_is_known_relay(circ->p_chan->identity_digest)) - rep_hist_note_circuit_handshake_completed(onionskin->handshake_type); + rep_hist_note_circuit_handshake_assigned(onionskin->handshake_type); should_time = should_time_request(onionskin->handshake_type); memset(&req, 0, sizeof(req)); diff --git a/src/or/directory.c b/src/or/directory.c index 5fe6897b51..8070a76a55 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -1383,13 +1383,14 @@ http_set_address_origin(const char *headers, connection_t *conn) if (!fwd) fwd = http_get_header(headers, "X-Forwarded-For: "); if (fwd) { - struct in_addr in; - if (!tor_inet_aton(fwd, &in) || is_internal_IP(ntohl(in.s_addr), 0)) { - log_debug(LD_DIR, "Ignoring unrecognized or internal IP %s", - escaped(fwd)); + tor_addr_t toraddr; + if (tor_addr_parse(&toraddr,fwd) == -1 || + tor_addr_is_internal(&toraddr,0)) { + log_debug(LD_DIR, "Ignoring local/internal IP %s", escaped(fwd)); tor_free(fwd); return; } + tor_free(conn->address); conn->address = tor_strdup(fwd); tor_free(fwd); diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 19ed12d7c1..b6c5dd41f4 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -504,9 +504,12 @@ dirserv_free_fingerprint_list(void) static int dirserv_router_has_valid_address(routerinfo_t *ri) { + tor_addr_t addr; if (get_options()->DirAllowPrivateAddresses) return 0; /* whatever it is, we're fine with it */ - if (is_internal_IP(ri->addr, 0)) { + tor_addr_from_ipv4h(&addr, ri->addr); + + if (tor_addr_is_internal(&addr, 0)) { log_info(LD_DIRSERV, "Router %s published internal IP address. Refusing.", router_describe(ri)); diff --git a/src/or/dnsserv.c b/src/or/dnsserv.c index ebff7b524c..4190e9cc23 100644 --- a/src/or/dnsserv.c +++ b/src/or/dnsserv.c @@ -131,6 +131,16 @@ evdns_server_callback(struct evdns_server_request *req, void *data_) else entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR; + if (q->type == EVDNS_TYPE_A) { + entry_conn->ipv4_traffic_ok = 1; + entry_conn->ipv6_traffic_ok = 0; + entry_conn->prefer_ipv6_traffic = 0; + } else if (q->type == EVDNS_TYPE_AAAA) { + entry_conn->ipv4_traffic_ok = 0; + entry_conn->ipv6_traffic_ok = 1; + entry_conn->prefer_ipv6_traffic = 1; + } + strlcpy(entry_conn->socks_request->address, q->name, sizeof(entry_conn->socks_request->address)); diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h index 73ac017ff0..e229f3b79a 100644 --- a/src/or/entrynodes.h +++ b/src/or/entrynodes.h @@ -5,7 +5,7 @@ /* See LICENSE for licensing information */ /** - * \file guardnodes.h + * \file entrynodes.h * \brief Header file for circuitbuild.c. **/ diff --git a/src/or/geoip.c b/src/or/geoip.c index 2e39fe0eb7..f722bac468 100644 --- a/src/or/geoip.c +++ b/src/or/geoip.c @@ -812,7 +812,7 @@ char * geoip_get_transport_history(void) { unsigned granularity = IP_GRANULARITY; - /** String hash table <name of transport> -> <number of users>. */ + /** String hash table (name of transport) -> (number of users). */ strmap_t *transport_counts = strmap_new(); /** Smartlist that contains copies of the names of the transports diff --git a/src/or/hibernate.c b/src/or/hibernate.c index 607dec8cd5..bbda8424f6 100644 --- a/src/or/hibernate.c +++ b/src/or/hibernate.c @@ -648,7 +648,15 @@ read_bandwidth_usage(void) { char *fname = get_datadir_fname("bw_accounting"); - unlink(fname); + int res; + + res = unlink(fname); + if (res != 0) { + log_warn(LD_FS, + "Failed to unlink %s: %s", + fname, strerror(errno)); + } + tor_free(fname); } diff --git a/src/or/main.c b/src/or/main.c index 7294c8955a..feca35c440 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -1196,7 +1196,7 @@ run_scheduled_events(time_t now) int i; int have_dir_info; - /** 0. See if we've been asked to shut down and our timeout has + /* 0. See if we've been asked to shut down and our timeout has * expired; or if our bandwidth limits are exhausted and we * should hibernate; or if it's time to wake up from hibernation. */ @@ -1213,7 +1213,7 @@ run_scheduled_events(time_t now) /* 0c. If we've deferred log messages for the controller, handle them now */ flush_pending_log_callbacks(); - /** 1a. Every MIN_ONION_KEY_LIFETIME seconds, rotate the onion keys, + /* 1a. Every MIN_ONION_KEY_LIFETIME seconds, rotate the onion keys, * shut down and restart all cpuworkers, and update the directory if * necessary. */ @@ -1247,7 +1247,7 @@ run_scheduled_events(time_t now) if (options->UseBridges) fetch_bridge_descriptors(options, now); - /** 1b. Every MAX_SSL_KEY_LIFETIME_INTERNAL seconds, we change our + /* 1b. Every MAX_SSL_KEY_LIFETIME_INTERNAL seconds, we change our * TLS context. */ if (!last_rotated_x509_certificate) last_rotated_x509_certificate = now; @@ -1273,7 +1273,7 @@ run_scheduled_events(time_t now) time_to_add_entropy = now + ENTROPY_INTERVAL; } - /** 1c. If we have to change the accounting interval or record + /* 1c. If we have to change the accounting interval or record * bandwidth used in this accounting interval, do so. */ if (accounting_is_enabled(options)) accounting_run_housekeeping(now); @@ -1286,7 +1286,7 @@ run_scheduled_events(time_t now) dirserv_test_reachability(now); } - /** 1d. Periodically, we discount older stability information so that new + /* 1d. Periodically, we discount older stability information so that new * stability info counts more, and save the stability information to disk as * appropriate. */ if (time_to_downrate_stability < now) @@ -1405,7 +1405,7 @@ run_scheduled_events(time_t now) dns_init(); } - /** 2. Periodically, we consider force-uploading our descriptor + /* 2. Periodically, we consider force-uploading our descriptor * (if we've passed our internal checks). */ /** How often do we check whether part of our router info has changed in a @@ -1465,11 +1465,11 @@ run_scheduled_events(time_t now) update_networkstatus_downloads(now); } - /** 2c. Let directory voting happen. */ + /* 2c. Let directory voting happen. */ if (authdir_mode_v3(options)) dirvote_act(options, now); - /** 3a. Every second, we examine pending circuits and prune the + /* 3a. Every second, we examine pending circuits and prune the * ones which have been pending for more than a few seconds. * We do this before step 4, so it can try building more if * it's not comfortable with the number of available circuits. @@ -1478,24 +1478,24 @@ run_scheduled_events(time_t now) * it can't, currently), we should do this more often.) */ circuit_expire_building(); - /** 3b. Also look at pending streams and prune the ones that 'began' + /* 3b. Also look at pending streams and prune the ones that 'began' * a long time ago but haven't gotten a 'connected' yet. * Do this before step 4, so we can put them back into pending * state to be picked up by the new circuit. */ connection_ap_expire_beginning(); - /** 3c. And expire connections that we've held open for too long. + /* 3c. And expire connections that we've held open for too long. */ connection_expire_held_open(); - /** 3d. And every 60 seconds, we relaunch listeners if any died. */ + /* 3d. And every 60 seconds, we relaunch listeners if any died. */ if (!net_is_disabled() && time_to_check_listeners < now) { retry_all_listeners(NULL, NULL, 0); time_to_check_listeners = now+60; } - /** 4. Every second, we try a new circuit if there are no valid + /* 4. Every second, we try a new circuit if there are no valid * circuits. Every NewCircuitPeriod seconds, we expire circuits * that became dirty more than MaxCircuitDirtiness seconds ago, * and we make a new circ if there are no clean circuits. @@ -1508,7 +1508,7 @@ run_scheduled_events(time_t now) if (now % 10 == 5) circuit_expire_old_circuits_serverside(now); - /** 5. We do housekeeping for each connection... */ + /* 5. We do housekeeping for each connection... */ connection_or_set_bad_connections(NULL, 0); for (i=0;i<smartlist_len(connection_array);i++) { run_connection_housekeeping(i, now); @@ -1528,30 +1528,30 @@ run_scheduled_events(time_t now) time_to_shrink_memory = now + MEM_SHRINK_INTERVAL; } - /** 6. And remove any marked circuits... */ + /* 6. And remove any marked circuits... */ circuit_close_all_marked(); - /** 7. And upload service descriptors if necessary. */ + /* 7. And upload service descriptors if necessary. */ if (can_complete_circuit && !net_is_disabled()) { rend_consider_services_upload(now); rend_consider_descriptor_republication(); } - /** 8. and blow away any connections that need to die. have to do this now, + /* 8. and blow away any connections that need to die. have to do this now, * because if we marked a conn for close and left its socket -1, then * we'll pass it to poll/select and bad things will happen. */ close_closeable_connections(); - /** 8b. And if anything in our state is ready to get flushed to disk, we + /* 8b. And if anything in our state is ready to get flushed to disk, we * flush it. */ or_state_save(now); - /** 8c. Do channel cleanup just like for connections */ + /* 8c. Do channel cleanup just like for connections */ channel_run_cleanup(); channel_listener_run_cleanup(); - /** 9. and if we're an exit node, check whether our DNS is telling stories + /* 9. and if we're an exit node, check whether our DNS is telling stories * to us. */ if (!net_is_disabled() && public_server_mode(options) && @@ -1566,7 +1566,7 @@ run_scheduled_events(time_t now) } } - /** 10. write bridge networkstatus file to disk */ + /* 10. write bridge networkstatus file to disk */ if (options->BridgeAuthoritativeDir && time_to_write_bridge_status_file < now) { networkstatus_dump_bridge_status_to_file(now); @@ -1574,7 +1574,7 @@ run_scheduled_events(time_t now) time_to_write_bridge_status_file = now+BRIDGE_STATUSFILE_INTERVAL; } - /** 11. check the port forwarding app */ + /* 11. check the port forwarding app */ if (!net_is_disabled() && time_to_check_port_forwarding < now && options->PortForwarding && @@ -1592,11 +1592,11 @@ run_scheduled_events(time_t now) time_to_check_port_forwarding = now+PORT_FORWARDING_CHECK_INTERVAL; } - /** 11b. check pending unconfigured managed proxies */ + /* 11b. check pending unconfigured managed proxies */ if (!net_is_disabled() && pt_proxies_configuration_pending()) pt_configure_remaining_proxies(); - /** 12. write the heartbeat message */ + /* 12. write the heartbeat message */ if (options->HeartbeatPeriod && time_to_next_heartbeat <= now) { if (time_to_next_heartbeat) /* don't log the first heartbeat */ @@ -2574,10 +2574,19 @@ tor_cleanup(void) time_t now = time(NULL); /* Remove our pid file. We don't care if there was an error when we * unlink, nothing we could do about it anyways. */ - if (options->PidFile) - unlink(options->PidFile); - if (options->ControlPortWriteToFile) - unlink(options->ControlPortWriteToFile); + if (options->PidFile) { + if (unlink(options->PidFile) != 0) { + log_warn(LD_FS, "Couldn't unlink pid file %s: %s", + options->PidFile, strerror(errno)); + } + } + if (options->ControlPortWriteToFile) { + if (unlink(options->ControlPortWriteToFile) != 0) { + log_warn(LD_FS, "Couldn't unlink control port file %s: %s", + options->ControlPortWriteToFile, + strerror(errno)); + } + } if (accounting_is_enabled(options)) accounting_record_bandwidth_usage(now, get_or_state()); or_state_mark_dirty(get_or_state(), 0); /* force an immediate save. */ diff --git a/src/or/microdesc.c b/src/or/microdesc.c index 6419ea79f8..ec85de0d6b 100644 --- a/src/or/microdesc.c +++ b/src/or/microdesc.c @@ -275,6 +275,7 @@ void microdesc_cache_clear(microdesc_cache_t *cache) { microdesc_t **entry, **next; + for (entry = HT_START(microdesc_map, &cache->map); entry; entry = next) { microdesc_t *md = *entry; next = HT_NEXT_RMV(microdesc_map, &cache->map, entry); @@ -283,7 +284,13 @@ microdesc_cache_clear(microdesc_cache_t *cache) } HT_CLEAR(microdesc_map, &cache->map); if (cache->cache_content) { - tor_munmap_file(cache->cache_content); + int res = tor_munmap_file(cache->cache_content); + if (res != 0) { + log_warn(LD_FS, + "tor_munmap_file() failed clearing microdesc cache; " + "we are probably about to leak memory."); + /* TODO something smarter? */ + } cache->cache_content = NULL; } cache->total_len_seen = 0; @@ -363,7 +370,9 @@ microdesc_cache_clean(microdesc_cache_t *cache, time_t cutoff, int force) cutoff = now - TOLERATE_MICRODESC_AGE; for (mdp = HT_START(microdesc_map, &cache->map); mdp != NULL; ) { - if ((*mdp)->last_listed < cutoff) { + const int is_old = (*mdp)->last_listed < cutoff; + const unsigned held_by_nodes = (*mdp)->held_by_nodes; + if (is_old && !held_by_nodes) { ++dropped; victim = *mdp; mdp = HT_NEXT_RMV(microdesc_map, &cache->map, mdp); @@ -371,6 +380,54 @@ microdesc_cache_clean(microdesc_cache_t *cache, time_t cutoff, int force) bytes_dropped += victim->bodylen; microdesc_free(victim); } else { + if (is_old) { + /* It's old, but it has held_by_nodes set. That's not okay. */ + /* Let's try to diagnose and fix #7164 . */ + smartlist_t *nodes = nodelist_find_nodes_with_microdesc(*mdp); + const networkstatus_t *ns = networkstatus_get_latest_consensus(); + long networkstatus_age = -1; + if (ns) { + networkstatus_age = now - ns->valid_after; + } + log_warn(LD_BUG, "Microdescriptor seemed very old " + "(last listed %d hours ago vs %d hour cutoff), but is still " + "marked as being held by %d node(s). I found %d node(s) " + "holding it. Current networkstatus is %ld hours old.", + (int)((now - (*mdp)->last_listed) / 3600), + (int)((now - cutoff) / 3600), + held_by_nodes, + smartlist_len(nodes), + networkstatus_age / 3600); + + SMARTLIST_FOREACH_BEGIN(nodes, const node_t *, node) { + const char *rs_match = "No RS"; + const char *rs_present = ""; + if (node->rs) { + if (tor_memeq(node->rs->descriptor_digest, + (*mdp)->digest, DIGEST256_LEN)) { + rs_match = "Microdesc digest in RS matches"; + } else { + rs_match = "Microdesc digest in RS does match"; + } + if (ns) { + /* This should be impossible, but let's see! */ + rs_present = " RS not present in networkstatus."; + SMARTLIST_FOREACH(ns->routerstatus_list, routerstatus_t *,rs, { + if (rs == node->rs) { + rs_present = " RS okay in networkstatus."; + } + }); + } + } + log_warn(LD_BUG, " [%d]: ID=%s. md=%p, rs=%p, ri=%p. %s.%s", + node_sl_idx, + hex_str(node->identity, DIGEST_LEN), + node->md, node->rs, node->ri, rs_match, rs_present); + } SMARTLIST_FOREACH_END(node); + smartlist_free(nodes); + (*mdp)->last_listed = now; + } + ++kept; mdp = HT_NEXT(microdesc_map, &cache->map, mdp); } @@ -429,7 +486,7 @@ int microdesc_cache_rebuild(microdesc_cache_t *cache, int force) { open_file_t *open_file; - int fd = -1; + int fd = -1, res; microdesc_t **mdp; smartlist_t *wrote; ssize_t size; @@ -496,8 +553,14 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force) /* We must do this unmap _before_ we call finish_writing_to_file(), or * windows will not actually replace the file. */ - if (cache->cache_content) - tor_munmap_file(cache->cache_content); + if (cache->cache_content) { + res = tor_munmap_file(cache->cache_content); + if (res != 0) { + log_warn(LD_FS, + "Failed to unmap old microdescriptor cache while rebuilding"); + } + cache->cache_content = NULL; + } if (finish_writing_to_file(open_file) < 0) { log_warn(LD_DIR, "Error rebuilding microdescriptor cache: %s", diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index 49478a7341..74c4ca45a2 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -1254,7 +1254,11 @@ networkstatus_set_current_consensus(const char *consensus, /* Even if we had enough signatures, we'd never use this as the * latest consensus. */ if (was_waiting_for_certs && from_cache) - unlink(unverified_fname); + if (unlink(unverified_fname) != 0) { + log_warn(LD_FS, + "Failed to unlink %s: %s", + unverified_fname, strerror(errno)); + } } goto done; } else { @@ -1264,8 +1268,13 @@ networkstatus_set_current_consensus(const char *consensus, "consensus"); result = -2; } - if (was_waiting_for_certs && (r < -1) && from_cache) - unlink(unverified_fname); + if (was_waiting_for_certs && (r < -1) && from_cache) { + if (unlink(unverified_fname) != 0) { + log_warn(LD_FS, + "Failed to unlink %s: %s", + unverified_fname, strerror(errno)); + } + } goto done; } } @@ -1313,7 +1322,11 @@ networkstatus_set_current_consensus(const char *consensus, waiting->body = NULL; waiting->set_at = 0; waiting->dl_failed = 0; - unlink(unverified_fname); + if (unlink(unverified_fname) != 0) { + log_warn(LD_FS, + "Failed to unlink %s: %s", + unverified_fname, strerror(errno)); + } } /* Reset the failure count only if this consensus is actually valid. */ diff --git a/src/or/nodelist.c b/src/or/nodelist.c index 3704822c72..52c92661c0 100644 --- a/src/or/nodelist.c +++ b/src/or/nodelist.c @@ -332,6 +332,25 @@ nodelist_drop_node(node_t *node, int remove_from_ht) node->nodelist_idx = -1; } +/** Return a newly allocated smartlist of the nodes that have <b>md</b> as + * their microdescriptor. */ +smartlist_t * +nodelist_find_nodes_with_microdesc(const microdesc_t *md) +{ + smartlist_t *result = smartlist_new(); + + if (the_nodelist == NULL) + return result; + + SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) { + if (node->md == md) { + smartlist_add(result, node); + } + } SMARTLIST_FOREACH_END(node); + + return result; +} + /** Release storage held by <b>node</b> */ static void node_free(node_t *node) diff --git a/src/or/nodelist.h b/src/or/nodelist.h index 565caa76cd..95d0c23283 100644 --- a/src/or/nodelist.h +++ b/src/or/nodelist.h @@ -26,6 +26,7 @@ void nodelist_set_consensus(networkstatus_t *ns); void nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md); void nodelist_remove_routerinfo(routerinfo_t *ri); void nodelist_purge(void); +smartlist_t *nodelist_find_nodes_with_microdesc(const microdesc_t *md); void nodelist_free_all(void); void nodelist_assert_ok(void); diff --git a/src/or/or.h b/src/or/or.h index 800e83f4b7..38ab1767e0 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -196,6 +196,7 @@ typedef enum { * and let it use any circuit ID it wants. */ CIRC_ID_TYPE_NEITHER=2 } circ_id_type_t; +#define circ_id_type_bitfield_t ENUM_BF(circ_id_type_t) #define CONN_TYPE_MIN_ 3 /** Type for sockets listening for OR connections. */ @@ -1683,6 +1684,7 @@ typedef enum { DIR_SPOOL_CACHED_DIR, DIR_SPOOL_NETWORKSTATUS, DIR_SPOOL_MICRODESC, /* NOTE: if we add another entry, add another bit. */ } dir_spool_source_t; +#define dir_spool_source_bitfield_t ENUM_BF(dir_spool_source_t) /** Subtype of connection_t for an "directory connection" -- that is, an HTTP * connection to retrieve or serve directory material. */ @@ -1702,7 +1704,7 @@ typedef struct dir_connection_t { * "spooling" of directory material to the outbuf. Otherwise, we'd have * to append everything to the outbuf in one enormous chunk. */ /** What exactly are we spooling right now? */ - ENUM_BF(dir_spool_source_t) dir_spool_src : 3; + dir_spool_source_bitfield_t dir_spool_src : 3; /** If we're fetching descriptors, what router purpose shall we assign * to them? */ @@ -1875,12 +1877,13 @@ typedef enum { ADDR_POLICY_ACCEPT=1, ADDR_POLICY_REJECT=2, } addr_policy_action_t; +#define addr_policy_action_bitfield_t ENUM_BF(addr_policy_action_t) /** A reference-counted address policy rule. */ typedef struct addr_policy_t { int refcnt; /**< Reference count */ /** What to do when the policy matches.*/ - ENUM_BF(addr_policy_action_t) policy_type:2; + addr_policy_action_bitfield_t policy_type:2; unsigned int is_private:1; /**< True iff this is the pseudo-address, * "private". */ unsigned int is_canonical:1; /**< True iff this policy is the canonical @@ -1932,6 +1935,7 @@ typedef enum { */ SAVED_IN_JOURNAL } saved_location_t; +#define saved_location_bitfield_t ENUM_BF(saved_location_t) /** Enumeration: what kind of download schedule are we using for a given * object? */ @@ -1940,6 +1944,7 @@ typedef enum { DL_SCHED_CONSENSUS = 1, DL_SCHED_BRIDGE = 2, } download_schedule_t; +#define download_schedule_bitfield_t ENUM_BF(download_schedule_t) /** Information about our plans for retrying downloads for a downloadable * object. */ @@ -1948,7 +1953,7 @@ typedef struct download_status_t { * again? */ uint8_t n_download_failures; /**< Number of failures trying to download the * most recent descriptor. */ - ENUM_BF(download_schedule_t) schedule : 8; + download_schedule_bitfield_t schedule : 8; } download_status_t; /** If n_download_failures is this high, the download can never happen. */ @@ -2203,7 +2208,7 @@ typedef struct microdesc_t { */ time_t last_listed; /** Where is this microdescriptor currently stored? */ - ENUM_BF(saved_location_t) saved_location : 3; + saved_location_bitfield_t saved_location : 3; /** If true, do not attempt to cache this microdescriptor on disk. */ unsigned int no_save : 1; /** If true, this microdesc has an entry in the microdesc_map */ @@ -2413,8 +2418,8 @@ typedef enum { /** A common structure to hold a v3 network status vote, or a v3 network * status consensus. */ typedef struct networkstatus_t { - ENUM_BF(networkstatus_type_t) type : 8; /**< Vote, consensus, or opinion? */ - ENUM_BF(consensus_flavor_t) flavor : 8; /**< If a consensus, what kind? */ + networkstatus_type_t type; /**< Vote, consensus, or opinion? */ + consensus_flavor_t flavor; /**< If a consensus, what kind? */ unsigned int has_measured_bws : 1;/**< True iff this networkstatus contains * measured= bandwidth values. */ @@ -2933,6 +2938,7 @@ typedef enum { */ PATH_STATE_ALREADY_COUNTED = 6, } path_state_t; +#define path_state_bitfield_t ENUM_BF(path_state_t) /** An origin_circuit_t holds data necessary to build and use a circuit. */ @@ -2983,7 +2989,7 @@ typedef struct origin_circuit_t { * circuit building and usage accounting. See path_state_t * for more details. */ - ENUM_BF(path_state_t) path_state : 3; + path_state_bitfield_t path_state : 3; /* If this flag is set, we should not consider attaching any more * connections to this circuit. */ @@ -4478,6 +4484,7 @@ typedef enum { * did this remapping happen." */ ADDRMAPSRC_NONE } addressmap_entry_source_t; +#define addressmap_entry_source_bitfield_t ENUM_BF(addressmap_entry_source_t) /********************************* control.c ***************************/ diff --git a/src/or/rendmid.c b/src/or/rendmid.c index 1bd11f6dc0..c68f6da597 100644 --- a/src/or/rendmid.c +++ b/src/or/rendmid.c @@ -231,7 +231,8 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request, } if (request_len != REND_COOKIE_LEN) { - log_warn(LD_PROTOCOL, "Invalid length on ESTABLISH_RENDEZVOUS."); + log_fn(LOG_PROTOCOL_WARN, + LD_PROTOCOL, "Invalid length on ESTABLISH_RENDEZVOUS."); goto err; } diff --git a/src/or/rephist.c b/src/or/rephist.c index 16e16ab651..87f930a28d 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -2992,11 +2992,11 @@ rep_hist_conn_stats_write(time_t now) } /** Internal statistics to track how many requests of each type of - * handshake we've received, and how many we've completed. Useful for - * seeing trends in cpu load. + * handshake we've received, and how many we've assigned to cpuworkers. + * Useful for seeing trends in cpu load. * @{ */ static int onion_handshakes_requested[MAX_ONION_HANDSHAKE_TYPE+1] = {0}; -static int onion_handshakes_completed[MAX_ONION_HANDSHAKE_TYPE+1] = {0}; +static int onion_handshakes_assigned[MAX_ONION_HANDSHAKE_TYPE+1] = {0}; /**@}*/ /** A new onionskin (using the <b>type</b> handshake) has arrived. */ @@ -3010,10 +3010,10 @@ rep_hist_note_circuit_handshake_requested(uint16_t type) /** We've sent an onionskin (using the <b>type</b> handshake) to a * cpuworker. */ void -rep_hist_note_circuit_handshake_completed(uint16_t type) +rep_hist_note_circuit_handshake_assigned(uint16_t type) { if (type <= MAX_ONION_HANDSHAKE_TYPE) - onion_handshakes_completed[type]++; + onion_handshakes_assigned[type]++; } /** Log our onionskin statistics since the last time we were called. */ @@ -3023,11 +3023,11 @@ rep_hist_log_circuit_handshake_stats(time_t now) (void)now; log_notice(LD_HEARTBEAT, "Circuit handshake stats since last time: " "%d/%d TAP, %d/%d NTor.", - onion_handshakes_completed[ONION_HANDSHAKE_TYPE_TAP], + onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_TAP], onion_handshakes_requested[ONION_HANDSHAKE_TYPE_TAP], - onion_handshakes_completed[ONION_HANDSHAKE_TYPE_NTOR], + onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_NTOR], onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR]); - memset(onion_handshakes_completed, 0, sizeof(onion_handshakes_completed)); + memset(onion_handshakes_assigned, 0, sizeof(onion_handshakes_assigned)); memset(onion_handshakes_requested, 0, sizeof(onion_handshakes_requested)); } diff --git a/src/or/rephist.h b/src/or/rephist.h index de824749b4..df01ae6cb3 100644 --- a/src/or/rephist.h +++ b/src/or/rephist.h @@ -97,7 +97,7 @@ time_t rep_hist_conn_stats_write(time_t now); void rep_hist_conn_stats_term(void); void rep_hist_note_circuit_handshake_requested(uint16_t type); -void rep_hist_note_circuit_handshake_completed(uint16_t type); +void rep_hist_note_circuit_handshake_assigned(uint16_t type); void rep_hist_log_circuit_handshake_stats(time_t now); void rep_hist_free_all(void); diff --git a/src/or/routerlist.c b/src/or/routerlist.c index c8232606bf..f1bd12c193 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -1064,8 +1064,11 @@ router_rebuild_store(int flags, desc_store_t *store) /* Our mmap is now invalid. */ if (store->mmap) { - tor_munmap_file(store->mmap); + int res = tor_munmap_file(store->mmap); store->mmap = NULL; + if (res != 0) { + log_warn(LD_FS, "Unable to munmap route store in %s", fname); + } } if (replace_file(fname_tmp, fname)<0) { @@ -1139,9 +1142,16 @@ router_reload_router_list_impl(desc_store_t *store) fname = get_datadir_fname(store->fname_base); - if (store->mmap) /* get rid of it first */ - tor_munmap_file(store->mmap); - store->mmap = NULL; + if (store->mmap) { + /* get rid of it first */ + int res = tor_munmap_file(store->mmap); + store->mmap = NULL; + if (res != 0) { + log_warn(LD_FS, "Failed to munmap %s", fname); + tor_free(fname); + return -1; + } + } store->mmap = tor_mmap_file(fname); if (store->mmap) { @@ -2794,10 +2804,18 @@ routerlist_free(routerlist_t *rl) signed_descriptor_free(sd)); smartlist_free(rl->routers); smartlist_free(rl->old_routers); - if (routerlist->desc_store.mmap) - tor_munmap_file(routerlist->desc_store.mmap); - if (routerlist->extrainfo_store.mmap) - tor_munmap_file(routerlist->extrainfo_store.mmap); + if (rl->desc_store.mmap) { + int res = tor_munmap_file(routerlist->desc_store.mmap); + if (res != 0) { + log_warn(LD_FS, "Failed to munmap routerlist->desc_store.mmap"); + } + } + if (rl->extrainfo_store.mmap) { + int res = tor_munmap_file(routerlist->extrainfo_store.mmap); + if (res != 0) { + log_warn(LD_FS, "Failed to munmap routerlist->extrainfo_store.mmap"); + } + } tor_free(rl); router_dir_info_changed(); diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 422278a5f8..7bf9a4d8e7 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -572,7 +572,7 @@ dump_desc(const char *desc, const char *type) char *content = tor_malloc_zero(filelen); tor_snprintf(content, filelen, "Unable to parse descriptor of type " "%s:\n%s", type, desc); - write_str_to_file(debugfile, content, 0); + write_str_to_file(debugfile, content, 1); log_info(LD_DIR, "Unable to parse descriptor of type %s. See file " "unparseable-desc in data directory for details.", type); tor_free(content); diff --git a/src/or/statefile.c b/src/or/statefile.c index 8ab04763d0..2251f25e94 100644 --- a/src/or/statefile.c +++ b/src/or/statefile.c @@ -260,7 +260,7 @@ or_state_set(or_state_t *new_state) static void or_state_save_broken(char *fname) { - int i; + int i, res; file_status_t status; char *fname2 = NULL; for (i = 0; i < 100; ++i) { @@ -274,7 +274,13 @@ or_state_save_broken(char *fname) log_warn(LD_BUG, "Unable to parse state in \"%s\"; too many saved bad " "state files to move aside. Discarding the old state file.", fname); - unlink(fname); + res = unlink(fname); + if (res != 0) { + log_warn(LD_FS, + "Also couldn't discard old state file \"%s\" because " + "unlink() failed: %s", + fname, strerror(errno)); + } } else { log_warn(LD_BUG, "Unable to parse state in \"%s\". Moving it aside " "to \"%s\". This could be a bug in Tor; please tell " diff --git a/src/test/test_addr.c b/src/test/test_addr.c index 036380fe85..1c2a90e1ec 100644 --- a/src/test/test_addr.c +++ b/src/test/test_addr.c @@ -402,7 +402,6 @@ test_addr_ip6_helpers(void) test_internal_ip("::ffff:169.254.0.0", 0); test_internal_ip("::ffff:169.254.255.255", 0); test_external_ip("::ffff:169.255.0.0", 0); - test_assert(is_internal_IP(0x7f000001, 0)); /* tor_addr_compare(tor_addr_t x2) */ test_addr_compare("ffff::", ==, "ffff::0"); diff --git a/src/test/test_circuitlist.c b/src/test/test_circuitlist.c index 720b407659..54aa51d3c7 100644 --- a/src/test/test_circuitlist.c +++ b/src/test/test_circuitlist.c @@ -150,13 +150,13 @@ test_clist_maps(void *arg) tt_assert(! circuit_id_in_use_on_channel(100, ch1)); done: - tor_free(ch1); - tor_free(ch2); - tor_free(ch3); if (or_c1) circuit_free(TO_CIRCUIT(or_c1)); if (or_c2) circuit_free(TO_CIRCUIT(or_c2)); + tor_free(ch1); + tor_free(ch2); + tor_free(ch3); UNMOCK(circuitmux_attach_circuit); UNMOCK(circuitmux_detach_circuit); } diff --git a/src/test/test_util.c b/src/test/test_util.c index 9104088c90..a471b8eb19 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -1577,14 +1577,14 @@ test_util_mmap(void) test_eq(mapping->size, strlen("Short file.")); test_streq(mapping->data, "Short file."); #ifdef _WIN32 - tor_munmap_file(mapping); + tt_int_op(0, ==, tor_munmap_file(mapping)); mapping = NULL; test_assert(unlink(fname1) == 0); #else /* make sure we can unlink. */ test_assert(unlink(fname1) == 0); test_streq(mapping->data, "Short file."); - tor_munmap_file(mapping); + tt_int_op(0, ==, tor_munmap_file(mapping)); mapping = NULL; #endif @@ -1605,7 +1605,7 @@ test_util_mmap(void) test_assert(mapping); test_eq(mapping->size, buflen); test_memeq(mapping->data, buf, buflen); - tor_munmap_file(mapping); + tt_int_op(0, ==, tor_munmap_file(mapping)); mapping = NULL; /* Now try a big aligned file. */ @@ -1614,7 +1614,7 @@ test_util_mmap(void) test_assert(mapping); test_eq(mapping->size, 16384); test_memeq(mapping->data, buf, 16384); - tor_munmap_file(mapping); + tt_int_op(0, ==, tor_munmap_file(mapping)); mapping = NULL; done: @@ -1627,8 +1627,7 @@ test_util_mmap(void) tor_free(fname3); tor_free(buf); - if (mapping) - tor_munmap_file(mapping); + tor_munmap_file(mapping); } /** Run unit tests for escaping/unescaping data for use by controllers. */ diff --git a/src/tools/tor-fw-helper/include.am b/src/tools/tor-fw-helper/include.am index 275a0e237c..1f862e6f06 100644 --- a/src/tools/tor-fw-helper/include.am +++ b/src/tools/tor-fw-helper/include.am @@ -33,4 +33,4 @@ endif src_tools_tor_fw_helper_tor_fw_helper_LDFLAGS = $(nat_pmp_ldflags) $(miniupnpc_ldflags) src_tools_tor_fw_helper_tor_fw_helper_LDADD = src/common/libor.a $(nat_pmp_ldadd) $(miniupnpc_ldadd) -lm @TOR_LIB_WS32@ -src_tools_tor_fw_helper_tor_fw_helper_CPPFLAGS = $(nat_pmp_cppflags) $(miniupnpc_cppflags) +src_tools_tor_fw_helper_tor_fw_helper_CPPFLAGS = $(nat_pmp_cppflags) $(miniupnpc_cppflags) -I"$(top_srcdir)/src/ext" |