aboutsummaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
Diffstat (limited to 'src/or')
-rw-r--r--src/or/addressmap.c2
-rw-r--r--src/or/buffers.c112
-rw-r--r--src/or/buffers.h8
-rw-r--r--src/or/channel.c11
-rw-r--r--src/or/channel.h84
-rw-r--r--src/or/circuitbuild.c11
-rw-r--r--src/or/circuitlist.c298
-rw-r--r--src/or/circuitlist.h8
-rw-r--r--src/or/circuitmux.c11
-rw-r--r--src/or/circuitmux.h3
-rw-r--r--src/or/circuitstats.c4
-rw-r--r--src/or/config.c90
-rw-r--r--src/or/connection.c46
-rw-r--r--src/or/connection.h3
-rw-r--r--src/or/connection_edge.c25
-rw-r--r--src/or/connection_or.c12
-rw-r--r--src/or/control.c36
-rw-r--r--src/or/control.h3
-rw-r--r--src/or/cpuworker.c2
-rw-r--r--src/or/directory.c213
-rw-r--r--src/or/directory.h2
-rw-r--r--src/or/dirserv.c326
-rw-r--r--src/or/dirserv.h5
-rw-r--r--src/or/dns.c2
-rw-r--r--src/or/entrynodes.c31
-rw-r--r--src/or/entrynodes.h3
-rw-r--r--src/or/fp_pair.c13
-rw-r--r--src/or/geoip.c15
-rw-r--r--src/or/hibernate.c10
-rw-r--r--src/or/main.c100
-rw-r--r--src/or/microdesc.c82
-rw-r--r--src/or/networkstatus.c67
-rw-r--r--src/or/networkstatus.h3
-rw-r--r--src/or/nodelist.c38
-rw-r--r--src/or/nodelist.h1
-rw-r--r--src/or/or.h60
-rw-r--r--src/or/policies.c58
-rw-r--r--src/or/policies.h2
-rw-r--r--src/or/relay.c27
-rw-r--r--src/or/relay.h4
-rw-r--r--src/or/rendclient.c8
-rw-r--r--src/or/rendcommon.c260
-rw-r--r--src/or/rendcommon.h18
-rw-r--r--src/or/rendmid.c3
-rw-r--r--src/or/rendservice.c21
-rw-r--r--src/or/rendservice.h1
-rw-r--r--src/or/rephist.c36
-rw-r--r--src/or/rephist.h2
-rw-r--r--src/or/router.c152
-rw-r--r--src/or/router.h3
-rw-r--r--src/or/routerlist.c106
-rw-r--r--src/or/routerparse.c27
-rw-r--r--src/or/routerparse.h2
-rw-r--r--src/or/routerset.c33
-rw-r--r--src/or/routerset.h6
-rw-r--r--src/or/statefile.c10
56 files changed, 1049 insertions, 1470 deletions
diff --git a/src/or/addressmap.c b/src/or/addressmap.c
index 9bc79bd84..998770a3d 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/buffers.c b/src/or/buffers.c
index 50016d3a8..012ced6d3 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -62,6 +62,8 @@ static int parse_socks_client(const uint8_t *data, size_t datalen,
int state, char **reason,
ssize_t *drain_out);
+#define DEBUG_CHUNK_ALLOC
+
/* Chunk manipulation functions */
/** A single chunk on a buffer or in a freelist. */
@@ -69,7 +71,12 @@ typedef struct chunk_t {
struct chunk_t *next; /**< The next chunk on the buffer or freelist. */
size_t datalen; /**< The number of bytes stored in this chunk */
size_t memlen; /**< The number of usable bytes of storage in <b>mem</b>. */
+#ifdef DEBUG_CHUNK_ALLOC
+ size_t DBG_alloc;
+#endif
char *data; /**< A pointer to the first byte of data stored in <b>mem</b>. */
+ uint32_t inserted_time; /**< Timestamp in truncated ms since epoch
+ * when this chunk was inserted. */
char mem[FLEXIBLE_ARRAY_MEMBER]; /**< The actual memory used for storage in
* this chunk. */
} chunk_t;
@@ -141,6 +148,9 @@ static chunk_freelist_t freelists[] = {
* could help with? */
static uint64_t n_freelist_miss = 0;
+/** DOCDOC */
+static size_t total_bytes_allocated_in_chunks = 0;
+
static void assert_freelist_ok(chunk_freelist_t *fl);
/** Return the freelist to hold chunks of size <b>alloc</b>, or NULL if
@@ -174,6 +184,11 @@ chunk_free_unchecked(chunk_t *chunk)
} else {
if (freelist)
++freelist->n_free;
+#ifdef DEBUG_CHUNK_ALLOC
+ tor_assert(alloc == chunk->DBG_alloc);
+#endif
+ tor_assert(total_bytes_allocated_in_chunks >= alloc);
+ total_bytes_allocated_in_chunks -= alloc;
tor_free(chunk);
}
}
@@ -200,6 +215,10 @@ chunk_new_with_alloc_size(size_t alloc)
else
++n_freelist_miss;
ch = tor_malloc(alloc);
+#ifdef DEBUG_CHUNK_ALLOC
+ ch->DBG_alloc = alloc;
+#endif
+ total_bytes_allocated_in_chunks += alloc;
}
ch->next = NULL;
ch->datalen = 0;
@@ -211,6 +230,14 @@ chunk_new_with_alloc_size(size_t alloc)
static void
chunk_free_unchecked(chunk_t *chunk)
{
+ if (!chunk)
+ return;
+#ifdef DEBUG_CHUNK_ALLOC
+ tor_assert(CHUNK_ALLOC_SIZE(chunk->memlen) == chunk->DBG_alloc);
+#endif
+ tor_assert(total_bytes_allocated_in_chunks >=
+ CHUNK_ALLOC_SIZE(chunk->memlen));
+ total_bytes_allocated_in_chunks -= CHUNK_ALLOC_SIZE(chunk->memlen);
tor_free(chunk);
}
static INLINE chunk_t *
@@ -220,7 +247,11 @@ chunk_new_with_alloc_size(size_t alloc)
ch = tor_malloc(alloc);
ch->next = NULL;
ch->datalen = 0;
+#ifdef DEBUG_CHUNK_ALLOC
+ ch->DBG_alloc = alloc;
+#endif
ch->memlen = CHUNK_SIZE_WITH_ALLOC(alloc);
+ total_bytes_allocated_in_chunks += alloc;
ch->data = &ch->mem[0];
return ch;
}
@@ -232,11 +263,18 @@ static INLINE chunk_t *
chunk_grow(chunk_t *chunk, size_t sz)
{
off_t offset;
+ size_t memlen_orig = chunk->memlen;
tor_assert(sz > chunk->memlen);
offset = chunk->data - chunk->mem;
chunk = tor_realloc(chunk, CHUNK_ALLOC_SIZE(sz));
chunk->memlen = sz;
chunk->data = chunk->mem + offset;
+#ifdef DEBUG_CHUNK_ALLOC
+ tor_assert(chunk->DBG_alloc == CHUNK_ALLOC_SIZE(memlen_orig));
+ chunk->DBG_alloc = CHUNK_ALLOC_SIZE(sz);
+#endif
+ total_bytes_allocated_in_chunks +=
+ CHUNK_ALLOC_SIZE(sz) - CHUNK_ALLOC_SIZE(memlen_orig);
return chunk;
}
@@ -261,12 +299,14 @@ preferred_chunk_size(size_t target)
}
/** Remove from the freelists most chunks that have not been used since the
- * last call to buf_shrink_freelists(). */
-void
+ * last call to buf_shrink_freelists(). Return the amount of memory
+ * freed. */
+size_t
buf_shrink_freelists(int free_all)
{
#ifdef ENABLE_BUF_FREELISTS
int i;
+ size_t total_freed = 0;
disable_control_logging();
for (i = 0; freelists[i].alloc_size; ++i) {
int slack = freelists[i].slack;
@@ -298,6 +338,13 @@ buf_shrink_freelists(int free_all)
*chp = NULL;
while (chunk) {
chunk_t *next = chunk->next;
+#ifdef DEBUG_CHUNK_ALLOC
+ tor_assert(chunk->DBG_alloc == CHUNK_ALLOC_SIZE(chunk->memlen));
+#endif
+ tor_assert(total_bytes_allocated_in_chunks >=
+ CHUNK_ALLOC_SIZE(chunk->memlen));
+ total_bytes_allocated_in_chunks -= CHUNK_ALLOC_SIZE(chunk->memlen);
+ total_freed += CHUNK_ALLOC_SIZE(chunk->memlen);
tor_free(chunk);
chunk = next;
--n_to_free;
@@ -315,18 +362,21 @@ buf_shrink_freelists(int free_all)
}
// tor_assert(!n_to_free);
freelists[i].cur_length = new_length;
+ tor_assert(orig_n_to_skip == new_length);
log_info(LD_MM, "Cleaned freelist for %d-byte chunks: original "
- "length %d, kept %d, dropped %d.",
+ "length %d, kept %d, dropped %d. New length is %d",
(int)freelists[i].alloc_size, orig_length,
- orig_n_to_skip, orig_n_to_free);
+ orig_n_to_skip, orig_n_to_free, new_length);
}
freelists[i].lowest_length = freelists[i].cur_length;
assert_freelist_ok(&freelists[i]);
}
done:
enable_control_logging();
+ return total_freed;
#else
(void) free_all;
+ return 0;
#endif
}
@@ -376,9 +426,10 @@ struct buf_t {
*
* If <b>nulterminate</b> is true, ensure that there is a 0 byte in
* buf->head->mem right after all the data. */
-static void
+STATIC void
buf_pullup(buf_t *buf, size_t bytes, int nulterminate)
{
+ /* XXXX nothing uses nulterminate; remove it. */
chunk_t *dest, *src;
size_t capacity;
if (!buf->head)
@@ -450,6 +501,20 @@ buf_pullup(buf_t *buf, size_t bytes, int nulterminate)
check();
}
+#ifdef TOR_UNIT_TESTS
+void
+buf_get_first_chunk_data(const buf_t *buf, const char **cp, size_t *sz)
+{
+ if (!buf || !buf->head) {
+ *cp = NULL;
+ *sz = 0;
+ } else {
+ *cp = buf->head->data;
+ *sz = buf->head->datalen;
+ }
+}
+#endif
+
/** Resize buf so it won't hold extra memory that we haven't been
* using lately.
*/
@@ -504,6 +569,12 @@ buf_new(void)
return buf;
}
+size_t
+buf_get_default_chunk_size(const buf_t *buf)
+{
+ return buf->default_chunk_size;
+}
+
/** Remove all data from <b>buf</b>. */
void
buf_clear(buf_t *buf)
@@ -531,7 +602,7 @@ buf_allocation(const buf_t *buf)
size_t total = 0;
const chunk_t *chunk;
for (chunk = buf->head; chunk; chunk = chunk->next) {
- total += chunk->memlen;
+ total += CHUNK_ALLOC_SIZE(chunk->memlen);
}
return total;
}
@@ -564,6 +635,10 @@ static chunk_t *
chunk_copy(const chunk_t *in_chunk)
{
chunk_t *newch = tor_memdup(in_chunk, CHUNK_ALLOC_SIZE(in_chunk->memlen));
+ total_bytes_allocated_in_chunks += CHUNK_ALLOC_SIZE(in_chunk->memlen);
+#ifdef DEBUG_CHUNK_ALLOC
+ newch->DBG_alloc = CHUNK_ALLOC_SIZE(in_chunk->memlen);
+#endif
newch->next = NULL;
if (in_chunk->data) {
off_t offset = in_chunk->data - in_chunk->mem;
@@ -599,6 +674,7 @@ static chunk_t *
buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped)
{
chunk_t *chunk;
+ struct timeval now;
if (CHUNK_ALLOC_SIZE(capacity) < buf->default_chunk_size) {
chunk = chunk_new_with_alloc_size(buf->default_chunk_size);
} else if (capped && CHUNK_ALLOC_SIZE(capacity) > MAX_CHUNK_ALLOC) {
@@ -606,6 +682,10 @@ buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped)
} else {
chunk = chunk_new_with_alloc_size(preferred_chunk_size(capacity));
}
+
+ tor_gettimeofday_cached_monotonic(&now);
+ chunk->inserted_time = (uint32_t)tv_to_msec(&now);
+
if (buf->tail) {
tor_assert(buf->head);
buf->tail->next = chunk;
@@ -618,6 +698,26 @@ buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped)
return chunk;
}
+/** Return the age of the oldest chunk in the buffer <b>buf</b>, in
+ * milliseconds. Requires the current time, in truncated milliseconds since
+ * the epoch, as its input <b>now</b>.
+ */
+uint32_t
+buf_get_oldest_chunk_timestamp(const buf_t *buf, uint32_t now)
+{
+ if (buf->head) {
+ return now - buf->head->inserted_time;
+ } else {
+ return 0;
+ }
+}
+
+size_t
+buf_get_total_allocation(void)
+{
+ return total_bytes_allocated_in_chunks;
+}
+
/** Read up to <b>at_most</b> bytes from the socket <b>fd</b> into
* <b>chunk</b> (which must be on <b>buf</b>). If we get an EOF, set
* *<b>reached_eof</b> to 1. Return -1 on error, 0 on eof or blocking,
diff --git a/src/or/buffers.h b/src/or/buffers.h
index 48b118520..a201282da 100644
--- a/src/or/buffers.h
+++ b/src/or/buffers.h
@@ -16,17 +16,21 @@
buf_t *buf_new(void);
buf_t *buf_new_with_capacity(size_t size);
+size_t buf_get_default_chunk_size(const buf_t *buf);
void buf_free(buf_t *buf);
void buf_clear(buf_t *buf);
buf_t *buf_copy(const buf_t *buf);
void buf_shrink(buf_t *buf);
-void buf_shrink_freelists(int free_all);
+size_t buf_shrink_freelists(int free_all);
void buf_dump_freelist_sizes(int severity);
size_t buf_datalen(const buf_t *buf);
size_t buf_allocation(const buf_t *buf);
size_t buf_slack(const buf_t *buf);
+uint32_t buf_get_oldest_chunk_timestamp(const buf_t *buf, uint32_t now);
+size_t buf_get_total_allocation(void);
+
int read_to_buf(tor_socket_t s, size_t at_most, buf_t *buf, int *reached_eof,
int *socket_error);
int read_to_buf_tls(tor_tls_t *tls, size_t at_most, buf_t *buf);
@@ -100,6 +104,8 @@ void assert_buf_ok(buf_t *buf);
#ifdef BUFFERS_PRIVATE
STATIC int buf_find_string_offset(const buf_t *buf, const char *s, size_t n);
+STATIC void buf_pullup(buf_t *buf, size_t bytes, int nulterminate);
+void buf_get_first_chunk_data(const buf_t *buf, const char **cp, size_t *sz);
#endif
#endif
diff --git a/src/or/channel.c b/src/or/channel.c
index a345bab20..32e87c342 100644
--- a/src/or/channel.c
+++ b/src/or/channel.c
@@ -95,12 +95,7 @@ typedef struct channel_idmap_entry_s {
static INLINE unsigned
channel_idmap_hash(const channel_idmap_entry_t *ent)
{
- const unsigned *a = (const unsigned *)ent->digest;
-#if SIZEOF_INT == 4
- return a[0] ^ a[1] ^ a[2] ^ a[3] ^ a[4];
-#elif SIZEOF_INT == 8
- return a[0] ^ a[1];
-#endif
+ return (unsigned) siphash24g(ent->digest, DIGEST_LEN);
}
static INLINE int
@@ -805,7 +800,7 @@ channel_free(channel_t *chan)
/* Get rid of cmux */
if (chan->cmux) {
- circuitmux_detach_all_circuits(chan->cmux);
+ circuitmux_detach_all_circuits(chan->cmux, NULL);
circuitmux_mark_destroyed_circids_usable(chan->cmux, chan);
circuitmux_free(chan->cmux);
chan->cmux = NULL;
@@ -2865,7 +2860,7 @@ channel_free_list(smartlist_t *channels, int mark_for_close)
channel_state_to_string(curr->state), curr->state);
/* Detach circuits early so they can find the channel */
if (curr->cmux) {
- circuitmux_detach_all_circuits(curr->cmux);
+ circuitmux_detach_all_circuits(curr->cmux, NULL);
}
channel_unregister(curr);
if (mark_for_close) {
diff --git a/src/or/channel.h b/src/or/channel.h
index 7e3f5ad07..7ec222df0 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/circuitbuild.c b/src/or/circuitbuild.c
index ffcca4666..98fef4c14 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -606,27 +606,30 @@ int
inform_testing_reachability(void)
{
char dirbuf[128];
+ char *address;
const routerinfo_t *me = router_get_my_routerinfo();
if (!me)
return 0;
+ address = tor_dup_ip(me->addr);
control_event_server_status(LOG_NOTICE,
"CHECKING_REACHABILITY ORADDRESS=%s:%d",
- me->address, me->or_port);
+ address, me->or_port);
if (me->dir_port) {
tor_snprintf(dirbuf, sizeof(dirbuf), " and DirPort %s:%d",
- me->address, me->dir_port);
+ address, me->dir_port);
control_event_server_status(LOG_NOTICE,
"CHECKING_REACHABILITY DIRADDRESS=%s:%d",
- me->address, me->dir_port);
+ address, me->dir_port);
}
log_notice(LD_OR, "Now checking whether ORPort %s:%d%s %s reachable... "
"(this may take up to %d minutes -- look for log "
"messages indicating success)",
- me->address, me->or_port,
+ address, me->or_port,
me->dir_port ? dirbuf : "",
me->dir_port ? "are" : "is",
TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT/60);
+ tor_free(address);
return 1;
}
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 947489636..931332550 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -930,72 +930,6 @@ circuit_dump_by_conn(connection_t *conn, int severity)
}
}
-/** A helper function for circuit_dump_by_chan() below. Log a bunch
- * of information about circuit <b>circ</b>.
- */
-static void
-circuit_dump_chan_details(int severity,
- circuit_t *circ,
- channel_t *chan,
- const char *type,
- circid_t this_circid,
- circid_t other_circid)
-{
- tor_log(severity, LD_CIRC, "Conn %p has %s circuit: circID %u "
- "(other side %u), state %d (%s), born %ld:",
- chan, type, (unsigned)this_circid, (unsigned)other_circid, circ->state,
- circuit_state_to_string(circ->state),
- (long)circ->timestamp_began.tv_sec);
- if (CIRCUIT_IS_ORIGIN(circ)) { /* circ starts at this node */
- circuit_log_path(severity, LD_CIRC, TO_ORIGIN_CIRCUIT(circ));
- }
-}
-
-/** Log, at severity <b>severity</b>, information about each circuit
- * that is connected to <b>chan</b>.
- */
-void
-circuit_dump_by_chan(channel_t *chan, int severity)
-{
- circuit_t *circ;
-
- tor_assert(chan);
-
- TOR_LIST_FOREACH(circ, &global_circuitlist, head) {
- circid_t n_circ_id = circ->n_circ_id, p_circ_id = 0;
-
- if (circ->marked_for_close) {
- continue;
- }
-
- if (!CIRCUIT_IS_ORIGIN(circ)) {
- p_circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
- }
-
- if (! CIRCUIT_IS_ORIGIN(circ) && TO_OR_CIRCUIT(circ)->p_chan &&
- TO_OR_CIRCUIT(circ)->p_chan == chan) {
- circuit_dump_chan_details(severity, circ, chan, "App-ward",
- p_circ_id, n_circ_id);
- }
-
- if (circ->n_chan && circ->n_chan == chan) {
- circuit_dump_chan_details(severity, circ, chan, "Exit-ward",
- n_circ_id, p_circ_id);
- }
-
- if (!circ->n_chan && circ->n_hop &&
- channel_matches_extend_info(chan, circ->n_hop) &&
- tor_memeq(chan->identity_digest,
- circ->n_hop->identity_digest, DIGEST_LEN)) {
- circuit_dump_chan_details(severity, circ, chan,
- (circ->state == CIRCUIT_STATE_OPEN &&
- !CIRCUIT_IS_ORIGIN(circ)) ?
- "Endpoint" : "Pending",
- n_circ_id, p_circ_id);
- }
- }
-}
-
/** Return the circuit whose global ID is <b>id</b>, or NULL if no
* such circuit exists. */
origin_circuit_t *
@@ -1143,13 +1077,59 @@ 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();
- channel_unlink_all_circuits(chan);
+/* #define DEBUG_CIRCUIT_UNLINK_ALL */
- TOR_LIST_FOREACH(circ, &global_circuitlist, head) {
+ 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;
+
+ TOR_LIST_FOREACH(circ, &global_circuitlist, head) {
+ if (circ->n_chan == chan ||
+ (!CIRCUIT_IS_ORIGIN(circ) &&
+ TO_OR_CIRCUIT(circ)->p_chan == chan)) {
+ smartlist_add(detached_2, circ);
+ }
+ }
+
+ if (smartlist_len(detached) != smartlist_len(detached_2)) {
+ log_warn(LD_BUG, "List of detached circuits had the wrong length! "
+ "(got %d, should have gotten %d)",
+ (int)smartlist_len(detached),
+ (int)smartlist_len(detached_2));
+ badlen = 1;
+ }
+ smartlist_sort_pointers(detached);
+ smartlist_sort_pointers(detached_2);
+
+ SMARTLIST_FOREACH(detached, circuit_t *, c,
+ if (c != smartlist_get(detached_2, c_sl_idx))
+ mismatch = 1;
+ );
+
+ if (mismatch)
+ log_warn(LD_BUG, "Mismatch in list of detached circuits.");
+
+ if (badlen || mismatch) {
+ smartlist_free(detached);
+ detached = detached_2;
+ } else {
+ log_notice(LD_CIRC, "List of %d circuits was as expected.",
+ (int)smartlist_len(detached));
+ smartlist_free(detached_2);
+ }
+ }
+#endif
+
+ SMARTLIST_FOREACH_BEGIN(detached, circuit_t *, circ) {
int mark = 0;
if (circ->n_chan == chan) {
+
circuit_set_n_circid_chan(circ, 0, NULL);
mark = 1;
@@ -1165,9 +1145,16 @@ circuit_unlink_all_from_channel(channel_t *chan, int reason)
mark = 1;
}
}
- if (mark && !circ->marked_for_close)
+ if (!mark) {
+ log_warn(LD_BUG, "Circuit on detached list which I had no reason "
+ "to mark");
+ continue;
+ }
+ if (!circ->marked_for_close)
circuit_mark_for_close(circ, reason);
- }
+ } SMARTLIST_FOREACH_END(circ);
+
+ smartlist_free(detached);
}
/** Return a circ such that
@@ -1435,9 +1422,9 @@ circuit_mark_all_dirty_circs_as_unusable(void)
* - If circ->rend_splice is set (we are the midpoint of a joined
* rendezvous stream), then mark the other circuit to close as well.
*/
-void
-circuit_mark_for_close_(circuit_t *circ, int reason, int line,
- const char *file)
+MOCK_IMPL(void,
+circuit_mark_for_close_, (circuit_t *circ, int reason, int line,
+ const char *file))
{
int orig_reason = reason; /* Passed to the controller */
assert_circuit_ok(circ);
@@ -1541,6 +1528,7 @@ circuit_mark_for_close_(circuit_t *circ, int reason, int line,
channel_send_destroy(circ->n_circ_id, circ->n_chan, reason);
}
circuitmux_detach_circuit(circ->n_chan->cmux, circ);
+ circuit_set_n_circid_chan(circ, 0, NULL);
}
if (! CIRCUIT_IS_ORIGIN(circ)) {
@@ -1574,6 +1562,7 @@ circuit_mark_for_close_(circuit_t *circ, int reason, int line,
channel_send_destroy(or_circ->p_circ_id, or_circ->p_chan, reason);
}
circuitmux_detach_circuit(or_circ->p_chan->cmux, circ);
+ circuit_set_p_circid_chan(or_circ, 0, NULL);
}
} else {
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
@@ -1612,6 +1601,38 @@ marked_circuit_free_cells(circuit_t *circ)
cell_queue_clear(& TO_OR_CIRCUIT(circ)->p_chan_cells);
}
+/** Aggressively free buffer contents on all the buffers of all streams in the
+ * list starting at <b>stream</b>. Return the number of bytes recovered. */
+static size_t
+marked_circuit_streams_free_bytes(edge_connection_t *stream)
+{
+ size_t result = 0;
+ for ( ; stream; stream = stream->next_stream) {
+ connection_t *conn = TO_CONN(stream);
+ if (conn->inbuf) {
+ result += buf_allocation(conn->inbuf);
+ buf_clear(conn->inbuf);
+ }
+ if (conn->outbuf) {
+ result += buf_allocation(conn->outbuf);
+ buf_clear(conn->outbuf);
+ }
+ }
+ return result;
+}
+
+/** Aggressively free buffer contents on all the buffers of all streams on
+ * circuit <b>c</b>. Return the number of bytes recovered. */
+static size_t
+marked_circuit_free_stream_bytes(circuit_t *c)
+{
+ if (CIRCUIT_IS_ORIGIN(c)) {
+ return marked_circuit_streams_free_bytes(TO_ORIGIN_CIRCUIT(c)->p_streams);
+ } else {
+ return marked_circuit_streams_free_bytes(TO_OR_CIRCUIT(c)->n_streams);
+ }
+}
+
/** Return the number of cells used by the circuit <b>c</b>'s cell queues. */
STATIC size_t
n_cells_in_circ_queues(const circuit_t *c)
@@ -1632,7 +1653,7 @@ n_cells_in_circ_queues(const circuit_t *c)
* This function will return incorrect results if the oldest cell queued on
* the circuit is older than 2**32 msec (about 49 days) old.
*/
-static uint32_t
+STATIC uint32_t
circuit_max_queued_cell_age(const circuit_t *c, uint32_t now)
{
uint32_t age = 0;
@@ -1652,20 +1673,68 @@ circuit_max_queued_cell_age(const circuit_t *c, uint32_t now)
return age;
}
-/** Temporary variable for circuits_compare_by_oldest_queued_cell_ This is a
- * kludge to work around the fact that qsort doesn't provide a way for
- * comparison functions to take an extra argument. */
-static uint32_t circcomp_now_tmp;
+/** Return the age in milliseconds of the oldest buffer chunk on any stream in
+ * the linked list <b>stream</b>, where age is taken in milliseconds before
+ * the time <b>now</b> (in truncated milliseconds since the epoch). */
+static uint32_t
+circuit_get_streams_max_data_age(const edge_connection_t *stream, uint32_t now)
+{
+ uint32_t age = 0, age2;
+ for (; stream; stream = stream->next_stream) {
+ const connection_t *conn = TO_CONN(stream);
+ if (conn->outbuf) {
+ age2 = buf_get_oldest_chunk_timestamp(conn->outbuf, now);
+ if (age2 > age)
+ age = age2;
+ }
+ if (conn->inbuf) {
+ age2 = buf_get_oldest_chunk_timestamp(conn->inbuf, now);
+ if (age2 > age)
+ age = age2;
+ }
+ }
+
+ return age;
+}
+
+/** Return the age in milliseconds of the oldest buffer chunk on any stream
+ * attached to the circuit <b>c</b>, where age is taken in milliseconds before
+ * the time <b>now</b> (in truncated milliseconds since the epoch). */
+STATIC uint32_t
+circuit_max_queued_data_age(const circuit_t *c, uint32_t now)
+{
+ if (CIRCUIT_IS_ORIGIN(c)) {
+ return circuit_get_streams_max_data_age(
+ TO_ORIGIN_CIRCUIT((circuit_t*)c)->p_streams, now);
+ } else {
+ return circuit_get_streams_max_data_age(
+ TO_OR_CIRCUIT((circuit_t*)c)->n_streams, now);
+ }
+}
-/** Helper to sort a list of circuit_t by age of oldest cell, in descending
- * order. Requires that circcomp_now_tmp is set correctly. */
+/** Return the age of the oldest cell or stream buffer chunk on the circuit
+ * <b>c</b>, where age is taken in milliseconds before the time <b>now</b> (in
+ * truncated milliseconds since the epoch). */
+STATIC uint32_t
+circuit_max_queued_item_age(const circuit_t *c, uint32_t now)
+{
+ uint32_t cell_age = circuit_max_queued_cell_age(c, now);
+ uint32_t data_age = circuit_max_queued_data_age(c, now);
+ if (cell_age > data_age)
+ return cell_age;
+ else
+ return data_age;
+}
+
+/** Helper to sort a list of circuit_t by age of oldest item, in descending
+ * order. */
static int
-circuits_compare_by_oldest_queued_cell_(const void **a_, const void **b_)
+circuits_compare_by_oldest_queued_item_(const void **a_, const void **b_)
{
const circuit_t *a = *a_;
const circuit_t *b = *b_;
- uint32_t age_a = circuit_max_queued_cell_age(a, circcomp_now_tmp);
- uint32_t age_b = circuit_max_queued_cell_age(b, circcomp_now_tmp);
+ uint32_t age_a = a->age_tmp;
+ uint32_t age_b = b->age_tmp;
if (age_a < age_b)
return 1;
@@ -1675,67 +1744,88 @@ circuits_compare_by_oldest_queued_cell_(const void **a_, const void **b_)
return -1;
}
-#define FRACTION_OF_CELLS_TO_RETAIN_ON_OOM 0.90
+#define FRACTION_OF_DATA_TO_RETAIN_ON_OOM 0.90
/** We're out of memory for cells, having allocated <b>current_allocation</b>
* bytes' worth. Kill the 'worst' circuits until we're under
- * FRACTION_OF_CIRCS_TO_RETAIN_ON_OOM of our maximum usage. */
+ * FRACTION_OF_DATA_TO_RETAIN_ON_OOM of our maximum usage. */
void
circuits_handle_oom(size_t current_allocation)
{
/* Let's hope there's enough slack space for this allocation here... */
smartlist_t *circlist = smartlist_new();
circuit_t *circ;
- size_t n_cells_removed=0, n_cells_to_remove;
+ size_t mem_to_recover;
+ size_t mem_recovered=0;
int n_circuits_killed=0;
struct timeval now;
+ uint32_t now_ms;
log_notice(LD_GENERAL, "We're low on memory. Killing circuits with "
"over-long queues. (This behavior is controlled by "
- "MaxMemInCellQueues.)");
+ "MaxMemInQueues.)");
{
- size_t mem_target = (size_t)(get_options()->MaxMemInCellQueues *
- FRACTION_OF_CELLS_TO_RETAIN_ON_OOM);
- size_t mem_to_recover;
+ const size_t recovered = buf_shrink_freelists(1);
+ if (recovered >= current_allocation) {
+ log_warn(LD_BUG, "We somehow recovered more memory from freelists "
+ "than we thought we had allocated");
+ current_allocation = 0;
+ } else {
+ current_allocation -= recovered;
+ }
+ }
+
+ {
+ size_t mem_target = (size_t)(get_options()->MaxMemInQueues *
+ FRACTION_OF_DATA_TO_RETAIN_ON_OOM);
if (current_allocation <= mem_target)
return;
mem_to_recover = current_allocation - mem_target;
- n_cells_to_remove = CEIL_DIV(mem_to_recover, packed_cell_mem_cost());
}
+ tor_gettimeofday_cached_monotonic(&now);
+ now_ms = (uint32_t)tv_to_msec(&now);
+
/* This algorithm itself assumes that you've got enough memory slack
* to actually run it. */
- TOR_LIST_FOREACH(circ, &global_circuitlist, head)
+ TOR_LIST_FOREACH(circ, &global_circuitlist, head) {
+ circ->age_tmp = circuit_max_queued_item_age(circ, now_ms);
smartlist_add(circlist, circ);
-
- /* Set circcomp_now_tmp so that the sort can work. */
- tor_gettimeofday_cached(&now);
- circcomp_now_tmp = (uint32_t)tv_to_msec(&now);
+ }
/* This is O(n log n); there are faster algorithms we could use instead.
* Let's hope this doesn't happen enough to be in the critical path. */
- smartlist_sort(circlist, circuits_compare_by_oldest_queued_cell_);
+ smartlist_sort(circlist, circuits_compare_by_oldest_queued_item_);
/* Okay, now the worst circuits are at the front of the list. Let's mark
* them, and reclaim their storage aggressively. */
SMARTLIST_FOREACH_BEGIN(circlist, circuit_t *, circ) {
size_t n = n_cells_in_circ_queues(circ);
+ size_t freed;
if (! circ->marked_for_close) {
circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
}
marked_circuit_free_cells(circ);
+ freed = marked_circuit_free_stream_bytes(circ);
++n_circuits_killed;
- n_cells_removed += n;
- if (n_cells_removed >= n_cells_to_remove)
+
+ mem_recovered += n * packed_cell_mem_cost();
+ mem_recovered += freed;
+
+ if (mem_recovered >= mem_to_recover)
break;
} SMARTLIST_FOREACH_END(circ);
clean_cell_pool(); /* In case this helps. */
-
- log_notice(LD_GENERAL, "Removed "U64_FORMAT" bytes by killing %d circuits.",
- U64_PRINTF_ARG(n_cells_removed * packed_cell_mem_cost()),
- n_circuits_killed);
+ buf_shrink_freelists(1); /* This is necessary to actually release buffer
+ chunks. */
+
+ log_notice(LD_GENERAL, "Removed "U64_FORMAT" bytes by killing %d circuits; "
+ "%d circuits remain alive.",
+ U64_PRINTF_ARG(mem_recovered),
+ n_circuits_killed,
+ smartlist_len(circlist) - n_circuits_killed);
smartlist_free(circlist);
}
diff --git a/src/or/circuitlist.h b/src/or/circuitlist.h
index 1c8cf7de2..54a7ef42f 100644
--- a/src/or/circuitlist.h
+++ b/src/or/circuitlist.h
@@ -22,7 +22,6 @@ const char *circuit_purpose_to_controller_string(uint8_t purpose);
const char *circuit_purpose_to_controller_hs_state_string(uint8_t purpose);
const char *circuit_purpose_to_string(uint8_t purpose);
void circuit_dump_by_conn(connection_t *conn, int severity);
-void circuit_dump_by_chan(channel_t *chan, int severity);
void circuit_set_p_circid_chan(or_circuit_t *circ, circid_t id,
channel_t *chan);
void circuit_set_n_circid_chan(circuit_t *circ, circid_t id,
@@ -53,8 +52,8 @@ origin_circuit_t *circuit_find_to_cannibalize(uint8_t purpose,
extend_info_t *info, int flags);
void circuit_mark_all_unused_circs(void);
void circuit_mark_all_dirty_circs_as_unusable(void);
-void circuit_mark_for_close_(circuit_t *circ, int reason,
- int line, const char *file);
+MOCK_DECL(void, circuit_mark_for_close_, (circuit_t *circ, int reason,
+ int line, const char *file));
int circuit_get_cpath_len(origin_circuit_t *circ);
void circuit_clear_cpath(origin_circuit_t *circ);
crypt_path_t *circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum);
@@ -76,6 +75,9 @@ void channel_note_destroy_not_pending(channel_t *chan, circid_t id);
#ifdef CIRCUITLIST_PRIVATE
STATIC void circuit_free(circuit_t *circ);
STATIC size_t n_cells_in_circ_queues(const circuit_t *c);
+STATIC uint32_t circuit_max_queued_data_age(const circuit_t *c, uint32_t now);
+STATIC uint32_t circuit_max_queued_cell_age(const circuit_t *c, uint32_t now);
+STATIC uint32_t circuit_max_queued_item_age(const circuit_t *c, uint32_t now);
#endif
#endif
diff --git a/src/or/circuitmux.c b/src/or/circuitmux.c
index f2af94393..2d05c748e 100644
--- a/src/or/circuitmux.c
+++ b/src/or/circuitmux.c
@@ -390,10 +390,13 @@ circuitmux_alloc(void)
/**
* Detach all circuits from a circuitmux (use before circuitmux_free())
+ *
+ * If <b>detached_out</b> is non-NULL, add every detached circuit_t to
+ * detached_out.
*/
void
-circuitmux_detach_all_circuits(circuitmux_t *cmux)
+circuitmux_detach_all_circuits(circuitmux_t *cmux, smartlist_t *detached_out)
{
chanid_circid_muxinfo_t **i = NULL, *to_remove;
channel_t *chan = NULL;
@@ -430,6 +433,9 @@ circuitmux_detach_all_circuits(circuitmux_t *cmux)
/* Clear n_mux */
circ->n_mux = NULL;
+
+ if (detached_out)
+ smartlist_add(detached_out, circ);
} else if (circ->magic == OR_CIRCUIT_MAGIC) {
/*
* Update active_circuits et al.; this does policy notifies, so
@@ -445,6 +451,9 @@ circuitmux_detach_all_circuits(circuitmux_t *cmux)
* so clear p_mux.
*/
TO_OR_CIRCUIT(circ)->p_mux = NULL;
+
+ if (detached_out)
+ smartlist_add(detached_out, circ);
} else {
/* Complain and move on */
log_warn(LD_CIRC,
diff --git a/src/or/circuitmux.h b/src/or/circuitmux.h
index ee2f5d153..c4c0649c6 100644
--- a/src/or/circuitmux.h
+++ b/src/or/circuitmux.h
@@ -99,7 +99,8 @@ void circuitmux_assert_okay(circuitmux_t *cmux);
/* Create/destroy */
circuitmux_t * circuitmux_alloc(void);
-void circuitmux_detach_all_circuits(circuitmux_t *cmux);
+void circuitmux_detach_all_circuits(circuitmux_t *cmux,
+ smartlist_t *detached_out);
void circuitmux_free(circuitmux_t *cmux);
/* Policy control */
diff --git a/src/or/circuitstats.c b/src/or/circuitstats.c
index eaefc9edd..c093ecd26 100644
--- a/src/or/circuitstats.c
+++ b/src/or/circuitstats.c
@@ -94,18 +94,22 @@ circuit_build_times_disabled(void)
if (consensus_disabled || config_disabled || dirauth_disabled ||
state_disabled) {
+#if 0
log_debug(LD_CIRC,
"CircuitBuildTime learning is disabled. "
"Consensus=%d, Config=%d, AuthDir=%d, StateFile=%d",
consensus_disabled, config_disabled, dirauth_disabled,
state_disabled);
+#endif
return 1;
} else {
+#if 0
log_debug(LD_CIRC,
"CircuitBuildTime learning is not disabled. "
"Consensus=%d, Config=%d, AuthDir=%d, StateFile=%d",
consensus_disabled, config_disabled, dirauth_disabled,
state_disabled);
+#endif
return 0;
}
}
diff --git a/src/or/config.c b/src/or/config.c
index dcbe88dcc..c42ceb3d0 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -85,6 +85,7 @@ static config_abbrev_t option_abbrevs_[] = {
{ "DirFetchPostPeriod", "StatusFetchPeriod", 0, 0},
{ "DirServer", "DirAuthority", 0, 0}, /* XXXX024 later, make this warn? */
{ "MaxConn", "ConnLimit", 0, 1},
+ { "MaxMemInCellQueues", "MaxMemInQueues", 0, 0},
{ "ORBindAddress", "ORListenAddress", 0, 0},
{ "DirBindAddress", "DirListenAddress", 0, 0},
{ "SocksBindAddress", "SocksListenAddress", 0, 0},
@@ -306,7 +307,7 @@ static config_var_t option_vars_[] = {
V(MaxAdvertisedBandwidth, MEMUNIT, "1 GB"),
V(MaxCircuitDirtiness, INTERVAL, "10 minutes"),
V(MaxClientCircuitsPending, UINT, "32"),
- V(MaxMemInCellQueues, MEMUNIT, "8 GB"),
+ V(MaxMemInQueues, MEMUNIT, "8 GB"),
OBSOLETE("MaxOnionsPending"),
V(MaxOnionQueueDelay, MSEC_INTERVAL, "1750 msec"),
V(MinMeasuredBWsForAuthToIgnoreAdvertised, INT, "500"),
@@ -317,6 +318,7 @@ static config_var_t option_vars_[] = {
V(NATDListenAddress, LINELIST, NULL),
VPORT(NATDPort, LINELIST, NULL),
V(Nickname, STRING, NULL),
+ V(PredictedPortsRelevanceTime, INTERVAL, "1 hour"),
V(WarnUnsafeSocks, BOOL, "1"),
OBSOLETE("NoPublish"),
VAR("NodeFamily", LINELIST, NodeFamilies, NULL),
@@ -418,7 +420,7 @@ static config_var_t option_vars_[] = {
V(UseNTorHandshake, AUTOBOOL, "1"),
V(User, STRING, NULL),
V(UserspaceIOCPBuffers, BOOL, "0"),
- VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir, "0"),
+ OBSOLETE("V1AuthoritativeDirectory"),
OBSOLETE("V2AuthoritativeDirectory"),
VAR("V3AuthoritativeDirectory",BOOL, V3AuthoritativeDir, "0"),
V(TestingV3AuthInitialVotingInterval, INTERVAL, "30 minutes"),
@@ -844,7 +846,7 @@ add_default_trusted_dir_authorities(dirinfo_type_t type)
"moria1 orport=9101 "
"v3ident=D586D18309DED4CD6D57C18FDB97EFA96D330566 "
"128.31.0.39:9131 9695 DFC3 5FFE B861 329B 9F1A B04C 4639 7020 CE31",
- "tor26 v1 orport=443 v3ident=14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4 "
+ "tor26 orport=443 v3ident=14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4 "
"86.59.21.38:80 847B 1F85 0344 D787 6491 A548 92F9 0493 4E4E B85D",
"dizum orport=443 v3ident=E8A9C45EDE6D711294FADF8E7951F4DE6CA56B58 "
"194.109.206.212:80 7EA6 EAD6 FD83 083C 538F 4403 8BBF A077 587D D755",
@@ -976,8 +978,7 @@ consider_adding_dir_servers(const or_options_t *options,
if (!options->AlternateBridgeAuthority)
type |= BRIDGE_DIRINFO;
if (!options->AlternateDirAuthority)
- type |= V1_DIRINFO | V3_DIRINFO | EXTRAINFO_DIRINFO |
- MICRODESC_DIRINFO;
+ type |= V3_DIRINFO | EXTRAINFO_DIRINFO | MICRODESC_DIRINFO;
add_default_trusted_dir_authorities(type);
}
if (!options->FallbackDir)
@@ -1360,6 +1361,19 @@ options_act(const or_options_t *old_options)
}
#endif
+ /* If we are a bridge with a pluggable transport proxy but no
+ Extended ORPort, inform the user that she is missing out. */
+ if (server_mode(options) && options->ServerTransportPlugin &&
+ !options->ExtORPort_lines) {
+ log_notice(LD_CONFIG, "We use pluggable transports but the Extended "
+ "ORPort is disabled. Tor and your pluggable transports proxy "
+ "communicate with each other via the Extended ORPort so it "
+ "is suggested you enable it: it will also allow your Bridge "
+ "to collect statistics about its clients that use pluggable "
+ "transports. Please enable it using the ExtORPort torrc option "
+ "(e.g. set 'ExtORPort auto').");
+ }
+
if (options->Bridges) {
mark_bridge_list();
for (cl = options->Bridges; cl; cl = cl->next) {
@@ -1672,10 +1686,14 @@ options_act(const or_options_t *old_options)
time_t now = time(NULL);
int print_notice = 0;
- /* If we aren't acting as a server, we can't collect stats anyway. */
+ /* Only collect directory-request statistics on relays and bridges. */
if (!server_mode(options)) {
- options->CellStatistics = 0;
options->DirReqStatistics = 0;
+ }
+
+ /* Only collect other relay-only statistics on relays. */
+ if (!public_server_mode(options)) {
+ options->CellStatistics = 0;
options->EntryStatistics = 0;
options->ExitPortStatistics = 0;
}
@@ -2360,14 +2378,16 @@ compute_publishserverdescriptor(or_options_t *options)
return 0;
SMARTLIST_FOREACH_BEGIN(list, const char *, string) {
if (!strcasecmp(string, "v1"))
- *auth |= V1_DIRINFO;
+ log_warn(LD_CONFIG, "PublishServerDescriptor v1 has no effect, because "
+ "there are no v1 directory authorities anymore.");
else if (!strcmp(string, "1"))
if (options->BridgeRelay)
*auth |= BRIDGE_DIRINFO;
else
*auth |= V3_DIRINFO;
else if (!strcasecmp(string, "v2"))
- /* obsolete */;
+ log_warn(LD_CONFIG, "PublishServerDescriptor v2 has no effect, because "
+ "there are no v2 directory authorities anymore.");
else if (!strcasecmp(string, "v3"))
*auth |= V3_DIRINFO;
else if (!strcasecmp(string, "bridge"))
@@ -2388,6 +2408,11 @@ compute_publishserverdescriptor(or_options_t *options)
* services can overload the directory system. */
#define MIN_REND_POST_PERIOD (10*60)
+/** Higest allowable value for PredictedPortsRelevanceTime; if this is
+ * too high, our selection of exits will decrease for an extended
+ * period of time to an uncomfortable level .*/
+#define MAX_PREDICTED_CIRCS_RELEVANCE (60*60)
+
/** Highest allowable value for RendPostPeriod. */
#define MAX_DIR_PERIOD (MIN_ONION_KEY_LIFETIME/2)
@@ -2456,7 +2481,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
!strcmpstart(uname, "Windows Me"))) {
log_warn(LD_CONFIG, "Tor is running as a server, but you are "
"running %s; this probably won't work. See "
- "https://wiki.torproject.org/TheOnionRouter/TorFAQ#ServerOS "
+ "https://www.torproject.org/docs/faq.html#BestOSForRelay "
"for details.", uname);
}
@@ -2583,8 +2608,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (options->AuthoritativeDir) {
if (!options->ContactInfo && !options->TestingTorNetwork)
REJECT("Authoritative directory servers must set ContactInfo");
- if (options->V1AuthoritativeDir && !options->RecommendedVersions)
- REJECT("V1 authoritative dir servers must set RecommendedVersions.");
if (!options->RecommendedClientVersions)
options->RecommendedClientVersions =
config_lines_dup(options->RecommendedVersions);
@@ -2607,10 +2630,9 @@ options_validate(or_options_t *old_options, or_options_t *options,
options->DownloadExtraInfo = 1;
}
if (!(options->BridgeAuthoritativeDir ||
- options->V1AuthoritativeDir ||
options->V3AuthoritativeDir))
REJECT("AuthoritativeDir is set, but none of "
- "(Bridge/V1/V3)AuthoritativeDir is set.");
+ "(Bridge/V3)AuthoritativeDir is set.");
/* If we have a v3bandwidthsfile and it's broken, complain on startup */
if (options->V3BandwidthsFile && !old_options) {
dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL);
@@ -2766,10 +2788,10 @@ options_validate(or_options_t *old_options, or_options_t *options,
REJECT("If EntryNodes is set, UseEntryGuards must be enabled.");
}
- if (options->MaxMemInCellQueues < (500 << 20)) {
- log_warn(LD_CONFIG, "MaxMemInCellQueues must be at least 500 MB for now. "
+ if (options->MaxMemInQueues < (256 << 20)) {
+ log_warn(LD_CONFIG, "MaxMemInQueues must be at least 256 MB for now. "
"Ideally, have it as large as you can afford.");
- options->MaxMemInCellQueues = (500 << 20);
+ options->MaxMemInQueues = (256 << 20);
}
options->AllowInvalid_ = 0;
@@ -2815,8 +2837,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
if ((options->BridgeRelay
|| options->PublishServerDescriptor_ & BRIDGE_DIRINFO)
- && (options->PublishServerDescriptor_
- & (V1_DIRINFO|V3_DIRINFO))) {
+ && (options->PublishServerDescriptor_ & V3_DIRINFO)) {
REJECT("Bridges are not supposed to publish router descriptors to the "
"directory authorities. Please correct your "
"PublishServerDescriptor line.");
@@ -2848,6 +2869,13 @@ options_validate(or_options_t *old_options, or_options_t *options,
options->RendPostPeriod = MAX_DIR_PERIOD;
}
+ if (options->PredictedPortsRelevanceTime >
+ MAX_PREDICTED_CIRCS_RELEVANCE) {
+ log_warn(LD_CONFIG, "PredictedPortsRelevanceTime is too large; "
+ "clipping to %ds.", MAX_PREDICTED_CIRCS_RELEVANCE);
+ options->PredictedPortsRelevanceTime = MAX_PREDICTED_CIRCS_RELEVANCE;
+ }
+
if (options->Tor2webMode && options->LearnCircuitBuildTimeout) {
/* LearnCircuitBuildTimeout and Tor2webMode are incompatible in
* two ways:
@@ -3266,17 +3294,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
smartlist_free(options_sl);
}
- /* If we are a bridge with a pluggable transport proxy but no
- Extended ORPort, inform the user that she is missing out. */
- if (server_mode(options) && options->ServerTransportPlugin &&
- !options->ExtORPort_lines) {
- log_notice(LD_CONFIG, "We are a bridge with a pluggable transport "
- "proxy but the Extended ORPort is disabled. The "
- "Extended ORPort helps Tor communicate with the pluggable "
- "transport proxy. Please enable it using the ExtORPort "
- "torrc option.");
- }
-
if (options->ConstrainedSockets) {
/* If the user wants to constrain socket buffer use, make sure the desired
* limit is between MIN|MAX_TCPSOCK_BUFFER in k increments. */
@@ -4673,8 +4690,8 @@ parse_client_transport_line(const char *line, int validate_only)
if (is_managed) { /* managed */
if (!validate_only && is_useless_proxy) {
- log_warn(LD_GENERAL, "Pluggable transport proxy (%s) does not provide "
- "any needed transports and will not be launched.", line);
+ log_notice(LD_GENERAL, "Pluggable transport proxy (%s) does not provide "
+ "any needed transports and will not be launched.", line);
}
/* If we are not just validating, use the rest of the line as the
@@ -5047,9 +5064,7 @@ parse_dir_authority_line(const char *line, dirinfo_type_t required_type,
char *flag = smartlist_get(items, 0);
if (TOR_ISDIGIT(flag[0]))
break;
- if (!strcasecmp(flag, "v1")) {
- type |= V1_DIRINFO;
- } else if (!strcasecmp(flag, "hs") ||
+ if (!strcasecmp(flag, "hs") ||
!strcasecmp(flag, "no-hs")) {
log_warn(LD_CONFIG, "The DirAuthority options 'hs' and 'no-hs' are "
"obsolete; you don't need them any more.");
@@ -6455,7 +6470,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.c b/src/or/connection.c
index 0a01e5020..8c697d6c2 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -1008,9 +1008,9 @@ tor_listen(tor_socket_t fd)
*/
static connection_t *
connection_listener_new(const struct sockaddr *listensockaddr,
- socklen_t socklen,
- int type, const char *address,
- const port_cfg_t *port_cfg)
+ socklen_t socklen,
+ int type, const char *address,
+ const port_cfg_t *port_cfg)
{
listener_connection_t *lis_conn;
connection_t *conn = NULL;
@@ -2227,7 +2227,7 @@ retry_listener_ports(smartlist_t *old_conns,
if (listensockaddr) {
conn = connection_listener_new(listensockaddr, listensocklen,
- port->type, address, port);
+ port->type, address, port);
tor_free(listensockaddr);
tor_free(address);
} else {
@@ -2513,9 +2513,8 @@ connection_bucket_write_limit(connection_t *conn, time_t now)
* shouldn't send <b>attempt</b> bytes of low-priority directory stuff
* out to <b>conn</b>. Else return 0.
- * Priority is 1 for v1 requests (directories and running-routers),
- * and 2 for v2 requests (statuses and descriptors). But see FFFF in
- * directory_handle_command_get() for why we don't use priority 2 yet.
+ * Priority was 1 for v1 requests (directories and running-routers),
+ * and 2 for v2 requests and later (statuses and descriptors).
*
* There are a lot of parameters we could use here:
* - global_relayed_write_bucket. Low is bad.
@@ -4164,20 +4163,29 @@ connection_dir_get_by_purpose_and_resource(int purpose,
return NULL;
}
-/** Return an open, non-marked connection of a given type and purpose, or NULL
- * if no such connection exists. */
-connection_t *
-connection_get_by_type_purpose(int type, int purpose)
+/** Return 1 if there are any active OR connections apart from
+ * <b>this_conn</b>.
+ *
+ * We use this to guess if we should tell the controller that we
+ * didn't manage to connect to any of our bridges. */
+int
+any_other_active_or_conns(const or_connection_t *this_conn)
{
smartlist_t *conns = get_connection_array();
- SMARTLIST_FOREACH(conns, connection_t *, conn,
- {
- if (conn->type == type &&
- !conn->marked_for_close &&
- (purpose == conn->purpose))
- return conn;
- });
- return NULL;
+ SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
+ if (conn == TO_CONN(this_conn)) { /* don't consider this conn */
+ continue;
+ }
+
+ if (conn->type == CONN_TYPE_OR &&
+ !conn->marked_for_close) {
+ log_debug(LD_DIR, "%s: Found an OR connection: %s",
+ __func__, conn->address);
+ return 1;
+ }
+ } SMARTLIST_FOREACH_END(conn);
+
+ return 0;
}
/** Return 1 if <b>conn</b> is a listener conn, else return 0. */
diff --git a/src/or/connection.h b/src/or/connection.h
index 4073d9fc9..13dcbcd91 100644
--- a/src/or/connection.h
+++ b/src/or/connection.h
@@ -178,7 +178,6 @@ connection_get_outbuf_len(connection_t *conn)
connection_t *connection_get_by_global_id(uint64_t id);
connection_t *connection_get_by_type(int type);
-connection_t *connection_get_by_type_purpose(int type, int purpose);
connection_t *connection_get_by_type_addr_port_purpose(int type,
const tor_addr_t *addr,
uint16_t port, int purpose);
@@ -188,6 +187,8 @@ connection_t *connection_get_by_type_state_rendquery(int type, int state,
dir_connection_t *connection_dir_get_by_purpose_and_resource(
int state, const char *resource);
+int any_other_active_or_conns(const or_connection_t *this_conn);
+
#define connection_speaks_cells(conn) ((conn)->type == CONN_TYPE_OR)
int connection_is_listener(connection_t *conn);
int connection_state_is_open(connection_t *conn);
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 4ca926e38..630c3b918 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -2273,13 +2273,24 @@ connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply,
/* leave version, destport, destip zero */
connection_write_to_buf(buf, SOCKS4_NETWORK_LEN, ENTRY_TO_CONN(conn));
} else if (conn->socks_request->socks_version == 5) {
- buf[0] = 5; /* version 5 */
- buf[1] = (char)status;
- buf[2] = 0;
- buf[3] = 1; /* ipv4 addr */
- memset(buf+4,0,6); /* Set external addr/port to 0.
- The spec doesn't seem to say what to do here. -RD */
- connection_write_to_buf(buf,10,ENTRY_TO_CONN(conn));
+ size_t buf_len;
+ memset(buf,0,sizeof(buf));
+ if (tor_addr_family(&conn->edge_.base_.addr) == AF_INET) {
+ buf[0] = 5; /* version 5 */
+ buf[1] = (char)status;
+ buf[2] = 0;
+ buf[3] = 1; /* ipv4 addr */
+ /* 4 bytes for the header, 2 bytes for the port, 4 for the address. */
+ buf_len = 10;
+ } else { /* AF_INET6. */
+ buf[0] = 5; /* version 5 */
+ buf[1] = (char)status;
+ buf[2] = 0;
+ buf[3] = 4; /* ipv6 addr */
+ /* 4 bytes for the header, 2 bytes for the port, 16 for the address. */
+ buf_len = 22;
+ }
+ connection_write_to_buf(buf,buf_len,ENTRY_TO_CONN(conn));
}
/* If socks_version isn't 4 or 5, don't send anything.
* This can happen in the case of AP bridges. */
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index dbf05a6fc..04ad2cc00 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)
@@ -714,7 +714,8 @@ connection_or_about_to_close(or_connection_t *or_conn)
reason);
if (!authdir_mode_tests_reachability(options))
control_event_bootstrap_problem(
- orconn_end_reason_to_control_string(reason), reason);
+ orconn_end_reason_to_control_string(reason),
+ reason, or_conn);
}
}
} else if (conn->hold_open_until_flushed) {
@@ -1077,7 +1078,7 @@ connection_or_connect_failed(or_connection_t *conn,
{
control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED, reason);
if (!authdir_mode_tests_reachability(get_options()))
- control_event_bootstrap_problem(msg, reason);
+ control_event_bootstrap_problem(msg, reason, conn);
}
/** <b>conn</b> got an error in connection_handle_read_impl() or
@@ -1708,7 +1709,8 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
if (!authdir_mode_tests_reachability(options))
control_event_bootstrap_problem(
"Unexpected identity in router certificate",
- END_OR_CONN_REASON_OR_IDENTITY);
+ END_OR_CONN_REASON_OR_IDENTITY,
+ conn);
return -1;
}
if (authdir_mode_tests_reachability(options)) {
@@ -1758,8 +1760,6 @@ connection_tls_finish_handshake(or_connection_t *conn)
safe_str_client(conn->base_.address),
tor_tls_get_ciphersuite_name(conn->tls));
- directory_set_dirty();
-
if (connection_or_check_valid_tls_handshake(conn, started_here,
digest_rcvd) < 0)
return -1;
diff --git a/src/or/control.c b/src/or/control.c
index 42db3613d..23e2054f9 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -3176,27 +3176,22 @@ connection_control_reached_eof(control_connection_t *conn)
return 0;
}
+static void lost_owning_controller(const char *owner_type,
+ const char *loss_manner)
+ ATTR_NORETURN;
+
/** Shut down this Tor instance in the same way that SIGINT would, but
* with a log message appropriate for the loss of an owning controller. */
static void
lost_owning_controller(const char *owner_type, const char *loss_manner)
{
- int shutdown_slowly = server_mode(get_options());
-
- log_notice(LD_CONTROL, "Owning controller %s has %s -- %s.",
- owner_type, loss_manner,
- shutdown_slowly ? "shutting down" : "exiting now");
+ log_notice(LD_CONTROL, "Owning controller %s has %s -- exiting now.",
+ owner_type, loss_manner);
/* XXXX Perhaps this chunk of code should be a separate function,
* called here and by process_signal(SIGINT). */
-
- if (!shutdown_slowly) {
- tor_cleanup();
- exit(0);
- }
- /* XXXX This will close all listening sockets except control-port
- * listeners. Perhaps we should close those too. */
- hibernate_begin_shutdown();
+ tor_cleanup();
+ exit(0);
}
/** Called when <b>conn</b> is being freed. */
@@ -4679,6 +4674,8 @@ static char *owning_controller_process_spec = NULL;
* if this Tor instance is not currently owned by a process. */
static tor_process_monitor_t *owning_controller_process_monitor = NULL;
+static void owning_controller_procmon_cb(void *unused) ATTR_NORETURN;
+
/** Process-termination monitor callback for Tor's owning controller
* process. */
static void
@@ -4882,10 +4879,12 @@ control_event_bootstrap(bootstrap_status_t status, int progress)
/** Called when Tor has failed to make bootstrapping progress in a way
* that indicates a problem. <b>warn</b> gives a hint as to why, and
- * <b>reason</b> provides an "or_conn_end_reason" tag.
+ * <b>reason</b> provides an "or_conn_end_reason" tag. <b>or_conn</b>
+ * is the connection that caused this problem.
*/
MOCK_IMPL(void,
-control_event_bootstrap_problem, (const char *warn, int reason))
+ control_event_bootstrap_problem, (const char *warn, int reason,
+ const or_connection_t *or_conn))
{
int status = bootstrap_percent;
const char *tag, *summary;
@@ -4907,9 +4906,10 @@ control_event_bootstrap_problem, (const char *warn, int reason))
if (reason == END_OR_CONN_REASON_NO_ROUTE)
recommendation = "warn";
- if (get_options()->UseBridges &&
- !any_bridge_descriptors_known() &&
- !any_pending_bridge_descriptor_fetches())
+ /* If we are using bridges and all our OR connections are now
+ closed, it means that we totally failed to connect to our
+ bridges. Throw a warning. */
+ if (get_options()->UseBridges && !any_other_active_or_conns(or_conn))
recommendation = "warn";
if (we_are_hibernating())
diff --git a/src/or/control.h b/src/or/control.h
index 0466de17f..ce605a120 100644
--- a/src/or/control.h
+++ b/src/or/control.h
@@ -93,7 +93,8 @@ void monitor_owning_controller_process(const char *process_spec);
void control_event_bootstrap(bootstrap_status_t status, int progress);
MOCK_DECL(void, control_event_bootstrap_problem,(const char *warn,
- int reason));
+ int reason,
+ const or_connection_t *or_conn));
void control_event_clients_seen(const char *controller_str);
void control_event_transport_launched(const char *mode,
diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c
index ecf0d2035..209274da6 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 c102512c2..5fe6897b5 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -82,8 +82,7 @@ static void dir_microdesc_download_failed(smartlist_t *failed,
static void note_client_request(int purpose, int compressed, size_t bytes);
static int client_likes_consensus(networkstatus_t *v, const char *want_url);
-static void directory_initiate_command_rend(const char *address,
- const tor_addr_t *addr,
+static void directory_initiate_command_rend(const tor_addr_t *addr,
uint16_t or_port,
uint16_t dir_port,
const char *digest,
@@ -149,8 +148,6 @@ authdir_type_to_string(dirinfo_type_t auth)
{
char *result;
smartlist_t *lst = smartlist_new();
- if (auth & V1_DIRINFO)
- smartlist_add(lst, (void*)"V1");
if (auth & V3_DIRINFO)
smartlist_add(lst, (void*)"V3");
if (auth & BRIDGE_DIRINFO)
@@ -170,12 +167,8 @@ dir_conn_purpose_to_string(int purpose)
{
switch (purpose)
{
- case DIR_PURPOSE_FETCH_RENDDESC:
- return "hidden-service descriptor fetch";
case DIR_PURPOSE_UPLOAD_DIR:
return "server descriptor upload";
- case DIR_PURPOSE_UPLOAD_RENDDESC:
- return "hidden-service descriptor upload";
case DIR_PURPOSE_UPLOAD_VOTE:
return "server vote upload";
case DIR_PURPOSE_UPLOAD_SIGNATURES:
@@ -247,13 +240,13 @@ directories_have_accepted_server_descriptor(void)
/** Start a connection to every suitable directory authority, using
* connection purpose <b>dir_purpose</b> and uploading <b>payload</b>
* (of length <b>payload_len</b>). The dir_purpose should be one of
- * 'DIR_PURPOSE_UPLOAD_DIR' or 'DIR_PURPOSE_UPLOAD_RENDDESC'.
+ * 'DIR_PURPOSE_UPLOAD_{DIR|VOTE|SIGNATURES}'.
*
* <b>router_purpose</b> describes the type of descriptor we're
* publishing, if we're publishing a descriptor -- e.g. general or bridge.
*
- * <b>type</b> specifies what sort of dir authorities (V1, V3,
- * HIDSERV, BRIDGE, etc) we should upload to.
+ * <b>type</b> specifies what sort of dir authorities (V3,
+ * BRIDGE, etc) we should upload to.
*
* If <b>extrainfo_len</b> is nonzero, the first <b>payload_len</b> bytes of
* <b>payload</b> hold a router descriptor, and the next <b>extrainfo_len</b>
@@ -410,9 +403,6 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_DIRINFO :
V3_DIRINFO);
break;
- case DIR_PURPOSE_FETCH_RENDDESC:
- type = HIDSERV_DIRINFO;
- break;
case DIR_PURPOSE_FETCH_STATUS_VOTE:
case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
case DIR_PURPOSE_FETCH_CERTIFICATE:
@@ -452,7 +442,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
}
}
- if (!options->FetchServerDescriptors && type != HIDSERV_DIRINFO)
+ if (!options->FetchServerDescriptors)
return;
if (!get_via_tor) {
@@ -471,7 +461,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
tor_addr_t addr;
routerinfo_t *ri = node->ri;
node_get_addr(node, &addr);
- directory_initiate_command(ri->address, &addr,
+ directory_initiate_command(&addr,
ri->or_port, 0/*no dirport*/,
ri->cache_info.identity_digest,
dir_purpose,
@@ -523,11 +513,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
}
} else { /* get_via_tor */
/* Never use fascistfirewall; we're going via Tor. */
- if (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) {
- /* only ask hidserv authorities, any of them will do */
- pds_flags |= PDS_IGNORE_FASCISTFIREWALL|PDS_ALLOW_SELF;
- rs = router_pick_trusteddirserver(HIDSERV_DIRINFO, pds_flags);
- } else {
+ if (1) {
/* anybody with a non-zero dirport will do. Disregard firewalls. */
pds_flags |= PDS_IGNORE_FASCISTFIREWALL;
rs = router_pick_directory_server(type, pds_flags);
@@ -604,9 +590,6 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
{
const or_options_t *options = get_options();
const node_t *node;
- char address_buf[INET_NTOA_BUF_LEN+1];
- struct in_addr in;
- const char *address;
tor_addr_t addr;
const int anonymized_connection = dirind_is_anon(indirection);
node = node_get_by_id(status->identity_digest);
@@ -616,13 +599,6 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
"don't have its router descriptor.",
routerstatus_describe(status));
return;
- } else if (node) {
- node_get_address_string(node, address_buf, sizeof(address_buf));
- address = address_buf;
- } else {
- in.s_addr = htonl(status->addr);
- tor_inet_ntoa(&in, address_buf, sizeof(address_buf));
- address = address_buf;
}
tor_addr_from_ipv4h(&addr, status->addr);
@@ -636,7 +612,7 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
return;
}
- directory_initiate_command_rend(address, &addr,
+ directory_initiate_command_rend(&addr,
status->or_port, status->dir_port,
status->identity_digest,
dir_purpose, router_purpose,
@@ -649,7 +625,7 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
* upload or download a server or rendezvous
* descriptor. <b>dir_purpose</b> determines what
* kind of directory connection we're launching, and must be one of
- * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC|RENDDESC_V2}. <b>router_purpose</b>
+ * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC_V2}. <b>router_purpose</b>
* specifies the descriptor purposes we have in mind (currently only
* used for FETCH_DIR).
*
@@ -878,7 +854,7 @@ directory_command_should_use_begindir(const or_options_t *options,
* <b>supports_begindir</b>, and whose identity key digest is
* <b>digest</b>. */
void
-directory_initiate_command(const char *address, const tor_addr_t *_addr,
+directory_initiate_command(const tor_addr_t *_addr,
uint16_t or_port, uint16_t dir_port,
const char *digest,
uint8_t dir_purpose, uint8_t router_purpose,
@@ -886,7 +862,7 @@ directory_initiate_command(const char *address, const tor_addr_t *_addr,
const char *payload, size_t payload_len,
time_t if_modified_since)
{
- directory_initiate_command_rend(address, _addr, or_port, dir_port,
+ directory_initiate_command_rend(_addr, or_port, dir_port,
digest, dir_purpose,
router_purpose, indirection,
resource, payload, payload_len,
@@ -900,9 +876,7 @@ directory_initiate_command(const char *address, const tor_addr_t *_addr,
static int
is_sensitive_dir_purpose(uint8_t dir_purpose)
{
- return ((dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) ||
- (dir_purpose == DIR_PURPOSE_HAS_FETCHED_RENDDESC) ||
- (dir_purpose == DIR_PURPOSE_UPLOAD_RENDDESC) ||
+ return ((dir_purpose == DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2) ||
(dir_purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) ||
(dir_purpose == DIR_PURPOSE_FETCH_RENDDESC_V2));
}
@@ -910,7 +884,7 @@ is_sensitive_dir_purpose(uint8_t dir_purpose)
/** Same as directory_initiate_command(), but accepts rendezvous data to
* fetch a hidden service descriptor. */
static void
-directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
+directory_initiate_command_rend(const tor_addr_t *_addr,
uint16_t or_port, uint16_t dir_port,
const char *digest,
uint8_t dir_purpose, uint8_t router_purpose,
@@ -928,7 +902,6 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
const int anonymized_connection = dirind_is_anon(indirection);
tor_addr_t addr;
- tor_assert(address);
tor_assert(_addr);
tor_assert(or_port || dir_port);
tor_assert(digest);
@@ -961,7 +934,7 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
/* set up conn so it's got all the data we need to remember */
tor_addr_copy(&conn->base_.addr, &addr);
conn->base_.port = use_begindir ? or_port : dir_port;
- conn->base_.address = tor_strdup(address);
+ conn->base_.address = tor_dup_addr(&addr);
memcpy(conn->identity_digest, digest, DIGEST_LEN);
conn->base_.purpose = dir_purpose;
@@ -1267,12 +1240,6 @@ directory_send_command(dir_connection_t *conn,
httpcommand = "GET";
tor_asprintf(&url, "/tor/rendezvous2/%s", resource);
break;
- case DIR_PURPOSE_UPLOAD_RENDDESC:
- tor_assert(!resource);
- tor_assert(payload);
- httpcommand = "POST";
- url = tor_strdup("/tor/rendezvous/publish");
- break;
case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
tor_assert(!resource);
tor_assert(payload);
@@ -1519,8 +1486,8 @@ parse_http_response(const char *headers, int *code, time_t *date,
}
/** Return true iff <b>body</b> doesn't start with a plausible router or
- * running-list or directory opening. This is a sign of possible compression.
- **/
+ * network-status or microdescriptor opening. This is a sign of possible
+ * compression. */
static int
body_is_plausible(const char *body, size_t len, int purpose)
{
@@ -1532,20 +1499,16 @@ body_is_plausible(const char *body, size_t len, int purpose)
if (purpose == DIR_PURPOSE_FETCH_MICRODESC) {
return (!strcmpstart(body,"onion-key"));
}
- if (purpose != DIR_PURPOSE_FETCH_RENDDESC) {
+ if (1) {
if (!strcmpstart(body,"router") ||
- !strcmpstart(body,"signed-directory") ||
- !strcmpstart(body,"network-status") ||
- !strcmpstart(body,"running-routers"))
- return 1;
+ !strcmpstart(body,"network-status"))
+ return 1;
for (i=0;i<32;++i) {
if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
return 0;
}
- return 1;
- } else {
- return 1;
}
+ return 1;
}
/** Called when we've just fetched a bunch of router descriptors in
@@ -2104,46 +2067,6 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
* dirservers down just because they don't like us. */
}
- if (conn->base_.purpose == DIR_PURPOSE_FETCH_RENDDESC) {
- tor_assert(conn->rend_data);
- log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
- "(%s))",
- (int)body_len, status_code, escaped(reason));
- switch (status_code) {
- case 200:
- if (rend_cache_store(body, body_len, 0,
- conn->rend_data->onion_address) < -1) {
- log_warn(LD_REND,"Failed to parse rendezvous descriptor.");
- /* Any pending rendezvous attempts will notice when
- * connection_about_to_close_connection()
- * cleans this dir conn up. */
- /* We could retry. But since v0 descriptors are going out of
- * style, it isn't worth the hassle. We'll do better in v2. */
- } else {
- /* Success, or at least there's a v2 descriptor already
- * present. Notify pending connections about this. */
- conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
- rend_client_desc_trynow(conn->rend_data->onion_address);
- }
- break;
- case 404:
- /* Not there. Pending connections will be notified when
- * connection_about_to_close_connection() cleans this conn up. */
- break;
- case 400:
- log_warn(LD_REND,
- "http status 400 (%s). Dirserver didn't like our "
- "rendezvous query?", escaped(reason));
- break;
- default:
- log_warn(LD_REND,"http status %d (%s) response unexpected while "
- "fetching hidden service descriptor (server '%s:%d').",
- status_code, escaped(reason), conn->base_.address,
- conn->base_.port);
- break;
- }
- }
-
if (conn->base_.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) {
#define SEND_HS_DESC_FAILED_EVENT() ( \
control_event_hs_descriptor_failed(conn->rend_data, \
@@ -2155,27 +2078,22 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
switch (status_code) {
case 200:
switch (rend_cache_store_v2_desc_as_client(body, conn->rend_data)) {
- case -2:
+ case RCS_BADDESC:
+ case RCS_NOTDIR: /* Impossible */
log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed. "
"Retrying at another directory.");
/* We'll retry when connection_about_to_close_connection()
* cleans this dir conn up. */
SEND_HS_DESC_FAILED_EVENT();
break;
- case -1:
- /* We already have a v0 descriptor here. Ignoring this one
- * and _not_ performing another request. */
- log_info(LD_REND, "Successfully fetched v2 rendezvous "
- "descriptor, but we already have a v0 descriptor.");
- conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
- break;
+ case RCS_OKAY:
default:
/* success. notify pending connections about this. */
log_info(LD_REND, "Successfully fetched v2 rendezvous "
"descriptor.");
control_event_hs_descriptor_received(conn->rend_data,
conn->identity_digest);
- conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
+ conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2;
rend_client_desc_trynow(conn->rend_data->onion_address);
break;
}
@@ -2206,8 +2124,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
}
}
- if (conn->base_.purpose == DIR_PURPOSE_UPLOAD_RENDDESC ||
- conn->base_.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) {
+ if (conn->base_.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) {
log_info(LD_REND,"Uploaded rendezvous descriptor (status %d "
"(%s))",
status_code, escaped(reason));
@@ -2311,7 +2228,7 @@ connection_dir_about_to_close(dir_connection_t *dir_conn)
}
/* If we were trying to fetch a v2 rend desc and did not succeed,
* retry as needed. (If a fetch is successful, the connection state
- * is changed to DIR_PURPOSE_HAS_FETCHED_RENDDESC to mark that
+ * is changed to DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2 to mark that
* refetching is unnecessary.) */
if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2 &&
dir_conn->rend_data &&
@@ -2452,9 +2369,7 @@ note_client_request(int purpose, int compressed, size_t bytes)
case DIR_PURPOSE_UPLOAD_DIR: kind = "dl/ul-dir"; break;
case DIR_PURPOSE_UPLOAD_VOTE: kind = "dl/ul-vote"; break;
case DIR_PURPOSE_UPLOAD_SIGNATURES: kind = "dl/ul-sig"; break;
- case DIR_PURPOSE_FETCH_RENDDESC: kind = "dl/rend"; break;
case DIR_PURPOSE_FETCH_RENDDESC_V2: kind = "dl/rend2"; break;
- case DIR_PURPOSE_UPLOAD_RENDDESC: kind = "dl/ul-rend"; break;
case DIR_PURPOSE_UPLOAD_RENDDESC_V2: kind = "dl/ul-rend2"; break;
}
if (kind) {
@@ -2666,75 +2581,6 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
/* if no disclaimer file, fall through and continue */
}
- if (!strcmp(url,"/tor/") || !strcmp(url,"/tor/dir")) { /* v1 dir fetch */
- cached_dir_t *d = dirserv_get_directory();
-
- if (!d) {
- log_info(LD_DIRSERV,"Client asked for the mirrored directory, but we "
- "don't have a good one yet. Sending 503 Dir not available.");
- write_http_status_line(conn, 503, "Directory unavailable");
- goto done;
- }
- if (d->published < if_modified_since) {
- write_http_status_line(conn, 304, "Not modified");
- goto done;
- }
-
- dlen = compressed ? d->dir_z_len : d->dir_len;
-
- if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
- log_debug(LD_DIRSERV,
- "Client asked for the mirrored directory, but we've been "
- "writing too many bytes lately. Sending 503 Dir busy.");
- write_http_status_line(conn, 503, "Directory busy, try again later");
- goto done;
- }
-
- note_request(url, dlen);
-
- log_debug(LD_DIRSERV,"Dumping %sdirectory to client.",
- compressed?"compressed ":"");
- write_http_response_header(conn, dlen, compressed,
- FULL_DIR_CACHE_LIFETIME);
- conn->cached_dir = d;
- conn->cached_dir_offset = 0;
- if (!compressed)
- conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
- ++d->refcnt;
-
- /* Prime the connection with some data. */
- conn->dir_spool_src = DIR_SPOOL_CACHED_DIR;
- connection_dirserv_flushed_some(conn);
- goto done;
- }
-
- if (!strcmp(url,"/tor/running-routers")) { /* running-routers fetch */
- cached_dir_t *d = dirserv_get_runningrouters();
- if (!d) {
- write_http_status_line(conn, 503, "Directory unavailable");
- goto done;
- }
- if (d->published < if_modified_since) {
- write_http_status_line(conn, 304, "Not modified");
- goto done;
- }
- dlen = compressed ? d->dir_z_len : d->dir_len;
-
- if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
- log_info(LD_DIRSERV,
- "Client asked for running-routers, but we've been "
- "writing too many bytes lately. Sending 503 Dir busy.");
- write_http_status_line(conn, 503, "Directory busy, try again later");
- goto done;
- }
- note_request(url, dlen);
- write_http_response_header(conn, dlen, compressed,
- RUNNINGROUTERS_CACHE_LIFETIME);
- connection_write_to_buf(compressed ? d->dir_z : d->dir, dlen,
- TO_CONN(conn));
- goto done;
- }
-
if (!strcmpstart(url, "/tor/status-vote/current/consensus")) {
/* v3 network status fetch. */
smartlist_t *dir_fps = smartlist_new();
@@ -3312,19 +3158,20 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers,
connection_dir_is_encrypted(conn) &&
!strcmpstart(url,"/tor/rendezvous2/publish")) {
switch (rend_cache_store_v2_desc_as_dir(body)) {
- case -2:
+ case RCS_NOTDIR:
log_info(LD_REND, "Rejected v2 rend descriptor (length %d) from %s "
"since we're not currently a hidden service directory.",
(int)body_len, conn->base_.address);
write_http_status_line(conn, 503, "Currently not acting as v2 "
"hidden service directory");
break;
- case -1:
+ case RCS_BADDESC:
log_warn(LD_REND, "Rejected v2 rend descriptor (length %d) from %s.",
(int)body_len, conn->base_.address);
write_http_status_line(conn, 400,
"Invalid v2 service descriptor rejected");
break;
+ case RCS_OKAY:
default:
write_http_status_line(conn, 200, "Service descriptor (v2) stored");
log_info(LD_REND, "Handled v2 rendezvous descriptor post: accepted");
@@ -3348,8 +3195,6 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers,
was_router_added_t r = dirserv_add_multiple_descriptors(body, purpose,
conn->base_.address, &msg);
tor_assert(msg);
- if (WRA_WAS_ADDED(r))
- dirserv_get_directory(); /* rebuild and write to disk */
if (r == ROUTER_ADDED_NOTIFY_GENERATOR) {
/* Accepted with a message. */
diff --git a/src/or/directory.h b/src/or/directory.h
index 3de69329a..bc200797d 100644
--- a/src/or/directory.h
+++ b/src/or/directory.h
@@ -63,7 +63,7 @@ int connection_dir_process_inbuf(dir_connection_t *conn);
int connection_dir_finished_flushing(dir_connection_t *conn);
int connection_dir_finished_connecting(dir_connection_t *conn);
void connection_dir_about_to_close(dir_connection_t *dir_conn);
-void directory_initiate_command(const char *address, const tor_addr_t *addr,
+void directory_initiate_command(const tor_addr_t *addr,
uint16_t or_port, uint16_t dir_port,
const char *digest,
uint8_t dir_purpose, uint8_t router_purpose,
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index c0e000c75..19ed12d7c 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -42,28 +42,10 @@
* directory authorities. */
#define MAX_UNTRUSTED_NETWORKSTATUSES 16
-/** If a v1 directory is older than this, discard it. */
-#define MAX_V1_DIRECTORY_AGE (30*24*60*60)
-/** If a v1 running-routers is older than this, discard it. */
-#define MAX_V1_RR_AGE (7*24*60*60)
-
extern time_t time_of_process_start; /* from main.c */
extern long stats_n_seconds_working; /* from main.c */
-/** Do we need to regenerate the v1 directory when someone asks for it? */
-static time_t the_directory_is_dirty = 1;
-/** Do we need to regenerate the v1 runningrouters document when somebody
- * asks for it? */
-static time_t runningrouters_is_dirty = 1;
-
-/** Most recently generated encoded signed v1 directory. (v1 auth dirservers
- * only.) */
-static cached_dir_t *the_directory = NULL;
-
-/** For authoritative directories: the current (v1) network status. */
-static cached_dir_t the_runningrouters;
-
/** Total number of routers with measured bandwidth; this is set by
* dirserv_count_measured_bws() before the loop in
* dirserv_generate_networkstatus_vote_obj() and checked by
@@ -72,14 +54,12 @@ static cached_dir_t the_runningrouters;
static int routers_with_measured_bw = 0;
static void directory_remove_invalid(void);
-static cached_dir_t *dirserv_regenerate_directory(void);
static char *format_versions_list(config_line_t *ln);
struct authdir_config_t;
static int add_fingerprint_to_dir(const char *nickname, const char *fp,
struct authdir_config_t *list);
static uint32_t
dirserv_get_status_impl(const char *fp, const char *nickname,
- const char *address,
uint32_t addr, uint16_t or_port,
const char *platform, const char *contact,
const char **msg, int should_log);
@@ -327,7 +307,6 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg)
}
return dirserv_get_status_impl(d, router->nickname,
- router->address,
router->addr, router->or_port,
router->platform, router->contact_info,
msg, 1);
@@ -341,7 +320,6 @@ dirserv_would_reject_router(const routerstatus_t *rs)
uint32_t res;
res = dirserv_get_status_impl(rs->identity_digest, rs->nickname,
- "", /* address is only used in logs */
rs->addr, rs->or_port,
NULL, NULL,
NULL, 0);
@@ -380,7 +358,6 @@ dirserv_get_name_status(const char *id_digest, const char *nickname)
*/
static uint32_t
dirserv_get_status_impl(const char *id_digest, const char *nickname,
- const char *address,
uint32_t addr, uint16_t or_port,
const char *platform, const char *contact,
const char **msg, int should_log)
@@ -397,13 +374,15 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname,
strmap_size(fingerprint_list->fp_by_name),
digestmap_size(fingerprint_list->status_by_digest));
- /* Versions before Tor 0.2.2.35 have known security issues that
- * make them unsuitable for the current network. */
- if (platform && !tor_version_as_new_as(platform,"0.2.2.35")) {
+ /* Versions before Tor 0.2.3.16-alpha are too old to support, and are
+ * missing some important security fixes too. Disable them. */
+ if (platform && !tor_version_as_new_as(platform,"0.2.3.16-alpha")) {
if (msg)
*msg = "Tor version is insecure or unsupported. Please upgrade!";
return FP_REJECT;
- } else if (platform && tor_version_as_new_as(platform,"0.2.3.0-alpha")) {
+ }
+#if 0
+ else if (platform && tor_version_as_new_as(platform,"0.2.3.0-alpha")) {
/* Versions from 0.2.3-alpha...0.2.3.9-alpha have known security
* issues that make them unusable for the current network */
if (!tor_version_as_new_as(platform, "0.2.3.10-alpha")) {
@@ -412,6 +391,7 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname,
return FP_REJECT;
}
}
+#endif
result = dirserv_get_name_status(id_digest, nickname);
if (result & FP_NAMED) {
@@ -452,14 +432,14 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname,
if (should_log)
log_info(LD_DIRSERV,
"Marking '%s' as bad directory because of address '%s'",
- nickname, address);
+ nickname, fmt_addr32(addr));
result |= FP_BADDIR;
}
if (authdir_policy_badexit_address(addr, or_port)) {
if (should_log)
log_info(LD_DIRSERV, "Marking '%s' as bad exit because of address '%s'",
- nickname, address);
+ nickname, fmt_addr32(addr));
result |= FP_BADEXIT;
}
@@ -467,7 +447,7 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname,
if (!authdir_policy_permits_address(addr, or_port)) {
if (should_log)
log_info(LD_DIRSERV, "Rejecting '%s' because of address '%s'",
- nickname, address);
+ nickname, fmt_addr32(addr));
if (msg)
*msg = "Authdir is rejecting routers in this range.";
return FP_REJECT;
@@ -475,7 +455,7 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname,
if (!authdir_policy_valid_address(addr, or_port)) {
if (should_log)
log_info(LD_DIRSERV, "Not marking '%s' valid because of address '%s'",
- nickname, address);
+ nickname, fmt_addr32(addr));
result |= FP_INVALID;
}
if (reject_unlisted) {
@@ -524,19 +504,12 @@ dirserv_free_fingerprint_list(void)
static int
dirserv_router_has_valid_address(routerinfo_t *ri)
{
- struct in_addr iaddr;
if (get_options()->DirAllowPrivateAddresses)
return 0; /* whatever it is, we're fine with it */
- if (!tor_inet_aton(ri->address, &iaddr)) {
- log_info(LD_DIRSERV,"Router %s published non-IP address '%s'. Refusing.",
- router_describe(ri),
- ri->address);
- return -1;
- }
- if (is_internal_IP(ntohl(iaddr.s_addr), 0)) {
+ if (is_internal_IP(ri->addr, 0)) {
log_info(LD_DIRSERV,
- "Router %s published internal IP address '%s'. Refusing.",
- router_describe(ri), ri->address);
+ "Router %s published internal IP address. Refusing.",
+ router_describe(ri));
return -1; /* it's a private IP, we should reject it */
}
return 0;
@@ -588,12 +561,10 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
}
if (dirserv_router_has_valid_address(ri) < 0) {
log_fn(severity, LD_DIRSERV,
- "Router %s has invalid address '%s'. "
- "Not adding (%s).",
+ "Router %s has invalid address. Not adding (%s).",
router_describe(ri),
- ri->address,
esc_router_info(ri));
- *msg = "Rejected: Address is not an IP, or IP is a private address.";
+ *msg = "Rejected: Address is a private address.";
return -1;
}
@@ -837,7 +808,6 @@ dirserv_add_extrainfo(extrainfo_t *ei, const char **msg)
static void
directory_remove_invalid(void)
{
- int changed = 0;
routerlist_t *rl = router_get_routerlist();
smartlist_t *nodes = smartlist_new();
smartlist_add_all(nodes, nodelist_get_list());
@@ -855,7 +825,6 @@ directory_remove_invalid(void)
log_info(LD_DIRSERV, "Router %s is now rejected: %s",
description, msg?msg:"");
routerlist_remove(rl, ent, 0, time(NULL));
- changed = 1;
continue;
}
#if 0
@@ -864,70 +833,35 @@ directory_remove_invalid(void)
"Router %s is now %snamed.", description,
(r&FP_NAMED)?"":"un");
ent->is_named = (r&FP_NAMED)?1:0;
- changed = 1;
}
if (bool_neq((r & FP_UNNAMED), ent->auth_says_is_unnamed)) {
log_info(LD_DIRSERV,
"Router '%s' is now %snamed. (FP_UNNAMED)", description,
(r&FP_NAMED)?"":"un");
ent->is_named = (r&FP_NUNAMED)?0:1;
- changed = 1;
}
#endif
if (bool_neq((r & FP_INVALID), !node->is_valid)) {
log_info(LD_DIRSERV, "Router '%s' is now %svalid.", description,
(r&FP_INVALID) ? "in" : "");
node->is_valid = (r&FP_INVALID)?0:1;
- changed = 1;
}
if (bool_neq((r & FP_BADDIR), node->is_bad_directory)) {
log_info(LD_DIRSERV, "Router '%s' is now a %s directory", description,
(r & FP_BADDIR) ? "bad" : "good");
node->is_bad_directory = (r&FP_BADDIR) ? 1: 0;
- changed = 1;
}
if (bool_neq((r & FP_BADEXIT), node->is_bad_exit)) {
log_info(LD_DIRSERV, "Router '%s' is now a %s exit", description,
(r & FP_BADEXIT) ? "bad" : "good");
node->is_bad_exit = (r&FP_BADEXIT) ? 1: 0;
- changed = 1;
}
} SMARTLIST_FOREACH_END(node);
- if (changed)
- directory_set_dirty();
routerlist_assert_ok(rl);
smartlist_free(nodes);
}
-/** Mark the directory as <b>dirty</b> -- when we're next asked for a
- * directory, we will rebuild it instead of reusing the most recently
- * generated one.
- */
-void
-directory_set_dirty(void)
-{
- time_t now = time(NULL);
- int set_v1_dirty=0;
-
- /* Regenerate stubs only every 8 hours.
- * XXXX It would be nice to generate less often, but these are just
- * stubs: it doesn't matter. */
-#define STUB_REGENERATE_INTERVAL (8*60*60)
- if (!the_directory || !the_runningrouters.dir)
- set_v1_dirty = 1;
- else if (the_directory->published < now - STUB_REGENERATE_INTERVAL ||
- the_runningrouters.published < now - STUB_REGENERATE_INTERVAL)
- set_v1_dirty = 1;
-
- if (set_v1_dirty) {
- if (!the_directory_is_dirty)
- the_directory_is_dirty = now;
- if (!runningrouters_is_dirty)
- runningrouters_is_dirty = now;
- }
-}
-
/**
* Allocate and return a description of the status of the server <b>desc</b>,
* for use in a v1-style router-status line. The server is listed
@@ -1301,15 +1235,6 @@ directory_permits_begindir_requests(const or_options_t *options)
return options->BridgeRelay != 0 || options->DirPort_set;
}
-/** Return 1 if we want to allow controllers to ask us directory
- * requests via the controller interface, which doesn't require
- * having any separate port open. */
-int
-directory_permits_controller_requests(const or_options_t *options)
-{
- return options->DirPort_set;
-}
-
/** Return 1 if we have no need to fetch new descriptors. This generally
* happens when we're not a dir cache and we haven't built any circuits
* lately.
@@ -1325,51 +1250,10 @@ directory_too_idle_to_fetch_descriptors(const or_options_t *options,
/********************************************************************/
-/* Used only by non-v1-auth dirservers: The v1 directory and
- * runningrouters we'll serve when requested. */
-
-/** The v1 directory we'll serve (as a cache or as an authority) if
- * requested. */
-static cached_dir_t *cached_directory = NULL;
-/** The v1 runningrouters document we'll serve (as a cache or as an authority)
- * if requested. */
-static cached_dir_t cached_runningrouters;
-
/** Map from flavor name to the cached_dir_t for the v3 consensuses that we're
* currently serving. */
static strmap_t *cached_consensuses = NULL;
-/** Possibly replace the contents of <b>d</b> with the value of
- * <b>directory</b> published on <b>when</b>, unless <b>when</b> is older than
- * the last value, or too far in the future.
- *
- * Does not copy <b>directory</b>; frees it if it isn't used.
- */
-static void
-set_cached_dir(cached_dir_t *d, char *directory, time_t when)
-{
- time_t now = time(NULL);
- if (when<=d->published) {
- log_info(LD_DIRSERV, "Ignoring old directory; not caching.");
- tor_free(directory);
- } else if (when>=now+ROUTER_MAX_AGE_TO_PUBLISH) {
- log_info(LD_DIRSERV, "Ignoring future directory; not caching.");
- tor_free(directory);
- } else {
- /* if (when>d->published && when<now+ROUTER_MAX_AGE) */
- log_debug(LD_DIRSERV, "Caching directory.");
- tor_free(d->dir);
- d->dir = directory;
- d->dir_len = strlen(directory);
- tor_free(d->dir_z);
- if (tor_gzip_compress(&(d->dir_z), &(d->dir_z_len), d->dir, d->dir_len,
- ZLIB_METHOD)) {
- log_warn(LD_BUG,"Error compressing cached directory");
- }
- d->published = when;
- }
-}
-
/** Decrement the reference count on <b>d</b>, and free it if it no longer has
* any references. */
void
@@ -1419,22 +1303,6 @@ free_cached_dir_(void *_d)
cached_dir_decref(d);
}
-/** If we have no cached v1 directory, or it is older than <b>published</b>,
- * then replace it with <b>directory</b>, published at <b>published</b>.
- *
- * If <b>published</b> is too old, do nothing.
- *
- * If <b>is_running_routers</b>, this is really a v1 running_routers
- * document rather than a v1 directory.
- */
-static void
-dirserv_set_cached_directory(const char *directory, time_t published)
-{
-
- cached_dir_decref(cached_directory);
- cached_directory = new_cached_dir(tor_strdup(directory), published);
-}
-
/** Replace the v3 consensus networkstatus of type <b>flavor_name</b> that
* we're serving with <b>networkstatus</b>, published at <b>published</b>. No
* validation is performed. */
@@ -1457,161 +1325,6 @@ dirserv_set_cached_consensus_networkstatus(const char *networkstatus,
cached_dir_decref(old_networkstatus);
}
-/** Remove any v1 info from the directory cache that was published
- * too long ago. */
-void
-dirserv_clear_old_v1_info(time_t now)
-{
- if (cached_directory &&
- cached_directory->published < (now - MAX_V1_DIRECTORY_AGE)) {
- cached_dir_decref(cached_directory);
- cached_directory = NULL;
- }
- if (cached_runningrouters.published < (now - MAX_V1_RR_AGE)) {
- clear_cached_dir(&cached_runningrouters);
- }
-}
-
-/** Helper: If we're an authority for the right directory version (v1)
- * (based on <b>auth_type</b>), try to regenerate
- * auth_src as appropriate and return it, falling back to cache_src on
- * failure. If we're a cache, simply return cache_src.
- */
-static cached_dir_t *
-dirserv_pick_cached_dir_obj(cached_dir_t *cache_src,
- cached_dir_t *auth_src,
- time_t dirty, cached_dir_t *(*regenerate)(void),
- const char *name,
- dirinfo_type_t auth_type)
-{
- const or_options_t *options = get_options();
- int authority = (auth_type == V1_DIRINFO && authdir_mode_v1(options));
-
- if (!authority || authdir_mode_bridge(options)) {
- return cache_src;
- } else {
- /* We're authoritative. */
- if (regenerate != NULL) {
- if (dirty && dirty + DIR_REGEN_SLACK_TIME < time(NULL)) {
- if (!(auth_src = regenerate())) {
- log_err(LD_BUG, "Couldn't generate %s?", name);
- exit(1);
- }
- } else {
- log_info(LD_DIRSERV, "The %s is still clean; reusing.", name);
- }
- }
- return auth_src ? auth_src : cache_src;
- }
-}
-
-/** Return the most recently generated encoded signed v1 directory,
- * generating a new one as necessary. If not a v1 authoritative directory
- * may return NULL if no directory is yet cached. */
-cached_dir_t *
-dirserv_get_directory(void)
-{
- return dirserv_pick_cached_dir_obj(cached_directory, the_directory,
- the_directory_is_dirty,
- dirserv_regenerate_directory,
- "v1 server directory", V1_DIRINFO);
-}
-
-/** Only called by v1 auth dirservers.
- * Generate a fresh v1 directory; set the_directory and return a pointer
- * to the new value.
- */
-static cached_dir_t *
-dirserv_regenerate_directory(void)
-{
- /* XXXX 024 Get rid of this function if we can confirm that nobody's
- * fetching these any longer */
- char *new_directory=NULL;
-
- if (dirserv_dump_directory_to_string(&new_directory,
- get_server_identity_key())) {
- log_warn(LD_BUG, "Error creating directory.");
- tor_free(new_directory);
- return NULL;
- }
- cached_dir_decref(the_directory);
- the_directory = new_cached_dir(new_directory, time(NULL));
- log_info(LD_DIRSERV,"New directory (size %d) has been built.",
- (int)the_directory->dir_len);
- log_debug(LD_DIRSERV,"New directory (size %d):\n%s",
- (int)the_directory->dir_len, the_directory->dir);
-
- the_directory_is_dirty = 0;
-
- /* Save the directory to disk so we re-load it quickly on startup.
- */
- dirserv_set_cached_directory(the_directory->dir, time(NULL));
-
- return the_directory;
-}
-
-/** Only called by v1 auth dirservers.
- * Replace the current running-routers list with a newly generated one. */
-static cached_dir_t *
-generate_runningrouters(void)
-{
- char *s=NULL;
- char digest[DIGEST_LEN];
- char published[ISO_TIME_LEN+1];
- size_t len;
- crypto_pk_t *private_key = get_server_identity_key();
- char *identity_pkey; /* Identity key, DER64-encoded. */
- size_t identity_pkey_len;
-
- if (crypto_pk_write_public_key_to_string(private_key,&identity_pkey,
- &identity_pkey_len)<0) {
- log_warn(LD_BUG,"write identity_pkey to string failed!");
- goto err;
- }
- format_iso_time(published, time(NULL));
-
- len = 2048;
- s = tor_malloc_zero(len);
- tor_snprintf(s, len,
- "network-status\n"
- "published %s\n"
- "router-status %s\n"
- "dir-signing-key\n%s"
- "directory-signature %s\n",
- published, "", identity_pkey,
- get_options()->Nickname);
- tor_free(identity_pkey);
- if (router_get_runningrouters_hash(s,digest)) {
- log_warn(LD_BUG,"couldn't compute digest");
- goto err;
- }
- note_crypto_pk_op(SIGN_DIR);
- if (router_append_dirobj_signature(s, len, digest, DIGEST_LEN,
- private_key)<0)
- goto err;
-
- set_cached_dir(&the_runningrouters, s, time(NULL));
- runningrouters_is_dirty = 0;
-
- return &the_runningrouters;
- err:
- tor_free(s);
- return NULL;
-}
-
-/** Set *<b>rr</b> to the most recently generated encoded signed
- * running-routers list, generating a new one as necessary. Return the
- * size of the directory on success, and 0 on failure. */
-cached_dir_t *
-dirserv_get_runningrouters(void)
-{
- return dirserv_pick_cached_dir_obj(
- &cached_runningrouters, &the_runningrouters,
- runningrouters_is_dirty,
- generate_runningrouters,
- "v1 network status list", V1_DIRINFO);
-}
-
/** Return the latest downloaded consensus networkstatus in encoded, signed,
* optionally compressed format, suitable for sending to clients. */
cached_dir_t *
@@ -3303,7 +3016,7 @@ dirserv_single_reachability_test(time_t now, routerinfo_t *router)
/* IPv4. */
log_debug(LD_OR,"Testing reachability of %s at %s:%u.",
- router->nickname, router->address, router->or_port);
+ router->nickname, fmt_addr32(router->addr), router->or_port);
tor_addr_from_ipv4h(&router_addr, router->addr);
chan = channel_tls_connect(&router_addr, router->or_port,
router->cache_info.identity_digest);
@@ -3767,11 +3480,6 @@ dirserv_free_all(void)
{
dirserv_free_fingerprint_list();
- cached_dir_decref(the_directory);
- clear_cached_dir(&the_runningrouters);
- cached_dir_decref(cached_directory);
- clear_cached_dir(&cached_runningrouters);
-
strmap_free(cached_consensuses, free_cached_dir_);
cached_consensuses = NULL;
diff --git a/src/or/dirserv.h b/src/or/dirserv.h
index 8591c4c18..858e6e3a0 100644
--- a/src/or/dirserv.h
+++ b/src/or/dirserv.h
@@ -59,20 +59,15 @@ int directory_fetches_dir_info_later(const or_options_t *options);
int directory_caches_unknown_auth_certs(const or_options_t *options);
int directory_caches_dir_info(const or_options_t *options);
int directory_permits_begindir_requests(const or_options_t *options);
-int directory_permits_controller_requests(const or_options_t *options);
int directory_too_idle_to_fetch_descriptors(const or_options_t *options,
time_t now);
-void directory_set_dirty(void);
-cached_dir_t *dirserv_get_directory(void);
-cached_dir_t *dirserv_get_runningrouters(void);
cached_dir_t *dirserv_get_consensus(const char *flavor_name);
void dirserv_set_cached_consensus_networkstatus(const char *consensus,
const char *flavor_name,
const digests_t *digests,
time_t published);
void dirserv_clear_old_networkstatuses(time_t cutoff);
-void dirserv_clear_old_v1_info(time_t now);
int dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key,
const char **msg,
int for_unencrypted_conn,
diff --git a/src/or/dns.c b/src/or/dns.c
index a1fe0de1d..a88a46eb7 100644
--- a/src/or/dns.c
+++ b/src/or/dns.c
@@ -239,7 +239,7 @@ cached_resolves_eq(cached_resolve_t *a, cached_resolve_t *b)
static INLINE unsigned int
cached_resolve_hash(cached_resolve_t *a)
{
- return ht_string_hash(a->address);
+ return (unsigned) siphash24g((const uint8_t*)a->address, strlen(a->address));
}
HT_PROTOTYPE(cache_map, cached_resolve_t, node, cached_resolve_hash,
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index d463303fc..b374ac7a3 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -1967,7 +1967,6 @@ get_socks_args_by_bridge_addrport(const tor_addr_t *addr, uint16_t port)
static void
launch_direct_bridge_descriptor_fetch(bridge_info_t *bridge)
{
- char *address;
const or_options_t *options = get_options();
if (connection_get_by_type_addr_port_purpose(
@@ -1982,15 +1981,12 @@ launch_direct_bridge_descriptor_fetch(bridge_info_t *bridge)
return;
}
- address = tor_dup_addr(&bridge->addr);
-
- directory_initiate_command(address, &bridge->addr,
+ directory_initiate_command(&bridge->addr,
bridge->port, 0/*no dirport*/,
bridge->identity,
DIR_PURPOSE_FETCH_SERVERDESC,
ROUTER_PURPOSE_BRIDGE,
DIRIND_ONEHOP, "authority.z", NULL, 0, 0);
- tor_free(address);
}
/** Fetching the bridge descriptor from the bridge authority returned a
@@ -2108,13 +2104,11 @@ rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node)
} else {
if (tor_addr_family(&bridge->addr) == AF_INET) {
ri->addr = tor_addr_to_ipv4h(&bridge->addr);
- tor_free(ri->address);
- ri->address = tor_dup_ip(ri->addr);
ri->or_port = bridge->port;
log_info(LD_DIR,
"Adjusted bridge routerinfo for '%s' to match configured "
"address %s:%d.",
- ri->nickname, ri->address, ri->or_port);
+ ri->nickname, fmt_addr32(ri->addr), ri->or_port);
} else if (tor_addr_family(&bridge->addr) == AF_INET6) {
tor_addr_copy(&ri->ipv6_addr, &bridge->addr);
ri->ipv6_orport = bridge->port;
@@ -2213,27 +2207,6 @@ any_bridge_descriptors_known(void)
return choose_random_entry(NULL) != NULL;
}
-/** Return 1 if there are any directory conns fetching bridge descriptors
- * that aren't marked for close. We use this to guess if we should tell
- * the controller that we have a problem. */
-int
-any_pending_bridge_descriptor_fetches(void)
-{
- smartlist_t *conns = get_connection_array();
- SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
- if (conn->type == CONN_TYPE_DIR &&
- conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC &&
- TO_DIR_CONN(conn)->router_purpose == ROUTER_PURPOSE_BRIDGE &&
- !conn->marked_for_close &&
- conn->linked &&
- conn->linked_conn && !conn->linked_conn->marked_for_close) {
- log_debug(LD_DIR, "found one: %s", conn->address);
- return 1;
- }
- } SMARTLIST_FOREACH_END(conn);
- return 0;
-}
-
/** Return 1 if we have at least one descriptor for an entry guard
* (bridge or member of EntryNodes) and all descriptors we know are
* down. Else return 0. If <b>act</b> is 1, then mark the down guards
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index 772c6662d..e229f3b79 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.
**/
@@ -105,7 +105,6 @@ void retry_bridge_descriptor_fetch_directly(const char *digest);
void fetch_bridge_descriptors(const or_options_t *options, time_t now);
void learned_bridge_descriptor(routerinfo_t *ri, int from_cache);
int any_bridge_descriptors_known(void);
-int any_pending_bridge_descriptor_fetches(void);
int entries_known_but_down(const or_options_t *options);
void entries_retry_all(const or_options_t *options);
diff --git a/src/or/fp_pair.c b/src/or/fp_pair.c
index 4d8a835c8..55e4c89a4 100644
--- a/src/or/fp_pair.c
+++ b/src/or/fp_pair.c
@@ -32,17 +32,8 @@ fp_pair_map_entries_eq(const fp_pair_map_entry_t *a,
static INLINE unsigned int
fp_pair_map_entry_hash(const fp_pair_map_entry_t *a)
{
- const uint32_t *p;
- unsigned int hash;
-
- p = (const uint32_t *)(a->key.first);
- /* Hashes are 20 bytes long, so 5 times uint32_t */
- hash = p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4];
- /* Now XOR in the second fingerprint */
- p = (const uint32_t *)(a->key.second);
- hash ^= p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4];
-
- return hash;
+ tor_assert(sizeof(a->key) == DIGEST_LEN*2);
+ return (unsigned) siphash24g(&a->key, DIGEST_LEN*2);
}
/*
diff --git a/src/or/geoip.c b/src/or/geoip.c
index dc4730c81..f722bac46 100644
--- a/src/or/geoip.c
+++ b/src/or/geoip.c
@@ -486,10 +486,12 @@ static HT_HEAD(clientmap, clientmap_entry_t) client_history =
static INLINE unsigned
clientmap_entry_hash(const clientmap_entry_t *a)
{
- unsigned h = tor_addr_hash(&a->addr);
+ unsigned h = (unsigned) tor_addr_hash(&a->addr);
+
if (a->transport_name)
- h += ht_string_hash(a->transport_name);
- return ht_improve_hash(h);
+ h += (unsigned) siphash24g(a->transport_name, strlen(a->transport_name));
+
+ return h;
}
/** Hashtable helper: compare two clientmap_entry_t values for equality. */
static INLINE int
@@ -554,8 +556,9 @@ geoip_note_client_seen(geoip_client_action_t action,
(!(options->BridgeRelay && options->BridgeRecordUsageByCountry)))
return;
} else {
- if (options->BridgeRelay || options->BridgeAuthoritativeDir ||
- !options->DirReqStatistics)
+ /* Only gather directory-request statistics if configured, and
+ * forcibly disable them on bridge authorities. */
+ if (!options->DirReqStatistics || options->BridgeAuthoritativeDir)
return;
}
@@ -809,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 607dec8cd..bbda8424f 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 a970e3580..feca35c44 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -1196,22 +1196,12 @@ 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.
*/
consider_hibernation(now);
-#if 0
- {
- static time_t nl_check_time = 0;
- if (nl_check_time <= now) {
- nodelist_assert_ok();
- nl_check_time = now + 30;
- }
- }
-#endif
-
/* 0b. If we've deferred a signewnym, make sure it gets handled
* eventually. */
if (signewnym_is_pending &&
@@ -1223,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.
*/
@@ -1257,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;
@@ -1283,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);
@@ -1296,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)
@@ -1415,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
@@ -1475,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.
@@ -1488,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.
@@ -1518,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);
@@ -1538,33 +1528,35 @@ 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 a server, check whether our DNS is telling stories to
- * us. */
+ /* 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) && time_to_check_for_correct_dns < now) {
+ public_server_mode(options) &&
+ time_to_check_for_correct_dns < now &&
+ ! router_my_exit_policy_is_reject_star()) {
if (!time_to_check_for_correct_dns) {
time_to_check_for_correct_dns = now + 60 + crypto_rand_int(120);
} else {
@@ -1574,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);
@@ -1582,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 &&
@@ -1600,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 */
@@ -1678,24 +1670,28 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg)
/* every 20 minutes, check and complain if necessary */
const routerinfo_t *me = router_get_my_routerinfo();
if (me && !check_whether_orport_reachable()) {
+ char *address = tor_dup_ip(me->addr);
log_warn(LD_CONFIG,"Your server (%s:%d) has not managed to confirm that "
"its ORPort is reachable. Please check your firewalls, ports, "
"address, /etc/hosts file, etc.",
- me->address, me->or_port);
+ address, me->or_port);
control_event_server_status(LOG_WARN,
"REACHABILITY_FAILED ORADDRESS=%s:%d",
- me->address, me->or_port);
+ address, me->or_port);
+ tor_free(address);
}
if (me && !check_whether_dirport_reachable()) {
+ char *address = tor_dup_ip(me->addr);
log_warn(LD_CONFIG,
"Your server (%s:%d) has not managed to confirm that its "
"DirPort is reachable. Please check your firewalls, ports, "
"address, /etc/hosts file, etc.",
- me->address, me->dir_port);
+ address, me->dir_port);
control_event_server_status(LOG_WARN,
"REACHABILITY_FAILED DIRADDRESS=%s:%d",
- me->address, me->dir_port);
+ address, me->dir_port);
+ tor_free(address);
}
}
@@ -2329,6 +2325,13 @@ tor_init(int argc, char *argv[])
/* Have the log set up with our application name. */
tor_snprintf(progname, sizeof(progname), "Tor %s", get_version());
log_set_application_name(progname);
+
+ /* Set up the crypto nice and early */
+ if (crypto_early_init() < 0) {
+ log_err(LD_GENERAL, "Unable to initialize the crypto subsystem!");
+ return 1;
+ }
+
/* Initialize the history structures. */
rep_hist_init();
/* Initialize the service cache. */
@@ -2571,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. */
@@ -2765,6 +2777,8 @@ sandbox_init_filter(void)
get_datadir_fname2("keys", "secret_id_key.tmp"), 1,
get_datadir_fname("fingerprint"), 1,
get_datadir_fname("fingerprint.tmp"), 1,
+ get_datadir_fname("hashed-fingerprint"), 1,
+ get_datadir_fname("hashed-fingerprint.tmp"), 1,
get_datadir_fname("cached-consensus"), 1,
get_datadir_fname("cached-consensus.tmp"), 1,
"/etc/resolv.conf", 0,
diff --git a/src/or/microdesc.c b/src/or/microdesc.c
index 11249910c..ec85de0d6 100644
--- a/src/or/microdesc.c
+++ b/src/or/microdesc.c
@@ -45,12 +45,7 @@ struct microdesc_cache_t {
static INLINE unsigned int
microdesc_hash_(microdesc_t *md)
{
- unsigned *d = (unsigned*)md->digest;
-#if SIZEOF_INT == 4
- return d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[6] ^ d[7];
-#else
- return d[0] ^ d[1] ^ d[2] ^ d[3];
-#endif
+ return (unsigned) siphash24g(md->digest, sizeof(md->digest));
}
/** Helper: compares <b>a</b> and </b> for equality for hash-table purposes. */
@@ -280,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);
@@ -288,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;
@@ -368,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);
@@ -376,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);
}
@@ -434,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;
@@ -501,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",
@@ -726,7 +784,7 @@ update_microdesc_downloads(time_t now)
smartlist_t *missing;
digestmap_t *pending;
- if (should_delay_dir_fetches(options))
+ if (should_delay_dir_fetches(options, NULL))
return;
if (directory_too_idle_to_fetch_descriptors(options, now))
return;
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index 6c9a6dd72..74c4ca45a 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -31,6 +31,7 @@
#include "router.h"
#include "routerlist.h"
#include "routerparse.h"
+#include "transports.h"
/** Map from lowercase nickname to identity digest of named server, if any. */
static strmap_t *named_server_map = NULL;
@@ -522,16 +523,6 @@ networkstatus_check_consensus_signature(networkstatus_t *consensus,
return -2;
}
-/** Helper: return a newly allocated string containing the name of the filename
- * where we plan to cache the network status with the given identity digest. */
-char *
-networkstatus_get_cache_filename(const char *identity_digest)
-{
- char fp[HEX_DIGEST_LEN+1];
- base16_encode(fp, HEX_DIGEST_LEN+1, identity_digest, DIGEST_LEN);
- return get_datadir_fname2("cached-status", fp);
-}
-
/** How far in the future do we allow a network-status to get before removing
* it? (seconds) */
#define NETWORKSTATUS_ALLOW_SKEW (24*60*60)
@@ -894,14 +885,37 @@ update_consensus_networkstatus_fetch_time(time_t now)
/** Return 1 if there's a reason we shouldn't try any directory
* fetches yet (e.g. we demand bridges and none are yet known).
- * Else return 0. */
+ * Else return 0.
+
+ * If we return 1 and <b>msg_out</b> is provided, set <b>msg_out</b>
+ * to an explanation of why directory fetches are delayed. (If we
+ * return 0, we set msg_out to NULL.)
+ */
int
-should_delay_dir_fetches(const or_options_t *options)
+should_delay_dir_fetches(const or_options_t *options, const char **msg_out)
{
- if (options->UseBridges && !any_bridge_descriptors_known()) {
- log_info(LD_DIR, "delaying dir fetches (no running bridges known)");
- return 1;
+ if (msg_out) {
+ *msg_out = NULL;
+ }
+
+ if (options->UseBridges) {
+ if (!any_bridge_descriptors_known()) {
+ if (msg_out) {
+ *msg_out = "No running bridges";
+ }
+ log_info(LD_DIR, "Delaying dir fetches (no running bridges known)");
+ return 1;
+ }
+
+ if (pt_proxies_configuration_pending()) {
+ if (msg_out) {
+ *msg_out = "Pluggable transport proxies still configuring";
+ }
+ log_info(LD_DIR, "Delaying dir fetches (pt proxies still configuring)");
+ return 1;
+ }
}
+
return 0;
}
@@ -911,7 +925,7 @@ void
update_networkstatus_downloads(time_t now)
{
const or_options_t *options = get_options();
- if (should_delay_dir_fetches(options))
+ if (should_delay_dir_fetches(options, NULL))
return;
update_consensus_networkstatus_downloads(now);
update_certificate_downloads(now);
@@ -1240,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 {
@@ -1250,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;
}
}
@@ -1299,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/networkstatus.h b/src/or/networkstatus.h
index fed32ea1a..1659818f0 100644
--- a/src/or/networkstatus.h
+++ b/src/or/networkstatus.h
@@ -25,7 +25,6 @@ int networkstatus_check_consensus_signature(networkstatus_t *consensus,
int networkstatus_check_document_signature(const networkstatus_t *consensus,
document_signature_t *sig,
const authority_cert_t *cert);
-char *networkstatus_get_cache_filename(const char *identity_digest);
int compare_digest_to_routerstatus_entry(const void *_key,
const void **_member);
int compare_digest_to_vote_routerstatus_entry(const void *_key,
@@ -54,7 +53,7 @@ int networkstatus_nickname_is_unnamed(const char *nickname);
void networkstatus_consensus_download_failed(int status_code,
const char *flavname);
void update_consensus_networkstatus_fetch_time(time_t now);
-int should_delay_dir_fetches(const or_options_t *options);
+int should_delay_dir_fetches(const or_options_t *options,const char **msg_out);
void update_networkstatus_downloads(time_t now);
void update_certificate_downloads(time_t now);
int consensus_is_waiting_for_certs(void);
diff --git a/src/or/nodelist.c b/src/or/nodelist.c
index 402fb2e96..52c92661c 100644
--- a/src/or/nodelist.c
+++ b/src/or/nodelist.c
@@ -43,14 +43,7 @@ typedef struct nodelist_t {
static INLINE unsigned int
node_id_hash(const node_t *node)
{
-#if SIZEOF_INT == 4
- const uint32_t *p = (const uint32_t*)node->identity;
- return p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4];
-#elif SIZEOF_INT == 8
- const uint64_t *p = (const uint32_t*)node->identity;
- const uint32_t *p32 = (const uint32_t*)node->identity;
- return p[0] ^ p[1] ^ p32[4];
-#endif
+ return (unsigned) siphash24g(node->identity, DIGEST_LEN);
}
static INLINE unsigned int
@@ -339,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)
@@ -792,7 +804,7 @@ void
node_get_address_string(const node_t *node, char *buf, size_t len)
{
if (node->ri) {
- strlcpy(buf, node->ri->address, len);
+ strlcpy(buf, fmt_addr32(node->ri->addr), len);
} else if (node->rs) {
tor_addr_t addr;
tor_addr_from_ipv4h(&addr, node->rs->addr);
@@ -1484,6 +1496,7 @@ update_router_have_minimum_dir_info(void)
const networkstatus_t *consensus =
networkstatus_get_reasonably_live_consensus(now,usable_consensus_flavor());
int using_md;
+ const char *delay_fetches_msg = NULL;
if (!consensus) {
if (!networkstatus_get_latest_consensus())
@@ -1496,10 +1509,9 @@ update_router_have_minimum_dir_info(void)
goto done;
}
- if (should_delay_dir_fetches(get_options())) {
- log_notice(LD_DIR, "no known bridge descriptors running yet; stalling");
- strlcpy(dir_info_status, "No live bridge descriptors.",
- sizeof(dir_info_status));
+ if (should_delay_dir_fetches(get_options(), &delay_fetches_msg)) {
+ log_notice(LD_DIR, "Delaying dir fetches: %s", delay_fetches_msg);
+ strlcpy(dir_info_status, "%s", sizeof(dir_info_status));
res = 0;
goto done;
}
diff --git a/src/or/nodelist.h b/src/or/nodelist.h
index 565caa76c..95d0c2328 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 cc4e5ed9d..38ab1767e 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. */
@@ -400,13 +401,10 @@ typedef enum {
#define CONTROL_CONN_STATE_NEEDAUTH 2
#define CONTROL_CONN_STATE_MAX_ 2
-#define DIR_PURPOSE_MIN_ 3
-/** A connection to a directory server: download a rendezvous
- * descriptor. */
-#define DIR_PURPOSE_FETCH_RENDDESC 3
-/** A connection to a directory server: set after a rendezvous
+#define DIR_PURPOSE_MIN_ 4
+/** A connection to a directory server: set after a v2 rendezvous
* descriptor is downloaded. */
-#define DIR_PURPOSE_HAS_FETCHED_RENDDESC 4
+#define DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2 4
/** A connection to a directory server: download one or more server
* descriptors. */
#define DIR_PURPOSE_FETCH_SERVERDESC 6
@@ -415,9 +413,6 @@ typedef enum {
#define DIR_PURPOSE_FETCH_EXTRAINFO 7
/** A connection to a directory server: upload a server descriptor. */
#define DIR_PURPOSE_UPLOAD_DIR 8
-/** A connection to a directory server: upload a rendezvous
- * descriptor. */
-#define DIR_PURPOSE_UPLOAD_RENDDESC 9
/** A connection to a directory server: upload a v3 networkstatus vote. */
#define DIR_PURPOSE_UPLOAD_VOTE 10
/** A connection to a directory server: upload a v3 consensus signature */
@@ -451,7 +446,6 @@ typedef enum {
* directory server. */
#define DIR_PURPOSE_IS_UPLOAD(p) \
((p)==DIR_PURPOSE_UPLOAD_DIR || \
- (p)==DIR_PURPOSE_UPLOAD_RENDDESC || \
(p)==DIR_PURPOSE_UPLOAD_VOTE || \
(p)==DIR_PURPOSE_UPLOAD_SIGNATURES)
@@ -1690,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. */
@@ -1709,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? */
@@ -1882,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
@@ -1939,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? */
@@ -1947,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. */
@@ -1955,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. */
@@ -2016,7 +2014,6 @@ typedef int16_t country_t;
/** Information about another onion router in the network. */
typedef struct {
signed_descriptor_t cache_info;
- char *address; /**< Location of OR: either a hostname or an IP address. */
char *nickname; /**< Human-readable OR name. */
uint32_t addr; /**< IPv4 address of OR, in host order. */
@@ -2211,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 */
@@ -2421,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. */
@@ -2594,13 +2591,8 @@ typedef struct authority_cert_t {
*/
typedef enum {
NO_DIRINFO = 0,
- /** Serves/signs v1 directory information: Big lists of routers, and short
- * routerstatus documents. */
- V1_DIRINFO = 1 << 0,
/** Serves/signs v3 directory information: votes, consensuses, certs */
V3_DIRINFO = 1 << 2,
- /** Serves hidden service descriptors. */
- HIDSERV_DIRINFO = 1 << 3,
/** Serves bridge descriptors. */
BRIDGE_DIRINFO = 1 << 4,
/** Serves extrainfo documents. */
@@ -2825,6 +2817,9 @@ typedef struct circuit_t {
* more. */
int deliver_window;
+ /** Temporary field used during circuits_handle_oom. */
+ uint32_t age_tmp;
+
/** For storage while n_chan is pending (state CIRCUIT_STATE_CHAN_WAIT). */
struct create_cell_t *n_chan_create_cell;
@@ -2943,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.
*/
@@ -2993,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. */
@@ -3478,9 +3474,8 @@ typedef struct {
config_line_t *DirPort_lines;
config_line_t *DNSPort_lines; /**< Ports to listen on for DNS requests. */
- uint64_t MaxMemInCellQueues; /**< If we have more memory than this allocated
- * for circuit cell queues, run the OOM handler
- */
+ uint64_t MaxMemInQueues; /**< If we have more memory than this allocated
+ * for queues and buffers, run the OOM handler */
/** @name port booleans
*
@@ -3502,8 +3497,6 @@ typedef struct {
int AssumeReachable; /**< Whether to publish our descriptor regardless. */
int AuthoritativeDir; /**< Boolean: is this an authoritative directory? */
- int V1AuthoritativeDir; /**< Boolean: is this an authoritative directory
- * for version 1 directories? */
int V3AuthoritativeDir; /**< Boolean: is this an authoritative directory
* for version 3 directories? */
int NamingAuthoritativeDir; /**< Boolean: is this an authoritative directory
@@ -3646,6 +3639,10 @@ typedef struct {
* a new one? */
int MaxCircuitDirtiness; /**< Never use circs that were first used more than
this interval ago. */
+ int PredictedPortsRelevanceTime; /** How long after we've requested a
+ * connection for a given port, do we want
+ * to continue to pick exits that support
+ * that port? */
uint64_t BandwidthRate; /**< How much bandwidth, on average, are we willing
* to use in a second? */
uint64_t BandwidthBurst; /**< How much bandwidth, at maximum, are we willing
@@ -4487,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 ***************************/
@@ -4845,9 +4843,9 @@ typedef struct rend_service_descriptor_t {
crypto_pk_t *pk; /**< This service's public key. */
int version; /**< Version of the descriptor format: 0 or 2. */
time_t timestamp; /**< Time when the descriptor was generated. */
- /** Bitmask: which rendezvous protocols are supported?
- * (We allow bits '0', '1', and '2' to be set.) */
- int protocols : REND_PROTOCOL_VERSION_BITMASK_WIDTH;
+ /** Bitmask: which introduce/rendezvous protocols are supported?
+ * (We allow bits '0', '1', '2' and '3' to be set.) */
+ unsigned protocols : REND_PROTOCOL_VERSION_BITMASK_WIDTH;
/** List of the service's introduction points. Elements are removed if
* introduction attempts fail. */
smartlist_t *intro_nodes;
diff --git a/src/or/policies.c b/src/or/policies.c
index be4da5506..42dc46b7f 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -438,7 +438,7 @@ validate_addr_policies(const or_options_t *options, char **msg)
if (policies_parse_exit_policy(options->ExitPolicy, &addr_policy,
options->IPv6Exit,
- options->ExitPolicyRejectPrivate, NULL,
+ options->ExitPolicyRejectPrivate, 0,
!options->BridgeRelay))
REJECT("Error in ExitPolicy entry.");
@@ -482,10 +482,12 @@ validate_addr_policies(const or_options_t *options, char **msg)
* Ignore port specifiers.
*/
static int
-load_policy_from_option(config_line_t *config, smartlist_t **policy,
+load_policy_from_option(config_line_t *config, const char *option_name,
+ smartlist_t **policy,
int assume_action)
{
int r;
+ int killed_any_ports = 0;
addr_policy_list_free(*policy);
*policy = NULL;
r = parse_addr_policy(config, policy, assume_action);
@@ -504,9 +506,13 @@ load_policy_from_option(config_line_t *config, smartlist_t **policy,
c = addr_policy_get_canonical_entry(&newp);
SMARTLIST_REPLACE_CURRENT(*policy, n, c);
addr_policy_free(n);
+ killed_any_ports = 1;
}
} SMARTLIST_FOREACH_END(n);
}
+ if (killed_any_ports) {
+ log_warn(LD_CONFIG, "Ignoring ports in %s option.", option_name);
+ }
return 0;
}
@@ -516,20 +522,22 @@ int
policies_parse_from_options(const or_options_t *options)
{
int ret = 0;
- if (load_policy_from_option(options->SocksPolicy, &socks_policy, -1) < 0)
+ if (load_policy_from_option(options->SocksPolicy, "SocksPolicy",
+ &socks_policy, -1) < 0)
ret = -1;
- if (load_policy_from_option(options->DirPolicy, &dir_policy, -1) < 0)
+ if (load_policy_from_option(options->DirPolicy, "DirPolicy",
+ &dir_policy, -1) < 0)
ret = -1;
- if (load_policy_from_option(options->AuthDirReject,
+ if (load_policy_from_option(options->AuthDirReject, "AuthDirReject",
&authdir_reject_policy, ADDR_POLICY_REJECT) < 0)
ret = -1;
- if (load_policy_from_option(options->AuthDirInvalid,
+ if (load_policy_from_option(options->AuthDirInvalid, "AuthDirInvalid",
&authdir_invalid_policy, ADDR_POLICY_REJECT) < 0)
ret = -1;
- if (load_policy_from_option(options->AuthDirBadDir,
+ if (load_policy_from_option(options->AuthDirBadDir, "AuthDirBadDir",
&authdir_baddir_policy, ADDR_POLICY_REJECT) < 0)
ret = -1;
- if (load_policy_from_option(options->AuthDirBadExit,
+ if (load_policy_from_option(options->AuthDirBadExit, "AuthDirBadExit",
&authdir_badexit_policy, ADDR_POLICY_REJECT) < 0)
ret = -1;
if (parse_reachable_addresses() < 0)
@@ -597,21 +605,25 @@ policy_eq(policy_map_ent_t *a, policy_map_ent_t *b)
/** Return a hashcode for <b>ent</b> */
static unsigned int
-policy_hash(policy_map_ent_t *ent)
+policy_hash(const policy_map_ent_t *ent)
{
- addr_policy_t *a = ent->policy;
- unsigned int r;
- if (a->is_private)
- r = 0x1234abcd;
- else
- r = tor_addr_hash(&a->addr);
- r += a->prt_min << 8;
- r += a->prt_max << 16;
- r += a->maskbits;
- if (a->policy_type == ADDR_POLICY_REJECT)
- r ^= 0xffffffff;
+ const addr_policy_t *a = ent->policy;
+ addr_policy_t aa;
+ memset(&aa, 0, sizeof(aa));
+
+ aa.prt_min = a->prt_min;
+ aa.prt_max = a->prt_max;
+ aa.maskbits = a->maskbits;
+ aa.policy_type = a->policy_type;
+ aa.is_private = a->is_private;
+
+ if (a->is_private) {
+ aa.is_private = 1;
+ } else {
+ tor_addr_copy_tight(&aa.addr, &a->addr);
+ }
- return r;
+ return (unsigned) siphash24g(&aa, sizeof(aa));
}
HT_PROTOTYPE(policy_map, policy_map_ent_t, node, policy_hash,
@@ -958,7 +970,7 @@ exit_policy_remove_redundancies(smartlist_t *dest)
int
policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
int ipv6_exit,
- int rejectprivate, const char *local_address,
+ int rejectprivate, uint32_t local_address,
int add_default_policy)
{
if (!ipv6_exit) {
@@ -968,7 +980,7 @@ policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
append_exit_policy_string(dest, "reject private:*");
if (local_address) {
char buf[POLICY_BUF_LEN];
- tor_snprintf(buf, sizeof(buf), "reject %s:*", local_address);
+ tor_snprintf(buf, sizeof(buf), "reject %s:*", fmt_addr32(local_address));
append_exit_policy_string(dest, buf);
}
}
diff --git a/src/or/policies.h b/src/or/policies.h
index facbbb6b5..91ac42749 100644
--- a/src/or/policies.h
+++ b/src/or/policies.h
@@ -45,7 +45,7 @@ addr_policy_result_t compare_tor_addr_to_node_policy(const tor_addr_t *addr,
int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
int ipv6exit,
- int rejectprivate, const char *local_address,
+ int rejectprivate, uint32_t local_address,
int add_default_policy);
void policies_exit_policy_append_reject_star(smartlist_t **dest);
void addr_policy_append_reject_addr(smartlist_t **dest,
diff --git a/src/or/relay.c b/src/or/relay.c
index dc234c1f2..8c009b556 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -2153,7 +2153,8 @@ cell_queue_append_packed_copy(circuit_t *circ, cell_queue_t *queue,
(void)circ;
(void)exitward;
(void)use_stats;
- tor_gettimeofday_cached(&now);
+ tor_gettimeofday_cached_monotonic(&now);
+
copy->inserted_time = (uint32_t)tv_to_msec(&now);
cell_queue_append(queue, copy);
@@ -2201,13 +2202,21 @@ packed_cell_mem_cost(void)
return sizeof(packed_cell_t) + MP_POOL_ITEM_OVERHEAD;
}
+/** DOCDOC */
+STATIC size_t
+cell_queues_get_total_allocation(void)
+{
+ return total_cells_allocated * packed_cell_mem_cost();
+}
+
/** Check whether we've got too much space used for cells. If so,
* call the OOM handler and return 1. Otherwise, return 0. */
-static int
+STATIC int
cell_queues_check_size(void)
{
- size_t alloc = total_cells_allocated * packed_cell_mem_cost();
- if (alloc >= get_options()->MaxMemInCellQueues) {
+ size_t alloc = cell_queues_get_total_allocation();
+ alloc += buf_get_total_allocation();
+ if (alloc >= get_options()->MaxMemInQueues) {
circuits_handle_oom(alloc);
return 1;
}
@@ -2262,14 +2271,18 @@ update_circuit_on_cmux_(circuit_t *circ, cell_direction_t direction,
assert_cmux_ok_paranoid(chan);
}
-/** Remove all circuits from the cmux on <b>chan</b>. */
+/** Remove all circuits from the cmux on <b>chan</b>.
+ *
+ * If <b>circuits_out</b> is non-NULL, add all detached circuits to
+ * <b>circuits_out</b>.
+ **/
void
-channel_unlink_all_circuits(channel_t *chan)
+channel_unlink_all_circuits(channel_t *chan, smartlist_t *circuits_out)
{
tor_assert(chan);
tor_assert(chan->cmux);
- circuitmux_detach_all_circuits(chan->cmux);
+ circuitmux_detach_all_circuits(chan->cmux, circuits_out);
chan->num_n_circuits = 0;
chan->num_p_circuits = 0;
}
diff --git a/src/or/relay.h b/src/or/relay.h
index 20eecfb40..4e1c7f509 100644
--- a/src/or/relay.h
+++ b/src/or/relay.h
@@ -61,7 +61,7 @@ void cell_queue_append_packed_copy(circuit_t *circ, cell_queue_t *queue,
void append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
cell_t *cell, cell_direction_t direction,
streamid_t fromstream);
-void channel_unlink_all_circuits(channel_t *chan);
+void channel_unlink_all_circuits(channel_t *chan, smartlist_t *detached_out);
int channel_flush_from_first_active_circuit(channel_t *chan, int max);
void assert_circuit_mux_okay(channel_t *chan);
void update_circuit_on_cmux_(circuit_t *circ, cell_direction_t direction,
@@ -85,6 +85,8 @@ STATIC int connected_cell_parse(const relay_header_t *rh, const cell_t *cell,
tor_addr_t *addr_out, int *ttl_out);
STATIC packed_cell_t *packed_cell_new(void);
STATIC packed_cell_t *cell_queue_pop(cell_queue_t *queue);
+STATIC size_t cell_queues_get_total_allocation(void);
+STATIC int cell_queues_check_size(void);
#endif
#endif
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index 2327a547c..d42024010 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -670,8 +670,9 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query)
"service directories, because we requested them all "
"recently without success.");
if (options->StrictNodes && excluded_some) {
- log_info(LD_REND, "There are others that we could have tried, but "
- "they are all excluded, and StrictNodes is set.");
+ log_warn(LD_REND, "Could not pick a hidden service directory for the "
+ "requested hidden service: they are all either down or "
+ "excluded, and StrictNodes is set.");
}
return 0;
}
@@ -796,8 +797,7 @@ rend_client_cancel_descriptor_fetches(void)
SMARTLIST_FOREACH_BEGIN(connection_array, connection_t *, conn) {
if (conn->type == CONN_TYPE_DIR &&
- (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC ||
- conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2)) {
+ conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) {
/* It's a rendezvous descriptor fetch in progress -- cancel it
* by marking the connection for close.
*
diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c
index d1b49411c..a664b5d50 100644
--- a/src/or/rendcommon.c
+++ b/src/or/rendcommon.c
@@ -672,79 +672,6 @@ rend_encode_v2_descriptors(smartlist_t *descs_out,
return seconds_valid;
}
-/** Parse a service descriptor at <b>str</b> (<b>len</b> bytes). On
- * success, return a newly alloced service_descriptor_t. On failure,
- * return NULL.
- */
-rend_service_descriptor_t *
-rend_parse_service_descriptor(const char *str, size_t len)
-{
- rend_service_descriptor_t *result = NULL;
- int i, n_intro_points;
- size_t keylen, asn1len;
- const char *end, *cp, *eos;
- rend_intro_point_t *intro;
-
- result = tor_malloc_zero(sizeof(rend_service_descriptor_t));
- cp = str;
- end = str+len;
- if (end-cp<2) goto truncated;
- result->version = 0;
- if (end-cp < 2) goto truncated;
- asn1len = ntohs(get_uint16(cp));
- cp += 2;
- if ((size_t)(end-cp) < asn1len) goto truncated;
- result->pk = crypto_pk_asn1_decode(cp, asn1len);
- if (!result->pk) goto truncated;
- cp += asn1len;
- if (end-cp < 4) goto truncated;
- result->timestamp = (time_t) ntohl(get_uint32(cp));
- cp += 4;
- result->protocols = 1<<2; /* always use intro format 2 */
- if (end-cp < 2) goto truncated;
- n_intro_points = ntohs(get_uint16(cp));
- cp += 2;
-
- result->intro_nodes = smartlist_new();
- for (i=0;i<n_intro_points;++i) {
- if (end-cp < 2) goto truncated;
- eos = (const char *)memchr(cp,'\0',end-cp);
- if (!eos) goto truncated;
- /* Write nickname to extend info, but postpone the lookup whether
- * we know that router. It's not part of the parsing process. */
- intro = tor_malloc_zero(sizeof(rend_intro_point_t));
- intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
- strlcpy(intro->extend_info->nickname, cp,
- sizeof(intro->extend_info->nickname));
- smartlist_add(result->intro_nodes, intro);
- cp = eos+1;
- }
- keylen = crypto_pk_keysize(result->pk);
- tor_assert(end-cp >= 0);
- if ((size_t)(end-cp) < keylen) goto truncated;
- if ((size_t)(end-cp) > keylen) {
- log_warn(LD_PROTOCOL,
- "Signature is %d bytes too long on service descriptor.",
- (int)((size_t)(end-cp) - keylen));
- goto error;
- }
- note_crypto_pk_op(REND_CLIENT);
- if (crypto_pk_public_checksig_digest(result->pk,
- (char*)str,cp-str, /* data */
- (char*)cp,end-cp /* signature*/
- )<0) {
- log_warn(LD_PROTOCOL, "Bad signature on service descriptor.");
- goto error;
- }
-
- return result;
- truncated:
- log_warn(LD_PROTOCOL, "Truncated service descriptor.");
- error:
- rend_service_descriptor_free(result);
- return NULL;
-}
-
/** Sets <b>out</b> to the first 10 bytes of the digest of <b>pk</b>,
* base32 encoded. NUL-terminates out. (We use this string to
* identify services in directory requests and .onion URLs.)
@@ -843,7 +770,7 @@ void
rend_cache_purge(void)
{
if (rend_cache) {
- log_info(LD_REND, "Purging client/v0-HS-authority HS descriptor cache");
+ log_info(LD_REND, "Purging HS descriptor cache");
strmap_free(rend_cache, rend_cache_entry_free_);
}
rend_cache = strmap_new();
@@ -954,27 +881,6 @@ rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **e)
return 1;
}
-/** <b>query</b> is a base32'ed service id. If it's malformed, return -1.
- * Else look it up.
- * - If it is found, point *desc to it, and write its length into
- * *desc_len, and return 1.
- * - If it is not found, return 0.
- * Note: calls to rend_cache_clean or rend_cache_store may invalidate
- * *desc.
- */
-int
-rend_cache_lookup_desc(const char *query, int version, const char **desc,
- size_t *desc_len)
-{
- rend_cache_entry_t *e;
- int r;
- r = rend_cache_lookup_entry(query,version,&e);
- if (r <= 0) return r;
- *desc = e->desc;
- *desc_len = e->len;
- return 1;
-}
-
/** Lookup the v2 service descriptor with base32-encoded <b>desc_id</b> and
* copy the pointer to it to *<b>desc</b>. Return 1 on success, 0 on
* well-formed-but-not-found, and -1 on failure.
@@ -1006,130 +912,16 @@ rend_cache_lookup_v2_desc_as_dir(const char *desc_id, const char **desc)
* descriptor */
#define MAX_INTRO_POINTS 10
-/** Parse *desc, calculate its service id, and store it in the cache.
- * If we have a newer v0 descriptor with the same ID, ignore this one.
- * If we have an older descriptor with the same ID, replace it.
- * If we are acting as client due to the published flag and have any v2
- * descriptor with the same ID, reject this one in order to not get
- * confused with having both versions for the same service.
- *
- * Return -2 if it's malformed or otherwise rejected; return -1 if we
- * already have a v2 descriptor here; return 0 if it's the same or older
- * than one we've already got; return 1 if it's novel.
- *
- * The published flag tells us if we store the descriptor
- * in our role as directory (1) or if we cache it as client (0).
- *
- * If <b>service_id</b> is non-NULL and the descriptor is not for that
- * service ID, reject it. <b>service_id</b> must be specified if and
- * only if <b>published</b> is 0 (we fetched this descriptor).
- */
-int
-rend_cache_store(const char *desc, size_t desc_len, int published,
- const char *service_id)
-{
- rend_cache_entry_t *e;
- rend_service_descriptor_t *parsed;
- char query[REND_SERVICE_ID_LEN_BASE32+1];
- char key[REND_SERVICE_ID_LEN_BASE32+2]; /* 0<query>\0 */
- time_t now;
- tor_assert(rend_cache);
- parsed = rend_parse_service_descriptor(desc,desc_len);
- if (!parsed) {
- log_warn(LD_PROTOCOL,"Couldn't parse service descriptor.");
- return -2;
- }
- if (rend_get_service_id(parsed->pk, query)<0) {
- log_warn(LD_BUG,"Couldn't compute service ID.");
- rend_service_descriptor_free(parsed);
- return -2;
- }
- if ((service_id != NULL) && strcmp(query, service_id)) {
- log_warn(LD_REND, "Received service descriptor for service ID %s; "
- "expected descriptor for service ID %s.",
- query, safe_str(service_id));
- rend_service_descriptor_free(parsed);
- return -2;
- }
- now = time(NULL);
- if (parsed->timestamp < now-REND_CACHE_MAX_AGE-REND_CACHE_MAX_SKEW) {
- log_fn(LOG_PROTOCOL_WARN, LD_REND,
- "Service descriptor %s is too old.",
- safe_str_client(query));
- rend_service_descriptor_free(parsed);
- return -2;
- }
- if (parsed->timestamp > now+REND_CACHE_MAX_SKEW) {
- log_fn(LOG_PROTOCOL_WARN, LD_REND,
- "Service descriptor %s is too far in the future.",
- safe_str_client(query));
- rend_service_descriptor_free(parsed);
- return -2;
- }
- /* Do we have a v2 descriptor and fetched this descriptor as a client? */
- tor_snprintf(key, sizeof(key), "2%s", query);
- if (!published && strmap_get_lc(rend_cache, key)) {
- log_info(LD_REND, "We already have a v2 descriptor for service %s.",
- safe_str_client(query));
- rend_service_descriptor_free(parsed);
- return -1;
- }
- if (parsed->intro_nodes &&
- smartlist_len(parsed->intro_nodes) > MAX_INTRO_POINTS) {
- log_warn(LD_REND, "Found too many introduction points on a hidden "
- "service descriptor for %s. This is probably a (misguided) "
- "attempt to improve reliability, but it could also be an "
- "attempt to do a guard enumeration attack. Rejecting.",
- safe_str_client(query));
- rend_service_descriptor_free(parsed);
- return -2;
- }
- tor_snprintf(key, sizeof(key), "0%s", query);
- e = (rend_cache_entry_t*) strmap_get_lc(rend_cache, key);
- if (e && e->parsed->timestamp > parsed->timestamp) {
- log_info(LD_REND,"We already have a newer service descriptor %s with the "
- "same ID and version.",
- safe_str_client(query));
- rend_service_descriptor_free(parsed);
- return 0;
- }
- if (e && e->len == desc_len && tor_memeq(desc,e->desc,desc_len)) {
- log_info(LD_REND,"We already have this service descriptor %s.",
- safe_str_client(query));
- e->received = time(NULL);
- rend_service_descriptor_free(parsed);
- return 0;
- }
- if (!e) {
- e = tor_malloc_zero(sizeof(rend_cache_entry_t));
- strmap_set_lc(rend_cache, key, e);
- } else {
- rend_service_descriptor_free(e->parsed);
- tor_free(e->desc);
- }
- e->received = time(NULL);
- e->parsed = parsed;
- e->len = desc_len;
- e->desc = tor_malloc(desc_len);
- memcpy(e->desc, desc, desc_len);
-
- log_debug(LD_REND,"Successfully stored rend desc '%s', len %d.",
- safe_str_client(query), (int)desc_len);
- return 1;
-}
-
/** Parse the v2 service descriptor(s) in <b>desc</b> and store it/them to the
* local rend cache. Don't attempt to decrypt the included list of introduction
* points (as we don't have a descriptor cookie for it).
*
* If we have a newer descriptor with the same ID, ignore this one.
* If we have an older descriptor with the same ID, replace it.
- * Return -2 if we are not acting as hidden service directory;
- * return -1 if the descriptor(s) were not parsable; return 0 if all
- * descriptors are the same or older than those we've already got;
- * return a positive number for the number of novel stored descriptors.
+ *
+ * Return an appropriate rend_cache_store_status_t.
*/
-int
+rend_cache_store_status_t
rend_cache_store_v2_desc_as_dir(const char *desc)
{
rend_service_descriptor_t *parsed;
@@ -1149,7 +941,7 @@ rend_cache_store_v2_desc_as_dir(const char *desc)
/* Cannot store descs, because we are (currently) not acting as
* hidden service directory. */
log_info(LD_REND, "Cannot store descs: Not acting as hs dir");
- return -2;
+ return RCS_NOTDIR;
}
while (rend_parse_v2_service_descriptor(&parsed, desc_id, &intro_content,
&intro_size, &encoded_size,
@@ -1225,11 +1017,11 @@ rend_cache_store_v2_desc_as_dir(const char *desc)
}
if (!number_parsed) {
log_info(LD_REND, "Could not parse any descriptor.");
- return -1;
+ return RCS_BADDESC;
}
log_info(LD_REND, "Parsed %d and added %d descriptor%s.",
number_parsed, number_stored, number_stored != 1 ? "s" : "");
- return number_stored;
+ return RCS_OKAY;
}
/** Parse the v2 service descriptor in <b>desc</b>, decrypt the included list
@@ -1239,15 +1031,12 @@ rend_cache_store_v2_desc_as_dir(const char *desc)
*
* If we have a newer v2 descriptor with the same ID, ignore this one.
* If we have an older descriptor with the same ID, replace it.
- * If we have any v0 descriptor with the same ID, reject this one in order
- * to not get confused with having both versions for the same service.
* If the descriptor's service ID does not match
* <b>rend_query</b>-\>onion_address, reject it.
- * Return -2 if it's malformed or otherwise rejected; return -1 if we
- * already have a v0 descriptor here; return 0 if it's the same or older
- * than one we've already got; return 1 if it's novel.
+ *
+ * Return an appropriate rend_cache_store_status_t.
*/
-int
+rend_cache_store_status_t
rend_cache_store_v2_desc_as_client(const char *desc,
const rend_data_t *rend_query)
{
@@ -1276,7 +1065,7 @@ rend_cache_store_v2_desc_as_client(const char *desc,
char key[REND_SERVICE_ID_LEN_BASE32+2];
char service_id[REND_SERVICE_ID_LEN_BASE32+1];
rend_cache_entry_t *e;
- int retval;
+ rend_cache_store_status_t retval = RCS_BADDESC;
tor_assert(rend_cache);
tor_assert(desc);
/* Parse the descriptor. */
@@ -1284,20 +1073,17 @@ rend_cache_store_v2_desc_as_client(const char *desc,
&intro_size, &encoded_size,
&next_desc, desc) < 0) {
log_warn(LD_REND, "Could not parse descriptor.");
- retval = -2;
goto err;
}
/* Compute service ID from public key. */
if (rend_get_service_id(parsed->pk, service_id)<0) {
log_warn(LD_REND, "Couldn't compute service ID.");
- retval = -2;
goto err;
}
if (strcmp(rend_query->onion_address, service_id)) {
log_warn(LD_REND, "Received service descriptor for service ID %s; "
"expected descriptor for service ID %s.",
service_id, safe_str(rend_query->onion_address));
- retval = -2;
goto err;
}
/* Decode/decrypt introduction points. */
@@ -1329,7 +1115,6 @@ rend_cache_store_v2_desc_as_client(const char *desc,
log_warn(LD_REND, "Failed to parse introduction points. Either the "
"service has published a corrupt descriptor or you have "
"provided invalid authorization data.");
- retval = -2;
goto err;
} else if (n_intro_points > MAX_INTRO_POINTS) {
log_warn(LD_REND, "Found too many introduction points on a hidden "
@@ -1337,7 +1122,7 @@ rend_cache_store_v2_desc_as_client(const char *desc,
"attempt to improve reliability, but it could also be an "
"attempt to do a guard enumeration attack. Rejecting.",
safe_str_client(rend_query->onion_address));
- retval = -2;
+
goto err;
}
} else {
@@ -1350,22 +1135,12 @@ rend_cache_store_v2_desc_as_client(const char *desc,
if (parsed->timestamp < now - REND_CACHE_MAX_AGE-REND_CACHE_MAX_SKEW) {
log_warn(LD_REND, "Service descriptor with service ID %s is too old.",
safe_str_client(service_id));
- retval = -2;
goto err;
}
/* Is descriptor too far in the future? */
if (parsed->timestamp > now + REND_CACHE_MAX_SKEW) {
log_warn(LD_REND, "Service descriptor with service ID %s is too far in "
"the future.", safe_str_client(service_id));
- retval = -2;
- goto err;
- }
- /* Do we have a v0 descriptor? */
- tor_snprintf(key, sizeof(key), "0%s", service_id);
- if (strmap_get_lc(rend_cache, key)) {
- log_info(LD_REND, "We already have a v0 descriptor for service ID %s.",
- safe_str_client(service_id));
- retval = -1;
goto err;
}
/* Do we already have a newer descriptor? */
@@ -1375,16 +1150,14 @@ rend_cache_store_v2_desc_as_client(const char *desc,
log_info(LD_REND, "We already have a newer service descriptor for "
"service ID %s with the same desc ID and version.",
safe_str_client(service_id));
- retval = 0;
- goto err;
+ goto okay;
}
/* Do we already have this descriptor? */
if (e && !strcmp(desc, e->desc)) {
log_info(LD_REND,"We already have this service descriptor %s.",
safe_str_client(service_id));
e->received = time(NULL);
- retval = 0;
- goto err;
+ goto okay;
}
if (!e) {
e = tor_malloc_zero(sizeof(rend_cache_entry_t));
@@ -1400,7 +1173,10 @@ rend_cache_store_v2_desc_as_client(const char *desc,
e->len = encoded_size;
log_debug(LD_REND,"Successfully stored rend desc '%s', len %d.",
safe_str_client(service_id), (int)encoded_size);
- return 1;
+ return RCS_OKAY;
+
+ okay:
+ retval = RCS_OKAY;
err:
rend_service_descriptor_free(parsed);
diff --git a/src/or/rendcommon.h b/src/or/rendcommon.h
index f476593d2..07a47accf 100644
--- a/src/or/rendcommon.h
+++ b/src/or/rendcommon.h
@@ -26,8 +26,6 @@ void rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint,
const uint8_t *payload);
void rend_service_descriptor_free(rend_service_descriptor_t *desc);
-rend_service_descriptor_t *rend_parse_service_descriptor(const char *str,
- size_t len);
int rend_get_service_id(crypto_pk_t *pk, char *out);
void rend_encoded_v2_service_descriptor_free(
rend_encoded_v2_service_descriptor_t *desc);
@@ -39,16 +37,20 @@ void rend_cache_clean_v2_descs_as_dir(time_t now);
void rend_cache_purge(void);
void rend_cache_free_all(void);
int rend_valid_service_id(const char *query);
-int rend_cache_lookup_desc(const char *query, int version, const char **desc,
- size_t *desc_len);
int rend_cache_lookup_entry(const char *query, int version,
rend_cache_entry_t **entry_out);
int rend_cache_lookup_v2_desc_as_dir(const char *query, const char **desc);
-int rend_cache_store(const char *desc, size_t desc_len, int published,
- const char *service_id);
-int rend_cache_store_v2_desc_as_client(const char *desc,
+/** Return value from rend_cache_store_v2_desc_as_{dir,client}. */
+typedef enum {
+ RCS_NOTDIR = -2, /**< We're not a directory */
+ RCS_BADDESC = -1, /**< This descriptor is no good. */
+ RCS_OKAY = 0 /**< All worked as expected */
+} rend_cache_store_status_t;
+
+rend_cache_store_status_t rend_cache_store_v2_desc_as_dir(const char *desc);
+rend_cache_store_status_t rend_cache_store_v2_desc_as_client(const char *desc,
const rend_data_t *rend_query);
-int rend_cache_store_v2_desc_as_dir(const char *desc);
+
int rend_encode_v2_descriptors(smartlist_t *descs_out,
rend_service_descriptor_t *desc, time_t now,
uint8_t period, rend_auth_type_t auth_type,
diff --git a/src/or/rendmid.c b/src/or/rendmid.c
index 1bd11f6dc..c68f6da59 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/rendservice.c b/src/or/rendservice.c
index cb2f96299..500efaf20 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -1503,27 +1503,6 @@ find_rp_for_intro(const rend_intro_cell_t *intro,
return rp;
}
-/** Remove unnecessary parts from a rend_intro_cell_t - the ciphertext if
- * already decrypted, the plaintext too if already parsed
- */
-
-void
-rend_service_compact_intro(rend_intro_cell_t *request)
-{
- if (!request) return;
-
- if ((request->plaintext && request->plaintext_len > 0) ||
- request->parsed) {
- tor_free(request->ciphertext);
- request->ciphertext_len = 0;
- }
-
- if (request->parsed) {
- tor_free(request->plaintext);
- request->plaintext_len = 0;
- }
-}
-
/** Free a parsed INTRODUCE1 or INTRODUCE2 cell that was allocated by
* rend_service_parse_intro().
*/
diff --git a/src/or/rendservice.h b/src/or/rendservice.h
index caf88a3d6..4a810eb52 100644
--- a/src/or/rendservice.h
+++ b/src/or/rendservice.h
@@ -83,7 +83,6 @@ int rend_service_intro_established(origin_circuit_t *circuit,
void rend_service_rendezvous_has_opened(origin_circuit_t *circuit);
int rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
size_t request_len);
-void rend_service_compact_intro(rend_intro_cell_t *request);
int rend_service_decrypt_intro(rend_intro_cell_t *request,
crypto_pk_t *key,
char **err_msg_out);
diff --git a/src/or/rephist.c b/src/or/rephist.c
index 66dc5f611..87f930a28 100644
--- a/src/or/rephist.c
+++ b/src/or/rephist.c
@@ -1862,22 +1862,20 @@ rep_hist_note_used_port(time_t now, uint16_t port)
add_predicted_port(now, port);
}
-/** For this long after we've seen a request for a given port, assume that
- * we'll want to make connections to the same port in the future. */
-#define PREDICTED_CIRCS_RELEVANCE_TIME (60*60)
-
/** Return a newly allocated pointer to a list of uint16_t * for ports that
* are likely to be asked for in the near future.
*/
smartlist_t *
rep_hist_get_predicted_ports(time_t now)
{
+ int predicted_circs_relevance_time;
smartlist_t *out = smartlist_new();
tor_assert(predicted_ports_list);
+ predicted_circs_relevance_time = get_options()->PredictedPortsRelevanceTime;
/* clean out obsolete entries */
SMARTLIST_FOREACH_BEGIN(predicted_ports_list, predicted_port_t *, pp) {
- if (pp->time + PREDICTED_CIRCS_RELEVANCE_TIME < now) {
+ if (pp->time + predicted_circs_relevance_time < now) {
log_debug(LD_CIRC, "Expiring predicted port %d", pp->port);
rephist_total_alloc -= sizeof(predicted_port_t);
@@ -1944,14 +1942,17 @@ int
rep_hist_get_predicted_internal(time_t now, int *need_uptime,
int *need_capacity)
{
+ int predicted_circs_relevance_time;
+ predicted_circs_relevance_time = get_options()->PredictedPortsRelevanceTime;
+
if (!predicted_internal_time) { /* initialize it */
predicted_internal_time = now;
predicted_internal_uptime_time = now;
predicted_internal_capacity_time = now;
}
- if (predicted_internal_time + PREDICTED_CIRCS_RELEVANCE_TIME < now)
+ if (predicted_internal_time + predicted_circs_relevance_time < now)
return 0; /* too long ago */
- if (predicted_internal_uptime_time + PREDICTED_CIRCS_RELEVANCE_TIME >= now)
+ if (predicted_internal_uptime_time + predicted_circs_relevance_time >= now)
*need_uptime = 1;
// Always predict that we need capacity.
*need_capacity = 1;
@@ -1963,8 +1964,11 @@ rep_hist_get_predicted_internal(time_t now, int *need_uptime,
int
any_predicted_circuits(time_t now)
{
+ int predicted_circs_relevance_time;
+ predicted_circs_relevance_time = get_options()->PredictedPortsRelevanceTime;
+
return smartlist_len(predicted_ports_list) ||
- predicted_internal_time + PREDICTED_CIRCS_RELEVANCE_TIME >= now;
+ predicted_internal_time + predicted_circs_relevance_time >= now;
}
/** Return 1 if we have no need for circuits currently, else return 0. */
@@ -2988,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. */
@@ -3006,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. */
@@ -3019,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 de824749b..df01ae6cb 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/router.c b/src/or/router.c
index b96428362..1f5df4b89 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -684,6 +684,63 @@ router_initialize_tls_context(void)
(unsigned int)lifetime);
}
+/** Compute fingerprint (or hashed fingerprint if hashed is 1) and write
+ * it to 'fingerprint' (or 'hashed-fingerprint'). Return 0 on success, or
+ * -1 if Tor should die,
+ */
+STATIC int
+router_write_fingerprint(int hashed)
+{
+ char *keydir = NULL, *cp = NULL;
+ const char *fname = hashed ? "hashed-fingerprint" :
+ "fingerprint";
+ char fingerprint[FINGERPRINT_LEN+1];
+ const or_options_t *options = get_options();
+ char *fingerprint_line = NULL;
+ int result = -1;
+
+ keydir = get_datadir_fname(fname);
+ log_info(LD_GENERAL,"Dumping %sfingerprint to \"%s\"...",
+ hashed ? "hashed " : "", keydir);
+ if (!hashed) {
+ if (crypto_pk_get_fingerprint(get_server_identity_key(),
+ fingerprint, 0) < 0) {
+ log_err(LD_GENERAL,"Error computing fingerprint");
+ goto done;
+ }
+ } else {
+ if (crypto_pk_get_hashed_fingerprint(get_server_identity_key(),
+ fingerprint) < 0) {
+ log_err(LD_GENERAL,"Error computing hashed fingerprint");
+ goto done;
+ }
+ }
+
+ tor_asprintf(&fingerprint_line, "%s %s\n", options->Nickname, fingerprint);
+
+ /* Check whether we need to write the (hashed-)fingerprint file. */
+
+ cp = read_file_to_str(keydir, RFTS_IGNORE_MISSING, NULL);
+ if (!cp || strcmp(cp, fingerprint_line)) {
+ if (write_str_to_file(keydir, fingerprint_line, 0)) {
+ log_err(LD_FS, "Error writing %sfingerprint line to file",
+ hashed ? "hashed " : "");
+ goto done;
+ }
+ }
+
+ log_notice(LD_GENERAL, "Your Tor %s identity key fingerprint is '%s %s'",
+ hashed ? "bridge's hashed" : "server's", options->Nickname,
+ fingerprint);
+
+ result = 0;
+ done:
+ tor_free(cp);
+ tor_free(keydir);
+ tor_free(fingerprint_line);
+ return result;
+}
+
/** Initialize all OR private keys, and the TLS context, as necessary.
* On OPs, this only initializes the tls context. Return 0 on success,
* or -1 if Tor should die.
@@ -692,14 +749,10 @@ int
init_keys(void)
{
char *keydir;
- char fingerprint[FINGERPRINT_LEN+1];
- /*nickname<space>fp\n\0 */
- char fingerprint_line[MAX_NICKNAME_LEN+FINGERPRINT_LEN+3];
const char *mydesc;
crypto_pk_t *prkey;
char digest[DIGEST_LEN];
char v3_digest[DIGEST_LEN];
- char *cp;
const or_options_t *options = get_options();
dirinfo_type_t type;
time_t now = time(NULL);
@@ -889,40 +942,16 @@ init_keys(void)
}
}
- /* 5. Dump fingerprint to 'fingerprint' */
- keydir = get_datadir_fname("fingerprint");
- log_info(LD_GENERAL,"Dumping fingerprint to \"%s\"...",keydir);
- if (crypto_pk_get_fingerprint(get_server_identity_key(),
- fingerprint, 0) < 0) {
- log_err(LD_GENERAL,"Error computing fingerprint");
- tor_free(keydir);
+ /* 5. Dump fingerprint and possibly hashed fingerprint to files. */
+ if (router_write_fingerprint(0)) {
+ log_err(LD_FS, "Error writing fingerprint to file");
return -1;
}
- tor_assert(strlen(options->Nickname) <= MAX_NICKNAME_LEN);
- if (tor_snprintf(fingerprint_line, sizeof(fingerprint_line),
- "%s %s\n",options->Nickname, fingerprint) < 0) {
- log_err(LD_GENERAL,"Error writing fingerprint line");
- tor_free(keydir);
+ if (!public_server_mode(options) && router_write_fingerprint(1)) {
+ log_err(LD_FS, "Error writing hashed fingerprint to file");
return -1;
}
- /* Check whether we need to write the fingerprint file. */
- cp = NULL;
- if (file_status(keydir) == FN_FILE)
- cp = read_file_to_str(keydir, 0, NULL);
- if (!cp || strcmp(cp, fingerprint_line)) {
- if (write_str_to_file(keydir, fingerprint_line, 0)) {
- log_err(LD_FS, "Error writing fingerprint line to file");
- tor_free(keydir);
- tor_free(cp);
- return -1;
- }
- }
- tor_free(cp);
- tor_free(keydir);
- log_notice(LD_GENERAL,
- "Your Tor server's identity key fingerprint is '%s %s'",
- options->Nickname, fingerprint);
if (!authdir_mode(options))
return 0;
/* 6. [authdirserver only] load approved-routers file */
@@ -932,8 +961,7 @@ init_keys(void)
}
/* 6b. [authdirserver only] add own key to approved directories. */
crypto_pk_get_digest(get_server_identity_key(), digest);
- type = ((options->V1AuthoritativeDir ? V1_DIRINFO : NO_DIRINFO) |
- (options->V3AuthoritativeDir ?
+ type = ((options->V3AuthoritativeDir ?
(V3_DIRINFO|MICRODESC_DIRINFO|EXTRAINFO_DIRINFO) : NO_DIRINFO) |
(options->BridgeAuthoritativeDir ? BRIDGE_DIRINFO : NO_DIRINFO));
@@ -1148,7 +1176,7 @@ consider_testing_reachability(int test_or, int test_dir)
/* XXX IPv6 self testing */
log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.",
!orport_reachable ? "reachability" : "bandwidth",
- me->address, me->or_port);
+ fmt_addr32(me->addr), me->or_port);
circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei,
CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
extend_info_free(ei);
@@ -1160,7 +1188,7 @@ consider_testing_reachability(int test_or, int test_dir)
CONN_TYPE_DIR, &addr, me->dir_port,
DIR_PURPOSE_FETCH_SERVERDESC)) {
/* ask myself, via tor, for my server descriptor. */
- directory_initiate_command(me->address, &addr,
+ directory_initiate_command(&addr,
me->or_port, me->dir_port,
me->cache_info.identity_digest,
DIR_PURPOSE_FETCH_SERVERDESC,
@@ -1175,6 +1203,7 @@ router_orport_found_reachable(void)
{
const routerinfo_t *me = router_get_my_routerinfo();
if (!can_reach_or_port && me) {
+ char *address = tor_dup_ip(me->addr);
log_notice(LD_OR,"Self-testing indicates your ORPort is reachable from "
"the outside. Excellent.%s",
get_options()->PublishServerDescriptor_ != NO_DIRINFO ?
@@ -1183,7 +1212,8 @@ router_orport_found_reachable(void)
mark_my_descriptor_dirty("ORPort found reachable");
control_event_server_status(LOG_NOTICE,
"REACHABILITY_SUCCEEDED ORADDRESS=%s:%d",
- me->address, me->or_port);
+ address, me->or_port);
+ tor_free(address);
}
}
@@ -1193,6 +1223,7 @@ router_dirport_found_reachable(void)
{
const routerinfo_t *me = router_get_my_routerinfo();
if (!can_reach_dir_port && me) {
+ char *address = tor_dup_ip(me->addr);
log_notice(LD_DIRSERV,"Self-testing indicates your DirPort is reachable "
"from the outside. Excellent.");
can_reach_dir_port = 1;
@@ -1200,7 +1231,8 @@ router_dirport_found_reachable(void)
mark_my_descriptor_dirty("DirPort found reachable");
control_event_server_status(LOG_NOTICE,
"REACHABILITY_SUCCEEDED DIRADDRESS=%s:%d",
- me->address, me->dir_port);
+ address, me->dir_port);
+ tor_free(address);
}
}
@@ -1250,14 +1282,6 @@ authdir_mode(const or_options_t *options)
{
return options->AuthoritativeDir != 0;
}
-/** Return true iff we believe ourselves to be a v1 authoritative
- * directory server.
- */
-int
-authdir_mode_v1(const or_options_t *options)
-{
- return authdir_mode(options) && options->V1AuthoritativeDir != 0;
-}
/** Return true iff we believe ourselves to be a v3 authoritative
* directory server.
*/
@@ -1266,12 +1290,11 @@ authdir_mode_v3(const or_options_t *options)
{
return authdir_mode(options) && options->V3AuthoritativeDir != 0;
}
-/** Return true iff we are a v1 or v3 directory authority. */
+/** Return true iff we are a v3 directory authority. */
int
authdir_mode_any_main(const or_options_t *options)
{
- return options->V1AuthoritativeDir ||
- options->V3AuthoritativeDir;
+ return options->V3AuthoritativeDir;
}
/** Return true if we believe ourselves to be any kind of
* authoritative directory beyond just a hidserv authority. */
@@ -1664,18 +1687,6 @@ router_is_me(const routerinfo_t *router)
return router_digest_is_me(router->cache_info.identity_digest);
}
-/** Return true iff <b>fp</b> is a hex fingerprint of my identity digest. */
-int
-router_fingerprint_is_me(const char *fp)
-{
- char digest[DIGEST_LEN];
- if (strlen(fp) == HEX_DIGEST_LEN &&
- base16_decode(digest, sizeof(digest), fp, HEX_DIGEST_LEN) == 0)
- return router_digest_is_me(digest);
-
- return 0;
-}
-
/** Return a routerinfo for this OR, rebuilding a fresh one if
* necessary. Return NULL on error, or if called on an OP. */
const routerinfo_t *
@@ -1783,7 +1794,6 @@ router_rebuild_descriptor(int force)
ri = tor_malloc_zero(sizeof(routerinfo_t));
ri->cache_info.routerlist_index = -1;
- ri->address = tor_dup_ip(addr);
ri->nickname = tor_strdup(options->Nickname);
ri->addr = addr;
ri->or_port = router_get_advertised_or_port(options);
@@ -1848,7 +1858,7 @@ router_rebuild_descriptor(int force)
policies_parse_exit_policy(options->ExitPolicy, &ri->exit_policy,
options->IPv6Exit,
options->ExitPolicyRejectPrivate,
- ri->address, !options->BridgeRelay);
+ ri->addr, !options->BridgeRelay);
}
ri->policy_is_reject_star =
policy_is_reject_star(ri->exit_policy, AF_INET) &&
@@ -1861,12 +1871,6 @@ router_rebuild_descriptor(int force)
tor_free(p_tmp);
}
-#if 0
- /* XXXX NM NM I belive this is safe to remove */
- if (authdir_mode(options))
- ri->is_valid = ri->is_named = 1; /* believe in yourself */
-#endif
-
if (options->MyFamily && ! options->BridgeRelay) {
smartlist_t *family;
if (!warned_nonexistent_family)
@@ -2260,8 +2264,7 @@ char *
router_dump_router_to_string(routerinfo_t *router,
crypto_pk_t *ident_key)
{
- /* XXXX025 Make this look entirely at its arguments, and not at globals.
- */
+ char *address = NULL;
char *onion_pkey = NULL; /* Onion key, PEM-encoded. */
char *identity_pkey = NULL; /* Identity key, PEM-encoded. */
char digest[DIGEST_LEN];
@@ -2335,7 +2338,9 @@ router_dump_router_to_string(routerinfo_t *router,
}
}
+ address = tor_dup_ip(router->addr);
chunks = smartlist_new();
+
/* Generate the easy portion of the router descriptor. */
smartlist_add_asprintf(chunks,
"router %s %s %d 0 %d\n"
@@ -2351,7 +2356,7 @@ router_dump_router_to_string(routerinfo_t *router,
"signing-key\n%s"
"%s%s%s%s",
router->nickname,
- router->address,
+ address,
router->or_port,
decide_to_advertise_dirport(options, router->dir_port),
extra_or_address ? extra_or_address : "",
@@ -2465,6 +2470,7 @@ router_dump_router_to_string(routerinfo_t *router,
SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
smartlist_free(chunks);
}
+ tor_free(address);
tor_free(family_line);
tor_free(onion_pkey);
tor_free(identity_pkey);
diff --git a/src/or/router.h b/src/or/router.h
index 1ee0577c8..bf6cdbea3 100644
--- a/src/or/router.h
+++ b/src/or/router.h
@@ -50,7 +50,6 @@ void router_perform_bandwidth_test(int num_circs, time_t now);
int net_is_disabled(void);
int authdir_mode(const or_options_t *options);
-int authdir_mode_v1(const or_options_t *options);
int authdir_mode_v3(const or_options_t *options);
int authdir_mode_any_main(const or_options_t *options);
int authdir_mode_any_nonhidserv(const or_options_t *options);
@@ -91,7 +90,6 @@ int router_digest_is_me(const char *digest);
const uint8_t *router_get_my_id_digest(void);
int router_extrainfo_digest_is_me(const char *digest);
int router_is_me(const routerinfo_t *router);
-int router_fingerprint_is_me(const char *fp);
int router_pick_published_address(const or_options_t *options, uint32_t *addr);
int router_rebuild_descriptor(int force);
char *router_dump_router_to_string(routerinfo_t *router,
@@ -148,6 +146,7 @@ smartlist_t *router_get_all_orports(const routerinfo_t *ri);
#ifdef ROUTER_PRIVATE
/* Used only by router.c and test.c */
STATIC void get_platform_str(char *platform, size_t len);
+STATIC int router_write_fingerprint(int hashed);
#endif
#endif
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 164b32d7d..f1bd12c19 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -130,16 +130,6 @@ static smartlist_t *warned_nicknames = NULL;
* download is low. */
static time_t last_descriptor_download_attempted = 0;
-/** When we last computed the weights to use for bandwidths on directory
- * requests, what were the total weighted bandwidth, and our share of that
- * bandwidth? Used to determine what fraction of directory requests we should
- * expect to see.
- *
- * @{ */
-static uint64_t sl_last_total_weighted_bw = 0,
- sl_last_weighted_bw_of_me = 0;
-/**@}*/
-
/** Return the number of directory authorities whose type matches some bit set
* in <b>type</b> */
int
@@ -679,7 +669,7 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now)
char id_digest_str[2*DIGEST_LEN+1];
char sk_digest_str[2*DIGEST_LEN+1];
- if (should_delay_dir_fetches(get_options()))
+ if (should_delay_dir_fetches(get_options(), NULL))
return;
pending_cert = fp_pair_map_new();
@@ -1074,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) {
@@ -1149,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) {
@@ -1270,38 +1270,6 @@ router_pick_directory_server(dirinfo_type_t type, int flags)
return choice;
}
-/** Try to determine which fraction ofv3 directory requests aimed at
- * caches will be sent to us. Set
- * *<b>v3_share_out</b> to the fraction of v3 protocol shares we
- * expect to see. Return 0 on success, negative on failure. */
-/* XXXX This function is unused. */
-int
-router_get_my_share_of_directory_requests(double *v3_share_out)
-{
- const routerinfo_t *me = router_get_my_routerinfo();
- const routerstatus_t *rs;
- const int pds_flags = PDS_ALLOW_SELF|PDS_IGNORE_FASCISTFIREWALL;
- *v3_share_out = 0.0;
- if (!me)
- return -1;
- rs = router_get_consensus_status_by_id(me->cache_info.identity_digest);
- if (!rs)
- return -1;
-
- /* Calling for side effect */
- /* XXXX This is a bit of a kludge */
- {
- sl_last_total_weighted_bw = 0;
- router_pick_directory_server(V3_DIRINFO, pds_flags);
- if (sl_last_total_weighted_bw != 0) {
- *v3_share_out = U64_TO_DBL(sl_last_weighted_bw_of_me) /
- U64_TO_DBL(sl_last_total_weighted_bw);
- }
- }
-
- return 0;
-}
-
/** Return the dir_server_t for the directory authority whose identity
* key hashes to <b>digest</b>, or NULL if no such authority is known.
*/
@@ -1944,8 +1912,7 @@ smartlist_choose_node_by_bandwidth_weights(const smartlist_t *sl,
if (compute_weighted_bandwidths(sl, rule, &bandwidths) < 0)
return NULL;
- scale_array_elements_to_u64(bandwidths, smartlist_len(sl),
- &sl_last_total_weighted_bw);
+ scale_array_elements_to_u64(bandwidths, smartlist_len(sl), NULL);
{
int idx = choose_array_element_by_weight(bandwidths,
@@ -2054,7 +2021,7 @@ compute_weighted_bandwidths(const smartlist_t *sl,
// Cycle through smartlist and total the bandwidth.
SMARTLIST_FOREACH_BEGIN(sl, const node_t *, node) {
- int is_exit = 0, is_guard = 0, is_dir = 0, this_bw = 0, is_me = 0;
+ int is_exit = 0, is_guard = 0, is_dir = 0, this_bw = 0;
double weight = 1;
is_exit = node->is_exit && ! node->is_bad_exit;
is_guard = node->is_possible_guard;
@@ -2077,7 +2044,6 @@ compute_weighted_bandwidths(const smartlist_t *sl,
/* We can't use this one. */
continue;
}
- is_me = router_digest_is_me(node->identity);
if (is_guard && is_exit) {
weight = (is_dir ? Wdb*Wd : Wd);
@@ -2096,8 +2062,6 @@ compute_weighted_bandwidths(const smartlist_t *sl,
weight = 0.0;
bandwidths[node_sl_idx].dbl = weight*this_bw + 0.5;
- if (is_me)
- sl_last_weighted_bw_of_me = (uint64_t) bandwidths[node_sl_idx].dbl;
} SMARTLIST_FOREACH_END(node);
log_debug(LD_CIRC, "Generated weighted bandwidths for rule %s based "
@@ -2179,7 +2143,6 @@ smartlist_choose_node_by_bandwidth(const smartlist_t *sl,
bitarray_t *fast_bits;
bitarray_t *exit_bits;
bitarray_t *guard_bits;
- int me_idx = -1;
// This function does not support WEIGHT_FOR_DIR
// or WEIGHT_FOR_MID
@@ -2213,9 +2176,6 @@ smartlist_choose_node_by_bandwidth(const smartlist_t *sl,
uint32_t this_bw = 0;
i = node_sl_idx;
- if (router_digest_is_me(node->identity))
- me_idx = node_sl_idx;
-
is_exit = node->is_exit;
is_guard = node->is_possible_guard;
if (node->rs) {
@@ -2319,7 +2279,6 @@ smartlist_choose_node_by_bandwidth(const smartlist_t *sl,
if (guard_weight <= 0.0)
guard_weight = 0.0;
- sl_last_weighted_bw_of_me = 0;
for (i=0; i < (unsigned)smartlist_len(sl); i++) {
tor_assert(bandwidths[i].dbl >= 0.0);
@@ -2331,9 +2290,6 @@ smartlist_choose_node_by_bandwidth(const smartlist_t *sl,
bandwidths[i].dbl *= guard_weight;
else if (is_exit)
bandwidths[i].dbl *= exit_weight;
-
- if (i == (unsigned) me_idx)
- sl_last_weighted_bw_of_me = (uint64_t) bandwidths[i].dbl;
}
}
@@ -2352,8 +2308,7 @@ smartlist_choose_node_by_bandwidth(const smartlist_t *sl,
guard_weight, (int)(rule == WEIGHT_FOR_GUARD));
#endif
- scale_array_elements_to_u64(bandwidths, smartlist_len(sl),
- &sl_last_total_weighted_bw);
+ scale_array_elements_to_u64(bandwidths, smartlist_len(sl), NULL);
{
int idx = choose_array_element_by_weight(bandwidths,
@@ -2764,7 +2719,6 @@ routerinfo_free(routerinfo_t *router)
return;
tor_free(router->cache_info.signed_descriptor_body);
- tor_free(router->address);
tor_free(router->nickname);
tor_free(router->platform);
tor_free(router->contact_info);
@@ -2850,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();
@@ -3470,7 +3432,6 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
signed_desc_append_to_journal(&router->cache_info,
&routerlist->desc_store);
}
- directory_set_dirty();
*msg = authdir_believes_valid ? "Valid server updated" :
("Invalid server updated. (This dirserver is marking your "
"server as unapproved.)");
@@ -3492,7 +3453,6 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
signed_desc_append_to_journal(&router->cache_info,
&routerlist->desc_store);
}
- directory_set_dirty();
return ROUTER_ADDED_SUCCESSFULLY;
}
@@ -4648,7 +4608,7 @@ void
update_router_descriptor_downloads(time_t now)
{
const or_options_t *options = get_options();
- if (should_delay_dir_fetches(options))
+ if (should_delay_dir_fetches(options, NULL))
return;
if (!we_fetch_router_descriptors(options))
return;
@@ -4669,7 +4629,7 @@ update_extrainfo_downloads(time_t now)
int n_no_ei = 0, n_pending = 0, n_have = 0, n_delay = 0;
if (! options->DownloadExtraInfo)
return;
- if (should_delay_dir_fetches(options))
+ if (should_delay_dir_fetches(options, NULL))
return;
if (!router_have_minimum_dir_info())
return;
@@ -4775,7 +4735,7 @@ router_differences_are_cosmetic(const routerinfo_t *r1, const routerinfo_t *r2)
}
/* If any key fields differ, they're different. */
- if (strcasecmp(r1->address, r2->address) ||
+ if (r1->addr != r2->addr ||
strcasecmp(r1->nickname, r2->nickname) ||
r1->or_port != r2->or_port ||
!tor_addr_eq(&r1->ipv6_addr, &r2->ipv6_addr) ||
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 4ad316cee..7bf9a4d8e 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);
@@ -603,17 +603,6 @@ router_get_router_hash(const char *s, size_t s_len, char *digest)
DIGEST_SHA1);
}
-/** Set <b>digest</b> to the SHA-1 digest of the hash of the running-routers
- * string in <b>s</b>. Return 0 on success, -1 on failure.
- */
-int
-router_get_runningrouters_hash(const char *s, char *digest)
-{
- return router_get_hash_impl(s, strlen(s), digest,
- "network-status","\ndirectory-signature", '\n',
- DIGEST_SHA1);
-}
-
/** Set <b>digests</b> to all the digests of the consensus document in
* <b>s</b> */
int
@@ -691,7 +680,7 @@ router_get_dirobj_signature(const char *digest,
/** Helper: used to generate signatures for routers, directories and
* network-status objects. Given a digest in <b>digest</b> and a secret
- * <b>private_key</b>, generate an PKCS1-padded signature, BASE64-encode it,
+ * <b>private_key</b>, generate a PKCS1-padded signature, BASE64-encode it,
* surround it with -----BEGIN/END----- pairs, and write it to the
* <b>buf_len</b>-byte buffer at <b>buf</b>. Return 0 on success, -1 on
* failure.
@@ -714,6 +703,7 @@ router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest,
return -1;
}
memcpy(buf+s_len, sig, sig_len+1);
+ tor_free(sig);
return 0;
}
@@ -1195,8 +1185,7 @@ router_parse_entry_from_string(const char *s, const char *end,
log_warn(LD_DIR,"Router nickname is invalid");
goto err;
}
- router->address = tor_strdup(tok->args[1]);
- if (!tor_inet_aton(router->address, &in)) {
+ if (!tor_inet_aton(tok->args[1], &in)) {
log_warn(LD_DIR,"Router address is not an IP address.");
goto err;
}
@@ -2040,14 +2029,6 @@ routerstatus_parse_entry_from_string(memarea_t *area,
return rs;
}
-/** Helper to sort a smartlist of pointers to routerstatus_t */
-int
-compare_routerstatus_entries(const void **_a, const void **_b)
-{
- const routerstatus_t *a = *_a, *b = *_b;
- return fast_memcmp(a->identity_digest, b->identity_digest, DIGEST_LEN);
-}
-
int
compare_vote_routerstatus_entries(const void **_a, const void **_b)
{
diff --git a/src/or/routerparse.h b/src/or/routerparse.h
index 177217dc3..5d5d9e59e 100644
--- a/src/or/routerparse.h
+++ b/src/or/routerparse.h
@@ -14,7 +14,6 @@
int router_get_router_hash(const char *s, size_t s_len, char *digest);
int router_get_dir_hash(const char *s, char *digest);
-int router_get_runningrouters_hash(const char *s, char *digest);
int router_get_networkstatus_v3_hashes(const char *s, digests_t *digests);
int router_get_extrainfo_hash(const char *s, size_t s_len, char *digest);
#define DIROBJ_MAX_SIG_LEN 256
@@ -51,7 +50,6 @@ void sort_version_list(smartlist_t *lst, int remove_duplicates);
void assert_addr_policy_ok(smartlist_t *t);
void dump_distinct_digest_count(int severity);
-int compare_routerstatus_entries(const void **_a, const void **_b);
int compare_vote_routerstatus_entries(const void **_a, const void **_b);
int networkstatus_verify_bw_weights(networkstatus_t *ns, int);
networkstatus_t *networkstatus_parse_vote_from_string(const char *s,
diff --git a/src/or/routerset.c b/src/or/routerset.c
index 2e41f7f6c..7aee90d6d 100644
--- a/src/or/routerset.c
+++ b/src/or/routerset.c
@@ -358,39 +358,6 @@ routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset,
}
}
-#if 0
-/** Add to <b>target</b> every node_t from <b>source</b> except:
- *
- * 1) Don't add it if <b>include</b> is non-empty and the relay isn't in
- * <b>include</b>; and
- * 2) Don't add it if <b>exclude</b> is non-empty and the relay is
- * excluded in a more specific fashion by <b>exclude</b>.
- * 3) If <b>running_only</b>, don't add non-running routers.
- */
-void
-routersets_get_node_disjunction(smartlist_t *target,
- const smartlist_t *source,
- const routerset_t *include,
- const routerset_t *exclude, int running_only)
-{
- SMARTLIST_FOREACH(source, const node_t *, node, {
- int include_result;
- if (running_only && !node->is_running)
- continue;
- if (!routerset_is_empty(include))
- include_result = routerset_contains_node(include, node);
- else
- include_result = 1;
-
- if (include_result) {
- int exclude_result = routerset_contains_node(exclude, node);
- if (include_result >= exclude_result)
- smartlist_add(target, (void*)node);
- }
- });
-}
-#endif
-
/** Remove every node_t from <b>lst</b> that is in <b>routerset</b>. */
void
routerset_subtract_nodes(smartlist_t *lst, const routerset_t *routerset)
diff --git a/src/or/routerset.h b/src/or/routerset.h
index bfa0c59ac..8261c7fb0 100644
--- a/src/or/routerset.h
+++ b/src/or/routerset.h
@@ -32,12 +32,6 @@ void routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset,
const routerset_t *excludeset,
int running_only);
int routerset_add_unknown_ccs(routerset_t **setp, int only_if_some_cc_set);
-#if 0
-void routersets_get_node_disjunction(smartlist_t *target,
- const smartlist_t *source,
- const routerset_t *include,
- const routerset_t *exclude, int running_only);
-#endif
void routerset_subtract_nodes(smartlist_t *out,
const routerset_t *routerset);
diff --git a/src/or/statefile.c b/src/or/statefile.c
index 8ab04763d..2251f25e9 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 "