diff options
Diffstat (limited to 'src/or/channel.c')
-rw-r--r-- | src/or/channel.c | 84 |
1 files changed, 74 insertions, 10 deletions
diff --git a/src/or/channel.c b/src/or/channel.c index 7f3c6f5868..cd5972f1ec 100644 --- a/src/or/channel.c +++ b/src/or/channel.c @@ -11,15 +11,17 @@ * should touch. */ -#define _TOR_CHANNEL_INTERNAL +#define TOR_CHANNEL_INTERNAL_ #include "or.h" #include "channel.h" #include "channeltls.h" #include "circuitbuild.h" #include "circuitlist.h" +#include "circuitstats.h" #include "connection_or.h" /* For var_cell_free() */ #include "circuitmux.h" +#include "entrynodes.h" #include "geoip.h" #include "nodelist.h" #include "relay.h" @@ -111,7 +113,7 @@ channel_idmap_eq(const channel_idmap_entry_t *a, HT_PROTOTYPE(channel_idmap, channel_idmap_entry_s, node, channel_idmap_hash, channel_idmap_eq); HT_GENERATE(channel_idmap, channel_idmap_entry_s, node, channel_idmap_hash, - channel_idmap_eq, 0.5, tor_malloc, tor_realloc, _tor_free); + channel_idmap_eq, 0.5, tor_malloc, tor_realloc, tor_free_); static cell_queue_entry_t * cell_queue_entry_dup(cell_queue_entry_t *q); static void cell_queue_entry_free(cell_queue_entry_t *q, int handed_off); @@ -779,11 +781,24 @@ channel_free(channel_t *chan) /* It must be deregistered */ tor_assert(!(chan->registered)); + log_debug(LD_CHANNEL, + "Freeing channel " U64_FORMAT " at %p", + U64_PRINTF_ARG(chan->global_identifier), chan); + + /* + * Get rid of cmux policy before we do anything, so cmux policies don't + * see channels in weird half-freed states. + */ + if (chan->cmux) { + circuitmux_set_policy(chan->cmux, NULL); + } + /* Call a free method if there is one */ if (chan->free) chan->free(chan); channel_clear_remote_end(chan); + /* Get rid of cmux */ if (chan->cmux) { circuitmux_detach_all_circuits(chan->cmux); circuitmux_free(chan->cmux); @@ -806,6 +821,11 @@ channel_listener_free(channel_listener_t *chan_l) { if (!chan_l) return; + log_debug(LD_CHANNEL, + "Freeing channel_listener_t " U64_FORMAT " at %p", + U64_PRINTF_ARG(chan_l->global_identifier), + chan_l); + /* It must be closed or errored */ tor_assert(chan_l->state == CHANNEL_LISTENER_STATE_CLOSED || chan_l->state == CHANNEL_LISTENER_STATE_ERROR); @@ -835,11 +855,29 @@ channel_force_free(channel_t *chan) cell_queue_entry_t *cell, *cell_tmp; tor_assert(chan); + log_debug(LD_CHANNEL, + "Force-freeing channel " U64_FORMAT " at %p", + U64_PRINTF_ARG(chan->global_identifier), chan); + + /* + * Get rid of cmux policy before we do anything, so cmux policies don't + * see channels in weird half-freed states. + */ + if (chan->cmux) { + circuitmux_set_policy(chan->cmux, NULL); + } + /* Call a free method if there is one */ if (chan->free) chan->free(chan); channel_clear_remote_end(chan); + /* Get rid of cmux */ + if (chan->cmux) { + circuitmux_free(chan->cmux); + chan->cmux = NULL; + } + /* We might still have a cell queue; kill it */ SIMPLEQ_FOREACH_SAFE(cell, &chan->incoming_queue, next, cell_tmp) { cell_queue_entry_free(cell, 0); @@ -866,6 +904,11 @@ channel_listener_force_free(channel_listener_t *chan_l) { tor_assert(chan_l); + log_debug(LD_CHANNEL, + "Force-freeing channel_listener_t " U64_FORMAT " at %p", + U64_PRINTF_ARG(chan_l->global_identifier), + chan_l); + /* Call a free method if there is one */ if (chan_l->free) chan_l->free(chan_l); @@ -3122,6 +3165,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)); remote_addr_str = tor_dup_addr(&remote_addr); log(severity, LD_GENERAL, " * Channel " U64_FORMAT " says its remote address" @@ -3130,16 +3174,19 @@ channel_dump_statistics(channel_t *chan, int severity) U64_PRINTF_ARG(chan->global_identifier), remote_addr_str, channel_get_canonical_remote_descr(chan), - channel_get_actual_remote_descr(chan)); + actual); tor_free(remote_addr_str); + tor_free(actual); } else { + char *actual = tor_strdup(channel_get_actual_remote_descr(chan)); log(severity, LD_GENERAL, " * Channel " U64_FORMAT " does not know its remote " "address, but gives a canonical description of \"%s\" and an " "actual description of \"%s\"", U64_PRINTF_ARG(chan->global_identifier), channel_get_canonical_remote_descr(chan), - channel_get_actual_remote_descr(chan)); + actual); + tor_free(actual); } /* Handle marks */ @@ -3352,8 +3399,10 @@ channel_listener_dump_transport_statistics(channel_listener_t *chan_l, * 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) { @@ -3361,7 +3410,20 @@ channel_get_actual_remote_descr(channel_t *chan) tor_assert(chan->get_remote_descr); /* Param 1 indicates the actual description */ - return chan->get_remote_descr(chan, 1); + 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); } /** @@ -3370,8 +3432,10 @@ channel_get_actual_remote_descr(channel_t *chan) * 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. + * + * Subsequent calls to channel_get_{actual,canonical}_remote_{address,descr} + * may invalidate the return value from this function. */ - const char * channel_get_canonical_remote_descr(channel_t *chan) { @@ -3383,12 +3447,12 @@ channel_get_canonical_remote_descr(channel_t *chan) } /** - * Get remote address if possible + * Get remote address if possible. * * Write the remote address out to a tor_addr_t if the underlying transport - * supports this operation. + * supports this operation, and return 1. Return 0 if the underlying transport + * doesn't let us do this. */ - int channel_get_addr_if_possible(channel_t *chan, tor_addr_t *addr_out) { |