aboutsummaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
Diffstat (limited to 'src/or')
-rw-r--r--src/or/buffers.c2
-rw-r--r--src/or/circuitbuild.c13
-rw-r--r--src/or/circuitbuild.h2
-rw-r--r--src/or/command.c17
-rw-r--r--src/or/config.c4
-rw-r--r--src/or/connection_edge.c26
-rw-r--r--src/or/connection_edge.h2
-rw-r--r--src/or/connection_or.c5
-rw-r--r--src/or/control.c3
-rw-r--r--src/or/dirserv.c16
-rw-r--r--src/or/hibernate.c28
-rw-r--r--src/or/main.c3
-rw-r--r--src/or/onion.c14
-rw-r--r--src/or/onion.h12
-rw-r--r--src/or/or.h6
-rw-r--r--src/or/relay.c84
-rw-r--r--src/or/relay.h10
-rw-r--r--src/or/rendclient.c13
-rw-r--r--src/or/rendclient.h9
-rw-r--r--src/or/rendcommon.c2
-rw-r--r--src/or/rendcommon.h3
-rw-r--r--src/or/rendmid.c30
-rw-r--r--src/or/rendmid.h8
-rw-r--r--src/or/rendservice.c9
-rw-r--r--src/or/rendservice.h4
-rw-r--r--src/or/rephist.c148
-rw-r--r--src/or/router.c2
27 files changed, 298 insertions, 177 deletions
diff --git a/src/or/buffers.c b/src/or/buffers.c
index 658a924cef..f84fb45c64 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -1048,7 +1048,7 @@ fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto)
result->circ_id = ntohs(get_uint16(hdr));
buf_remove_from_front(buf, VAR_CELL_HEADER_SIZE);
- peek_from_buf(result->payload, length, buf);
+ peek_from_buf((char*) result->payload, length, buf);
buf_remove_from_front(buf, length);
check();
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 473b28e872..2fe750ea5b 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -1902,7 +1902,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
* and a DH operation. */
cell_type = CELL_CREATE_FAST;
memset(payload, 0, sizeof(payload));
- crypto_rand(circ->cpath->fast_handshake_state,
+ crypto_rand((char*) circ->cpath->fast_handshake_state,
sizeof(circ->cpath->fast_handshake_state));
memcpy(payload, circ->cpath->fast_handshake_state,
sizeof(circ->cpath->fast_handshake_state));
@@ -2081,8 +2081,8 @@ circuit_extend(cell_t *cell, circuit_t *circ)
n_addr32 = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE));
n_port = ntohs(get_uint16(cell->payload+RELAY_HEADER_SIZE+4));
- onionskin = cell->payload+RELAY_HEADER_SIZE+4+2;
- id_digest = cell->payload+RELAY_HEADER_SIZE+4+2+ONIONSKIN_CHALLENGE_LEN;
+ onionskin = (char*) cell->payload+RELAY_HEADER_SIZE+4+2;
+ id_digest = (char*) cell->payload+RELAY_HEADER_SIZE+4+2+ONIONSKIN_CHALLENGE_LEN;
tor_addr_from_ipv4h(&n_addr, n_addr32);
if (!n_port || !n_addr32) {
@@ -2220,7 +2220,7 @@ circuit_init_cpath_crypto(crypt_path_t *cpath, const char *key_data,
*/
int
circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type,
- const char *reply)
+ const uint8_t *reply)
{
char keys[CPATH_KEY_MATERIAL_LEN];
crypt_path_t *hop;
@@ -2237,7 +2237,7 @@ circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type,
tor_assert(hop->state == CPATH_STATE_AWAITING_KEYS);
if (reply_type == CELL_CREATED && hop->dh_handshake_state) {
- if (onion_skin_client_handshake(hop->dh_handshake_state, reply, keys,
+ if (onion_skin_client_handshake(hop->dh_handshake_state, (char*)reply, keys,
DIGEST_LEN*2+CIPHER_KEY_LEN*2) < 0) {
log_warn(LD_CIRC,"onion_skin_client_handshake failed.");
return -END_CIRC_REASON_TORPROTOCOL;
@@ -2245,7 +2245,8 @@ circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type,
/* Remember hash of g^xy */
memcpy(hop->handshake_digest, reply+DH_KEY_LEN, DIGEST_LEN);
} else if (reply_type == CELL_CREATED_FAST && !hop->dh_handshake_state) {
- if (fast_client_handshake(hop->fast_handshake_state, reply, keys,
+ if (fast_client_handshake(hop->fast_handshake_state, reply,
+ (uint8_t*)keys,
DIGEST_LEN*2+CIPHER_KEY_LEN*2) < 0) {
log_warn(LD_CIRC,"fast_client_handshake failed.");
return -END_CIRC_REASON_TORPROTOCOL;
diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h
index 888bf9d255..a85c410133 100644
--- a/src/or/circuitbuild.h
+++ b/src/or/circuitbuild.h
@@ -31,7 +31,7 @@ int circuit_extend(cell_t *cell, circuit_t *circ);
int circuit_init_cpath_crypto(crypt_path_t *cpath, const char *key_data,
int reverse);
int circuit_finish_handshake(origin_circuit_t *circ, uint8_t cell_type,
- const char *reply);
+ const uint8_t *reply);
int circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer);
int onionskin_answer(or_circuit_t *circ, uint8_t cell_type,
const char *payload, const char *keys);
diff --git a/src/or/command.c b/src/or/command.c
index ea0bbea1e5..beb5d09a9d 100644
--- a/src/or/command.c
+++ b/src/or/command.c
@@ -306,7 +306,8 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn)
char keys[CPATH_KEY_MATERIAL_LEN];
char reply[DIGEST_LEN*2];
tor_assert(cell->command == CELL_CREATE_FAST);
- if (fast_server_handshake(cell->payload, reply, keys, sizeof(keys))<0) {
+ if (fast_server_handshake(cell->payload, (uint8_t*)reply,
+ (uint8_t*)keys, sizeof(keys))<0) {
log_warn(LD_OR,"Failed to generate key material. Closing.");
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
return;
@@ -353,7 +354,7 @@ command_process_created_cell(cell_t *cell, or_connection_t *conn)
int err_reason = 0;
log_debug(LD_OR,"at OP. Finishing handshake.");
if ((err_reason = circuit_finish_handshake(origin_circ, cell->command,
- cell->payload)) < 0) {
+ cell->payload)) < 0) {
log_warn(LD_OR,"circuit_finish_handshake failed.");
circuit_mark_for_close(circ, -err_reason);
return;
@@ -369,7 +370,7 @@ command_process_created_cell(cell_t *cell, or_connection_t *conn)
log_debug(LD_OR,
"Converting created cell to extended relay cell, sending.");
relay_send_command_from_edge(0, circ, RELAY_COMMAND_EXTENDED,
- cell->payload, ONIONSKIN_REPLY_LEN,
+ (char*)cell->payload, ONIONSKIN_REPLY_LEN,
NULL);
}
}
@@ -499,7 +500,7 @@ static void
command_process_versions_cell(var_cell_t *cell, or_connection_t *conn)
{
int highest_supported_version = 0;
- const char *cp, *end;
+ const uint8_t *cp, *end;
if (conn->link_proto != 0 ||
conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING ||
(conn->handshake_state && conn->handshake_state->received_versions)) {
@@ -553,8 +554,8 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn)
time_t timestamp;
uint8_t my_addr_type;
uint8_t my_addr_len;
- const char *my_addr_ptr;
- const char *cp, *end;
+ const uint8_t *my_addr_ptr;
+ const uint8_t *cp, *end;
uint8_t n_other_addrs;
time_t now = time(NULL);
@@ -582,7 +583,7 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn)
my_addr_type = (uint8_t) cell->payload[4];
my_addr_len = (uint8_t) cell->payload[5];
- my_addr_ptr = cell->payload + 6;
+ my_addr_ptr = (uint8_t*) cell->payload + 6;
end = cell->payload + CELL_PAYLOAD_SIZE;
cp = cell->payload + 6 + my_addr_len;
if (cp >= end) {
@@ -599,7 +600,7 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn)
/* Consider all the other addresses; if any matches, this connection is
* "canonical." */
tor_addr_t addr;
- const char *next = decode_address_from_payload(&addr, cp, (int)(end-cp));
+ const uint8_t *next = decode_address_from_payload(&addr, cp, (int)(end-cp));
if (next == NULL) {
log_fn(LOG_PROTOCOL_WARN, LD_OR,
"Bad address in netinfo cell; closing connection.");
diff --git a/src/or/config.c b/src/or/config.c
index bd8c45758b..7fea8500b2 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -787,9 +787,9 @@ add_default_trusted_dir_authorities(authority_type_t type)
"4A0C CD2D DC79 9508 3D73 F5D6 6710 0C8A 5831 F16D",
"ides orport=9090 no-v2 v3ident=27B6B5996C426270A5C95488AA5BCEB6BCC86956 "
"216.224.124.114:9030 F397 038A DC51 3361 35E7 B80B D99C A384 4360 292B",
- "gabelmoo orport=8080 no-v2 "
+ "gabelmoo orport=443 no-v2 "
"v3ident=ED03BB616EB2F60BEC80151114BB25CEF515B226 "
- "80.190.246.100:8180 F204 4413 DAC2 E02E 3D6B CF47 35A1 9BCA 1DE9 7281",
+ "212.112.245.170:80 F204 4413 DAC2 E02E 3D6B CF47 35A1 9BCA 1DE9 7281",
"dannenberg orport=443 no-v2 "
"v3ident=585769C78764D58426B8B52B6651A5A71137189A "
"193.23.244.244:80 7BE6 83E6 5D48 1413 21C5 ED92 F075 C553 64AC 7123",
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index cc040b1780..2bfa88e6a9 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -1492,7 +1492,8 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
tor_snprintf(socks->address, sizeof(socks->address), "REVERSE[%s]",
orig_address);
connection_ap_handshake_socks_resolved(conn, RESOLVED_TYPE_HOSTNAME,
- strlen(result), result, -1,
+ strlen(result), (uint8_t*)result,
+ -1,
map_expires);
connection_mark_unattached_ap(conn,
END_STREAM_REASON_DONE |
@@ -1613,7 +1614,8 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
/* remember _what_ is supposed to have been resolved. */
strlcpy(socks->address, orig_address, sizeof(socks->address));
connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_IPV4,4,
- (char*)&answer,-1,map_expires);
+ (uint8_t*)&answer,
+ -1,map_expires);
connection_mark_unattached_ap(conn,
END_STREAM_REASON_DONE |
END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
@@ -2318,7 +2320,7 @@ void
connection_ap_handshake_socks_resolved(edge_connection_t *conn,
int answer_type,
size_t answer_len,
- const char *answer,
+ const uint8_t *answer,
int ttl,
time_t expires)
{
@@ -2332,7 +2334,7 @@ connection_ap_handshake_socks_resolved(edge_connection_t *conn,
client_dns_set_addressmap(conn->socks_request->address, a,
conn->chosen_exit_name, ttl);
} else if (answer_type == RESOLVED_TYPE_HOSTNAME && answer_len < 256) {
- char *cp = tor_strndup(answer, answer_len);
+ char *cp = tor_strndup((char*)answer, answer_len);
client_dns_set_reverse_addressmap(conn->socks_request->address,
cp,
conn->chosen_exit_name, ttl);
@@ -2343,14 +2345,14 @@ connection_ap_handshake_socks_resolved(edge_connection_t *conn,
if (conn->is_dns_request) {
if (conn->dns_server_request) {
/* We had a request on our DNS port: answer it. */
- dnsserv_resolved(conn, answer_type, answer_len, answer, ttl);
+ dnsserv_resolved(conn, answer_type, answer_len, (char*)answer, ttl);
conn->socks_request->has_finished = 1;
return;
} else {
/* This must be a request from the controller. We already sent
* a mapaddress if there's a ttl. */
tell_controller_about_resolved_result(conn, answer_type, answer_len,
- answer, ttl, expires);
+ (char*)answer, ttl, expires);
conn->socks_request->has_finished = 1;
return;
}
@@ -2495,6 +2497,8 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
or_circ = TO_OR_CIRCUIT(circ);
relay_header_unpack(&rh, cell->payload);
+ if (rh.length > RELAY_PAYLOAD_SIZE)
+ return -1;
/* Note: we have to use relay_send_command_from_edge here, not
* connection_edge_end or connection_edge_send_command, since those require
@@ -2518,7 +2522,8 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
END_STREAM_REASON_TORPROTOCOL, NULL);
return 0;
}
- if (parse_addr_port(LOG_PROTOCOL_WARN, cell->payload+RELAY_HEADER_SIZE,
+ if (parse_addr_port(LOG_PROTOCOL_WARN,
+ (char*)(cell->payload+RELAY_HEADER_SIZE),
&address,NULL,&port)<0) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Unable to parse addr:port in relay begin cell. Closing.");
@@ -2683,6 +2688,8 @@ connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ)
assert_circuit_ok(TO_CIRCUIT(circ));
relay_header_unpack(&rh, cell->payload);
+ if (rh.length > RELAY_PAYLOAD_SIZE)
+ return -1;
/* This 'dummy_conn' only exists to remember the stream ID
* associated with the resolve request; and to make the
@@ -2693,8 +2700,9 @@ connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ)
*/
dummy_conn = edge_connection_new(CONN_TYPE_EXIT, AF_INET);
dummy_conn->stream_id = rh.stream_id;
- dummy_conn->_base.address = tor_strndup(cell->payload+RELAY_HEADER_SIZE,
- rh.length);
+ dummy_conn->_base.address = tor_strndup(
+ (char*)cell->payload+RELAY_HEADER_SIZE,
+ rh.length);
dummy_conn->_base.port = 0;
dummy_conn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED;
dummy_conn->_base.purpose = EXIT_PURPOSE_RESOLVE;
diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h
index 762af5172e..cca82022c3 100644
--- a/src/or/connection_edge.h
+++ b/src/or/connection_edge.h
@@ -38,7 +38,7 @@ void connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
void connection_ap_handshake_socks_resolved(edge_connection_t *conn,
int answer_type,
size_t answer_len,
- const char *answer,
+ const uint8_t *answer,
int ttl,
time_t expires);
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index 415a48dca3..45266a99b1 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -1259,7 +1259,8 @@ connection_or_write_var_cell_to_buf(const var_cell_t *cell,
tor_assert(conn);
var_cell_pack_header(cell, hdr);
connection_write_to_buf(hdr, sizeof(hdr), TO_CONN(conn));
- connection_write_to_buf(cell->payload, cell->payload_len, TO_CONN(conn));
+ connection_write_to_buf((char*)cell->payload,
+ cell->payload_len, TO_CONN(conn));
if (cell->command != CELL_PADDING)
conn->timestamp_last_added_nonpadding = approx_time();
}
@@ -1388,7 +1389,7 @@ connection_or_send_netinfo(or_connection_t *conn)
time_t now = time(NULL);
routerinfo_t *me;
int len;
- char *out;
+ uint8_t *out;
memset(&cell, 0, sizeof(cell_t));
cell.command = CELL_NETINFO;
diff --git a/src/or/control.c b/src/or/control.c
index 4d505a98fb..ad316c4ebc 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -2855,9 +2855,10 @@ connection_control_process_inbuf(control_connection_t *conn)
&& !TOR_ISSPACE(conn->incoming_cmd[cmd_len]))
++cmd_len;
- data_len -= cmd_len;
conn->incoming_cmd[cmd_len]='\0';
args = conn->incoming_cmd+cmd_len+1;
+ tor_assert(data_len>(size_t)cmd_len);
+ data_len -= (cmd_len+1); /* skip the command and NUL we added after it */
while (*args == ' ' || *args == '\t') {
++args;
--data_len;
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 42d7d561ce..841c86624b 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -386,13 +386,19 @@ 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));
- /* Tor 0.1.2.x is pretty old, but there are a lot of them running still,
- * and there aren't any critical relay-side vulnerabilities. Once more
- * of them die off, we should raise this minimum to 0.2.0.x. */
- if (platform && !tor_version_as_new_as(platform,"0.1.2.14")) {
+ /* Tor 0.2.0.26-rc is the oldest version that currently caches the right
+ * directory information. Once more of them die off, we should raise this
+ * minimum. */
+ if (platform && !tor_version_as_new_as(platform,"0.2.0.26-rc")) {
if (msg)
*msg = "Tor version is far too old to work.";
return FP_REJECT;
+ } else if (platform && tor_version_as_new_as(platform,"0.2.1.3-alpha")
+ && !tor_version_as_new_as(platform, "0.2.1.19")) {
+ /* These versions mishandled RELAY_EARLY cells on rend circuits. */
+ if (msg)
+ *msg = "Tor version is too buggy to work.";
+ return FP_REJECT;
}
result = dirserv_get_name_status(id_digest, nickname);
@@ -1160,7 +1166,7 @@ directory_fetches_from_authorities(or_options_t *options)
return 0;
if (server_mode(options) && router_pick_published_address(options, &addr)<0)
return 1; /* we don't know our IP address; ask an authority. */
- refuseunknown = router_my_exit_policy_is_reject_star() &&
+ refuseunknown = ! router_my_exit_policy_is_reject_star() &&
should_refuse_unknown_exits(options);
if (options->DirPort == 0 && !refuseunknown)
return 0;
diff --git a/src/or/hibernate.c b/src/or/hibernate.c
index e9be5930d1..929c1994c3 100644
--- a/src/or/hibernate.c
+++ b/src/or/hibernate.c
@@ -515,7 +515,6 @@ accounting_run_housekeeping(time_t now)
static void
accounting_set_wakeup_time(void)
{
- char buf[ISO_TIME_LEN+1];
char digest[DIGEST_LEN];
crypto_digest_env_t *d_env;
int time_in_interval;
@@ -529,21 +528,26 @@ accounting_set_wakeup_time(void)
}
}
- format_iso_time(buf, interval_start_time);
- crypto_pk_get_digest(get_server_identity_key(), digest);
+ if (server_identity_key_is_set()) {
+ char buf[ISO_TIME_LEN+1];
+ format_iso_time(buf, interval_start_time);
- d_env = crypto_new_digest_env();
- crypto_digest_add_bytes(d_env, buf, ISO_TIME_LEN);
- crypto_digest_add_bytes(d_env, digest, DIGEST_LEN);
- crypto_digest_get_digest(d_env, digest, DIGEST_LEN);
- crypto_free_digest_env(d_env);
+ crypto_pk_get_digest(get_server_identity_key(), digest);
+
+ d_env = crypto_new_digest_env();
+ crypto_digest_add_bytes(d_env, buf, ISO_TIME_LEN);
+ crypto_digest_add_bytes(d_env, digest, DIGEST_LEN);
+ crypto_digest_get_digest(d_env, digest, DIGEST_LEN);
+ crypto_free_digest_env(d_env);
+ } else {
+ crypto_rand(digest, DIGEST_LEN);
+ }
if (!expected_bandwidth_usage) {
char buf1[ISO_TIME_LEN+1];
char buf2[ISO_TIME_LEN+1];
format_local_iso_time(buf1, interval_start_time);
format_local_iso_time(buf2, interval_end_time);
- time_to_exhaust_bw = GUESS_TIME_TO_USE_BANDWIDTH;
interval_wakeup_time = interval_start_time;
log_notice(LD_ACCT,
@@ -558,8 +562,8 @@ accounting_set_wakeup_time(void)
time_to_exhaust_bw =
(get_options()->AccountingMax/expected_bandwidth_usage)*60;
- if (time_to_exhaust_bw > TIME_MAX) {
- time_to_exhaust_bw = TIME_MAX;
+ if (time_to_exhaust_bw > INT_MAX) {
+ time_to_exhaust_bw = INT_MAX;
time_to_consider = 0;
} else {
time_to_consider = time_in_interval - (int)time_to_exhaust_bw;
@@ -577,8 +581,6 @@ accounting_set_wakeup_time(void)
* to be chosen than the last half. */
interval_wakeup_time = interval_start_time +
(get_uint32(digest) % time_to_consider);
-
- format_iso_time(buf, interval_wakeup_time);
}
{
diff --git a/src/or/main.c b/src/or/main.c
index 9bdbbc17a6..e13215bd2e 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -893,6 +893,9 @@ run_scheduled_events(time_t now)
signewnym_impl(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,
* shut down and restart all cpuworkers, and update the directory if
* necessary.
diff --git a/src/or/onion.c b/src/or/onion.c
index fa001656e6..4d14f9095b 100644
--- a/src/or/onion.c
+++ b/src/or/onion.c
@@ -349,9 +349,9 @@ onion_skin_client_handshake(crypto_dh_env_t *handshake_state,
* Return 0 on success, &lt;0 on failure.
**/
int
-fast_server_handshake(const char *key_in, /* DIGEST_LEN bytes */
- char *handshake_reply_out, /* DIGEST_LEN*2 bytes */
- char *key_out,
+fast_server_handshake(const uint8_t *key_in, /* DIGEST_LEN bytes */
+ uint8_t *handshake_reply_out, /* DIGEST_LEN*2 bytes */
+ uint8_t *key_out,
size_t key_out_len)
{
char tmp[DIGEST_LEN+DIGEST_LEN];
@@ -359,7 +359,7 @@ fast_server_handshake(const char *key_in, /* DIGEST_LEN bytes */
size_t out_len;
int r = -1;
- if (crypto_rand(handshake_reply_out, DIGEST_LEN)<0)
+ if (crypto_rand((char*)handshake_reply_out, DIGEST_LEN)<0)
return -1;
memcpy(tmp, key_in, DIGEST_LEN);
@@ -392,9 +392,9 @@ fast_server_handshake(const char *key_in, /* DIGEST_LEN bytes */
* and protected by TLS).
*/
int
-fast_client_handshake(const char *handshake_state, /* DIGEST_LEN bytes */
- const char *handshake_reply_out, /* DIGEST_LEN*2 bytes */
- char *key_out,
+fast_client_handshake(const uint8_t *handshake_state, /* DIGEST_LEN bytes */
+ const uint8_t *handshake_reply_out, /* DIGEST_LEN*2 bytes */
+ uint8_t *key_out,
size_t key_out_len)
{
char tmp[DIGEST_LEN+DIGEST_LEN];
diff --git a/src/or/onion.h b/src/or/onion.h
index e84dbb47be..e097dcdbb3 100644
--- a/src/or/onion.h
+++ b/src/or/onion.h
@@ -32,14 +32,14 @@ int onion_skin_client_handshake(crypto_dh_env_t *handshake_state,
char *key_out,
size_t key_out_len);
-int fast_server_handshake(const char *key_in,
- char *handshake_reply_out,
- char *key_out,
+int fast_server_handshake(const uint8_t *key_in,
+ uint8_t *handshake_reply_out,
+ uint8_t *key_out,
size_t key_out_len);
-int fast_client_handshake(const char *handshake_state,
- const char *handshake_reply_out,
- char *key_out,
+int fast_client_handshake(const uint8_t *handshake_state,
+ const uint8_t *handshake_reply_out,
+ uint8_t *key_out,
size_t key_out_len);
void clear_pending_onions(void);
diff --git a/src/or/or.h b/src/or/or.h
index a2cefe2b4a..07b73ec9b7 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -838,7 +838,7 @@ typedef struct cell_t {
circid_t circ_id; /**< Circuit which received the cell. */
uint8_t command; /**< Type of the cell: one of CELL_PADDING, CELL_CREATE,
* CELL_DESTROY, etc */
- char payload[CELL_PAYLOAD_SIZE]; /**< Cell body. */
+ uint8_t payload[CELL_PAYLOAD_SIZE]; /**< Cell body. */
} cell_t;
/** Parsed variable-length onion routing cell. */
@@ -846,7 +846,7 @@ typedef struct var_cell_t {
uint8_t command;
circid_t circ_id;
uint16_t payload_len;
- char payload[1];
+ uint8_t payload[1];
} var_cell_t;
/** A cell as packed for writing to the network. */
@@ -1958,7 +1958,7 @@ typedef struct crypt_path_t {
* authentication, secrecy, and integrity we need, and we're already
* distinguishable from an OR.
*/
- char fast_handshake_state[DIGEST_LEN];
+ uint8_t fast_handshake_state[DIGEST_LEN];
/** Negotiated key material shared with the OR at this step. */
char handshake_digest[DIGEST_LEN];/* KH in tor-spec.txt */
diff --git a/src/or/relay.c b/src/or/relay.c
index 467f8847c8..c951cab560 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -97,7 +97,7 @@ relay_set_digest(crypto_digest_env_t *digest, cell_t *cell)
char integrity[4];
relay_header_t rh;
- crypto_digest_add_bytes(digest, cell->payload, CELL_PAYLOAD_SIZE);
+ crypto_digest_add_bytes(digest, (char*)cell->payload, CELL_PAYLOAD_SIZE);
crypto_digest_get_digest(digest, integrity, 4);
// log_fn(LOG_DEBUG,"Putting digest of %u %u %u %u into relay cell.",
// integrity[0], integrity[1], integrity[2], integrity[3]);
@@ -130,7 +130,7 @@ relay_digest_matches(crypto_digest_env_t *digest, cell_t *cell)
// received_integrity[0], received_integrity[1],
// received_integrity[2], received_integrity[3]);
- crypto_digest_add_bytes(digest, cell->payload, CELL_PAYLOAD_SIZE);
+ crypto_digest_add_bytes(digest, (char*) cell->payload, CELL_PAYLOAD_SIZE);
crypto_digest_get_digest(digest, calculated_integrity, 4);
if (memcmp(received_integrity, calculated_integrity, 4)) {
@@ -156,12 +156,12 @@ relay_digest_matches(crypto_digest_env_t *digest, cell_t *cell)
* Return -1 if the crypto fails, else return 0.
*/
static int
-relay_crypt_one_payload(crypto_cipher_env_t *cipher, char *in,
+relay_crypt_one_payload(crypto_cipher_env_t *cipher, uint8_t *in,
int encrypt_mode)
{
int r;
(void)encrypt_mode;
- r = crypto_cipher_crypt_inplace(cipher, in, CELL_PAYLOAD_SIZE);
+ r = crypto_cipher_crypt_inplace(cipher, (char*) in, CELL_PAYLOAD_SIZE);
if (r) {
log_warn(LD_BUG,"Error during relay encryption");
@@ -476,10 +476,9 @@ relay_lookup_conn(circuit_t *circ, cell_t *cell,
* about the wire format.
*/
void
-relay_header_pack(char *dest, const relay_header_t *src)
+relay_header_pack(uint8_t *dest, const relay_header_t *src)
{
- *(uint8_t*)(dest) = src->command;
-
+ set_uint8(dest, src->command);
set_uint16(dest+1, htons(src->recognized));
set_uint16(dest+3, htons(src->stream_id));
memcpy(dest+5, src->integrity, 4);
@@ -490,10 +489,9 @@ relay_header_pack(char *dest, const relay_header_t *src)
* relay_header_t structure <b>dest</b>.
*/
void
-relay_header_unpack(relay_header_t *dest, const char *src)
+relay_header_unpack(relay_header_t *dest, const uint8_t *src)
{
- dest->command = *(uint8_t*)(src);
-
+ dest->command = get_uint8(src);
dest->recognized = ntohs(get_uint16(src+1));
dest->stream_id = ntohs(get_uint16(src+3));
memcpy(dest->integrity, src+5, 4);
@@ -1124,13 +1122,13 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
}
stats_n_data_bytes_received += rh.length;
- connection_write_to_buf(cell->payload + RELAY_HEADER_SIZE,
+ connection_write_to_buf((char*)(cell->payload + RELAY_HEADER_SIZE),
rh.length, TO_CONN(conn));
connection_edge_consider_sending_sendme(conn);
return 0;
case RELAY_COMMAND_END:
reason = rh.length > 0 ?
- *(uint8_t *)(cell->payload+RELAY_HEADER_SIZE) : END_STREAM_REASON_MISC;
+ get_uint8(cell->payload+RELAY_HEADER_SIZE) : END_STREAM_REASON_MISC;
if (!conn) {
log_info(domain,"end cell (%s) dropped, unknown stream.",
stream_end_reason_to_string(reason));
@@ -1478,10 +1476,11 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn,
crypt_path_t *layer_hint)
{
edge_connection_t *conn;
- int n_streams, n_streams_left;
+ int n_packaging_streams, n_streams_left;
int packaged_this_round;
int cells_on_queue;
int cells_per_conn;
+ edge_connection_t *chosen_stream = NULL;
/* How many cells do we have space for? It will be the minimum of
* the number needed to exhaust the package window, and the minimum
@@ -1496,26 +1495,61 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn,
if (CELL_QUEUE_HIGHWATER_SIZE - cells_on_queue < max_to_package)
max_to_package = CELL_QUEUE_HIGHWATER_SIZE - cells_on_queue;
+ /* Once we used to start listening on the streams in the order they
+ * appeared in the linked list. That leads to starvation on the
+ * streams that appeared later on the list, since the first streams
+ * would always get to read first. Instead, we just pick a random
+ * stream on the list, and enable reading for streams starting at that
+ * point (and wrapping around as if the list were circular). It would
+ * probably be better to actually remember which streams we've
+ * serviced in the past, but this is simple and effective. */
+
+ /* Select a stream uniformly at random from the linked list. We
+ * don't need cryptographic randomness here. */
+ {
+ int num_streams = 0;
+ for (conn = first_conn; conn; conn = conn->next_stream) {
+ num_streams++;
+ if ((tor_weak_random() % num_streams)==0)
+ chosen_stream = conn;
+ /* Invariant: chosen_stream has been chosen uniformly at random from
+ * among the first num_streams streams on first_conn. */
+ }
+ }
+
/* Count how many non-marked streams there are that have anything on
* their inbuf, and enable reading on all of the connections. */
- n_streams = 0;
- for (conn=first_conn; conn; conn=conn->next_stream) {
+ n_packaging_streams = 0;
+ /* Activate reading starting from the chosen stream */
+ for (conn=chosen_stream; conn; conn = conn->next_stream) {
+ /* Start reading for the streams starting from here */
+ if (conn->_base.marked_for_close || conn->package_window <= 0)
+ continue;
+ if (!layer_hint || conn->cpath_layer == layer_hint) {
+ connection_start_reading(TO_CONN(conn));
+
+ if (buf_datalen(conn->_base.inbuf) > 0)
+ ++n_packaging_streams;
+ }
+ }
+ /* Go back and do the ones we skipped, circular-style */
+ for (conn = first_conn; conn != chosen_stream; conn = conn->next_stream) {
if (conn->_base.marked_for_close || conn->package_window <= 0)
continue;
if (!layer_hint || conn->cpath_layer == layer_hint) {
connection_start_reading(TO_CONN(conn));
if (buf_datalen(conn->_base.inbuf) > 0)
- ++n_streams;
+ ++n_packaging_streams;
}
}
- if (n_streams == 0) /* avoid divide-by-zero */
+ if (n_packaging_streams == 0) /* avoid divide-by-zero */
return 0;
again:
- cells_per_conn = CEIL_DIV(max_to_package, n_streams);
+ cells_per_conn = CEIL_DIV(max_to_package, n_packaging_streams);
packaged_this_round = 0;
n_streams_left = 0;
@@ -1563,7 +1597,7 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn,
if (packaged_this_round && packaged_this_round < max_to_package &&
n_streams_left) {
max_to_package -= packaged_this_round;
- n_streams = n_streams_left;
+ n_packaging_streams = n_streams_left;
goto again;
}
@@ -2427,7 +2461,7 @@ append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn,
* ADDRESS [length bytes]
* Return the number of bytes added, or -1 on error */
int
-append_address_to_payload(char *payload_out, const tor_addr_t *addr)
+append_address_to_payload(uint8_t *payload_out, const tor_addr_t *addr)
{
uint32_t a;
switch (tor_addr_family(addr)) {
@@ -2452,13 +2486,13 @@ append_address_to_payload(char *payload_out, const tor_addr_t *addr)
* encoded as by append_address_to_payload(), try to decode the address into
* *<b>addr_out</b>. Return the next byte in the payload after the address on
* success, or NULL on failure. */
-const char *
-decode_address_from_payload(tor_addr_t *addr_out, const char *payload,
+const uint8_t *
+decode_address_from_payload(tor_addr_t *addr_out, const uint8_t *payload,
int payload_len)
{
if (payload_len < 2)
return NULL;
- if (payload_len < 2+(uint8_t)payload[1])
+ if (payload_len < 2+payload[1])
return NULL;
switch (payload[0]) {
@@ -2470,13 +2504,13 @@ decode_address_from_payload(tor_addr_t *addr_out, const char *payload,
case RESOLVED_TYPE_IPV6:
if (payload[1] != 16)
return NULL;
- tor_addr_from_ipv6_bytes(addr_out, payload+2);
+ tor_addr_from_ipv6_bytes(addr_out, (char*)(payload+2));
break;
default:
tor_addr_make_unspec(addr_out);
break;
}
- return payload + 2 + (uint8_t)payload[1];
+ return payload + 2 + payload[1];
}
/** Remove all the cells queued on <b>circ</b> for <b>orconn</b>. */
diff --git a/src/or/relay.h b/src/or/relay.h
index 08a1ffe789..8ccf0e2b30 100644
--- a/src/or/relay.h
+++ b/src/or/relay.h
@@ -18,8 +18,8 @@ extern uint64_t stats_n_relay_cells_delivered;
int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ,
cell_direction_t cell_direction);
-void relay_header_pack(char *dest, const relay_header_t *src);
-void relay_header_unpack(relay_header_t *dest, const char *src);
+void relay_header_pack(uint8_t *dest, const relay_header_t *src);
+void relay_header_unpack(relay_header_t *dest, const uint8_t *src);
int relay_send_command_from_edge(streamid_t stream_id, circuit_t *circ,
uint8_t relay_command, const char *payload,
size_t payload_len, crypt_path_t *cpath_layer);
@@ -55,9 +55,9 @@ void assert_active_circuits_ok(or_connection_t *orconn);
void make_circuit_inactive_on_conn(circuit_t *circ, or_connection_t *conn);
void make_circuit_active_on_conn(circuit_t *circ, or_connection_t *conn);
-int append_address_to_payload(char *payload_out, const tor_addr_t *addr);
-const char *decode_address_from_payload(tor_addr_t *addr_out,
- const char *payload,
+int append_address_to_payload(uint8_t *payload_out, const tor_addr_t *addr);
+const uint8_t *decode_address_from_payload(tor_addr_t *addr_out,
+ const uint8_t *payload,
int payload_len);
unsigned cell_ewma_get_tick(void);
void cell_ewma_set_scale_factor(or_options_t *options,
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index 3e1083f694..ab968078e8 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -234,7 +234,7 @@ rend_client_rendcirc_has_opened(origin_circuit_t *circ)
*/
int
rend_client_introduction_acked(origin_circuit_t *circ,
- const char *request, size_t request_len)
+ const uint8_t *request, size_t request_len)
{
origin_circuit_t *rendcirc;
(void) request; // XXXX Use this.
@@ -583,7 +583,7 @@ rend_client_remove_intro_point(extend_info_t *failed_intro,
* the circuit to C_REND_READY.
*/
int
-rend_client_rendezvous_acked(origin_circuit_t *circ, const char *request,
+rend_client_rendezvous_acked(origin_circuit_t *circ, const uint8_t *request,
size_t request_len)
{
(void) request;
@@ -609,7 +609,7 @@ rend_client_rendezvous_acked(origin_circuit_t *circ, const char *request,
/** Bob sent us a rendezvous cell; join the circuits. */
int
-rend_client_receive_rendezvous(origin_circuit_t *circ, const char *request,
+rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request,
size_t request_len)
{
crypt_path_t *hop;
@@ -637,9 +637,10 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const char *request,
tor_assert(circ->build_state->pending_final_cpath);
hop = circ->build_state->pending_final_cpath;
tor_assert(hop->dh_handshake_state);
- if (crypto_dh_compute_secret(LOG_PROTOCOL_WARN, hop->dh_handshake_state,
- request, DH_KEY_LEN, keys,
- DIGEST_LEN+CPATH_KEY_MATERIAL_LEN)<0) {
+ if (crypto_dh_compute_secret(LOG_PROTOCOL_WARN,
+ hop->dh_handshake_state, (char*)request,
+ DH_KEY_LEN,
+ keys, DIGEST_LEN+CPATH_KEY_MATERIAL_LEN)<0) {
log_warn(LD_GENERAL, "Couldn't complete DH handshake.");
goto err;
}
diff --git a/src/or/rendclient.h b/src/or/rendclient.h
index 842fe0b8ce..79d37b2a58 100644
--- a/src/or/rendclient.h
+++ b/src/or/rendclient.h
@@ -14,14 +14,17 @@
void rend_client_introcirc_has_opened(origin_circuit_t *circ);
void rend_client_rendcirc_has_opened(origin_circuit_t *circ);
-int rend_client_introduction_acked(origin_circuit_t *circ, const char *request,
+int rend_client_introduction_acked(origin_circuit_t *circ,
+ const uint8_t *request,
size_t request_len);
void rend_client_refetch_v2_renddesc(const rend_data_t *rend_query);
int rend_client_remove_intro_point(extend_info_t *failed_intro,
const rend_data_t *rend_query);
-int rend_client_rendezvous_acked(origin_circuit_t *circ, const char *request,
+int rend_client_rendezvous_acked(origin_circuit_t *circ,
+ const uint8_t *request,
size_t request_len);
-int rend_client_receive_rendezvous(origin_circuit_t *circ, const char *request,
+int rend_client_receive_rendezvous(origin_circuit_t *circ,
+ const uint8_t *request,
size_t request_len);
void rend_client_desc_trynow(const char *query);
diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c
index ec6680b1e6..85d97e0253 100644
--- a/src/or/rendcommon.c
+++ b/src/or/rendcommon.c
@@ -1358,7 +1358,7 @@ rend_cache_store_v2_desc_as_client(const char *desc,
void
rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint,
int command, size_t length,
- const char *payload)
+ const uint8_t *payload)
{
or_circuit_t *or_circ = NULL;
origin_circuit_t *origin_circ = NULL;
diff --git a/src/or/rendcommon.h b/src/or/rendcommon.h
index 00705022a2..d3313faf5a 100644
--- a/src/or/rendcommon.h
+++ b/src/or/rendcommon.h
@@ -22,7 +22,8 @@ rend_data_free(rend_data_t *data)
int rend_cmp_service_ids(const char *one, const char *two);
void rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint,
- int command, size_t length, const char *payload);
+ int command, size_t length,
+ 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,
diff --git a/src/or/rendmid.c b/src/or/rendmid.c
index d392f8e53a..bc36a4e117 100644
--- a/src/or/rendmid.c
+++ b/src/or/rendmid.c
@@ -18,7 +18,7 @@
* setting the circuit's purpose and service pk digest.
*/
int
-rend_mid_establish_intro(or_circuit_t *circ, const char *request,
+rend_mid_establish_intro(or_circuit_t *circ, const uint8_t *request,
size_t request_len)
{
crypto_pk_env_t *pk = NULL;
@@ -48,7 +48,7 @@ rend_mid_establish_intro(or_circuit_t *circ, const char *request,
/* Next asn1len bytes: asn1-encoded key. */
if (request_len < 2+DIGEST_LEN+asn1len)
goto truncated;
- pk = crypto_pk_asn1_decode(request+2, asn1len);
+ pk = crypto_pk_asn1_decode((char*)(request+2), asn1len);
if (!pk) {
reason = END_CIRC_REASON_TORPROTOCOL;
log_warn(LD_PROTOCOL, "Couldn't decode public key.");
@@ -69,8 +69,8 @@ rend_mid_establish_intro(or_circuit_t *circ, const char *request,
}
/* Rest of body: signature of previous data */
note_crypto_pk_op(REND_MID);
- if (crypto_pk_public_checksig_digest(pk, request, 2+asn1len+DIGEST_LEN,
- request+2+DIGEST_LEN+asn1len,
+ if (crypto_pk_public_checksig_digest(pk, (char*)request, 2+asn1len+DIGEST_LEN,
+ (char*)(request+2+DIGEST_LEN+asn1len),
request_len-(2+DIGEST_LEN+asn1len))<0) {
log_warn(LD_PROTOCOL,
"Incorrect signature on ESTABLISH_INTRO cell; rejecting.");
@@ -130,7 +130,7 @@ rend_mid_establish_intro(or_circuit_t *circ, const char *request,
* INTRODUCE2 cell.
*/
int
-rend_mid_introduce(or_circuit_t *circ, const char *request, size_t request_len)
+rend_mid_introduce(or_circuit_t *circ, const uint8_t *request, size_t request_len)
{
or_circuit_t *intro_circ;
char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
@@ -159,10 +159,10 @@ rend_mid_introduce(or_circuit_t *circ, const char *request, size_t request_len)
}
base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
- request, REND_SERVICE_ID_LEN);
+ (char*)request, REND_SERVICE_ID_LEN);
/* The first 20 bytes are all we look at: they have a hash of Bob's PK. */
- intro_circ = circuit_get_intro_point(request);
+ intro_circ = circuit_get_intro_point((char*)request);
if (!intro_circ) {
log_info(LD_REND,
"No intro circ found for INTRODUCE1 cell (%s) from circuit %d; "
@@ -180,7 +180,7 @@ rend_mid_introduce(or_circuit_t *circ, const char *request, size_t request_len)
/* Great. Now we just relay the cell down the circuit. */
if (relay_send_command_from_edge(0, TO_CIRCUIT(intro_circ),
RELAY_COMMAND_INTRODUCE2,
- request, request_len, NULL)) {
+ (char*)request, request_len, NULL)) {
log_warn(LD_GENERAL,
"Unable to send INTRODUCE2 cell to Tor client.");
goto err;
@@ -212,7 +212,7 @@ rend_mid_introduce(or_circuit_t *circ, const char *request, size_t request_len)
* rendezvous cookie.
*/
int
-rend_mid_establish_rendezvous(or_circuit_t *circ, const char *request,
+rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request,
size_t request_len)
{
char hexid[9];
@@ -232,7 +232,7 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const char *request,
goto err;
}
- if (circuit_get_rendezvous(request)) {
+ if (circuit_get_rendezvous((char*)request)) {
log_warn(LD_PROTOCOL,
"Duplicate rendezvous cookie in ESTABLISH_RENDEZVOUS.");
goto err;
@@ -250,7 +250,7 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const char *request,
circ->_base.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
memcpy(circ->rend_token, request, REND_COOKIE_LEN);
- base16_encode(hexid,9,request,4);
+ base16_encode(hexid,9,(char*)request,4);
log_info(LD_REND,
"Established rendezvous point on circuit %d for cookie %s",
@@ -267,13 +267,13 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const char *request,
* connecting the two circuits.
*/
int
-rend_mid_rendezvous(or_circuit_t *circ, const char *request,
+rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request,
size_t request_len)
{
or_circuit_t *rend_circ;
char hexid[9];
int reason = END_CIRC_REASON_INTERNAL;
- base16_encode(hexid,9,request,request_len<4?request_len:4);
+ base16_encode(hexid,9,(char*)request,request_len<4?request_len:4);
if (request_len>=4) {
log_info(LD_REND,
@@ -297,7 +297,7 @@ rend_mid_rendezvous(or_circuit_t *circ, const char *request,
goto err;
}
- rend_circ = circuit_get_rendezvous(request);
+ rend_circ = circuit_get_rendezvous((char*)request);
if (!rend_circ) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Rejecting RENDEZVOUS1 cell with unrecognized rendezvous cookie %s.",
@@ -309,7 +309,7 @@ rend_mid_rendezvous(or_circuit_t *circ, const char *request,
/* Send the RENDEZVOUS2 cell to Alice. */
if (relay_send_command_from_edge(0, TO_CIRCUIT(rend_circ),
RELAY_COMMAND_RENDEZVOUS2,
- request+REND_COOKIE_LEN,
+ (char*)(request+REND_COOKIE_LEN),
request_len-REND_COOKIE_LEN, NULL)) {
log_warn(LD_GENERAL,
"Unable to send RENDEZVOUS2 cell to client on circuit %d.",
diff --git a/src/or/rendmid.h b/src/or/rendmid.h
index 4d08d4c8b9..f06dd3d85e 100644
--- a/src/or/rendmid.h
+++ b/src/or/rendmid.h
@@ -12,13 +12,13 @@
#ifndef _TOR_RENDMID_H
#define _TOR_RENDMID_H
-int rend_mid_establish_intro(or_circuit_t *circ, const char *request,
+int rend_mid_establish_intro(or_circuit_t *circ, const uint8_t *request,
size_t request_len);
-int rend_mid_introduce(or_circuit_t *circ, const char *request,
+int rend_mid_introduce(or_circuit_t *circ, const uint8_t *request,
size_t request_len);
-int rend_mid_establish_rendezvous(or_circuit_t *circ, const char *request,
+int rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request,
size_t request_len);
-int rend_mid_rendezvous(or_circuit_t *circ, const char *request,
+int rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request,
size_t request_len);
#endif
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index b0d791529b..f06c98337a 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -849,7 +849,7 @@ clean_accepted_intros(rend_service_t *service, time_t now)
* rendezvous point.
*/
int
-rend_service_introduce(origin_circuit_t *circuit, const char *request,
+rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
size_t request_len)
{
char *ptr, *r_cookie;
@@ -913,7 +913,7 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request,
crypto_pk_get_digest(intro_key, intro_key_digest);
if (memcmp(intro_key_digest, request, DIGEST_LEN)) {
base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
- request, REND_SERVICE_ID_LEN);
+ (char*)request, REND_SERVICE_ID_LEN);
log_warn(LD_REND, "Got an INTRODUCE2 cell for the wrong service (%s).",
escaped(serviceid));
return -1;
@@ -928,7 +928,7 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request,
/* Next N bytes is encrypted with service key */
note_crypto_pk_op(REND_SERVER);
r = crypto_pk_private_hybrid_decrypt(
- intro_key,buf,request+DIGEST_LEN,request_len-DIGEST_LEN,
+ intro_key,buf,(char*)(request+DIGEST_LEN),request_len-DIGEST_LEN,
PK_PKCS1_OAEP_PADDING,1);
if (r<0) {
log_warn(LD_PROTOCOL, "Couldn't decrypt INTRODUCE2 cell.");
@@ -1392,7 +1392,8 @@ rend_service_intro_has_opened(origin_circuit_t *circuit)
* live introduction point, and note that the service descriptor is
* now out-of-date.*/
int
-rend_service_intro_established(origin_circuit_t *circuit, const char *request,
+rend_service_intro_established(origin_circuit_t *circuit,
+ const uint8_t *request,
size_t request_len)
{
rend_service_t *service;
diff --git a/src/or/rendservice.h b/src/or/rendservice.h
index 1767714c60..722cec1561 100644
--- a/src/or/rendservice.h
+++ b/src/or/rendservice.h
@@ -22,10 +22,10 @@ void rend_consider_descriptor_republication(void);
void rend_service_intro_has_opened(origin_circuit_t *circuit);
int rend_service_intro_established(origin_circuit_t *circuit,
- const char *request,
+ const uint8_t *request,
size_t request_len);
void rend_service_rendezvous_has_opened(origin_circuit_t *circuit);
-int rend_service_introduce(origin_circuit_t *circuit, const char *request,
+int rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
size_t request_len);
void rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc);
int rend_service_set_connection_addr_port(edge_connection_t *conn,
diff --git a/src/or/rephist.c b/src/or/rephist.c
index 22b3ec5217..5a57b954fd 100644
--- a/src/or/rephist.c
+++ b/src/or/rephist.c
@@ -1943,9 +1943,8 @@ dump_pk_ops(int severity)
#define EXIT_STATS_ROUND_UP_STREAMS 4
/** Number of TCP ports */
#define EXIT_STATS_NUM_PORTS 65536
-/** Reciprocal of threshold (= 0.01%) of total bytes that a port needs to
- * see in order to be included in exit stats. */
-#define EXIT_STATS_THRESHOLD_RECIPROCAL 10000
+/** Top n ports that will be included in exit stats. */
+#define EXIT_STATS_TOP_N_PORTS 10
/* The following data structures are arrays and no fancy smartlists or maps,
* so that all write operations can be done in constant time. This comes at
@@ -1995,15 +1994,23 @@ rep_hist_exit_stats_term(void)
tor_free(exit_streams);
}
+/** Helper for qsort: compare two ints. */
+static int
+_compare_int(const void *x, const void *y) {
+ return (*(int*)x - *(int*)y);
+}
+
/** Return a newly allocated string containing the exit port statistics
* until <b>now</b>, or NULL if we're not collecting exit stats. */
char *
rep_hist_format_exit_stats(time_t now)
{
- int i;
- uint64_t total_bytes = 0, threshold_bytes, other_read = 0,
- other_written = 0;
- uint32_t other_streams = 0;
+ int i, j, top_elements = 0, cur_min_idx = 0, cur_port;
+ uint64_t top_bytes[EXIT_STATS_TOP_N_PORTS];
+ int top_ports[EXIT_STATS_TOP_N_PORTS];
+ uint64_t cur_bytes = 0, other_read = 0, other_written = 0,
+ total_read = 0, total_written = 0;
+ uint32_t total_streams = 0, other_streams = 0;
char *buf;
smartlist_t *written_strings, *read_strings, *streams_strings;
char *written_string, *read_string, *streams_string;
@@ -2013,52 +2020,101 @@ rep_hist_format_exit_stats(time_t now)
if (!start_of_exit_stats_interval)
return NULL; /* Not initialized. */
- /* Count total number of bytes, so that we can attribute observations
- * below or equal to a threshold of 1 / EXIT_STATS_THRESHOLD_RECIPROCAL
- * of all bytes to a special port 'other'. */
+ /* Go through all ports to find the n ports that saw most written and
+ * read bytes.
+ *
+ * Invariant: at the end of the loop for iteration i,
+ * total_read is the sum of all exit_bytes_read[0..i]
+ * total_written is the sum of all exit_bytes_written[0..i]
+ * total_stream is the sum of all exit_streams[0..i]
+ *
+ * top_elements = MAX(EXIT_STATS_TOP_N_PORTS,
+ * #{j | 0 <= j <= i && volume(i) > 0})
+ *
+ * For all 0 <= j < top_elements,
+ * top_bytes[j] > 0
+ * 0 <= top_ports[j] <= 65535
+ * top_bytes[j] = volume(top_ports[j])
+ *
+ * There is no j in 0..i and k in 0..top_elements such that:
+ * volume(j) > top_bytes[k] AND j is not in top_ports[0..top_elements]
+ *
+ * There is no j!=cur_min_idx in 0..top_elements such that:
+ * top_bytes[j] < top_bytes[cur_min_idx]
+ *
+ * where volume(x) == exit_bytes_read[x]+exit_bytes_written[x]
+ *
+ * Worst case: O(EXIT_STATS_NUM_PORTS * EXIT_STATS_TOP_N_PORTS)
+ */
for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) {
- total_bytes += exit_bytes_read[i];
- total_bytes += exit_bytes_written[i];
+ total_read += exit_bytes_read[i];
+ total_written += exit_bytes_written[i];
+ total_streams += exit_streams[i];
+ cur_bytes = exit_bytes_read[i] + exit_bytes_written[i];
+ if (cur_bytes == 0) {
+ continue;
+ }
+ if (top_elements < EXIT_STATS_TOP_N_PORTS) {
+ top_bytes[top_elements] = cur_bytes;
+ top_ports[top_elements++] = i;
+ } else if (cur_bytes > top_bytes[cur_min_idx]) {
+ top_bytes[cur_min_idx] = cur_bytes;
+ top_ports[cur_min_idx] = i;
+ } else {
+ continue;
+ }
+ cur_min_idx = 0;
+ for (j = 1; j < top_elements; j++) {
+ if (top_bytes[j] < top_bytes[cur_min_idx]) {
+ cur_min_idx = j;
+ }
+ }
}
- threshold_bytes = total_bytes / EXIT_STATS_THRESHOLD_RECIPROCAL;
- /* Add observations of all ports above the threshold to smartlists and
- * join them to single strings. Also count bytes and streams of ports
- * below or equal to the threshold. */
+ /* Add observations of top ports to smartlists. */
written_strings = smartlist_create();
read_strings = smartlist_create();
streams_strings = smartlist_create();
- for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) {
- if (exit_bytes_read[i] + exit_bytes_written[i] > threshold_bytes) {
- if (exit_bytes_written[i] > 0) {
- uint64_t num = round_uint64_to_next_multiple_of(
- exit_bytes_written[i], EXIT_STATS_ROUND_UP_BYTES);
- num /= 1024;
- buf = NULL;
- tor_asprintf(&buf, "%d="U64_FORMAT, i, U64_PRINTF_ARG(num));
- smartlist_add(written_strings, buf);
- }
- if (exit_bytes_read[i] > 0) {
- uint64_t num = round_uint64_to_next_multiple_of(
- exit_bytes_read[i], EXIT_STATS_ROUND_UP_BYTES);
- num /= 1024;
- buf = NULL;
- tor_asprintf(&buf, "%d="U64_FORMAT, i, U64_PRINTF_ARG(num));
- smartlist_add(read_strings, buf);
- }
- if (exit_streams[i] > 0) {
- uint32_t num = round_uint32_to_next_multiple_of(exit_streams[i],
- EXIT_STATS_ROUND_UP_STREAMS);
- buf = NULL;
- tor_asprintf(&buf, "%d=%u", i, num);
- smartlist_add(streams_strings, buf);
- }
- } else {
- other_read += exit_bytes_read[i];
- other_written += exit_bytes_written[i];
- other_streams += exit_streams[i];
+ other_read = total_read;
+ other_written = total_written;
+ other_streams = total_streams;
+ /* Sort the ports; this puts them out of sync with top_bytes, but we
+ * won't be using top_bytes again anyway */
+ qsort(top_ports, top_elements, sizeof(int), _compare_int);
+ for (j = 0; j < top_elements; j++) {
+ cur_port = top_ports[j];
+ if (exit_bytes_written[cur_port] > 0) {
+ uint64_t num = round_uint64_to_next_multiple_of(
+ exit_bytes_written[cur_port],
+ EXIT_STATS_ROUND_UP_BYTES);
+ num /= 1024;
+ buf = NULL;
+ tor_asprintf(&buf, "%d="U64_FORMAT, cur_port, U64_PRINTF_ARG(num));
+ smartlist_add(written_strings, buf);
+ other_written -= exit_bytes_written[cur_port];
+ }
+ if (exit_bytes_read[cur_port] > 0) {
+ uint64_t num = round_uint64_to_next_multiple_of(
+ exit_bytes_read[cur_port],
+ EXIT_STATS_ROUND_UP_BYTES);
+ num /= 1024;
+ buf = NULL;
+ tor_asprintf(&buf, "%d="U64_FORMAT, cur_port, U64_PRINTF_ARG(num));
+ smartlist_add(read_strings, buf);
+ other_read -= exit_bytes_read[cur_port];
+ }
+ if (exit_streams[cur_port] > 0) {
+ uint32_t num = round_uint32_to_next_multiple_of(
+ exit_streams[cur_port],
+ EXIT_STATS_ROUND_UP_STREAMS);
+ buf = NULL;
+ tor_asprintf(&buf, "%d=%u", cur_port, num);
+ smartlist_add(streams_strings, buf);
+ other_streams -= exit_streams[cur_port];
}
}
+
+ /* Add observations of other ports in a single element. */
other_written = round_uint64_to_next_multiple_of(other_written,
EXIT_STATS_ROUND_UP_BYTES);
other_written /= 1024;
@@ -2076,6 +2132,8 @@ rep_hist_format_exit_stats(time_t now)
buf = NULL;
tor_asprintf(&buf, "other=%u", other_streams);
smartlist_add(streams_strings, buf);
+
+ /* Join all observations in single strings. */
written_string = smartlist_join_strings(written_strings, ",", 0, NULL);
read_string = smartlist_join_strings(read_strings, ",", 0, NULL);
streams_string = smartlist_join_strings(streams_strings, ",", 0, NULL);
diff --git a/src/or/router.c b/src/or/router.c
index 3d4ee70399..66ef8ec52e 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -1523,7 +1523,7 @@ router_rebuild_descriptor(int force)
/* Let bridges serve their own descriptors unencrypted, so they can
* pass reachability testing. (If they want to be harder to notice,
* they can always leave the DirPort off). */
- if (!options->BridgeRelay)
+ if (ei && !options->BridgeRelay)
ei->cache_info.send_unencrypted = 1;
router_get_router_hash(ri->cache_info.signed_descriptor_body,