When closing circs build through a new guard, only close local ones

If we decide not to use a new guard because we want to retry older
guards, only close the locally-originating circuits passing through
that guard. Previously we would close all the circuits.

Fixes bug 9819; bugfix on 0.2.1.1-alpha. Reported by "skruffy".
This commit is contained in:
Nick Mathewson 2015-01-07 10:27:22 -05:00
parent 79aaad952f
commit b56c7614b6
4 changed files with 24 additions and 8 deletions

8
changes/bug9819 Normal file
View File

@ -0,0 +1,8 @@
o Major bugfixes (mixed relay-client operation):
- When running as a relay and a client at the same time (not
recommended), if we decide not to use a new guard because we
want to retry older guards, only close the locally-originating
circuits passing through that guard. Previously we would close
all the circuits. Fixes bug 9819; bugfix on
0.2.1.1-alpha. Reported by "skruffy".

View File

@ -56,7 +56,6 @@ static smartlist_t *finished_listeners = NULL;
/* Counter for ID numbers */
static uint64_t n_channels_allocated = 0;
/*
* Channel global byte/cell counters, for statistics and for scheduler high
* /low-water marks.
@ -1329,7 +1328,7 @@ channel_closed(channel_t *chan)
/* Inform any pending (not attached) circs that they should
* give up. */
if (! chan->has_been_open)
circuit_n_chan_done(chan, 0);
circuit_n_chan_done(chan, 0, 0);
/* Now close all the attached circuits on it. */
circuit_unlink_all_from_channel(chan, END_CIRC_REASON_CHANNEL_CLOSED);
@ -2527,8 +2526,9 @@ void
channel_do_open_actions(channel_t *chan)
{
tor_addr_t remote_addr;
int started_here, not_using = 0;
int started_here;
time_t now = time(NULL);
int close_origin_circuits = 0;
tor_assert(chan);
@ -2545,8 +2545,7 @@ channel_do_open_actions(channel_t *chan)
log_debug(LD_OR,
"New entry guard was reachable, but closing this "
"connection so we can retry the earlier entry guards.");
circuit_n_chan_done(chan, 0);
not_using = 1;
close_origin_circuits = 1;
}
router_set_status(chan->identity_digest, 1);
} else {
@ -2566,7 +2565,7 @@ channel_do_open_actions(channel_t *chan)
}
}
if (!not_using) circuit_n_chan_done(chan, 1);
circuit_n_chan_done(chan, 1, close_origin_circuits);
}
/**

View File

@ -551,9 +551,13 @@ circuit_handle_first_hop(origin_circuit_t *circ)
* open and get them to send their create cells forward.
*
* Status is 1 if connect succeeded, or 0 if connect failed.
*
* Close_origin_circs is 1 if we should close all the origin circuits through
* this channel, or 0 otherwise. (This happens when we want to retry an
* older guard.)
*/
void
circuit_n_chan_done(channel_t *chan, int status)
circuit_n_chan_done(channel_t *chan, int status, int close_origin_circuits)
{
smartlist_t *pending_circs;
int err_reason = 0;
@ -591,6 +595,11 @@ circuit_n_chan_done(channel_t *chan, int status)
circuit_mark_for_close(circ, END_CIRC_REASON_CHANNEL_CLOSED);
continue;
}
if (close_origin_circuits && CIRCUIT_IS_ORIGIN(circ)) {
log_info(LD_CIRC,"Channel deprecated for origin circs; closing circ.");
circuit_mark_for_close(circ, END_CIRC_REASON_CHANNEL_CLOSED);
continue;
}
log_debug(LD_CIRC, "Found circ, sending create cell.");
/* circuit_deliver_create_cell will set n_circ_id and add us to
* chan_circuid_circuit_map, so we don't need to call

View File

@ -22,7 +22,7 @@ origin_circuit_t *circuit_establish_circuit(uint8_t purpose,
extend_info_t *exit,
int flags);
int circuit_handle_first_hop(origin_circuit_t *circ);
void circuit_n_chan_done(channel_t *chan, int status);
void circuit_n_chan_done(channel_t *chan, int status, int close_origin_circuits);
int inform_testing_reachability(void);
int circuit_timeout_want_to_count_circ(origin_circuit_t *circ);
int circuit_send_next_onion_skin(origin_circuit_t *circ);