diff options
Diffstat (limited to 'src/core/or/channel.c')
-rw-r--r-- | src/core/or/channel.c | 233 |
1 files changed, 110 insertions, 123 deletions
diff --git a/src/core/or/channel.c b/src/core/or/channel.c index 9649bdf278..1ac029c152 100644 --- a/src/core/or/channel.c +++ b/src/core/or/channel.c @@ -1,5 +1,4 @@ - -/* * Copyright (c) 2012-2019, The Tor Project, Inc. */ +/* * Copyright (c) 2012-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -33,7 +32,7 @@ * * NOTE: For now, the separation between channels and specialized channels * (like channeltls) is not that well defined. So the channeltls layer calls - * channel_process_cell() which originally comes from the connection subsytem. + * channel_process_cell() which originally comes from the connection subsystem. * This should be hopefully be fixed with #23993. * * For *outbound* cells, the entry point is: channel_write_packed_cell(). @@ -52,10 +51,10 @@ * Define this so channel.h gives us things only channel_t subclasses * should touch. */ -#define TOR_CHANNEL_INTERNAL_ +#define CHANNEL_OBJECT_PRIVATE /* This one's for stuff only channel.c and the test suite should see */ -#define CHANNEL_PRIVATE_ +#define CHANNEL_FILE_PRIVATE #include "core/or/or.h" #include "app/config/config.h" @@ -107,7 +106,7 @@ static smartlist_t *finished_listeners = NULL; /** Map from channel->global_identifier to channel. Contains the same * elements as all_channels. */ -static HT_HEAD(channel_gid_map, channel_s) channel_gid_map = HT_INITIALIZER(); +static HT_HEAD(channel_gid_map, channel_t) channel_gid_map = HT_INITIALIZER(); static unsigned channel_id_hash(const channel_t *chan) @@ -119,13 +118,13 @@ channel_id_eq(const channel_t *a, const channel_t *b) { return a->global_identifier == b->global_identifier; } -HT_PROTOTYPE(channel_gid_map, channel_s, gidmap_node, - channel_id_hash, channel_id_eq) -HT_GENERATE2(channel_gid_map, channel_s, gidmap_node, +HT_PROTOTYPE(channel_gid_map, channel_t, gidmap_node, + channel_id_hash, channel_id_eq); +HT_GENERATE2(channel_gid_map, channel_t, gidmap_node, channel_id_hash, channel_id_eq, - 0.6, tor_reallocarray_, tor_free_) + 0.6, tor_reallocarray_, tor_free_); -HANDLE_IMPL(channel, channel_s,) +HANDLE_IMPL(channel, channel_t,) /* Counter for ID numbers */ static uint64_t n_channels_allocated = 0; @@ -138,13 +137,13 @@ static uint64_t n_channels_allocated = 0; * If more than one channel exists, follow the next_with_same_id pointer * as a linked list. */ -static HT_HEAD(channel_idmap, channel_idmap_entry_s) channel_identity_map = +static HT_HEAD(channel_idmap, channel_idmap_entry_t) channel_identity_map = HT_INITIALIZER(); -typedef struct channel_idmap_entry_s { - HT_ENTRY(channel_idmap_entry_s) node; +typedef struct channel_idmap_entry_t { + HT_ENTRY(channel_idmap_entry_t) node; uint8_t digest[DIGEST_LEN]; - TOR_LIST_HEAD(channel_list_s, channel_s) channel_list; + TOR_LIST_HEAD(channel_list_t, channel_t) channel_list; } channel_idmap_entry_t; static inline unsigned @@ -160,10 +159,10 @@ channel_idmap_eq(const channel_idmap_entry_t *a, return tor_memeq(a->digest, b->digest, DIGEST_LEN); } -HT_PROTOTYPE(channel_idmap, channel_idmap_entry_s, node, channel_idmap_hash, - channel_idmap_eq) -HT_GENERATE2(channel_idmap, channel_idmap_entry_s, node, channel_idmap_hash, - channel_idmap_eq, 0.5, tor_reallocarray_, tor_free_) +HT_PROTOTYPE(channel_idmap, channel_idmap_entry_t, node, channel_idmap_hash, + channel_idmap_eq); +HT_GENERATE2(channel_idmap, channel_idmap_entry_t, node, channel_idmap_hash, + channel_idmap_eq, 0.5, tor_reallocarray_, tor_free_); /* Functions to maintain the digest map */ static void channel_remove_from_digest_map(channel_t *chan); @@ -872,6 +871,8 @@ channel_init(channel_t *chan) /* Channel is not in the scheduler heap. */ chan->sched_heap_idx = -1; + + tor_addr_make_unspec(&chan->addr_according_to_peer); } /** @@ -1092,23 +1093,6 @@ channel_get_cell_handler(channel_t *chan) } /** - * Return the variable-length cell handler for a channel. - * - * This function gets the handler for incoming variable-length cells - * installed on a channel. - */ -channel_var_cell_handler_fn_ptr -channel_get_var_cell_handler(channel_t *chan) -{ - tor_assert(chan); - - if (CHANNEL_CAN_HANDLE_CELLS(chan)) - return chan->var_cell_handler; - - return NULL; -} - -/** * Set both cell handlers for a channel. * * This function sets both the fixed-length and variable length cell handlers @@ -1116,9 +1100,7 @@ channel_get_var_cell_handler(channel_t *chan) */ void channel_set_cell_handlers(channel_t *chan, - channel_cell_handler_fn_ptr cell_handler, - channel_var_cell_handler_fn_ptr - var_cell_handler) + channel_cell_handler_fn_ptr cell_handler) { tor_assert(chan); tor_assert(CHANNEL_CAN_HANDLE_CELLS(chan)); @@ -1126,13 +1108,9 @@ channel_set_cell_handlers(channel_t *chan, log_debug(LD_CHANNEL, "Setting cell_handler callback for channel %p to %p", chan, cell_handler); - log_debug(LD_CHANNEL, - "Setting var_cell_handler callback for channel %p to %p", - chan, var_cell_handler); /* Change them */ chan->cell_handler = cell_handler; - chan->var_cell_handler = var_cell_handler; } /* @@ -1443,6 +1421,7 @@ write_packed_cell(channel_t *chan, packed_cell_t *cell) { int ret = -1; size_t cell_bytes; + uint8_t command = packed_cell_get_command(cell, chan->wide_circ_ids); tor_assert(chan); tor_assert(cell); @@ -1477,6 +1456,16 @@ write_packed_cell(channel_t *chan, packed_cell_t *cell) /* Successfully sent the cell. */ ret = 0; + /* Update padding statistics for the packed codepath.. */ + rep_hist_padding_count_write(PADDING_TYPE_TOTAL); + if (command == CELL_PADDING) + rep_hist_padding_count_write(PADDING_TYPE_CELL); + if (chan->padding_enabled) { + rep_hist_padding_count_write(PADDING_TYPE_ENABLED_TOTAL); + if (command == CELL_PADDING) + rep_hist_padding_count_write(PADDING_TYPE_ENABLED_CELL); + } + done: return ret; } @@ -1893,11 +1882,11 @@ channel_do_open_actions(channel_t *chan) geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &remote_addr, transport_name, now); - tor_free(transport_name); /* Notify the DoS subsystem of a new client. */ if (tlschan && tlschan->conn) { dos_new_client_conn(tlschan->conn, transport_name); } + tor_free(transport_name); } /* Otherwise the underlying transport can't tell us this, so skip it */ } @@ -2372,7 +2361,7 @@ channel_is_better(channel_t *a, channel_t *b) if (!a->is_canonical_to_peer && b->is_canonical_to_peer) return 0; /* - * Okay, if we're here they tied on canonicity, the prefer the older + * Okay, if we're here they tied on canonicity. Prefer the older * connection, so that the adversary can't create a new connection * and try to switch us over to it (which will leak information * about long-lived circuits). Additionally, switching connections @@ -2397,19 +2386,27 @@ channel_is_better(channel_t *a, channel_t *b) /** * Get a channel to extend a circuit. * - * Pick a suitable channel to extend a circuit to given the desired digest - * the address we believe is correct for that digest; this tries to see - * if we already have one for the requested endpoint, but if there is no good - * channel, set *msg_out to a message describing the channel's state - * and our next action, and set *launch_out to a boolean indicated whether - * the caller should try to launch a new channel with channel_connect(). + * Given the desired relay identity, pick a suitable channel to extend a + * circuit to the target IPv4 or IPv6 address requested by the client. Search + * for an existing channel for the requested endpoint. Make sure the channel + * is usable for new circuits, and matches one of the target addresses. + * + * Try to return the best channel. But if there is no good channel, set + * *msg_out to a message describing the channel's state and our next action, + * and set *launch_out to a boolean indicated whether the caller should try to + * launch a new channel with channel_connect(). + * + * If `for_origin_circ` is set, mark the channel as interesting for origin + * circuits, and therefore interesting for our bootstrapping reports. */ -channel_t * -channel_get_for_extend(const char *rsa_id_digest, - const ed25519_public_key_t *ed_id, - const tor_addr_t *target_addr, - const char **msg_out, - int *launch_out) +MOCK_IMPL(channel_t *, +channel_get_for_extend,(const char *rsa_id_digest, + const ed25519_public_key_t *ed_id, + const tor_addr_t *target_ipv4_addr, + const tor_addr_t *target_ipv6_addr, + bool for_origin_circ, + const char **msg_out, + int *launch_out)) { channel_t *chan, *best = NULL; int n_inprogress_goodaddr = 0, n_old = 0; @@ -2420,9 +2417,7 @@ channel_get_for_extend(const char *rsa_id_digest, chan = channel_find_by_remote_identity(rsa_id_digest, ed_id); - /* Walk the list, unrefing the old one and refing the new at each - * iteration. - */ + /* Walk the list of channels */ for (; chan; chan = channel_next_with_rsa_identity(chan)) { tor_assert(tor_memeq(chan->identity_digest, rsa_id_digest, DIGEST_LEN)); @@ -2441,12 +2436,23 @@ channel_get_for_extend(const char *rsa_id_digest, continue; } + const bool matches_target = + channel_matches_target_addr_for_extend(chan, + target_ipv4_addr, + target_ipv6_addr); /* Never return a non-open connection. */ if (!CHANNEL_IS_OPEN(chan)) { /* If the address matches, don't launch a new connection for this * circuit. */ - if (channel_matches_target_addr_for_extend(chan, target_addr)) + if (matches_target) { ++n_inprogress_goodaddr; + if (for_origin_circ) { + /* We were looking for a connection for an origin circuit; this one + * matches, so we'll note that we decided to use it for an origin + * circuit. */ + channel_mark_as_used_for_origin_circuit(chan); + } + } continue; } @@ -2458,8 +2464,7 @@ channel_get_for_extend(const char *rsa_id_digest, /* Only return canonical connections or connections where the address * is the address we wanted. */ - if (!channel_is_canonical(chan) && - !channel_matches_target_addr_for_extend(chan, target_addr)) { + if (!channel_is_canonical(chan) && !matches_target) { ++n_noncanonical; continue; } @@ -2574,7 +2579,7 @@ channel_dump_statistics, (channel_t *chan, int severity)) /* Handle remote address and descriptions */ have_remote_addr = channel_get_addr_if_possible(chan, &remote_addr); if (have_remote_addr) { - char *actual = tor_strdup(channel_get_actual_remote_descr(chan)); + char *actual = tor_strdup(channel_describe_peer(chan)); remote_addr_str = tor_addr_to_str_dup(&remote_addr); tor_log(severity, LD_GENERAL, " * Channel %"PRIu64 " says its remote address" @@ -2582,18 +2587,18 @@ channel_dump_statistics, (channel_t *chan, int severity)) "actual description of \"%s\"", (chan->global_identifier), safe_str(remote_addr_str), - safe_str(channel_get_canonical_remote_descr(chan)), + safe_str(channel_describe_peer(chan)), safe_str(actual)); tor_free(remote_addr_str); tor_free(actual); } else { - char *actual = tor_strdup(channel_get_actual_remote_descr(chan)); + char *actual = tor_strdup(channel_describe_peer(chan)); tor_log(severity, LD_GENERAL, " * Channel %"PRIu64 " does not know its remote " "address, but gives a canonical description of \"%s\" and an " "actual description of \"%s\"", (chan->global_identifier), - channel_get_canonical_remote_descr(chan), + channel_describe_peer(chan), actual); tor_free(actual); } @@ -2799,75 +2804,41 @@ channel_listener_dump_transport_statistics(channel_listener_t *chan_l, } /** - * Return text description of the remote endpoint. - * - * This function return a test provided by the lower layer of the remote - * endpoint for this channel; it should specify the actual address connected - * to/from. - * - * Subsequent calls to channel_get_{actual,canonical}_remote_{address,descr} - * may invalidate the return value from this function. - */ -const char * -channel_get_actual_remote_descr(channel_t *chan) -{ - tor_assert(chan); - tor_assert(chan->get_remote_descr); - - /* Param 1 indicates the actual description */ - return chan->get_remote_descr(chan, GRD_FLAG_ORIGINAL); -} - -/** - * Return the text address of the remote endpoint. - * - * Subsequent calls to channel_get_{actual,canonical}_remote_{address,descr} - * may invalidate the return value from this function. - */ -const char * -channel_get_actual_remote_address(channel_t *chan) -{ - /* Param 1 indicates the actual description */ - return chan->get_remote_descr(chan, GRD_FLAG_ORIGINAL|GRD_FLAG_ADDR_ONLY); -} - -/** * Return text description of the remote endpoint canonical address. * - * This function return a test provided by the lower layer of the remote - * endpoint for this channel; it should use the known canonical address for - * this OR's identity digest if possible. + * This function returns a human-readable string for logging; nothing + * should parse it or rely on a particular format. * - * Subsequent calls to channel_get_{actual,canonical}_remote_{address,descr} - * may invalidate the return value from this function. + * Subsequent calls to this function may invalidate its return value. */ -const char * -channel_get_canonical_remote_descr(channel_t *chan) +MOCK_IMPL(const char *, +channel_describe_peer,(channel_t *chan)) { tor_assert(chan); - tor_assert(chan->get_remote_descr); + tor_assert(chan->describe_peer); - /* Param 0 indicates the canonicalized description */ - return chan->get_remote_descr(chan, 0); + return chan->describe_peer(chan); } /** - * Get remote address if possible. + * Get the remote address for this channel, if possible. * * Write the remote address out to a tor_addr_t if the underlying transport * supports this operation, and return 1. Return 0 if the underlying transport * doesn't let us do this. + * + * Always returns the "real" address of the peer -- the one we're connected to + * on the internet. */ MOCK_IMPL(int, -channel_get_addr_if_possible,(channel_t *chan, tor_addr_t *addr_out)) +channel_get_addr_if_possible,(const channel_t *chan, + tor_addr_t *addr_out)) { tor_assert(chan); tor_assert(addr_out); + tor_assert(chan->get_remote_addr); - if (chan->get_remote_addr) - return chan->get_remote_addr(chan, addr_out); - /* Else no support, method not implemented */ - else return 0; + return chan->get_remote_addr(chan, addr_out); } /** @@ -3291,6 +3262,9 @@ channel_when_last_xmit(channel_t *chan) * * This function calls the lower layer and asks if this channel matches a * given extend_info_t. + * + * NOTE that this function only checks for an address/port match, and should + * be used only when no identity is available. */ int channel_matches_extend_info(channel_t *chan, extend_info_t *extend_info) @@ -3303,20 +3277,33 @@ channel_matches_extend_info(channel_t *chan, extend_info_t *extend_info) } /** - * Check if a channel matches a given target address; return true iff we do. + * Check if a channel matches the given target IPv4 or IPv6 addresses. + * If either address matches, return true. If neither address matches, + * return false. + * + * Both addresses can't be NULL. * * This function calls into the lower layer and asks if this channel thinks - * it matches a given target address for circuit extension purposes. + * it matches the target addresses for circuit extension purposes. */ -int +STATIC bool channel_matches_target_addr_for_extend(channel_t *chan, - const tor_addr_t *target) + const tor_addr_t *target_ipv4_addr, + const tor_addr_t *target_ipv6_addr) { tor_assert(chan); tor_assert(chan->matches_target); - tor_assert(target); - return chan->matches_target(chan, target); + IF_BUG_ONCE(!target_ipv4_addr && !target_ipv6_addr) + return false; + + if (target_ipv4_addr && chan->matches_target(chan, target_ipv4_addr)) + return true; + + if (target_ipv6_addr && chan->matches_target(chan, target_ipv6_addr)) + return true; + + return false; } /** @@ -3389,7 +3376,7 @@ channel_sort_by_ed25519_identity(const void **a_, const void **b_) * all of which MUST have the same RSA ID. (They MAY have different * Ed25519 IDs.) */ static void -channel_rsa_id_group_set_badness(struct channel_list_s *lst, int force) +channel_rsa_id_group_set_badness(struct channel_list_t *lst, int force) { /*XXXX This function should really be about channels. 15056 */ channel_t *chan = TOR_LIST_FIRST(lst); |