Nick Mathewson [Wed, 20 Jul 2011 17:16:06 +0000 (13:16 -0400)]
Check return value in fmt_addr
Previously, if tor_addr_to_str() returned NULL, we would reuse the
last value returned by fmt_addr(). (This could happen if we were
erroneously asked to format an AF_UNSPEC address.) Now instead we
return "???".
Nick Mathewson [Wed, 20 Jul 2011 13:50:53 +0000 (09:50 -0400)]
Merge branch 'optimistic-client'
The conflicts are with the proposal 171 circuit isolation code, and
they're all trivial: they're just a matter of both branches adding
some unrelated code in the same places.
Nick Mathewson [Wed, 20 Jul 2011 00:40:15 +0000 (20:40 -0400)]
Fix spurious warning in bufferevent socks parsing
The problem was that we weren't initializing want_length to 0 before
calling parse_socks() the first time, so it looked like we were
risking an infinite loop when in fact we were safe.
Nick Mathewson [Tue, 19 Jul 2011 17:51:43 +0000 (13:51 -0400)]
Take a smarter approach to clearing isolation info
Back when I added this logic in 20c0581a79, the rule was that whenever
a circuit finished building, we cleared its isolation info. I did that
so that we would still use the circuit even if all the streams that
had previously led us to tentatively set its isolation info had closed.
But there were problems with that approach: We could pretty easily get
into a case where S1 had led us to launch C1 and S2 had led us to
launch C2, but when C1 finished, we cleared its isolation and attached
S2 first. Since C2 was still marked in a way that made S1
unattachable to it, we'd then launch another circuit needlessly.
So instead, we try the following approach now: when a circuit is done
building, we try to attach streams to it. If it remains unused after
we try attaching streams, then we clear its isolation info, and try
again to attach streams.
Thanks to Sebastian for helping me figure this out.
Nick Mathewson [Fri, 8 Jul 2011 19:15:59 +0000 (15:15 -0400)]
Implement destaddr-based isolation
The new candidate rule, which arma suggested and I like, is that
the original address as received from the client connection or as
rewritten by the controller is the address that counts.
Nick Mathewson [Thu, 7 Jul 2011 18:54:54 +0000 (14:54 -0400)]
Add an option to limit the number of non-open client circuits.
This is mainly meant as a way to keep clients from accidentally
DOSing themselves by (e.g.) enabling IsolateDestAddr or
IsolateDestPort on a port that they use for HTTP.
Nick Mathewson [Thu, 7 Jul 2011 14:40:23 +0000 (10:40 -0400)]
Launch sufficient circuits to satisfy pending isolated streams
Our old "do we need to launch a circuit for stream S" logic was,
more or less, that if we had a pending circuit that could handle S,
we didn't need to launch a new one.
But now that we have streams isolated from one another, we need
something stronger here: It's possible that some pending C can
handle either S1 or S2, but not both.
This patch reuses the existing isolation logic for a simple
solution: when we decide during circuit launching that some pending
C would satisfy stream S1, we "hypothetically" mark C as though S1
had been connected to it. Now if S2 is incompatible with S1, it
won't be something that can attach to C, and so we'll launch a new
stream.
When the circuit becomes OPEN for the first time (with no streams
attached to it), we reset the circuit's isolation status. I'm not
too sure about this part: I wanted some way to be sure that, if all
streams that would have used a circuit die before the circuit is
done, the circuit can still get used. But I worry that this
approach could also lead to us launching too many circuits. Careful
thought needed here.
Nick Mathewson [Wed, 6 Jul 2011 21:08:24 +0000 (17:08 -0400)]
Implement stream isolation
This is the meat of proposal 171: we change circuit_is_acceptable()
to require that the connection is compatible with every connection
that has been linked to the circuit; we update circuit_is_better to
prefer attaching streams to circuits in the way that decreases the
circuits' usefulness the least; and we update link_apconn_to_circ()
to do the appropriate bookkeeping.
Nick Mathewson [Wed, 6 Jul 2011 20:39:54 +0000 (16:39 -0400)]
Add a new isolation type and field: "nym epoch"
The "nym epoch" of a stream is defined as the number of times that
NEWNYM had been called before the stream was opened. All streams
are isolated by nym epoch.
This feature should be redundant with existing signewnym stuff, but
it provides a good belt-and-suspenders way for us to avoid ever
letting any circuit type bypass signewnym.
Nick Mathewson [Wed, 6 Jul 2011 20:03:47 +0000 (16:03 -0400)]
(Unused) backend logic for stream isolation
This patch adds fields to track how streams should be isolated, and
ensures that those fields are set correctly. It also adds fields to
track what streams can go on a circuit, and adds functions to see
whether a streams can go on a circuit and update the circuit
accordingly. Those functions aren't yet called.
Proposal 171 gives us a new syntax for parsing client port options.
You can now have as many FooPort options as you want (for Foo in
Socks, Trans, DNS, NATD), and they can have address:port arguments,
and you can specify the level of isolation on those ports.
Additionally, this patch refactors the client port parsing logic to
use a new type, port_cfg_t. Previously, ports to be bound were
half-parsed in config.c, and later re-parsed in connection.c when
we're about to bind them. Now, parsing a port means converting it
into a port_cfg_t, and binding it uses only a port_cfg_t, without
needing to parse the user-provided strings at all.
We should do a related refactoring on other port types. For
control ports, that'll be easy enough. For ORPort and DirPort,
we'll want to do this when we solve proposal 118 (letting servers
bind to and advertise multiple ports).
Nick Mathewson [Mon, 18 Jul 2011 17:56:22 +0000 (13:56 -0400)]
Only use optimistic data with exits that support it
This adds a little code complexity: we need to remember for each
node whether it supports the right feature, and then check for each
connection whether it's exiting at such a node. We store this in a
flag in the edge_connection_t, and set that flag at link time.
Nick Mathewson [Mon, 18 Jul 2011 17:00:48 +0000 (13:00 -0400)]
Initial optimistic_client fixes
- Conform to make check-spaces
- Build without warnings from passing size_t to %d
- Use connection_get_inbuf_len(), not buf_datalen (otherwise bufferevents
won't work).
- Don't log that we're using this feature at warn.
Nick Mathewson [Fri, 15 Jul 2011 22:53:29 +0000 (18:53 -0400)]
Fix bug in upload/download of hsdesc with microdescs
Previously we were using router_get_by_id(foo) to test "do we have a
descriptor that will let us make an anonymous circuit to foo". But
that isn't right for microdescs: we should have been using node_t.
Nick Mathewson [Fri, 15 Jul 2011 16:58:13 +0000 (12:58 -0400)]
Remove compare_addr_to_node_policy
Instead, use compare_tor_addr_to_node_policy everywhere.
One advantage of this is that compare_tor_addr_to_node_policy can
better distinguish 0.0.0.0 from "unknown", which caused a nasty bug
with microdesc users.
Nick Mathewson [Fri, 15 Jul 2011 16:44:51 +0000 (12:44 -0400)]
Treat null address as "unknown", not "rejected" in md policy
Previously, we had an issue where we'd treat an unknown address as
0, which turned into "0.0.0.0", which looked like a rejected
address. This meant in practice that as soon as we started doing
comparisons of unknown uint32 addresses to short policies, we'd get
'rejected' right away. Because of the circumstances under which
this would be called, it would only happen when we had local DNS
cached entries and we were looking to launch new circuits.
Nick Mathewson [Mon, 11 Jul 2011 20:10:24 +0000 (16:10 -0400)]
Disable recording new broken conns when we have bootstrapped
Rationale: right now there seems to be no way for our bootstrap
status to dip under 100% once it has reached 100%. Thus, recording
broken connections after that point is useless, and wastes memory.
If at some point in the future we allow our bootstrap level to go
backwards, then we should change this rule so that we disable
recording broken connection states _as long as_ the bootstrap status
is 100%.
Nick Mathewson [Tue, 28 Jun 2011 19:06:56 +0000 (15:06 -0400)]
Document feature3116 fns and improve output
- We were reporting the _bottom_ N failing states, not the top N.
- With bufferevents enabled, we logged all TLS states as being "in
bufferevent", which isn't actually informative.
- When we had nothing to report, we reported nothing too loudly.
- Also, we needed documentation.
Nick Mathewson [Wed, 22 Jun 2011 19:29:30 +0000 (15:29 -0400)]
Record the states of failing OR connections
This code lets us record the state of any outgoing OR connection
that fails before it becomes open, so we can notice if they're all
dying in the same SSL state or the same OR handshake state.
More work is still needed:
- We need documentation
- We need to actually call the code that reports the failure when
we realize that we're having a hard time connecting out or
making circuits.
- We need to periodically clear out all this data -- perhaps,
whenever we build a circuit successfully?
- We'll eventually want to expose it to controllers, perhaps.
Nick Mathewson [Mon, 11 Jul 2011 15:21:47 +0000 (11:21 -0400)]
Rename and tweak nodelist_add_node_family() to add node
It's very easy for nodelist_add_node_family(sl,node) to accidentally
add 'node', and kind of hard to make sure that it omits it. Instead
of taking pains to leave 'node' out, let's instead make sure that we
always include it.
I also rename the function to nodelist_add_node_and_family, and
audit its users so that they don't add the node itself any longer,
since the function will take care of that for them.
Nick Mathewson [Mon, 11 Jul 2011 14:48:46 +0000 (10:48 -0400)]
Revise code for adding EntryNodes to guards.
Previously, we'd just take all the nodes in EntryNodes, see which
ones were already in the guard list, and add the ones that weren't.
There were some problems there, though:
* We'd add _every_ entry in EntryNodes, and add them in the order
they appeared in the routerlist. This wasn't a problem
until we added the ability to give country-code or IP-range
entries in the EntryNodes set, but now that we did, it is.
(Fix: We now shuffle the entry nodes before adding them; only
add up to 10*NumEntryGuards)
* We didn't screen EntryNodes for the Guard flag. That's okay
if the user has specified two or three entry nodes manually,
but if they have listed a whole subcontinent, we should
restrict ourselves to the entries that are currently guards.
(Fix: separate out the new guard from the new non-guard nodes,
and add the Guards first.)
* We'd prepend new EntryNodes _before_ the already configured
EntryNodes. This could lead to churn.
(Fix: don't prepend these.)
This patch also pre-screens EntryNodes entries for
reachableaddresses/excludenodes, even though we check for that
later. This is important now, since we cap the number of entries
we'll add.
Nick Mathewson [Mon, 11 Jul 2011 14:02:24 +0000 (10:02 -0400)]
Look at the right consensus in router_add_to_routerlist()
Just looking at the "latest" consensus could give us a microdesc
consensus, if microdescs were enabled. That would make us decide
that every routerdesc was unlisted in the latest consensus and drop
them all: Ouch.
Nick Mathewson [Thu, 7 Jul 2011 19:17:50 +0000 (15:17 -0400)]
Make nodelist_purge avoid orphaned microdescs in rs-less nodes
We have an invariant that a node_t should have an md only if it has
a routerstatus. nodelist_purge tried to preserve this by removing
all nodes without a routerstatus or a routerinfo. But this left
nodes with a routerinfo and a microdesc untouched, even if they had
a routerstatus.
Nick Mathewson [Thu, 7 Jul 2011 15:52:13 +0000 (11:52 -0400)]
Kill redundant checks around routerset_contains_*()
All of the routerset_contains*() functions return 0 if their
routerset_t argument is NULL. Therefore, there's no point in
doing "if (ExcludeNodes && routerset_contains*(ExcludeNodes...))",
for example.
This patch fixes every instance of
if (X && routerstatus_contains*(X,...))
Note that there are other patterns that _aren't_ redundant. For
example, we *don't* want to change:
if (EntryNodes && !routerstatus_contains(EntryNodes,...))
Nick Mathewson [Thu, 7 Jul 2011 15:05:06 +0000 (11:05 -0400)]
Have transitions in public_server_mode count as affects_descriptor
Previously, we'd get a new descriptor for free when
public_server_mode() changed, since it would count as
affects_workers, which would call init_keys(), which would make us
regenerate a new descriptor. But now that we fixed bug 3263,
init_keys() is no longer necessarily a new descriptor, and so we
need to make sure that public_server_mode() counts as a descriptor
transition.
Sebastian Hahn [Thu, 7 Jul 2011 03:27:20 +0000 (05:27 +0200)]
Correctly send a SUCCEEDED event for rdns requests
The issue was that we overlooked the possibility of reverse DNS success
at the end of connection_ap_handshake_socks_resolved(). Issue discovered
by katmagic, thanks!