diff options
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)); |