summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changes/bug199211
-rw-r--r--changes/bug82077
-rw-r--r--changes/bug82106
-rw-r--r--changes/bug82186
-rw-r--r--changes/feature49947
-rw-r--r--changes/integers_donna3
-rw-r--r--doc/tor.1.txt3
-rw-r--r--src/ext/curve25519_donna/curve25519-donna-c64.c4
-rw-r--r--src/ext/curve25519_donna/curve25519-donna.c4
-rw-r--r--src/or/buffers.c42
-rw-r--r--src/or/channel.c14
-rw-r--r--src/or/channel.h5
-rw-r--r--src/or/channeltls.c29
-rw-r--r--src/or/circuitbuild.c19
-rw-r--r--src/or/circuitlist.c2
-rw-r--r--src/or/command.c5
-rw-r--r--src/or/config.c8
-rw-r--r--src/or/config.h1
-rw-r--r--src/or/connection.c9
-rw-r--r--src/or/connection_or.c105
-rw-r--r--src/or/connection_or.h14
-rw-r--r--src/or/cpuworker.c10
-rw-r--r--src/or/directory.c11
-rw-r--r--src/or/dirvote.c2
-rw-r--r--src/or/entrynodes.c69
-rw-r--r--src/or/entrynodes.h2
-rw-r--r--src/or/main.c13
-rw-r--r--src/or/microdesc.c4
-rw-r--r--src/or/or.h31
-rw-r--r--src/or/relay.c11
-rw-r--r--src/or/relay.h3
-rw-r--r--src/or/rendservice.c12
-rw-r--r--src/or/rephist.c5
-rw-r--r--src/or/router.c11
-rw-r--r--src/or/routerlist.c3
-rw-r--r--src/test/test.c1
-rw-r--r--src/test/test_util.c2
-rw-r--r--src/tools/tor-resolve.c2
38 files changed, 340 insertions, 156 deletions
diff --git a/changes/bug1992 b/changes/bug1992
new file mode 100644
index 0000000000..6a751dc7e6
--- /dev/null
+++ b/changes/bug1992
@@ -0,0 +1,11 @@
+ o Minor bugfixes:
+ - Stop trying to resolve our hostname so often (e.g. every time we
+ think about doing a directory fetch). Now we reuse the cached
+ answer in some cases. Fixes bugs 1992 (bugfix on 0.2.0.20-rc)
+ and 2410 (bugfix on 0.1.2.2-alpha).
+
+ o Minor features:
+ - Make bridge relays check once a minute for whether their IP
+ address has changed, rather than only every 15 minutes. Resolves
+ bugs 1913 and 1992.
+
diff --git a/changes/bug8207 b/changes/bug8207
new file mode 100644
index 0000000000..0028d3380f
--- /dev/null
+++ b/changes/bug8207
@@ -0,0 +1,7 @@
+ o Major bugfixes (hidden services):
+ - Allow hidden service authentication to succeed again. When we
+ refactored the hidden service introduction code back in 0.2.4.1-alpha,
+ we didn't update the code that checks whether authentication
+ information is present, causing all authentication checks to
+ return "false". Fix for bug 8207; bugfix on 0.2.4.1-alpha. Found by
+ Coverity; this is CID 718615.
diff --git a/changes/bug8210 b/changes/bug8210
new file mode 100644
index 0000000000..85d41b844a
--- /dev/null
+++ b/changes/bug8210
@@ -0,0 +1,6 @@
+ o Minor bugfixes:
+ - Fix an impossible-to-trigger integer overflow when
+ estimating how long out onionskin queue would take. (This overflow
+ would require us to accept 4 million onionskins before processing
+ 100 of them.) Fixes bug 8210; bugfix on 0.2.4.10-alpha.
+
diff --git a/changes/bug8218 b/changes/bug8218
new file mode 100644
index 0000000000..ce8d53ba62
--- /dev/null
+++ b/changes/bug8218
@@ -0,0 +1,6 @@
+ o Major bugfixes:
+ - Stop marking every relay as having been down for one hour every
+ time we restart a directory authority. These artificial downtimes
+ were messing with our Stable and Guard flag calculations. Fixes
+ bug 8218 (introduced by the fix for 1035). Bugfix on 0.2.2.23-alpha.
+
diff --git a/changes/feature4994 b/changes/feature4994
new file mode 100644
index 0000000000..4fa0e037b7
--- /dev/null
+++ b/changes/feature4994
@@ -0,0 +1,7 @@
+ o Minor features:
+ - Teach bridge-using clients to avoid 0.2.2 bridges when making
+ microdescriptor-related dir requests, and only fall back to normal
+ descriptors if none of their bridges can handle microdescriptors
+ (as opposed to the fix in ticket 4013, which caused them to fall
+ back to normal descriptors if *any* of their bridges preferred
+ them). Resolves ticket 4994.
diff --git a/changes/integers_donna b/changes/integers_donna
new file mode 100644
index 0000000000..e9c69e8e1c
--- /dev/null
+++ b/changes/integers_donna
@@ -0,0 +1,3 @@
+ o Minor bugfixes (portability)
+ - Tweak the curve25519-donna*.c implementations to tolerate systems
+ that lack stdint.h. Fixes bug 3894; bugfix on 0.2.4.8-alpha.
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index b1e758f552..0b3b94d70c 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -1537,7 +1537,8 @@ is non-zero):
Prevent nodes that don't appear in the consensus from exiting using this
relay. If the option is 1, we always block exit attempts from such
nodes; if it's 0, we never do, and if the option is "auto", then we do
- whatever the authorities suggest in the consensus. (Default: auto)
+ whatever the authorities suggest in the consensus (and block if the consensus
+ is quiet on the issue). (Default: auto)
**ServerDNSResolvConfFile** __filename__::
Overrides the default DNS configuration with the configuration in
diff --git a/src/ext/curve25519_donna/curve25519-donna-c64.c b/src/ext/curve25519_donna/curve25519-donna-c64.c
index 9ebd8a12d8..b68ff3695a 100644
--- a/src/ext/curve25519_donna/curve25519-donna-c64.c
+++ b/src/ext/curve25519_donna/curve25519-donna-c64.c
@@ -22,8 +22,10 @@
* from the sample implementation.
*/
+#include "orconfig.h"
+
#include <string.h>
-#include <stdint.h>
+#include "torint.h"
typedef uint8_t u8;
typedef uint64_t limb;
diff --git a/src/ext/curve25519_donna/curve25519-donna.c b/src/ext/curve25519_donna/curve25519-donna.c
index 80e4594eec..5c6821ccd8 100644
--- a/src/ext/curve25519_donna/curve25519-donna.c
+++ b/src/ext/curve25519_donna/curve25519-donna.c
@@ -46,8 +46,10 @@
* from the sample implementation.
*/
+#include "orconfig.h"
+
#include <string.h>
-#include <stdint.h>
+#include "torint.h"
typedef uint8_t u8;
typedef int32_t s32;
diff --git a/src/or/buffers.c b/src/or/buffers.c
index 73c25579d6..33ea978daa 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -1045,28 +1045,34 @@ cell_command_is_var_length(uint8_t command, int linkproto)
int
fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto)
{
- char hdr[VAR_CELL_HEADER_SIZE];
+ char hdr[VAR_CELL_MAX_HEADER_SIZE];
var_cell_t *result;
uint8_t command;
uint16_t length;
+ const int wide_circ_ids = linkproto >= MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS;
+ const int circ_id_len = get_circ_id_size(wide_circ_ids);
+ const unsigned header_len = get_var_cell_header_size(wide_circ_ids);
check();
*out = NULL;
- if (buf->datalen < VAR_CELL_HEADER_SIZE)
+ if (buf->datalen < header_len)
return 0;
peek_from_buf(hdr, sizeof(hdr), buf);
- command = get_uint8(hdr+2);
+ command = get_uint8(hdr + circ_id_len);
if (!(cell_command_is_var_length(command, linkproto)))
return 0;
- length = ntohs(get_uint16(hdr+3));
- if (buf->datalen < (size_t)(VAR_CELL_HEADER_SIZE+length))
+ length = ntohs(get_uint16(hdr + circ_id_len + 1));
+ if (buf->datalen < (size_t)(header_len+length))
return 1;
result = var_cell_new(length);
result->command = command;
- result->circ_id = ntohs(get_uint16(hdr));
+ if (wide_circ_ids)
+ result->circ_id = ntohl(get_uint32(hdr));
+ else
+ result->circ_id = ntohs(get_uint16(hdr));
- buf_remove_from_front(buf, VAR_CELL_HEADER_SIZE);
+ buf_remove_from_front(buf, header_len);
peek_from_buf((char*) result->payload, length, buf);
buf_remove_from_front(buf, length);
check();
@@ -1125,30 +1131,36 @@ fetch_var_cell_from_evbuffer(struct evbuffer *buf, var_cell_t **out,
uint16_t cell_length;
var_cell_t *cell;
int result = 0;
+ const int wide_circ_ids = linkproto >= MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS;
+ const int circ_id_len = get_circ_id_size(wide_circ_ids);
+ const unsigned header_len = get_var_cell_header_size(wide_circ_ids);
*out = NULL;
buf_len = evbuffer_get_length(buf);
- if (buf_len < VAR_CELL_HEADER_SIZE)
+ if (buf_len < header_len)
return 0;
- n = inspect_evbuffer(buf, &hdr, VAR_CELL_HEADER_SIZE, &free_hdr, NULL);
- tor_assert(n >= VAR_CELL_HEADER_SIZE);
+ n = inspect_evbuffer(buf, &hdr, header_len, &free_hdr, NULL);
+ tor_assert(n >= header_len);
- command = get_uint8(hdr+2);
+ command = get_uint8(hdr + circ_id_len);
if (!(cell_command_is_var_length(command, linkproto))) {
goto done;
}
- cell_length = ntohs(get_uint16(hdr+3));
- if (buf_len < (size_t)(VAR_CELL_HEADER_SIZE+cell_length)) {
+ cell_length = ntohs(get_uint16(hdr + circ_id_len + 1));
+ if (buf_len < (size_t)(header_len+cell_length)) {
result = 1; /* Not all here yet. */
goto done;
}
cell = var_cell_new(cell_length);
cell->command = command;
- cell->circ_id = ntohs(get_uint16(hdr));
- evbuffer_drain(buf, VAR_CELL_HEADER_SIZE);
+ if (wide_circ_ids)
+ cell->circ_id = ntohl(get_uint32(hdr));
+ else
+ cell->circ_id = ntohs(get_uint16(hdr));
+ evbuffer_drain(buf, header_len);
evbuffer_remove(buf, cell->payload, cell_length);
*out = cell;
result = 1;
diff --git a/src/or/channel.c b/src/or/channel.c
index 104b018cf4..f8afc405e6 100644
--- a/src/or/channel.c
+++ b/src/or/channel.c
@@ -4068,9 +4068,10 @@ channel_num_circuits(channel_t *chan)
* This is called when setting up a channel and replaces the old
* connection_or_set_circid_type()
*/
-
void
-channel_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd)
+channel_set_circid_type(channel_t *chan,
+ crypto_pk_t *identity_rcvd,
+ int consider_identity)
{
int started_here;
crypto_pk_t *our_identity;
@@ -4078,6 +4079,15 @@ channel_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd)
tor_assert(chan);
started_here = channel_is_outgoing(chan);
+
+ if (! consider_identity) {
+ if (started_here)
+ chan->circ_id_type = CIRC_ID_TYPE_HIGHER;
+ else
+ chan->circ_id_type = CIRC_ID_TYPE_LOWER;
+ return;
+ }
+
our_identity = started_here ?
get_tlsclient_identity_key() : get_server_identity_key();
diff --git a/src/or/channel.h b/src/or/channel.h
index ec79888063..0933ec8d39 100644
--- a/src/or/channel.h
+++ b/src/or/channel.h
@@ -143,6 +143,8 @@ struct channel_s {
* space should we use?
*/
ENUM_BF(circ_id_type_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.
@@ -447,7 +449,8 @@ int channel_matches_extend_info(channel_t *chan, extend_info_t *extend_info);
int channel_matches_target_addr_for_extend(channel_t *chan,
const tor_addr_t *target);
unsigned int channel_num_circuits(channel_t *chan);
-void channel_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd);
+void channel_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd,
+ int consider_identity);
void channel_timestamp_client(channel_t *chan);
const char * channel_listener_describe_transport(channel_listener_t *chan_l);
diff --git a/src/or/channeltls.c b/src/or/channeltls.c
index e3dfdcc25e..1035a14127 100644
--- a/src/or/channeltls.c
+++ b/src/or/channeltls.c
@@ -600,12 +600,13 @@ channel_tls_write_packed_cell_method(channel_t *chan,
packed_cell_t *packed_cell)
{
channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan);
+ size_t cell_network_size = get_cell_network_size(chan->wide_circ_ids);
tor_assert(tlschan);
tor_assert(packed_cell);
tor_assert(tlschan->conn);
- connection_write_to_buf(packed_cell->body, CELL_NETWORK_SIZE,
+ connection_write_to_buf(packed_cell->body, cell_network_size,
TO_CONN(tlschan->conn));
/* This is where the cell is finished; used to be done from relay.c */
@@ -893,7 +894,7 @@ channel_tls_handle_cell(cell_t *cell, or_connection_t *conn)
}
if (conn->base_.state == OR_CONN_STATE_OR_HANDSHAKING_V3)
- or_handshake_state_record_cell(conn->handshake_state, cell, 1);
+ or_handshake_state_record_cell(conn, conn->handshake_state, cell, 1);
switch (cell->command) {
case CELL_PADDING:
@@ -1034,7 +1035,8 @@ channel_tls_handle_var_cell(var_cell_t *var_cell, or_connection_t *conn)
break;
case OR_CONN_STATE_OR_HANDSHAKING_V3:
if (var_cell->command != CELL_AUTHENTICATE)
- or_handshake_state_record_var_cell(conn->handshake_state, var_cell, 1);
+ or_handshake_state_record_var_cell(conn, conn->handshake_state,
+ var_cell, 1);
break; /* Everything is allowed */
case OR_CONN_STATE_OPEN:
if (conn->link_proto < 3) {
@@ -1154,7 +1156,8 @@ enter_v3_handshake_with_cell(var_cell_t *cell, channel_tls_t *chan)
connection_or_close_for_error(chan->conn, 0);
return -1;
}
- or_handshake_state_record_var_cell(chan->conn->handshake_state, cell, 1);
+ or_handshake_state_record_var_cell(chan->conn,
+ chan->conn->handshake_state, cell, 1);
return 0;
}
@@ -1225,7 +1228,7 @@ channel_tls_process_versions_cell(var_cell_t *cell, channel_tls_t *chan)
connection_or_close_for_error(chan->conn, 0);
return;
} else if (highest_supported_version < 3 &&
- chan->conn->base_.state == OR_CONN_STATE_OR_HANDSHAKING_V3) {
+ chan->conn->base_.state == OR_CONN_STATE_OR_HANDSHAKING_V3) {
log_fn(LOG_PROTOCOL_WARN, LD_OR,
"Negotiated link protocol 2 or lower after doing a v3 TLS "
"handshake. Closing connection.");
@@ -1294,6 +1297,13 @@ channel_tls_process_versions_cell(var_cell_t *cell, channel_tls_t *chan)
return;
}
}
+
+ /* We set this after sending the verions cell. */
+ /*XXXXX symbolic const.*/
+ chan->base_.wide_circ_ids =
+ chan->conn->link_proto >= MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS;
+ chan->conn->wide_circ_ids = chan->base_.wide_circ_ids;
+
if (send_certs) {
if (connection_or_send_certs_cell(chan->conn) < 0) {
log_warn(LD_OR, "Couldn't send certs cell");
@@ -1375,7 +1385,8 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
tor_assert(tor_digest_is_zero(
(const char*)(chan->conn->handshake_state->
authenticated_peer_id)));
- channel_set_circid_type(TLS_CHAN_TO_BASE(chan), NULL);
+ channel_set_circid_type(TLS_CHAN_TO_BASE(chan), NULL,
+ chan->conn->link_proto < MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS);
connection_or_init_conn_from_address(chan->conn,
&(chan->conn->base_.addr),
@@ -1629,7 +1640,8 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
ERR("Internal error: Couldn't get RSA key from ID cert.");
memcpy(chan->conn->handshake_state->authenticated_peer_id,
id_digests->d[DIGEST_SHA1], DIGEST_LEN);
- channel_set_circid_type(TLS_CHAN_TO_BASE(chan), identity_rcvd);
+ channel_set_circid_type(TLS_CHAN_TO_BASE(chan), identity_rcvd,
+ chan->conn->link_proto < MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS);
crypto_pk_free(identity_rcvd);
}
@@ -1913,7 +1925,8 @@ channel_tls_process_authenticate_cell(var_cell_t *cell, channel_tls_t *chan)
memcpy(chan->conn->handshake_state->authenticated_peer_id,
id_digests->d[DIGEST_SHA1], DIGEST_LEN);
- channel_set_circid_type(TLS_CHAN_TO_BASE(chan), identity_rcvd);
+ channel_set_circid_type(TLS_CHAN_TO_BASE(chan), identity_rcvd,
+ chan->conn->link_proto < MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS);
crypto_pk_free(identity_rcvd);
connection_or_init_conn_from_address(chan->conn,
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index b9a4f89030..40751e02b1 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -25,6 +25,7 @@
#include "directory.h"
#include "entrynodes.h"
#include "main.h"
+#include "microdesc.h"
#include "networkstatus.h"
#include "nodelist.h"
#include "onion.h"
@@ -99,7 +100,7 @@ get_unique_circ_id_by_chan(channel_t *chan)
{
circid_t test_circ_id;
circid_t attempts=0;
- circid_t high_bit;
+ circid_t high_bit, max_range;
tor_assert(chan);
@@ -109,17 +110,17 @@ get_unique_circ_id_by_chan(channel_t *chan)
"a client with no identity.");
return 0;
}
- high_bit =
- (chan->circ_id_type == CIRC_ID_TYPE_HIGHER) ? 1<<15 : 0;
+ max_range = (chan->wide_circ_ids) ? (1u<<31) : (1u<<15);
+ high_bit = (chan->circ_id_type == CIRC_ID_TYPE_HIGHER) ? max_range : 0;
do {
- /* Sequentially iterate over test_circ_id=1...1<<15-1 until we find a
+ /* Sequentially iterate over test_circ_id=1...max_range until we find a
* circID such that (high_bit|test_circ_id) is not already used. */
test_circ_id = chan->next_circ_id++;
- if (test_circ_id == 0 || test_circ_id >= 1<<15) {
+ if (test_circ_id == 0 || test_circ_id >= max_range) {
test_circ_id = 1;
chan->next_circ_id = 2;
}
- if (++attempts > 1<<15) {
+ if (++attempts > max_range) {
/* Make sure we don't loop forever if all circ_id's are used. This
* matters because it's an external DoS opportunity.
*/
@@ -1307,7 +1308,8 @@ pathbias_is_new_circ_attempt(origin_circuit_t *circ)
/* cpath is a circular list. We want circs with more than one hop,
* and the second hop must be waiting for keys still (it's just
* about to get them). */
- return circ->cpath->next != circ->cpath &&
+ return circ->cpath &&
+ circ->cpath->next != circ->cpath &&
circ->cpath->next->state == CPATH_STATE_AWAITING_KEYS;
#else
/* If tagging attacks are no longer possible, we probably want to
@@ -1315,7 +1317,8 @@ pathbias_is_new_circ_attempt(origin_circuit_t *circ)
* timing-based tagging is still more useful than per-hop failure.
* In which case, we'd never want to use this.
*/
- return circ->cpath->state == CPATH_STATE_AWAITING_KEYS;
+ return circ->cpath &&
+ circ->cpath->state == CPATH_STATE_AWAITING_KEYS;
#endif
}
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 6987dc42fd..ef32680736 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -71,7 +71,7 @@ chan_circid_entries_eq_(chan_circid_circuit_map_t *a,
static INLINE unsigned int
chan_circid_entry_hash_(chan_circid_circuit_map_t *a)
{
- return (((unsigned)a->circ_id)<<8) ^ (unsigned)(uintptr_t)(a->chan);
+ return ((unsigned)a->circ_id) ^ (unsigned)(uintptr_t)(a->chan);
}
/** Map from [chan,circid] to circuit. */
diff --git a/src/or/command.c b/src/or/command.c
index 09313b48a2..dfe4f65916 100644
--- a/src/or/command.c
+++ b/src/or/command.c
@@ -231,7 +231,10 @@ command_process_create_cell(cell_t *cell, channel_t *chan)
/* If the high bit of the circuit ID is not as expected, close the
* circ. */
- id_is_high = cell->circ_id & (1<<15);
+ if (chan->wide_circ_ids)
+ id_is_high = cell->circ_id & (1u<<31);
+ else
+ id_is_high = cell->circ_id & (1u<<15);
if ((id_is_high &&
chan->circ_id_type == CIRC_ID_TYPE_HIGHER) ||
(!id_is_high &&
diff --git a/src/or/config.c b/src/or/config.c
index 7ca20e46b4..f88842624c 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -1893,6 +1893,14 @@ list_torrc_options(void)
/** Last value actually set by resolve_my_address. */
static uint32_t last_resolved_addr = 0;
+
+/** Accessor for last_resolved_addr from outside this file. */
+uint32_t
+get_last_resolved_addr(void)
+{
+ return last_resolved_addr;
+}
+
/**
* Use <b>options-\>Address</b> to guess our public IP address.
*
diff --git a/src/or/config.h b/src/or/config.h
index e0748a07bf..ef4acac514 100644
--- a/src/or/config.h
+++ b/src/or/config.h
@@ -26,6 +26,7 @@ const char *get_short_version(void);
setopt_err_t options_trial_assign(config_line_t *list, int use_defaults,
int clear_first, char **msg);
+uint32_t get_last_resolved_addr(void);
int resolve_my_address(int warn_severity, const or_options_t *options,
uint32_t *addr_out,
const char **method_out, char **hostname_out);
diff --git a/src/or/connection.c b/src/or/connection.c
index 7b0f081fde..c659e65fe5 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -1068,6 +1068,7 @@ connection_listener_new(const struct sockaddr *listensockaddr,
log_warn(LD_NET,"Unable to chown() %s socket: user %s not found.",
address, options->User);
tor_close_socket(s);
+ goto err;
} else if (chown(address, pw->pw_uid, pw->pw_gid) < 0) {
log_warn(LD_NET,"Unable to chown() %s socket: %s.",
address, strerror(errno));
@@ -2222,8 +2223,7 @@ connection_bucket_round_robin(int base, int priority,
static ssize_t
connection_bucket_read_limit(connection_t *conn, time_t now)
{
- int base = connection_speaks_cells(conn) ?
- CELL_NETWORK_SIZE : RELAY_PAYLOAD_SIZE;
+ int base = RELAY_PAYLOAD_SIZE;
int priority = conn->type != CONN_TYPE_DIR;
int conn_bucket = -1;
int global_bucket = global_read_bucket;
@@ -2232,6 +2232,7 @@ connection_bucket_read_limit(connection_t *conn, time_t now)
or_connection_t *or_conn = TO_OR_CONN(conn);
if (conn->state == OR_CONN_STATE_OPEN)
conn_bucket = or_conn->read_bucket;
+ base = get_cell_network_size(or_conn->wide_circ_ids);
}
if (!connection_is_rate_limited(conn)) {
@@ -2251,8 +2252,7 @@ connection_bucket_read_limit(connection_t *conn, time_t now)
ssize_t
connection_bucket_write_limit(connection_t *conn, time_t now)
{
- int base = connection_speaks_cells(conn) ?
- CELL_NETWORK_SIZE : RELAY_PAYLOAD_SIZE;
+ int base = RELAY_PAYLOAD_SIZE;
int priority = conn->type != CONN_TYPE_DIR;
int conn_bucket = (int)conn->outbuf_flushlen;
int global_bucket = global_write_bucket;
@@ -2270,6 +2270,7 @@ connection_bucket_write_limit(connection_t *conn, time_t now)
if (or_conn->write_bucket < conn_bucket)
conn_bucket = or_conn->write_bucket >= 0 ?
or_conn->write_bucket : 0;
+ base = get_cell_network_size(or_conn->wide_circ_ids);
}
if (connection_counts_as_relayed_traffic(conn, now) &&
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index 5ec32d6324..c4415c5f88 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -352,33 +352,56 @@ connection_or_get_num_circuits(or_connection_t *conn)
* should set it or clear it as appropriate.
*/
void
-cell_pack(packed_cell_t *dst, const cell_t *src)
+cell_pack(packed_cell_t *dst, const cell_t *src, int wide_circ_ids)
{
char *dest = dst->body;
- set_uint16(dest, htons(src->circ_id));
- set_uint8(dest+2, src->command);
- memcpy(dest+3, src->payload, CELL_PAYLOAD_SIZE);
+ if (wide_circ_ids) {
+ set_uint32(dest, htonl(src->circ_id));
+ dest += 4;
+ } else {
+ set_uint16(dest, htons(src->circ_id));
+ dest += 2;
+ memset(dest+CELL_MAX_NETWORK_SIZE-2, 0, 2); /*make sure it's clear */
+ }
+ set_uint8(dest, src->command);
+ memcpy(dest+1, src->payload, CELL_PAYLOAD_SIZE);
}
/** Unpack the network-order buffer <b>src</b> into a host-order
* cell_t structure <b>dest</b>.
*/
static void
-cell_unpack(cell_t *dest, const char *src)
+cell_unpack(cell_t *dest, const char *src, int wide_circ_ids)
{
- dest->circ_id = ntohs(get_uint16(src));
- dest->command = get_uint8(src+2);
- memcpy(dest->payload, src+3, CELL_PAYLOAD_SIZE);
+ if (wide_circ_ids) {
+ dest->circ_id = ntohl(get_uint32(src));
+ src += 4;
+ } else {
+ dest->circ_id = ntohs(get_uint16(src));
+ src += 2;
+ }
+ dest->command = get_uint8(src);
+ memcpy(dest->payload, src+1, CELL_PAYLOAD_SIZE);
}
-/** Write the header of <b>cell</b> into the first VAR_CELL_HEADER_SIZE
- * bytes of <b>hdr_out</b>. */
-void
-var_cell_pack_header(const var_cell_t *cell, char *hdr_out)
+/** Write the header of <b>cell</b> into the first VAR_CELL_MAX_HEADER_SIZE
+ * bytes of <b>hdr_out</b>. Returns number of bytes used. */
+int
+var_cell_pack_header(const var_cell_t *cell, char *hdr_out, int wide_circ_ids)
{
- set_uint16(hdr_out, htons(cell->circ_id));
- set_uint8(hdr_out+2, cell->command);
- set_uint16(hdr_out+3, htons(cell->payload_len));
+ int r;
+ if (wide_circ_ids) {
+ set_uint32(hdr_out, htonl(cell->circ_id));
+ hdr_out += 4;
+ r = VAR_CELL_MAX_HEADER_SIZE;
+ } else {
+ set_uint16(hdr_out, htons(cell->circ_id));
+ hdr_out += 2;
+ r = VAR_CELL_MAX_HEADER_SIZE - 2;
+ }
+ set_uint8(hdr_out, cell->command);
+ set_uint16(hdr_out+1, htons(cell->payload_len));
+ return r;
}
/** Allocate and return a new var_cell_t with <b>payload_len</b> bytes of
@@ -498,6 +521,7 @@ connection_or_flushed_some(or_connection_t *conn)
{
size_t datalen, temp;
ssize_t n, flushed;
+ size_t cell_network_size = get_cell_network_size(conn->wide_circ_ids);
/* If we're under the low water mark, add cells until we're just over the
* high water mark. */
@@ -505,7 +529,7 @@ connection_or_flushed_some(or_connection_t *conn)
if (datalen < OR_CONN_LOWWATER) {
while ((conn->chan) && channel_tls_more_to_flush(conn->chan)) {
/* Compute how many more cells we want at most */
- n = CEIL_DIV(OR_CONN_HIGHWATER - datalen, CELL_NETWORK_SIZE);
+ n = CEIL_DIV(OR_CONN_HIGHWATER - datalen, cell_network_size);
/* Bail out if we don't want any more */
if (n <= 0) break;
/* We're still here; try to flush some more cells */
@@ -1533,7 +1557,8 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
}
tor_assert(conn->chan);
- channel_set_circid_type(TLS_CHAN_TO_BASE(conn->chan), identity_rcvd);
+ channel_set_circid_type(TLS_CHAN_TO_BASE(conn->chan), identity_rcvd, 1);
+
crypto_pk_free(identity_rcvd);
if (started_here)
@@ -1739,10 +1764,12 @@ or_handshake_state_free(or_handshake_state_t *state)
* authenticate cell.)
*/
void
-or_handshake_state_record_cell(or_handshake_state_t *state,
+or_handshake_state_record_cell(or_connection_t *conn,
+ or_handshake_state_t *state,
const cell_t *cell,
int incoming)
{
+ size_t cell_network_size = get_cell_network_size(conn->wide_circ_ids);
crypto_digest_t *d, **dptr;
packed_cell_t packed;
if (incoming) {
@@ -1764,8 +1791,8 @@ or_handshake_state_record_cell(or_handshake_state_t *state,
d = *dptr;
/* Re-packing like this is a little inefficient, but we don't have to do
this very often at all. */
- cell_pack(&packed, cell);
- crypto_digest_add_bytes(d, packed.body, sizeof(packed.body));
+ cell_pack(&packed, cell, conn->wide_circ_ids);
+ crypto_digest_add_bytes(d, packed.body, cell_network_size);
memwipe(&packed, 0, sizeof(packed));
}
@@ -1778,12 +1805,14 @@ or_handshake_state_record_cell(or_handshake_state_t *state,
* authenticate cell.)
*/
void
-or_handshake_state_record_var_cell(or_handshake_state_t *state,
+or_handshake_state_record_var_cell(or_connection_t *conn,
+ or_handshake_state_t *state,
const var_cell_t *cell,
int incoming)
{
crypto_digest_t *d, **dptr;
- char buf[VAR_CELL_HEADER_SIZE];
+ int n;
+ char buf[VAR_CELL_MAX_HEADER_SIZE];
if (incoming) {
if (!state->digest_received_data)
return;
@@ -1797,8 +1826,8 @@ or_handshake_state_record_var_cell(or_handshake_state_t *state,
d = *dptr;
- var_cell_pack_header(cell, buf);
- crypto_digest_add_bytes(d, buf, sizeof(buf));
+ n = var_cell_pack_header(cell, buf, conn->wide_circ_ids);
+ crypto_digest_add_bytes(d, buf, n);
crypto_digest_add_bytes(d, (const char *)cell->payload, cell->payload_len);
memwipe(buf, 0, sizeof(buf));
@@ -1832,20 +1861,21 @@ void
connection_or_write_cell_to_buf(const cell_t *cell, or_connection_t *conn)
{
packed_cell_t networkcell;
+ size_t cell_network_size = get_cell_network_size(conn->wide_circ_ids);
tor_assert(cell);
tor_assert(conn);
- cell_pack(&networkcell, cell);
+ cell_pack(&networkcell, cell, conn->wide_circ_ids);
- connection_write_to_buf(networkcell.body, CELL_NETWORK_SIZE, TO_CONN(conn));
+ connection_write_to_buf(networkcell.body, cell_network_size, TO_CONN(conn));
/* Touch the channel's active timestamp if there is one */
if (conn->chan)
channel_timestamp_active(TLS_CHAN_TO_BASE(conn->chan));
if (conn->base_.state == OR_CONN_STATE_OR_HANDSHAKING_V3)
- or_handshake_state_record_cell(conn->handshake_state, cell, 0);
+ or_handshake_state_record_cell(conn, conn->handshake_state, cell, 0);
if (cell->command != CELL_PADDING)
conn->timestamp_last_added_nonpadding = approx_time();
@@ -1859,15 +1889,16 @@ void
connection_or_write_var_cell_to_buf(const var_cell_t *cell,
or_connection_t *conn)
{
- char hdr[VAR_CELL_HEADER_SIZE];
+ int n;
+ char hdr[VAR_CELL_MAX_HEADER_SIZE];
tor_assert(cell);
tor_assert(conn);
- var_cell_pack_header(cell, hdr);
- connection_write_to_buf(hdr, sizeof(hdr), TO_CONN(conn));
+ n = var_cell_pack_header(cell, hdr, conn->wide_circ_ids);
+ connection_write_to_buf(hdr, n, TO_CONN(conn));
connection_write_to_buf((char*)cell->payload,
cell->payload_len, TO_CONN(conn));
if (conn->base_.state == OR_CONN_STATE_OR_HANDSHAKING_V3)
- or_handshake_state_record_var_cell(conn->handshake_state, cell, 0);
+ or_handshake_state_record_var_cell(conn, conn->handshake_state, cell, 0);
if (cell->command != CELL_PADDING)
conn->timestamp_last_added_nonpadding = approx_time();
@@ -1920,10 +1951,12 @@ connection_or_process_cells_from_inbuf(or_connection_t *conn)
channel_tls_handle_var_cell(var_cell, conn);
var_cell_free(var_cell);
} else {
- char buf[CELL_NETWORK_SIZE];
+ const int wide_circ_ids = conn->wide_circ_ids;
+ size_t cell_network_size = get_cell_network_size(conn->wide_circ_ids);
+ char buf[CELL_MAX_NETWORK_SIZE];
cell_t cell;
if (connection_get_inbuf_len(TO_CONN(conn))
- < CELL_NETWORK_SIZE) /* whole response available? */
+ < cell_network_size) /* whole response available? */
return 0; /* not yet */
/* Touch the channel's active timestamp if there is one */
@@ -1931,11 +1964,11 @@ connection_or_process_cells_from_inbuf(or_connection_t *conn)
channel_timestamp_active(TLS_CHAN_TO_BASE(conn->chan));
circuit_build_times_network_is_live(&circ_times);
- connection_fetch_from_buf(buf, CELL_NETWORK_SIZE, TO_CONN(conn));
+ connection_fetch_from_buf(buf, cell_network_size, TO_CONN(conn));
/* retrieve cell info from buf (create the host-order struct from the
* network-order string) */
- cell_unpack(&cell, buf);
+ cell_unpack(&cell, buf, wide_circ_ids);
channel_tls_handle_cell(&cell, conn);
}
@@ -1943,7 +1976,7 @@ connection_or_process_cells_from_inbuf(or_connection_t *conn)
}
/** Array of recognized link protocol versions. */
-static const uint16_t or_protocol_versions[] = { 1, 2, 3 };
+static const uint16_t or_protocol_versions[] = { 1, 2, 3, 4 };
/** Number of versions in <b>or_protocol_versions</b>. */
static const int n_or_protocol_versions =
(int)( sizeof(or_protocol_versions)/sizeof(uint16_t) );
diff --git a/src/or/connection_or.h b/src/or/connection_or.h
index 21178774a3..85e68f1a33 100644
--- a/src/or/connection_or.h
+++ b/src/or/connection_or.h
@@ -60,10 +60,12 @@ int connection_or_client_learned_peer_id(or_connection_t *conn,
time_t connection_or_client_used(or_connection_t *conn);
int connection_or_get_num_circuits(or_connection_t *conn);
void or_handshake_state_free(or_handshake_state_t *state);
-void or_handshake_state_record_cell(or_handshake_state_t *state,
+void or_handshake_state_record_cell(or_connection_t *conn,
+ or_handshake_state_t *state,
const cell_t *cell,
int incoming);
-void or_handshake_state_record_var_cell(or_handshake_state_t *state,
+void or_handshake_state_record_var_cell(or_connection_t *conn,
+ or_handshake_state_t *state,
const var_cell_t *cell,
int incoming);
@@ -84,10 +86,14 @@ int connection_or_send_authenticate_cell(or_connection_t *conn, int type);
int is_or_protocol_version_known(uint16_t version);
-void cell_pack(packed_cell_t *dest, const cell_t *src);
-void var_cell_pack_header(const var_cell_t *cell, char *hdr_out);
+void cell_pack(packed_cell_t *dest, const cell_t *src, int wide_circ_ids);
+int var_cell_pack_header(const var_cell_t *cell, char *hdr_out,
+ int wide_circ_ids);
var_cell_t *var_cell_new(uint16_t payload_len);
void var_cell_free(var_cell_t *cell);
+/** DOCDOC */
+#define MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS 4
+
#endif
diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c
index 6b52f3b5d7..af5f91a623 100644
--- a/src/or/cpuworker.c
+++ b/src/or/cpuworker.c
@@ -31,7 +31,7 @@
#define MIN_CPUWORKERS 1
/** The tag specifies which circuit this onionskin was from. */
-#define TAG_LEN 10
+#define TAG_LEN 12
/** How many cpuworkers we have running right now. */
static int num_cpuworkers=0;
@@ -72,7 +72,7 @@ tag_pack(uint8_t *tag, uint64_t chan_id, circid_t circ_id)
/*XXXX RETHINK THIS WHOLE MESS !!!! !NM NM NM NM*/
/*XXXX DOUBLEPLUSTHIS!!!! AS AS AS AS*/
set_uint64(tag, chan_id);
- set_uint16(tag+8, circ_id);
+ set_uint32(tag+8, circ_id);
}
/** Unpack <b>tag</b> into addr, port, and circ_id.
@@ -81,7 +81,7 @@ static void
tag_unpack(const uint8_t *tag, uint64_t *chan_id, circid_t *circ_id)
{
*chan_id = get_uint64(tag);
- *circ_id = get_uint16(tag+8);
+ *circ_id = get_uint32(tag+8);
}
/** Magic numbers to make sure our cpuworker_requests don't grow any
@@ -222,10 +222,10 @@ uint64_t
estimated_usec_for_onionskins(uint32_t n_requests, uint16_t onionskin_type)
{
if (onionskin_type > MAX_ONION_HANDSHAKE_TYPE) /* should be impossible */
- return 1000 * n_requests;
+ return 1000 * (uint64_t)n_requests;
if (PREDICT_UNLIKELY(onionskins_n_processed[onionskin_type] < 100)) {
/* Until we have 100 data points, just asssume everything takes 1 msec. */
- return 1000 * n_requests;
+ return 1000 * (uint64_t)n_requests;
} else {
/* This can't overflow: we'll never have more than 500000 onionskins
* measured in onionskin_usec_internal, and they won't take anything near
diff --git a/src/or/directory.c b/src/or/directory.c
index c101418446..6b61fc6a99 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -472,12 +472,13 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
if (options->UseBridges && type != BRIDGE_DIRINFO) {
/* We want to ask a running bridge for which we have a descriptor.
*
- * Be careful here: we should only ask questions that we know our
- * bridges can answer. So far we're solving that by backing off to
- * the behavior supported by our oldest bridge; see for example
- * any_bridges_dont_support_microdescriptors().
+ * When we ask choose_random_entry() for a bridge, we specify what
+ * sort of dir fetch we'll be doing, so it won't return a bridge
+ * that can't answer our question.
*/
- const node_t *node = choose_random_entry(NULL);
+ /* XXX024 Not all bridges handle conditional consensus downloading,
+ * so, for now, never assume the server supports that. -PP */
+ const node_t *node = choose_random_dirguard(type);
if (node && node->ri) {
/* every bridge has a routerinfo. */
tor_addr_t addr;
diff --git a/src/or/dirvote.c b/src/or/dirvote.c
index 66dc50debe..358708b6c5 100644
--- a/src/or/dirvote.c
+++ b/src/or/dirvote.c
@@ -2121,7 +2121,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
digest, digest_len,
signing_key)) {
log_warn(LD_BUG, "Couldn't sign consensus networkstatus.");
- return NULL; /* This leaks, but it should never happen. */
+ goto done;
}
smartlist_add(chunks, tor_strdup(sigbuf));
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 4ca56cbacf..51c3a56742 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -23,6 +23,7 @@
#include "directory.h"
#include "entrynodes.h"
#include "main.h"
+#include "microdesc.h"
#include "nodelist.h"
#include "policies.h"
#include "router.h"
@@ -829,11 +830,45 @@ entry_list_is_constrained(const or_options_t *options)
return 0;
}
+/** Return true iff this node can answer directory questions about
+ * microdescriptors. */
+static int
+node_understands_microdescriptors(const node_t *node)
+{
+ tor_assert(node);
+ if (node->rs && node->rs->version_supports_microdesc_cache)
+ return 1;
+ if (node->ri && tor_version_supports_microdescriptors(node->ri->platform))
+ return 1;
+ return 0;
+}
+
+/** Return true iff <b>node</b> is able to answer directory questions
+ * of type <b>dirinfo</b>. */
+static int
+node_can_handle_dirinfo(const node_t *node, dirinfo_type_t dirinfo)
+{
+ /* Checking dirinfo for any type other than microdescriptors isn't required
+ yet, since we only choose directory guards that can support microdescs,
+ routerinfos, and networkstatuses, AND we don't use directory guards if
+ we're configured to do direct downloads of anything else. The only case
+ where we might have a guard that doesn't know about a type of directory
+ information is when we're retrieving directory information from a
+ bridge. */
+
+ if ((dirinfo & MICRODESC_DIRINFO) &&
+ !node_understands_microdescriptors(node))
+ return 0;
+ return 1;
+}
+
/** Pick a live (up and listed) entry guard from entry_guards. If
* <b>state</b> is non-NULL, this is for a specific circuit --
* make sure not to pick this circuit's exit or any node in the
* exit's family. If <b>state</b> is NULL, we're looking for a random
- * guard (likely a bridge). */
+ * guard (likely a bridge). If <b>dirinfo</b> is not NO_DIRINFO, then
+ * only select from nodes that know how to answer directory questions
+ * of that type. */
const node_t *
choose_random_entry(cpath_build_state_t *state)
{
@@ -866,12 +901,6 @@ choose_random_entry_impl(cpath_build_state_t *state, int for_directory,
const int num_needed = for_directory ? options->NumDirectoryGuards :
options->NumEntryGuards;
- /* Checking dirinfo_type isn't required yet, since we only choose directory
- guards that can support microdescs, routerinfos, and networkstatuses, AND
- we don't use directory guards if we're configured to do direct downloads
- of anything else. */
- (void) dirinfo_type;
-
if (chosen_exit) {
nodelist_add_node_and_family(exit_family, chosen_exit);
consider_exit_family = 1;
@@ -903,6 +932,9 @@ choose_random_entry_impl(cpath_build_state_t *state, int for_directory,
continue; /* don't pick the same node for entry and exit */
if (consider_exit_family && smartlist_contains(exit_family, node))
continue; /* avoid relays that are family members of our exit */
+ if (dirinfo_type != NO_DIRINFO &&
+ !node_can_handle_dirinfo(node, dirinfo_type))
+ continue; /* this node won't be able to answer our dir questions */
#if 0 /* since EntryNodes is always strict now, this clause is moot */
if (options->EntryNodes &&
!routerset_contains_node(options->EntryNodes, node)) {
@@ -1982,7 +2014,7 @@ int
any_bridge_descriptors_known(void)
{
tor_assert(get_options()->UseBridges);
- return choose_random_entry(NULL)!=NULL ? 1 : 0;
+ return choose_random_entry(NULL) != NULL;
}
/** Return 1 if there are any directory conns fetching bridge descriptors
@@ -2064,29 +2096,24 @@ entries_retry_all(const or_options_t *options)
entries_retry_helper(options, 1);
}
-/** Return true if we've ever had a bridge running a Tor version that can't
- * provide microdescriptors to us. In that case fall back to asking for
- * full descriptors. Eventually all bridges will support microdescriptors
- * and we can take this check out; see bug 4013. */
+/** Return true if at least one of our bridges runs a Tor version that can
+ * provide microdescriptors to us. If not, we'll fall back to asking for
+ * full descriptors. */
int
-any_bridges_dont_support_microdescriptors(void)
+any_bridge_supports_microdescriptors(void)
{
const node_t *node;
- static int ever_answered_yes = 0;
if (!get_options()->UseBridges || !entry_guards)
return 0;
- if (ever_answered_yes)
- return 1; /* if we ever answer 'yes', always answer 'yes' */
SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) {
node = node_get_by_id(e->identity);
- if (node && node->ri &&
+ if (node && node->is_running &&
node_is_bridge(node) && node_is_a_configured_bridge(node) &&
- !tor_version_supports_microdescriptors(node->ri->platform)) {
+ node_understands_microdescriptors(node)) {
/* This is one of our current bridges, and we know enough about
- * it to know that it won't be able to answer our microdescriptor
+ * it to know that it will be able to answer our microdescriptor
* questions. */
- ever_answered_yes = 1;
- return 1;
+ return 1;
}
} SMARTLIST_FOREACH_END(e);
return 0;
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index b673d02681..52b8dc00e4 100644
--- a/src/or/entrynodes.h
+++ b/src/or/entrynodes.h
@@ -108,7 +108,7 @@ 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);
-int any_bridges_dont_support_microdescriptors(void);
+int any_bridge_supports_microdescriptors(void);
void entry_guards_free_all(void);
diff --git a/src/or/main.c b/src/or/main.c
index aa601e5a4f..b5d1e2da34 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -1157,7 +1157,6 @@ run_scheduled_events(time_t now)
static time_t time_to_check_v3_certificate = 0;
static time_t time_to_check_listeners = 0;
static time_t time_to_check_descriptor = 0;
- static time_t time_to_check_ipaddress = 0;
static time_t time_to_shrink_memory = 0;
static time_t time_to_try_getting_descriptors = 0;
static time_t time_to_reset_descriptor_failures = 0;
@@ -1403,11 +1402,10 @@ run_scheduled_events(time_t now)
/** 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 way
- * that would require an upload? */
+/** How often do we check whether part of our router info has changed in a
+ * way that would require an upload? That includes checking whether our IP
+ * address has changed. */
#define CHECK_DESCRIPTOR_INTERVAL (60)
-/** How often do we (as a router) check whether our IP address has changed? */
-#define CHECK_IPADDRESS_INTERVAL (15*60)
/* 2b. Once per minute, regenerate and upload the descriptor if the old
* one is inaccurate. */
@@ -1415,10 +1413,7 @@ run_scheduled_events(time_t now)
static int dirport_reachability_count = 0;
time_to_check_descriptor = now + CHECK_DESCRIPTOR_INTERVAL;
check_descriptor_bandwidth_changed(now);
- if (time_to_check_ipaddress < now) {
- time_to_check_ipaddress = now + CHECK_IPADDRESS_INTERVAL;
- check_descriptor_ipaddress_changed(now);
- }
+ check_descriptor_ipaddress_changed(now);
mark_my_descriptor_dirty_if_too_old(now);
consider_publishable_server(0);
/* also, check religiously for reachability, if it's within the first
diff --git a/src/or/microdesc.c b/src/or/microdesc.c
index e99b3ebe78..ac48930faf 100644
--- a/src/or/microdesc.c
+++ b/src/or/microdesc.c
@@ -730,9 +730,9 @@ we_use_microdescriptors_for_circuits(const or_options_t *options)
int ret = options->UseMicrodescriptors;
if (ret == -1) {
/* UseMicrodescriptors is "auto"; we need to decide: */
- /* If we are configured to use bridges and one of our bridges doesn't
+ /* If we are configured to use bridges and none of our bridges
* know what a microdescriptor is, the answer is no. */
- if (options->UseBridges && any_bridges_dont_support_microdescriptors())
+ if (options->UseBridges && !any_bridge_supports_microdescriptors())
return 0;
/* Otherwise, we decide that we'll use microdescriptors iff we are
* not a server, and we're not autofetching everything. */
diff --git a/src/or/or.h b/src/or/or.h
index 04640d050a..d9da49d32d 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -869,11 +869,29 @@ typedef enum {
/** Number of bytes in a cell, minus cell header. */
#define CELL_PAYLOAD_SIZE 509
-/** Number of bytes in a cell transmitted over the network. */
-#define CELL_NETWORK_SIZE 512
+/** Number of bytes in a cell transmitted over the network, in the longest
+ * form */
+#define CELL_MAX_NETWORK_SIZE 514
-/** Length of a header on a variable-length cell. */
-#define VAR_CELL_HEADER_SIZE 5
+/** Maximum length of a header on a variable-length cell. */
+#define VAR_CELL_MAX_HEADER_SIZE 7
+
+static int get_cell_network_size(int wide_circ_ids);
+static INLINE int get_cell_network_size(int wide_circ_ids)
+{
+ return wide_circ_ids ? CELL_MAX_NETWORK_SIZE : CELL_MAX_NETWORK_SIZE - 2;
+}
+static int get_var_cell_header_size(int wide_circ_ids);
+static INLINE int get_var_cell_header_size(int wide_circ_ids)
+{
+ return wide_circ_ids ? VAR_CELL_MAX_HEADER_SIZE :
+ VAR_CELL_MAX_HEADER_SIZE - 2;
+}
+static int get_circ_id_size(int wide_circ_ids);
+static INLINE int get_circ_id_size(int wide_circ_ids)
+{
+ return wide_circ_ids ? 4 : 2;
+}
/** Number of bytes in a relay cell's header (not including general cell
* header). */
@@ -882,7 +900,7 @@ typedef enum {
#define RELAY_PAYLOAD_SIZE (CELL_PAYLOAD_SIZE-RELAY_HEADER_SIZE)
/** Identifies a circuit on an or_connection */
-typedef uint16_t circid_t;
+typedef uint32_t circid_t;
/** Identifies a stream on a circuit */
typedef uint16_t streamid_t;
@@ -1051,7 +1069,7 @@ typedef struct var_cell_t {
/** A cell as packed for writing to the network. */
typedef struct packed_cell_t {
struct packed_cell_t *next; /**< Next cell queued on this circuit. */
- char body[CELL_NETWORK_SIZE]; /**< Cell as packed for network. */
+ char body[CELL_MAX_NETWORK_SIZE]; /**< Cell as packed for network. */
} packed_cell_t;
/** Number of cells added to a circuit queue including their insertion
@@ -1400,6 +1418,7 @@ typedef struct or_connection_t {
/** True iff this is an outgoing connection. */
unsigned int is_outgoing:1;
unsigned int proxy_type:2; /**< One of PROXY_NONE...PROXY_SOCKS5 */
+ unsigned int wide_circ_ids:1;
uint8_t link_proto; /**< What protocol version are we using? 0 for
* "none negotiated yet." */
diff --git a/src/or/relay.c b/src/or/relay.c
index 22bc40d655..9ff9e1e1f4 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -2064,10 +2064,10 @@ dump_cell_pool_usage(int severity)
/** Allocate a new copy of packed <b>cell</b>. */
static INLINE packed_cell_t *
-packed_cell_copy(const cell_t *cell)
+packed_cell_copy(const cell_t *cell, int wide_circ_ids)
{
packed_cell_t *c = packed_cell_new();
- cell_pack(c, cell);
+ cell_pack(c, cell, wide_circ_ids);
c->next = NULL;
return c;
}
@@ -2089,9 +2089,10 @@ cell_queue_append(cell_queue_t *queue, packed_cell_t *cell)
/** Append a newly allocated copy of <b>cell</b> to the end of <b>queue</b> */
void
-cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell)
+cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell,
+ int wide_circ_ids)
{
- packed_cell_t *copy = packed_cell_copy(cell);
+ packed_cell_t *copy = packed_cell_copy(cell, wide_circ_ids);
/* Remember the time when this cell was put in the queue. */
if (get_options()->CellStatistics) {
struct timeval now;
@@ -2423,7 +2424,7 @@ append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
streams_blocked = circ->streams_blocked_on_p_chan;
}
- cell_queue_append_packed_copy(queue, cell);
+ cell_queue_append_packed_copy(queue, cell, chan->wide_circ_ids);
/* If we have too many cells on the circuit, we should stop reading from
* the edge streams for a while. */
diff --git a/src/or/relay.h b/src/or/relay.h
index 9e2d8af1e9..7e59838f95 100644
--- a/src/or/relay.h
+++ b/src/or/relay.h
@@ -46,7 +46,8 @@ void packed_cell_free(packed_cell_t *cell);
void cell_queue_clear(cell_queue_t *queue);
void cell_queue_append(cell_queue_t *queue, packed_cell_t *cell);
-void cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell);
+void cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell,
+ int wide_circ_ids);
void append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
cell_t *cell, cell_direction_t direction,
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 10d232c039..a066e02024 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -1119,11 +1119,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
crypt_path_t *cpath = NULL;
char hexcookie[9];
int circ_needs_uptime;
- char intro_key_digest[DIGEST_LEN];
- size_t auth_len = 0;
- char auth_data[REND_DESC_COOKIE_LEN];
time_t now = time(NULL);
- char diffie_hellman_hash[DIGEST_LEN];
time_t elapsed;
int replay;
@@ -1296,8 +1292,9 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
/* If the service performs client authorization, check included auth data. */
if (service->clients) {
- if (auth_len > 0) {
- if (rend_check_authorization(service, auth_data)) {
+ if (parsed_req->version == 3 && parsed_req->u.v3.auth_len > 0) {
+ if (rend_check_authorization(service,
+ (const char*)parsed_req->u.v3.auth_data)) {
log_info(LD_REND, "Authorization data in INTRODUCE2 cell are valid.");
} else {
log_info(LD_REND, "The authorization data that are contained in "
@@ -1410,9 +1407,6 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
memwipe(buf, 0, sizeof(buf));
memwipe(serviceid, 0, sizeof(serviceid));
memwipe(hexcookie, 0, sizeof(hexcookie));
- memwipe(intro_key_digest, 0, sizeof(intro_key_digest));
- memwipe(auth_data, 0, sizeof(auth_data));
- memwipe(diffie_hellman_hash, 0, sizeof(diffie_hellman_hash));
/* Free the parsed cell */
if (parsed_req) {
diff --git a/src/or/rephist.c b/src/or/rephist.c
index 1bee6459cc..55f321d5ff 100644
--- a/src/or/rephist.c
+++ b/src/or/rephist.c
@@ -310,9 +310,10 @@ rep_hist_note_router_reachable(const char *id, const tor_addr_t *at_addr,
tor_assert(hist);
tor_assert((!at_addr && !at_port) || (at_addr && at_port));
- addr_changed = at_addr &&
+ addr_changed = at_addr && !tor_addr_is_null(&hist->last_reached_addr) &&
tor_addr_compare(at_addr, &hist->last_reached_addr, CMP_EXACT) != 0;
- port_changed = at_port && at_port != hist->last_reached_port;
+ port_changed = at_port && hist->last_reached_port &&
+ at_port != hist->last_reached_port;
if (!started_tracking_stability)
started_tracking_stability = time(NULL);
diff --git a/src/or/router.c b/src/or/router.c
index 4492ed271f..1f372711cc 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -1192,7 +1192,8 @@ router_dirport_found_reachable(void)
void
router_perform_bandwidth_test(int num_circs, time_t now)
{
- int num_cells = (int)(get_options()->BandwidthRate * 10 / CELL_NETWORK_SIZE);
+ int num_cells = (int)(get_options()->BandwidthRate * 10 /
+ CELL_MAX_NETWORK_SIZE);
int max_cells = num_cells < CIRCWINDOW_START ?
num_cells : CIRCWINDOW_START;
int cells_per_circuit = max_cells / num_circs;
@@ -1712,7 +1713,9 @@ static int router_guess_address_from_dir_headers(uint32_t *guess);
int
router_pick_published_address(const or_options_t *options, uint32_t *addr)
{
- if (resolve_my_address(LOG_INFO, options, addr, NULL, NULL) < 0) {
+ *addr = get_last_resolved_addr();
+ if (!*addr &&
+ resolve_my_address(LOG_INFO, options, addr, NULL, NULL) < 0) {
log_info(LD_CONFIG, "Could not determine our address locally. "
"Checking if directory headers provide any hints.");
if (router_guess_address_from_dir_headers(addr) < 0) {
@@ -2159,7 +2162,9 @@ router_new_address_suggestion(const char *suggestion,
}
/* XXXX ipv6 */
- if (resolve_my_address(LOG_INFO, options, &cur, NULL, NULL) >= 0) {
+ cur = get_last_resolved_addr();
+ if (cur ||
+ resolve_my_address(LOG_INFO, options, &cur, NULL, NULL) >= 0) {
/* We're all set -- we already know our address. Great. */
tor_addr_from_ipv4h(&last_guessed_ip, cur); /* store it in case we
need it later */
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 90b707bcdb..2f08167f18 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -3951,7 +3951,8 @@ trusted_dir_server_new(const char *nickname, const char *address,
dir_server_t *result;
if (!address) { /* The address is us; we should guess. */
- if (resolve_my_address(LOG_WARN, get_options(), &a, NULL, &hostname) < 0) {
+ if (resolve_my_address(LOG_WARN, get_options(),
+ &a, NULL, &hostname) < 0) {
log_warn(LD_CONFIG,
"Couldn't find a suitable address when adding ourself as a "
"trusted directory server.");
diff --git a/src/test/test.c b/src/test/test.c
index be0737ceb7..6c64d35990 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -1678,6 +1678,7 @@ test_geoip(void)
* the connecting clients added above. */
geoip_bridge_stats_init(now);
s = geoip_format_bridge_stats(now + 86400);
+ test_assert(s);
test_streq(bridge_stats_1, s);
tor_free(s);
diff --git a/src/test/test_util.c b/src/test/test_util.c
index b17e414255..c2cb4448e6 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -2713,7 +2713,7 @@ test_util_join_win_cmdline(void *ptr)
};
int i;
- char *joined_argv;
+ char *joined_argv = NULL;
(void)ptr;
diff --git a/src/tools/tor-resolve.c b/src/tools/tor-resolve.c
index 9b3aa98d1d..306f6c66ab 100644
--- a/src/tools/tor-resolve.c
+++ b/src/tools/tor-resolve.c
@@ -201,7 +201,7 @@ do_resolve(const char *hostname, uint32_t sockshost, uint16_t socksport,
s = tor_open_socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
if (s<0) {
log_sock_error("creating_socket", -1);
- goto err;
+ return -1;
}
memset(&socksaddr, 0, sizeof(socksaddr));