summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changes/bug61746
-rw-r--r--changes/bug62066
-rw-r--r--changes/bug66734
-rw-r--r--changes/bug72804
-rw-r--r--changes/bug79474
-rw-r--r--changes/bug80145
-rw-r--r--changes/bug80596
-rw-r--r--changes/bug80625
-rw-r--r--changes/bug81807
-rw-r--r--changes/bug82034
-rw-r--r--changes/bug82315
-rw-r--r--changes/bug82733
-rw-r--r--changes/bug82909
-rw-r--r--changes/bug83773
-rw-r--r--changes/bug84354
-rw-r--r--changes/bug84645
-rw-r--r--changes/bug8477-easypart3
-rw-r--r--configure.ac4
-rw-r--r--contrib/include.am3
-rw-r--r--contrib/tor-tsocks.conf13
-rwxr-xr-xdoc/asciidoc-helper.sh4
-rw-r--r--doc/contrib/incentives.txt479
-rw-r--r--doc/tor.1.txt2
-rw-r--r--doc/torify.1.txt18
-rw-r--r--src/common/address.c116
-rw-r--r--src/common/address.h4
-rw-r--r--src/common/compat.c74
-rw-r--r--src/common/compat.h2
-rw-r--r--src/common/container.h5
-rw-r--r--src/common/crypto.c27
-rw-r--r--src/common/crypto.h1
-rw-r--r--src/common/util.c109
-rw-r--r--src/common/util.h6
-rw-r--r--src/ext/eventdns.c7
-rw-r--r--src/or/channeltls.c2
-rw-r--r--src/or/circuitbuild.c3
-rw-r--r--src/or/circuitlist.c15
-rw-r--r--src/or/circuitlist.h2
-rw-r--r--src/or/circuituse.c36
-rw-r--r--src/or/circuituse.h1
-rw-r--r--src/or/config.c11
-rw-r--r--src/or/connection.c23
-rw-r--r--src/or/connection_edge.c33
-rw-r--r--src/or/control.c10
-rw-r--r--src/or/cpuworker.c7
-rw-r--r--src/or/dirserv.c293
-rw-r--r--src/or/dirserv.h14
-rw-r--r--src/or/dnsserv.c11
-rw-r--r--src/or/dnsserv.h3
-rw-r--r--src/or/entrynodes.c31
-rw-r--r--src/or/hibernate.c4
-rw-r--r--src/or/main.c8
-rw-r--r--src/or/networkstatus.c12
-rw-r--r--src/or/networkstatus.h1
-rw-r--r--src/or/or.h28
-rw-r--r--src/or/relay.c13
-rw-r--r--src/or/rendcommon.c7
-rw-r--r--src/or/rendcommon.h1
-rw-r--r--src/or/router.c17
-rw-r--r--src/or/router.h2
-rw-r--r--src/or/routerlist.c53
-rw-r--r--src/or/routerlist.h2
-rw-r--r--src/or/routerparse.c2
-rw-r--r--src/or/transports.c4
-rw-r--r--src/test/test.c5
-rw-r--r--src/test/test_addr.c36
-rw-r--r--src/test/test_crypto.c16
-rw-r--r--src/test/test_dir.c80
-rw-r--r--src/test/test_util.c73
-rw-r--r--src/tools/tor-fw-helper/tor-fw-helper-natpmp.c14
-rw-r--r--src/tools/tor-fw-helper/tor-fw-helper.c2
71 files changed, 748 insertions, 1084 deletions
diff --git a/changes/bug6174 b/changes/bug6174
new file mode 100644
index 0000000000..79d2930ec3
--- /dev/null
+++ b/changes/bug6174
@@ -0,0 +1,6 @@
+ o Major bugfixes:
+ - When we mark a circuit as unusable for new circuits, have it
+ continue to be unusable for new circuits even if MaxCircuitDirtiness
+ is increased too much at the wrong time, or the system clock jumped
+ backwards. Fix for bug 6174; bugfix on 0.0.2pre26.
+
diff --git a/changes/bug6206 b/changes/bug6206
new file mode 100644
index 0000000000..61a16d291a
--- /dev/null
+++ b/changes/bug6206
@@ -0,0 +1,6 @@
+ o Minor bugfixes:
+ - Always check the return values of functions fcntl() and
+ setsockopt(). We don't believe these are ever actually failing in
+ practice, but better safe than sorry. Also, checking these return
+ values should please some analysis tools (like Coverity). Patch
+ from 'flupzor'. Fix for bug 8206; bugfix on all versions of Tor.
diff --git a/changes/bug6673 b/changes/bug6673
new file mode 100644
index 0000000000..506b449892
--- /dev/null
+++ b/changes/bug6673
@@ -0,0 +1,4 @@
+ o Minor features (build):
+ - Detect and reject attempts to build Tor with threading support
+ when OpenSSL have been compiled with threading support disabled.
+ Fixes bug 6673.
diff --git a/changes/bug7280 b/changes/bug7280
new file mode 100644
index 0000000000..ef5d36a802
--- /dev/null
+++ b/changes/bug7280
@@ -0,0 +1,4 @@
+ o Minor bugfixes:
+ - Fix some bugs in tor-fw-helper-natpmp when trying to build and
+ run it on Windows. More bugs likely remain. Patch from Gisle Vanem.
+ Fixes bug 7280; bugfix on 0.2.3.1-alpha.
diff --git a/changes/bug7947 b/changes/bug7947
new file mode 100644
index 0000000000..6200ba2d8a
--- /dev/null
+++ b/changes/bug7947
@@ -0,0 +1,4 @@
+ o Minor bugfixes:
+ - Fix the handling of a TRUNCATE cell when it arrives while the circuit
+ extension is in progress. Fixes bug 7947; bugfix on 0.0.7.1.
+
diff --git a/changes/bug8014 b/changes/bug8014
new file mode 100644
index 0000000000..c09a86098c
--- /dev/null
+++ b/changes/bug8014
@@ -0,0 +1,5 @@
+ o Minor usability improvements (build):
+ - Clarify that when autconf is checking for nacl, it is checking
+ specifically for nacl with a fast curve25519 implementation.
+ Fixes bug 8014.
+
diff --git a/changes/bug8059 b/changes/bug8059
new file mode 100644
index 0000000000..47273ed0ac
--- /dev/null
+++ b/changes/bug8059
@@ -0,0 +1,6 @@
+ o Minor bugfixes (protocol conformance):
+ - Fix a misframing issue when reading the version numbers in a
+ VERSIONS cell. Previously we would recognize [00 01 00 02] as
+ 'version 1, version 2, and version 0x100', when it should have
+ only included versions 1 and 2. Fixes bug 8059; bugfix on
+ 0.2.0.10-alpha. Reported pseudonymously.
diff --git a/changes/bug8062 b/changes/bug8062
new file mode 100644
index 0000000000..805e51ed41
--- /dev/null
+++ b/changes/bug8062
@@ -0,0 +1,5 @@
+ o Minor bugfixes:
+ - Increase the width of the field used to remember a connection's
+ link protocol version to two bytes. Harmless for now, since the
+ only currently recognized versions are one byte long. Reported
+ pseudynmously. Fixes bug 8062, bugfix on 0.2.0.10-alpha.
diff --git a/changes/bug8180 b/changes/bug8180
new file mode 100644
index 0000000000..39e6ce7f9a
--- /dev/null
+++ b/changes/bug8180
@@ -0,0 +1,7 @@
+ o Minor bugfixes (security usability):
+ - Elevate the severity of the warning message when setting
+ EntryNodes but disabling UseGuardNodes to an error. The outcome
+ of letting Tor procede with those options enabled (which causes
+ EntryNodes to get ignored) is sufficiently different from what
+ was expected that it's best to just refuse to proceed. Fixes bug
+ 8180; bugfix on 0.2.3.11-alpha.
diff --git a/changes/bug8203 b/changes/bug8203
new file mode 100644
index 0000000000..d26dc0fccf
--- /dev/null
+++ b/changes/bug8203
@@ -0,0 +1,4 @@
+ o Minor bugfixes:
+ - Make the format and order of STREAM events for DNS lookups consistent
+ among the various ways to launch DNS lookups. Fix for bug 8203;
+ bugfix on 0.2.0.24-rc. Patch by "Desoxy."
diff --git a/changes/bug8231 b/changes/bug8231
new file mode 100644
index 0000000000..fd87a1daec
--- /dev/null
+++ b/changes/bug8231
@@ -0,0 +1,5 @@
+ o Major bugfixes:
+ - When unable to find any working directory nodes to use as a
+ directory guard, give up rather than adding the same non-working
+ nodes to the list over and over. Fixes bug 8231; bugfix on
+ 0.2.4.8-alpha.
diff --git a/changes/bug8273 b/changes/bug8273
new file mode 100644
index 0000000000..257f57e7ab
--- /dev/null
+++ b/changes/bug8273
@@ -0,0 +1,3 @@
+ o Critical bugfixes:
+ - When dirserv.c computes flags and thresholds, use measured bandwidths
+ in preference to advertised ones.
diff --git a/changes/bug8290 b/changes/bug8290
new file mode 100644
index 0000000000..d1fce7d8b5
--- /dev/null
+++ b/changes/bug8290
@@ -0,0 +1,9 @@
+ o Removed files:
+ - The tor-tsocks.conf is no longer distributed or installed. We
+ recommend that tsocks users use torsocks instead. Resolves
+ ticket 8290.
+
+ o Documentation fixes:
+ - The torify manpage no longer refers to tsocks; torify hasn't
+ supported tsocks since 0.2.3.14-alpha.
+ - The manpages no longer reference tsocks.
diff --git a/changes/bug8377 b/changes/bug8377
new file mode 100644
index 0000000000..c9ad151bc9
--- /dev/null
+++ b/changes/bug8377
@@ -0,0 +1,3 @@
+ o Minor bugfixes:
+ - Correctly recognize that [::1] is a loopback address. Fixes bug #8377;
+ bugfix on 0.2.1.3-alpha.
diff --git a/changes/bug8435 b/changes/bug8435
new file mode 100644
index 0000000000..da7ca7c1f8
--- /dev/null
+++ b/changes/bug8435
@@ -0,0 +1,4 @@
+ o Major bugfixes:
+ - When dirserv.c computes flags and thresholds, ignore advertised
+ bandwidths if we have more than a threshold number of routers with
+ measured bandwidths.
diff --git a/changes/bug8464 b/changes/bug8464
new file mode 100644
index 0000000000..74ff2e39ff
--- /dev/null
+++ b/changes/bug8464
@@ -0,0 +1,5 @@
+ o Minor bugfixes:
+ - Correct our check for which versions of Tor support the EXTEND2
+ cell. We had been willing to send it to Tor 0.2.4.7-alpha and
+ later, when support was really added in version 0.2.4.8-alpha.
+ Fixes bug 8464; bugfix on 0.2.4.8-alpha.
diff --git a/changes/bug8477-easypart b/changes/bug8477-easypart
new file mode 100644
index 0000000000..0f8f1031c5
--- /dev/null
+++ b/changes/bug8477-easypart
@@ -0,0 +1,3 @@
+ o Minor bugfixes:
+ - Log the purpose of a path-bias testing circuit correctly.
+ Improves a log message from bug 8477; bugfix on 0.2.4.8-alpha.
diff --git a/configure.ac b/configure.ac
index 4bc0db363f..d588984162 100644
--- a/configure.ac
+++ b/configure.ac
@@ -693,7 +693,7 @@ if test x$enable_curve25519 != xno; then
AC_CHECK_HEADERS([crypto_scalarmult_curve25519.h \
nacl/crypto_scalarmult_curve25519.h])
- AC_CACHE_CHECK([whether we can use curve25519 from nacl],
+ AC_CACHE_CHECK([for nacl compiled with a fast curve25519 implementation],
tor_cv_can_use_curve25519_nacl,
[tor_saved_LIBS="$LIBS"
LIBS="$LIBS -lnacl"
@@ -705,7 +705,7 @@ if test x$enable_curve25519 != xno; then
#include <nacl/crypto_scalarmult_curve25519.h>
#endif
#ifdef crypto_scalarmult_curve25519_ref_BYTES
- #error Hey, this is the reference implementation!
+ #error Hey, this is the reference implementation! That's not fast.
#endif
], [
unsigned char *a, *b, *c; crypto_scalarmult_curve25519(a,b,c);
diff --git a/contrib/include.am b/contrib/include.am
index 4a995a37d2..6d7fb16f9a 100644
--- a/contrib/include.am
+++ b/contrib/include.am
@@ -9,12 +9,9 @@ EXTRA_DIST+= \
contrib/tor-ctrl.sh \
contrib/tor-exit-notice.html \
contrib/tor-mingw.nsi.in \
- contrib/tor-tsocks.conf \
contrib/tor.ico \
contrib/tor.nsi.in \
contrib/tor.sh \
contrib/torctl
-conf_DATA+= contrib/tor-tsocks.conf
-
bin_SCRIPTS+= contrib/torify
diff --git a/contrib/tor-tsocks.conf b/contrib/tor-tsocks.conf
deleted file mode 100644
index 3dddaddbce..0000000000
--- a/contrib/tor-tsocks.conf
+++ /dev/null
@@ -1,13 +0,0 @@
-# This is the configuration for libtsocks (transparent socks) for use
-# with tor, which is providing a socks server on port 9050 by default.
-#
-# See tsocks.conf(5) and torify(1) manpages.
-
-server = 127.0.0.1
-server_port = 9050
-
-# We specify local as 127.0.0.0 - 127.191.255.255 because the
-# Tor MAPADDRESS virtual IP range is the rest of net 127.
-local = 127.0.0.0/255.128.0.0
-local = 127.128.0.0/255.192.0.0
-
diff --git a/doc/asciidoc-helper.sh b/doc/asciidoc-helper.sh
index dd420f7c4f..c06b57026b 100755
--- a/doc/asciidoc-helper.sh
+++ b/doc/asciidoc-helper.sh
@@ -52,8 +52,8 @@ elif [ "$1" = "man" ]; then
You need a working asciidoc installed to be able to build the manpage.
a2x is installed, but for some reason it isn't working. Sometimes
-This happens because required docbook support files are missing.
-Please install docbook-xsl, docbook-xml, and libxml2-utils (Debian) or
+this happens because required docbook support files are missing.
+Please install docbook-xsl, docbook-xml, and xmlto (Debian) or
similar. If you use homebrew on Mac OS X, install the docbook formula
and add "export XML_CATALOG_FILES=/usr/local/etc/xml/catalog" to your
.bashrc
diff --git a/doc/contrib/incentives.txt b/doc/contrib/incentives.txt
deleted file mode 100644
index 850a0d01e9..0000000000
--- a/doc/contrib/incentives.txt
+++ /dev/null
@@ -1,479 +0,0 @@
-
- Tor Incentives Design Brainstorms
-
-1. Goals: what do we want to achieve with an incentive scheme?
-
-1.1. Encourage users to provide good relay service (throughput, latency).
-1.2. Encourage users to allow traffic to exit the Tor network from
- their node.
-
-2. Approaches to learning who should get priority.
-
-2.1. "Hard" or quantitative reputation tracking.
-
- In this design, we track the number of bytes and throughput in and
- out of nodes we interact with. When a node asks to send or receive
- bytes, we provide service proportional to our current record of the
- node's value. One approach is to let each circuit be either a normal
- circuit or a premium circuit, and nodes can "spend" their value by
- sending and receiving bytes on premium circuits: see section 4.1 for
- details of this design. Another approach (section 4.2) would treat
- all traffic from the node with the same priority class, and so nodes
- that provide resources will get and provide better service on average.
-
- This approach could be complemented with an anonymous e-cash
- implementation to let people spend reputations gained from one context
- in another context.
-
-2.2. "Soft" or qualitative reputation tracking.
-
- Rather than accounting for every byte (if I owe you a byte, I don't
- owe it anymore once you've spent it), instead I keep a general opinion
- about each server: my opinion increases when they do good work for me,
- and it decays with time, but it does not decrease as they send traffic.
- Therefore we reward servers who provide value to the system without
- nickle and diming them at each step. We also let them benefit from
- relaying traffic for others without having to "reserve" some of the
- payment for their own use. See section 4.3 for a possible design.
-
-2.3. Centralized opinions from the reputation servers.
-
- The above approaches are complex and we don't have all the answers
- for them yet. A simpler approach is just to let some central set
- of trusted servers (say, the Tor directory servers) measure whether
- people are contributing to the network, and provide a signal about
- which servers should be rewarded. They can even do the measurements
- via Tor so servers can't easily perform only when they're being
- tested. See section 4.4.
-
-2.4. Reputation servers that aggregate opinions.
-
- The option above has the directory servers doing all of the
- measurements. This doesn't scale. We can set it up so we have "deputy
- testers" -- trusted other nodes that do performance testing and report
- their results.
-
- If we want to be really adventurous, we could even
- accept claims from every Tor user and build a complex weighting /
- reputation system to decide which claims are "probably" right.
- One possible way to implement the latter is something similar to
- EigenTrust [http://www.stanford.edu/~sdkamvar/papers/eigentrust.pdf],
- where the opinion of nodes with high reputation more is weighted
- higher.
-
-3. Related issues we need to keep in mind.
-
-3.1. Relay and exit configuration needs to be easy and usable.
-
- Implicit in all of the above designs is the need to make it easy to
- run a Tor server out of the box. We need to make it stable on all
- common platforms (including XP), it needs to detect its available
- bandwidth and not overreach that, and it needs to help the operator
- through opening up ports on his firewall. Then we need a slick GUI
- that lets people click a button or two rather than editing text files.
-
- Once we've done all this, we'll hit our first big question: is
- most of the barrier to growth caused by the unusability of the current
- software? If so, are the rest of these incentive schemes superfluous?
-
-3.2. The network effect: how many nodes will you interact with?
-
- One of the concerns with pairwise reputation systems is that as the
- network gets thousands of servers, the chance that you're going to
- interact with a given server decreases. So if 90% of interactions
- don't have any prior information, the "local" incentive schemes above
- are going to degrade. This doesn't mean they're pointless -- it just
- means we need to be aware that this is a limitation, and plan in the
- background for what step to take next. (It seems that e-cash solutions
- would scale better, though they have issues of their own.)
-
-3.3. Guard nodes
-
- As of Tor 0.1.1.11, Tor users pick from a small set of semi-permanent
- "guard nodes" for their first hop of each circuit. This seems like it
- would have a big impact on pairwise reputation systems since you
- will only be cashing in on your reputation to a few people, and it is
- unlikely that a given pair of nodes will use each other as guard nodes.
-
- What does this imply? For one, it means that we don't care at all
- about the opinions of most of the servers out there -- we should
- focus on keeping our guard nodes happy with us.
-
- One conclusion from that is that our design needs to judge performance
- not just through direct interaction (beginning of the circuit) but
- also through indirect interaction (middle of the circuit). That way
- you can never be sure when your guards are measuring you.
-
- Both 3.2 and 3.3 may be solved by having a global notion of reputation,
- as in 2.3 and 2.4. However, computing the global reputation from local
- views could be expensive (O(n^2)) when the network is really large.
-
-3.4. Restricted topology: benefits and roadmap.
-
- As the Tor network continues to grow, we will need to make design
- changes to the network topology so that each node does not need
- to maintain connections to an unbounded number of other nodes. For
- anonymity's sake, we may partition the network such that all
- the nodes have the same belief about the divisions and each node is
- in only one partition. (The alternative is that every user fetches
- his own random subset of the overall node list -- this is bad because
- of intersection attacks.)
-
- Therefore the "network horizon" for each user will stay bounded,
- which helps against the above issues in 3.2 and 3.3.
-
- It could be that the core of long-lived servers will all get to know
- each other, and so the critical point that decides whether you get
- good service is whether the core likes you. Or perhaps it will turn
- out to work some other way.
-
- A special case here is the social network, where the network isn't
- partitioned randomly but instead based on some external properties.
- Social network topologies can provide incentives in other ways, because
- people may be more inclined to help out their friends, and more willing
- to relay traffic if most of the traffic they are relaying comes
- from their friends. It also opens the door for out-of-band incentive
- schemes because of the out-of-band links in the graph.
-
-3.5. Profit-maximizing vs. Altruism.
-
- There are some interesting game theory questions here.
-
- First, in a volunteer culture, success is measured in public utility
- or in public esteem. If we add a reward mechanism, there's a risk that
- reward-maximizing behavior will surpass utility- or esteem-maximizing
- behavior.
-
- Specifically, if most of our servers right now are relaying traffic
- for the good of the community, we may actually *lose* those volunteers
- if we turn the act of relaying traffic into a selfish act.
-
- I am not too worried about this issue for now, since we're aiming
- for an incentive scheme so effective that it produces tens of
- thousands of new servers.
-
-3.6. What part of the node's performance do you measure?
-
- We keep referring to having a node measure how well the other nodes
- receive bytes. But don't leeching clients receive bytes just as well
- as servers?
-
- Further, many transactions in Tor involve fetching lots of
- bytes and not sending very many. So it seems that we want to turn
- things around: we need to measure how quickly a node is _sending_
- us bytes, and then only send it bytes in proportion to that.
-
- However, a sneaky user could simply connect to a node and send some
- traffic through it, and voila, he has performed for the network. This
- is no good. The first fix is that we only count if you're receiving
- bytes "backwards" in the circuit. Now the sneaky user needs to
- construct a circuit such that his node appears later in the circuit,
- and then send some bytes back quickly.
-
- Maybe that complexity is sufficient to deter most lazy users. Or
- maybe it's an argument in favor of a more penny-counting reputation
- approach.
-
- Addendum: I was more thinking of measuring based on who is the service
- provider and service receiver for the circuit. Say Alice builds a
- circuit to Bob. Then Bob is providing service to Alice, since he
- otherwise wouldn't need to spend his bandwidth. So traffic in either
- direction should be charged to Alice. Of course, the same attack would
- work, namely, Bob could cheat by sending bytes back quickly. So someone
- close to the origin needs to detect this and close the circuit, if
- necessary. -JN
-
-3.7. What is the appropriate resource balance for servers vs. clients?
-
- If we build a good incentive system, we'll still need to tune it
- to provide the right bandwidth allocation -- if we reserve too much
- bandwidth for fast servers, then we're wasting some potential, but
- if we reserve too little, then fewer people will opt to become servers.
- In fact, finding an optimum balance is especially hard because it's
- a moving target: the better our incentive mechanism (and the lower
- the barrier to setup), the more servers there will be. How do we find
- the right balance?
-
- One answer is that it doesn't have to be perfect: we can err on the
- side of providing extra resources to servers. Then we will achieve our
- desired goal -- when people complain about speed, we can tell them to
- run a server, and they will in fact get better performance.
-
-3.8. Anonymity attack: fast connections probably come from good servers.
-
- If only fast servers can consistently get good performance in the
- network, they will stand out. "Oh, that connection probably came from
- one of the top ten servers in the network." Intersection attacks over
- time can improve the certainty of the attack.
-
- I'm not too worried about this. First, in periods of low activity,
- many different people might be getting good performance. This dirties
- the intersection attack. Second, with many of these schemes, we will
- still be uncertain whether the fast node originated the traffic, or
- was the entry node for some other lucky user -- and we already accept
- this level of attack in other cases such as the Murdoch-Danezis attack
- [http://freehaven.net/anonbib/#torta05].
-
-3.9. How do we allocate bandwidth over the course of a second?
-
- This may be a simple matter of engineering, but it still needs to be
- addressed. Our current token bucket design refills each bucket once a
- second. If we have N tokens in our bucket, and we don't know ahead of
- time how many connections are going to want to send out how many bytes,
- how do we balance providing quick service to the traffic that is
- already here compared to providing service to potential high-importance
- future traffic?
-
- If we have only two classes of service, here is a simple design:
- At each point, when we are 1/t through the second, the total number
- of non-priority bytes we are willing to send out is N/t. Thus if N
- priority bytes are waiting at the beginning of the second, we drain
- our whole bucket then, and otherwise we provide some delayed service
- to the non-priority bytes.
-
- Does this design expand to cover the case of three priority classes?
- Ideally we'd give each remote server its own priority number. Or
- hopefully there's an easy design in the literature to point to --
- this is clearly not my field.
-
- Is our current flow control mechanism (each circuit and each stream
- start out with a certain window, and once they've exhausted it they
- need to receive an ack before they can send more) going to have
- problems with this new design now that we'll be queueing more bytes
- for less preferred nodes? If it turns out we do, the first fix is
- to have the windows start out at zero rather than start out full --
- it will slow down the startup phase but protect us better.
-
- While we have outgoing cells queued for a given server, we have the
- option of reordering them based on the priority of the previous hop.
- Is this going to turn out to be useful? If we're the exit node (that
- is, there is no previous hop) what priority do those cells get?
-
- Should we do this prioritizing just for sending out bytes (as I've
- described here) or would it help to do it also for receiving bytes?
- See next section.
-
-3.10. Different-priority cells arriving on the same TCP connection.
-
- In some of the proposed designs, servers want to give specific circuits
- priority rather than having all circuits from them get the same class
- of service.
-
- Since Tor uses TCP's flow control for rate limiting, this constraints
- our design choices -- it is easy to give different TCP connections
- different priorities, but it is hard to give different cells on the
- same connection priority, because you have to read them to know what
- priority they're supposed to get.
-
- There are several possible solutions though. First is that we rely on
- the sender to reorder them so the highest priority cells (circuits) are
- more often first. Second is that if we open two TCP connections -- one
- for the high-priority cells, and one for the low-priority cells. (But
- this prevents us from changing the priority of a circuit because
- we would need to migrate it from one connection to the other.) A
- third approach is to remember which connections have recently sent
- us high-priority cells, and preferentially read from those connections.
-
- Hopefully we can get away with not solving this section at all. But if
- necessary, we can consult Ed Knightly, a Professor at Rice
- [http://www.ece.rice.edu/~knightly/], for his extensive experience on
- networking QoS.
-
-3.11. Global reputation system: Congestion on high reputation servers?
-
- If the notion of reputation is global (as in 2.3 or 2.4), circuits that
- go through successive high reputation servers would be the fastest and
- most reliable. This would incentivize everyone, regardless of their own
- reputation, to choose only the highest reputation servers in its
- circuits, causing an over-congestion on those servers.
-
- One could argue, though, that once those servers are over-congested,
- their bandwidth per circuit drops, which would in turn lower their
- reputation in the future. A question is whether this would overall
- stabilize.
-
- Another possible way is to keep a cap on reputation. In this way, a
- fraction of servers would have the same high reputation, thus balancing
- such load.
-
-3.12. Another anonymity attack: learning from service levels.
-
- If reputation is local, it may be possible for an evil node to learn
- the identity of the origin through provision of differential service.
- For instance, the evil node provides crappy bandwidth to everyone,
- until it finds a circuit that it wants to trace the origin, then it
- provides good bandwidth. Now, as only those directly or indirectly
- observing this circuit would like the evil node, it can test each node
- by building a circuit via each node to another evil node. If the
- bandwidth is high, it is (somewhat) likely that the node was a part of
- the circuit.
-
- This problem does not exist if the reputation is global and nodes only
- follow the global reputation, i.e., completely ignore their own view.
-
-3.13. DoS through high priority traffic.
-
- Assume there is an evil node with high reputation (or high value on
- Alice) and this evil node wants to deny the service to Alice. What it
- needs to do is to send a lot of traffic to Alice. To Alice, all traffic
- from this evil node is of high priority. If the choice of circuits are
- too based toward high priority circuits, Alice would spend most of her
- available bandwidth on this circuit, thus providing poor bandwidth to
- everyone else. Everyone else would start to dislike Alice, making it
- even harder for her to forward other nodes' traffic. This could cause
- Alice to have a low reputation, and the only high bandwidth circuit
- Alice could use would be via the evil node.
-
-3.14. If you run a fast server, can you run your client elsewhere?
-
- A lot of people want to run a fast server at a colocation facility,
- and then reap the rewards using their cablemodem or DSL Tor client.
-
- If we use anonymous micropayments, where reputation can literally
- be transferred, this is trivial.
-
- If we pick a design where servers accrue reputation and can only
- use it themselves, though, the clients can configure the servers as
- their entry nodes and "inherit" their reputation. In this approach
- we would let servers configure a set of IP addresses or keys that get
- "like local" service.
-
-4. Sample designs.
-
-4.1. Two classes of service for circuits.
-
- Whenever a circuit is built, it is specified by the origin which class,
- either "premium" or "normal", this circuit belongs. A premium circuit
- gets preferred treatment at each node. A node "spends" its value, which
- it earned a priori by providing service, to the next node by sending
- and receiving bytes. Once a node has overspent its values, the circuit
- cannot stay as premium. It either breaks or converts into a normal
- circuit. Each node also reserves a small portion of bandwidth for
- normal circuits to prevent starvation.
-
- Pro: Even if a node has no value to spend, it can still use normal
- circuits. This allow casual user to use Tor without forcing them to run
- a server.
-
- Pro: Nodes have incentive to forward traffic as quick and as much as
- possible to accumulate value.
-
- Con: There is no proactive method for a node to rebalance its debt. It
- has to wait until there happens to be a circuit in the opposite
- direction.
-
- Con: A node needs to build circuits in such a way that each node in the
- circuit has to have good values to the next node. This requires
- non-local knowledge and makes circuits less reliable as the values are
- used up in the circuit.
-
- Con: May discourage nodes to forward traffic in some circuits, as they
- worry about spending more useful values to get less useful values in
- return.
-
-4.2. Treat all the traffic from the node with the same service;
- hard reputation system.
-
- This design is similar to 4.1, except that instead of having two
- classes of circuits, there is only one. All the circuits are
- prioritized based on the value of the interacting node.
-
- Pro: It is simpler to design and give priority based on connections,
- not circuits.
-
- Con: A node only needs to keep a few guard nodes happy to forward their
- traffic.
-
- Con: Same as in 4.1, may discourage nodes to forward traffic in some
- circuits, as they worry about spending more useful values to get less
- useful values in return.
-
-4.3. Treat all the traffic from the node with the same service;
- soft reputation system.
-
- Rather than a guaranteed system with accounting (as 4.1 and 4.2),
- we instead try for a best-effort system. All bytes are in the same
- class of service. You keep track of other Tors by key, and give them
- service proportional to the service they have given you. That is, in
- the past when you have tried to push bytes through them, you track the
- number of bytes and the average bandwidth, and use that to weight the
- priority of their connections if they try to push bytes through you.
-
- Now you're going to get minimum service if you don't ever push bytes
- for other people, and you get increasingly improved service the more
- active you are. We should have memories fade over time (we'll have
- to tune that, which could be quite hard).
-
- Pro: Sybil attacks are pointless because new identities get lowest
- priority.
-
- Pro: Smoothly handles periods of both low and high network load. Rather
- than keeping track of the ratio/difference between what he's done for
- you and what you've done for him, simply keep track of what he's done
- for you, and give him priority based on that.
-
- Based on 3.3 above, it seems we should reward all the nodes in our
- path, not just the first one -- otherwise the node can provide good
- service only to its guards. On the other hand, there might be a
- second-order effect where you want nodes to like you so that *when*
- your guards choose you for a circuit, they'll be able to get good
- performance. This tradeoff needs more simulation/analysis.
-
- This approach focuses on incenting people to relay traffic, but it
- doesn't do much for incenting them to allow exits. It may help in
- one way through: if there are few exits, then they will attract a
- lot of use, so lots of people will like them, so when they try to
- use the network they will find their first hop to be particularly
- pleasant. After that they're like the rest of the world though. (An
- alternative would be to reward exit nodes with higher values. At the
- extreme, we could even ask the directory servers to suggest the extra
- values, based on the current availability of exit nodes.)
-
- Pro: this is a pretty easy design to add; and it can be phased in
- incrementally simply by having new nodes behave differently.
-
-4.4. Centralized opinions from the reputation servers.
-
- Have a set of official measurers who spot-check servers from the
- directory to see if they really do offer roughly the bandwidth
- they advertise. Include these observations in the directory. (For
- simplicity, the directory servers could be the measurers.) Then Tor
- servers give priority to other servers. We'd like to weight the
- priority by advertised bandwidth to encourage people to donate more,
- but it seems hard to distinguish between a slow server and a busy
- server.
-
- The spot-checking can be done anonymously to prevent selectively
- performing only for the measurers, because hey, we have an anonymity
- network.
-
- We could also reward exit nodes by giving them better priority, but
- like above this only will affect their first hop. Another problem
- is that it's darn hard to spot-check whether a server allows exits
- to all the pieces of the Internet that it claims to. If necessary,
- perhaps this can be solved by a distributed reporting mechanism,
- where clients that can reach a site from one exit but not another
- anonymously submit that site to the measurers, who verify.
-
- A last problem is that since directory servers will be doing their
- tests directly (easy to detect) or indirectly (through other Tor
- servers), then we know that we can get away with poor performance for
- people that aren't listed in the directory. Maybe we can turn this
- around and call it a feature though -- another reason to get listed
- in the directory.
-
-5. Recommendations and next steps.
-
-5.1. Simulation.
-
- For simulation trace, we can use two: one is what we obtained from Tor
- and one from existing web traces.
-
- We want to simulate all the four cases in 4.1-4. For 4.4, we may want
- to look at two variations: (1) the directory servers check the
- bandwidth themselves through Tor; (2) each node reports their perceived
- values on other nodes, while the directory servers use EigenTrust to
- compute global reputation and broadcast those.
-
-5.2. Deploying into existing Tor network.
-
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index 505a0834b5..b73d4a05dd 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -2139,7 +2139,7 @@ __HiddenServiceDirectory__**/client_keys**::
SEE ALSO
--------
-**privoxy**(1), **tsocks**(1), **torify**(1) +
+**privoxy**(1), **torsocks**(1), **torify**(1) +
**https://www.torproject.org/**
diff --git a/doc/torify.1.txt b/doc/torify.1.txt
index 22b3fe5370..8dca901317 100644
--- a/doc/torify.1.txt
+++ b/doc/torify.1.txt
@@ -9,7 +9,7 @@ torify(1)
NAME
----
-torify - wrapper for torsocks or tsocks and tor
+torify - wrapper for torsocks and tor
SYNOPSIS
--------
@@ -18,36 +18,24 @@ SYNOPSIS
DESCRIPTION
-----------
**torify** is a simple wrapper that attempts to find the best underlying Tor
-wrapper available on a system. It calls torsocks or tsocks with a tor specific
+wrapper available on a system. It calls torsocks with a tor specific
configuration file. +
torsocks is an improved wrapper that explicitly rejects UDP, safely resolves DNS
lookups and properly socksifies your TCP connections. +
-tsocks itself is a wrapper between the tsocks library and the application that
-you would like to run socksified. +
-
Please note that since both method use LD_PRELOAD, torify cannot be applied to
suid binaries.
WARNING
-------
-You should also be aware that the way tsocks currently works only TCP
-connections are socksified. Be aware that this will in most circumstances not
-include hostname lookups which would still be routed through your normal system
-resolver to your usual resolving nameservers. The **tor-resolve**(1) tool can be
-useful as a workaround in some cases. The Tor FAQ at
-https://wiki.torproject.org/noreply/TheOnionRouter/TorFAQ might have further
-information on this subject. +
-
When used with torsocks, torify should not leak DNS requests or UDP data. +
Both will leak ICMP data.
SEE ALSO
--------
-**tor**(1), **tor-resolve**(1), **torsocks**(1), **tsocks**(1),
-**tsocks.conf**(5).
+**tor**(1), **tor-resolve**(1), **torsocks**(1)
AUTHORS
-------
diff --git a/src/common/address.c b/src/common/address.c
index 6fc9fb3c47..227b4fbaee 100644
--- a/src/common/address.c
+++ b/src/common/address.c
@@ -817,7 +817,8 @@ tor_addr_is_loopback(const tor_addr_t *addr)
case AF_INET6: {
/* ::1 */
uint32_t *a32 = tor_addr_to_in6_addr32(addr);
- return (a32[0] == 0) && (a32[1] == 0) && (a32[2] == 0) && (a32[3] == 1);
+ return (a32[0] == 0) && (a32[1] == 0) && (a32[2] == 0) &&
+ (ntohl(a32[3]) == 1);
}
case AF_INET:
/* 127.0.0.1 */
@@ -1565,32 +1566,6 @@ addr_mask_get_bits(uint32_t mask)
return -1;
}
-/** Compare two addresses <b>a1</b> and <b>a2</b> for equality under a
- * netmask of <b>mbits</b> bits. Return -1, 0, or 1.
- *
- * XXXX_IP6 Temporary function to allow masks as bitcounts everywhere. This
- * will be replaced with an IPv6-aware version as soon as 32-bit addresses are
- * no longer passed around.
- */
-int
-addr_mask_cmp_bits(uint32_t a1, uint32_t a2, maskbits_t bits)
-{
- if (bits > 32)
- bits = 32;
- else if (bits == 0)
- return 0;
-
- a1 >>= (32-bits);
- a2 >>= (32-bits);
-
- if (a1 < a2)
- return -1;
- else if (a1 > a2)
- return 1;
- else
- return 0;
-}
-
/** Parse a string <b>s</b> in the format of (*|port(-maxport)?)?, setting the
* various *out pointers as appropriate. Return 0 on success, -1 on failure.
*/
@@ -1643,93 +1618,6 @@ parse_port_range(const char *port, uint16_t *port_min_out,
return 0;
}
-/** Parse a string <b>s</b> in the format of
- * (IP(/mask|/mask-bits)?|*)(:(*|port(-maxport))?)?, setting the various
- * *out pointers as appropriate. Return 0 on success, -1 on failure.
- */
-int
-parse_addr_and_port_range(const char *s, uint32_t *addr_out,
- maskbits_t *maskbits_out, uint16_t *port_min_out,
- uint16_t *port_max_out)
-{
- char *address;
- char *mask, *port, *endptr;
- struct in_addr in;
- int bits;
-
- tor_assert(s);
- tor_assert(addr_out);
- tor_assert(maskbits_out);
- tor_assert(port_min_out);
- tor_assert(port_max_out);
-
- address = tor_strdup(s);
- /* Break 'address' into separate strings.
- */
- mask = strchr(address,'/');
- port = strchr(mask?mask:address,':');
- if (mask)
- *mask++ = '\0';
- if (port)
- *port++ = '\0';
- /* Now "address" is the IP|'*' part...
- * "mask" is the Mask|Maskbits part...
- * and "port" is the *|port|min-max part.
- */
-
- if (strcmp(address,"*")==0) {
- *addr_out = 0;
- } else if (tor_inet_aton(address, &in) != 0) {
- *addr_out = ntohl(in.s_addr);
- } else {
- log_warn(LD_GENERAL, "Malformed IP %s in address pattern; rejecting.",
- escaped(address));
- goto err;
- }
-
- if (!mask) {
- if (strcmp(address,"*")==0)
- *maskbits_out = 0;
- else
- *maskbits_out = 32;
- } else {
- endptr = NULL;
- bits = (int) strtol(mask, &endptr, 10);
- if (!*endptr) {
- /* strtol handled the whole mask. */
- if (bits < 0 || bits > 32) {
- log_warn(LD_GENERAL,
- "Bad number of mask bits on address range; rejecting.");
- goto err;
- }
- *maskbits_out = bits;
- } else if (tor_inet_aton(mask, &in) != 0) {
- bits = addr_mask_get_bits(ntohl(in.s_addr));
- if (bits < 0) {
- log_warn(LD_GENERAL,
- "Mask %s on address range isn't a prefix; dropping",
- escaped(mask));
- goto err;
- }
- *maskbits_out = bits;
- } else {
- log_warn(LD_GENERAL,
- "Malformed mask %s on address range; rejecting.",
- escaped(mask));
- goto err;
- }
- }
-
- if (parse_port_range(port, port_min_out, port_max_out)<0)
- goto err;
-
- tor_free(address);
- return 0;
- err:
- tor_free(address);
- return -1;
-}
-
/** Given an IPv4 in_addr struct *<b>in</b> (in network order, as usual),
* write it as a string into the <b>buf_len</b>-byte buffer in
* <b>buf</b>.
diff --git a/src/common/address.h b/src/common/address.h
index 9cbc32ce9b..77e5855346 100644
--- a/src/common/address.h
+++ b/src/common/address.h
@@ -219,11 +219,7 @@ int addr_port_lookup(int severity, const char *addrport, char **address,
uint32_t *addr, uint16_t *port_out);
int parse_port_range(const char *port, uint16_t *port_min_out,
uint16_t *port_max_out);
-int parse_addr_and_port_range(const char *s, uint32_t *addr_out,
- maskbits_t *maskbits_out, uint16_t *port_min_out,
- uint16_t *port_max_out);
int addr_mask_get_bits(uint32_t mask);
-int addr_mask_cmp_bits(uint32_t a1, uint32_t a2, maskbits_t bits);
/** Length of a buffer to allocate to hold the results of tor_inet_ntoa.*/
#define INET_NTOA_BUF_LEN 16
int tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len);
diff --git a/src/common/compat.c b/src/common/compat.c
index d7ce89479a..4fa9fee42e 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -137,8 +137,13 @@ tor_open_cloexec(const char *path, int flags, unsigned mode)
fd = open(path, flags, mode);
#ifdef FD_CLOEXEC
- if (fd >= 0)
- fcntl(fd, F_SETFD, FD_CLOEXEC);
+ if (fd >= 0) {
+ if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
+ log_warn(LD_FS,"Couldn't set FD_CLOEXEC: %s", strerror(errno));
+ close(fd);
+ return -1;
+ }
+ }
#endif
return fd;
}
@@ -150,8 +155,13 @@ tor_fopen_cloexec(const char *path, const char *mode)
{
FILE *result = fopen(path, mode);
#ifdef FD_CLOEXEC
- if (result != NULL)
- fcntl(fileno(result), F_SETFD, FD_CLOEXEC);
+ if (result != NULL) {
+ if (fcntl(fileno(result), F_SETFD, FD_CLOEXEC) == -1) {
+ log_warn(LD_FS,"Couldn't set FD_CLOEXEC: %s", strerror(errno));
+ fclose(result);
+ return NULL;
+ }
+ }
#endif
return result;
}
@@ -1024,7 +1034,15 @@ tor_open_socket(int domain, int type, int protocol)
return s;
#if defined(FD_CLOEXEC)
- fcntl(s, F_SETFD, FD_CLOEXEC);
+ if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1) {
+ log_warn(LD_FS,"Couldn't set FD_CLOEXEC: %s", strerror(errno));
+#if defined(_WIN32)
+ closesocket(s);
+#else
+ close(s);
+#endif
+ return -1;
+ }
#endif
goto socket_ok; /* So that socket_ok will not be unused. */
@@ -1059,7 +1077,11 @@ tor_accept_socket(tor_socket_t sockfd, struct sockaddr *addr, socklen_t *len)
return s;
#if defined(FD_CLOEXEC)
- fcntl(s, F_SETFD, FD_CLOEXEC);
+ if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1) {
+ log_warn(LD_NET, "Couldn't set FD_CLOEXEC: %s", strerror(errno));
+ close(s);
+ return TOR_INVALID_SOCKET;
+ }
#endif
goto socket_ok; /* So that socket_ok will not be unused. */
@@ -1083,17 +1105,31 @@ get_n_open_sockets(void)
return n;
}
-/** Turn <b>socket</b> into a nonblocking socket.
+/** Turn <b>socket</b> into a nonblocking socket. Return 0 on success, -1
+ * on failure.
*/
-void
+int
set_socket_nonblocking(tor_socket_t socket)
{
#if defined(_WIN32)
unsigned long nonblocking = 1;
ioctlsocket(socket, FIONBIO, (unsigned long*) &nonblocking);
#else
- fcntl(socket, F_SETFL, O_NONBLOCK);
+ int flags;
+
+ flags = fcntl(socket, F_GETFL, 0);
+ if (flags == -1) {
+ log_warn(LD_NET, "Couldn't get file status flags: %s", strerror(errno));
+ return -1;
+ }
+ flags |= O_NONBLOCK;
+ if (fcntl(socket, F_SETFL, flags) == -1) {
+ log_warn(LD_NET, "Couldn't set file status flags: %s", strerror(errno));
+ return -1;
+ }
#endif
+
+ return 0;
}
/**
@@ -1136,10 +1172,22 @@ tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2])
return -errno;
#if defined(FD_CLOEXEC)
- if (SOCKET_OK(fd[0]))
- fcntl(fd[0], F_SETFD, FD_CLOEXEC);
- if (SOCKET_OK(fd[1]))
- fcntl(fd[1], F_SETFD, FD_CLOEXEC);
+ if (SOCKET_OK(fd[0])) {
+ r = fcntl(fd[0], F_SETFD, FD_CLOEXEC);
+ if (r == -1) {
+ close(fd[0]);
+ close(fd[1]);
+ return -errno;
+ }
+ }
+ if (SOCKET_OK(fd[1])) {
+ r = fcntl(fd[1], F_SETFD, FD_CLOEXEC);
+ if (r == -1) {
+ close(fd[0]);
+ close(fd[1]);
+ return -errno;
+ }
+ }
#endif
goto sockets_ok; /* So that sockets_ok will not be unused. */
diff --git a/src/common/compat.h b/src/common/compat.h
index f9eb4ba0be..f0a34aae41 100644
--- a/src/common/compat.h
+++ b/src/common/compat.h
@@ -518,7 +518,7 @@ int tor_inet_aton(const char *cp, struct in_addr *addr) ATTR_NONNULL((1,2));
const char *tor_inet_ntop(int af, const void *src, char *dst, size_t len);
int tor_inet_pton(int af, const char *src, void *dst);
int tor_lookup_hostname(const char *name, uint32_t *addr) ATTR_NONNULL((1,2));
-void set_socket_nonblocking(tor_socket_t socket);
+int set_socket_nonblocking(tor_socket_t socket);
int tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2]);
int network_init(void);
diff --git a/src/common/container.h b/src/common/container.h
index e247fb7ea6..1a68b8f67b 100644
--- a/src/common/container.h
+++ b/src/common/container.h
@@ -675,11 +675,6 @@ median_int32(int32_t *array, int n_elements)
{
return find_nth_int32(array, n_elements, (n_elements-1)/2);
}
-static INLINE long
-median_long(long *array, int n_elements)
-{
- return find_nth_long(array, n_elements, (n_elements-1)/2);
-}
#endif
diff --git a/src/common/crypto.c b/src/common/crypto.c
index 22d57c7c8a..949fd52eb2 100644
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@ -113,8 +113,8 @@ crypto_get_rsa_padding_overhead(int padding)
{
switch (padding)
{
- case RSA_PKCS1_OAEP_PADDING: return 42;
- case RSA_PKCS1_PADDING: return 11;
+ case RSA_PKCS1_OAEP_PADDING: return PKCS1_OAEP_PADDING_OVERHEAD;
+ case RSA_PKCS1_PADDING: return PKCS1_PADDING_OVERHEAD;
default: tor_assert(0); return -1;
}
}
@@ -1294,23 +1294,6 @@ crypto_pk_get_fingerprint(crypto_pk_t *pk, char *fp_out, int add_space)
return 0;
}
-/** Return true iff <b>s</b> is in the correct format for a fingerprint.
- */
-int
-crypto_pk_check_fingerprint_syntax(const char *s)
-{
- int i;
- for (i = 0; i < FINGERPRINT_LEN; ++i) {
- if ((i%5) == 4) {
- if (!TOR_ISSPACE(s[i])) return 0;
- } else {
- if (!TOR_ISXDIGIT(s[i])) return 0;
- }
- }
- if (s[FINGERPRINT_LEN]) return 0;
- return 1;
-}
-
/* symmetric crypto */
/** Return a pointer to the key set for the cipher in <b>env</b>.
@@ -3000,6 +2983,12 @@ memwipe(void *mem, uint8_t byte, size_t sz)
}
#ifdef TOR_IS_MULTITHREADED
+
+#ifndef OPENSSL_THREADS
+#error OpenSSL has been built without thread support. Tor requires an \
+ OpenSSL library with thread support enabled.
+#endif
+
/** Helper: OpenSSL uses this callback to manipulate mutexes. */
static void
openssl_locking_cb_(int mode, int n, const char *file, int line)
diff --git a/src/common/crypto.h b/src/common/crypto.h
index 12fcfae27e..b783230780 100644
--- a/src/common/crypto.h
+++ b/src/common/crypto.h
@@ -183,7 +183,6 @@ crypto_pk_t *crypto_pk_asn1_decode(const char *str, size_t len);
int crypto_pk_get_digest(crypto_pk_t *pk, char *digest_out);
int crypto_pk_get_all_digests(crypto_pk_t *pk, digests_t *digests_out);
int crypto_pk_get_fingerprint(crypto_pk_t *pk, char *fp_out,int add_space);
-int crypto_pk_check_fingerprint_syntax(const char *s);
/* symmetric crypto */
const char *crypto_cipher_get_key(crypto_cipher_t *env);
diff --git a/src/common/util.c b/src/common/util.c
index 6a69635594..17fb9496cd 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -1176,119 +1176,10 @@ escaped(const char *s)
return escaped_val_;
}
-/** Rudimentary string wrapping code: given a un-wrapped <b>string</b> (no
- * newlines!), break the string into newline-terminated lines of no more than
- * <b>width</b> characters long (not counting newline) and insert them into
- * <b>out</b> in order. Precede the first line with prefix0, and subsequent
- * lines with prefixRest.
- */
-/* This uses a stupid greedy wrapping algorithm right now:
- * - For each line:
- * - Try to fit as much stuff as possible, but break on a space.
- * - If the first "word" of the line will extend beyond the allowable
- * width, break the word at the end of the width.
- */
-void
-wrap_string(smartlist_t *out, const char *string, size_t width,
- const char *prefix0, const char *prefixRest)
-{
- size_t p0Len, pRestLen, pCurLen;
- const char *eos, *prefixCur;
- tor_assert(out);
- tor_assert(string);
- tor_assert(width);
- if (!prefix0)
- prefix0 = "";
- if (!prefixRest)
- prefixRest = "";
-
- p0Len = strlen(prefix0);
- pRestLen = strlen(prefixRest);
- tor_assert(width > p0Len && width > pRestLen);
- eos = strchr(string, '\0');
- tor_assert(eos);
- pCurLen = p0Len;
- prefixCur = prefix0;
-
- while ((eos-string)+pCurLen > width) {
- const char *eol = string + width - pCurLen;
- while (eol > string && *eol != ' ')
- --eol;
- /* eol is now the last space that can fit, or the start of the string. */
- if (eol > string) {
- size_t line_len = (eol-string) + pCurLen + 2;
- char *line = tor_malloc(line_len);
- memcpy(line, prefixCur, pCurLen);
- memcpy(line+pCurLen, string, eol-string);
- line[line_len-2] = '\n';
- line[line_len-1] = '\0';
- smartlist_add(out, line);
- string = eol + 1;
- } else {
- size_t line_len = width + 2;
- char *line = tor_malloc(line_len);
- memcpy(line, prefixCur, pCurLen);
- memcpy(line+pCurLen, string, width - pCurLen);
- line[line_len-2] = '\n';
- line[line_len-1] = '\0';
- smartlist_add(out, line);
- string += width-pCurLen;
- }
- prefixCur = prefixRest;
- pCurLen = pRestLen;
- }
-
- if (string < eos) {
- size_t line_len = (eos-string) + pCurLen + 2;
- char *line = tor_malloc(line_len);
- memcpy(line, prefixCur, pCurLen);
- memcpy(line+pCurLen, string, eos-string);
- line[line_len-2] = '\n';
- line[line_len-1] = '\0';
- smartlist_add(out, line);
- }
-}
-
/* =====
* Time
* ===== */
-/**
- * Converts struct timeval to a double value.
- * Preserves microsecond precision, but just barely.
- * Error is approx +/- 0.1 usec when dealing with epoch values.
- */
-double
-tv_to_double(const struct timeval *tv)
-{
- double conv = tv->tv_sec;
- conv += tv->tv_usec/1000000.0;
- return conv;
-}
-
-/**
- * Converts timeval to milliseconds.
- */
-int64_t
-tv_to_msec(const struct timeval *tv)
-{
- int64_t conv = ((int64_t)tv->tv_sec)*1000L;
- /* Round ghetto-style */
- conv += ((int64_t)tv->tv_usec+500)/1000L;
- return conv;
-}
-
-/**
- * Converts timeval to microseconds.
- */
-int64_t
-tv_to_usec(const struct timeval *tv)
-{
- int64_t conv = ((int64_t)tv->tv_sec)*1000000L;
- conv += tv->tv_usec;
- return conv;
-}
-
/** Return the number of microseconds elapsed between *start and *end.
*/
long
diff --git a/src/common/util.h b/src/common/util.h
index ac88f1ca1c..8206a6d8a4 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -112,7 +112,6 @@ extern int dmalloc_free(const char *file, const int line, void *pnt,
#define tor_malloc(size) tor_malloc_(size DMALLOC_ARGS)
#define tor_malloc_zero(size) tor_malloc_zero_(size DMALLOC_ARGS)
#define tor_calloc(nmemb,size) tor_calloc_(nmemb, size DMALLOC_ARGS)
-#define tor_malloc_roundup(szp) _tor_malloc_roundup(szp DMALLOC_ARGS)
#define tor_realloc(ptr, size) tor_realloc_(ptr, size DMALLOC_ARGS)
#define tor_strdup(s) tor_strdup_(s DMALLOC_ARGS)
#define tor_strndup(s, n) tor_strndup_(s, n DMALLOC_ARGS)
@@ -216,8 +215,6 @@ int tor_digest256_is_zero(const char *digest);
char *esc_for_log(const char *string) ATTR_MALLOC;
const char *escaped(const char *string);
struct smartlist_t;
-void wrap_string(struct smartlist_t *out, const char *string, size_t width,
- const char *prefix0, const char *prefixRest);
int tor_vsscanf(const char *buf, const char *pattern, va_list ap)
#ifdef __GNUC__
__attribute__((format(scanf, 2, 0)))
@@ -240,9 +237,6 @@ void base16_encode(char *dest, size_t destlen, const char *src, size_t srclen);
int base16_decode(char *dest, size_t destlen, const char *src, size_t srclen);
/* Time helpers */
-double tv_to_double(const struct timeval *tv);
-int64_t tv_to_msec(const struct timeval *tv);
-int64_t tv_to_usec(const struct timeval *tv);
long tv_udiff(const struct timeval *start, const struct timeval *end);
long tv_mdiff(const struct timeval *start, const struct timeval *end);
int tor_timegm(const struct tm *tm, time_t *time_out);
diff --git a/src/ext/eventdns.c b/src/ext/eventdns.c
index 3ee9f72459..66280cccdb 100644
--- a/src/ext/eventdns.c
+++ b/src/ext/eventdns.c
@@ -2306,7 +2306,12 @@ _evdns_nameserver_add_impl(const struct sockaddr *address,
ioctlsocket(ns->socket, FIONBIO, &nonblocking);
}
#else
- fcntl(ns->socket, F_SETFL, O_NONBLOCK);
+ if (fcntl(ns->socket, F_SETFL, O_NONBLOCK) == -1) {
+ evdns_log(EVDNS_LOG_WARN, "Error %s (%d) while settings file status flags.",
+ tor_socket_strerror(errno), errno);
+ err = 2;
+ goto out2;
+ }
#endif
if (global_bind_addr_is_set &&
diff --git a/src/or/channeltls.c b/src/or/channeltls.c
index 1035a14127..60693daeb2 100644
--- a/src/or/channeltls.c
+++ b/src/or/channeltls.c
@@ -1208,7 +1208,7 @@ channel_tls_process_versions_cell(var_cell_t *cell, channel_tls_t *chan)
tor_assert(chan->conn->handshake_state);
end = cell->payload + cell->payload_len;
- for (cp = cell->payload; cp+1 < end; ++cp) {
+ for (cp = cell->payload; cp+1 < end; cp += 2) {
uint16_t v = ntohs(get_uint16(cp));
if (is_or_protocol_version_known(v) && v > highest_supported_version)
highest_supported_version = v;
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index fbe94a98ba..8e768e76f5 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -901,7 +901,7 @@ circuit_note_clock_jumped(int seconds_elapsed)
control_event_client_status(severity, "CIRCUIT_NOT_ESTABLISHED REASON=%s",
"CLOCK_JUMPED");
circuit_mark_all_unused_circs();
- circuit_expire_all_dirty_circs();
+ circuit_mark_all_dirty_circs_as_unusable();
}
/** Take the 'extend' <b>cell</b>, pull out addr/port plus the onion
@@ -3398,6 +3398,7 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state)
});
}
/* and exclude current entry guards and their families, if applicable */
+ /*XXXX025 use the using_as_guard flag to accomplish this.*/
if (options->UseEntryGuards) {
SMARTLIST_FOREACH(get_entry_guards(), const entry_guard_t *, entry,
{
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index eab3ebff2d..1903fbe2eb 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -532,6 +532,9 @@ circuit_purpose_to_string(uint8_t purpose)
case CIRCUIT_PURPOSE_CONTROLLER:
return "Circuit made by controller";
+ case CIRCUIT_PURPOSE_PATH_BIAS_TESTING:
+ return "Path-bias testing circuit";
+
default:
tor_snprintf(buf, sizeof(buf), "UNKNOWN_%d", (int)purpose);
return buf;
@@ -1206,6 +1209,7 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
if ((!need_uptime || circ->build_state->need_uptime) &&
(!need_capacity || circ->build_state->need_capacity) &&
(internal == circ->build_state->is_internal) &&
+ !circ->unusable_for_new_conns &&
circ->remaining_relay_early_cells &&
circ->build_state->desired_path_len == DEFAULT_ROUTE_LEN &&
!circ->build_state->onehop_tunnel &&
@@ -1301,20 +1305,17 @@ circuit_mark_all_unused_circs(void)
* This is useful for letting the user change pseudonyms, so new
* streams will not be linkable to old streams.
*/
-/* XXX024 this is a bad name for what this function does */
void
-circuit_expire_all_dirty_circs(void)
+circuit_mark_all_dirty_circs_as_unusable(void)
{
circuit_t *circ;
- const or_options_t *options = get_options();
for (circ=global_circuitlist; circ; circ = circ->next) {
if (CIRCUIT_IS_ORIGIN(circ) &&
!circ->marked_for_close &&
- circ->timestamp_dirty)
- /* XXXX024 This is a screwed-up way to say "This is too dirty
- * for new circuits. */
- circ->timestamp_dirty -= options->MaxCircuitDirtiness;
+ circ->timestamp_dirty) {
+ mark_circuit_unusable_for_new_conns(TO_ORIGIN_CIRCUIT(circ));
+ }
}
}
diff --git a/src/or/circuitlist.h b/src/or/circuitlist.h
index e81c0785fe..d67f80b065 100644
--- a/src/or/circuitlist.h
+++ b/src/or/circuitlist.h
@@ -46,7 +46,7 @@ or_circuit_t *circuit_get_intro_point(const char *digest);
origin_circuit_t *circuit_find_to_cannibalize(uint8_t purpose,
extend_info_t *info, int flags);
void circuit_mark_all_unused_circs(void);
-void circuit_expire_all_dirty_circs(void);
+void circuit_mark_all_dirty_circs_as_unusable(void);
void circuit_mark_for_close_(circuit_t *circ, int reason,
int line, const char *file);
int circuit_get_cpath_len(origin_circuit_t *circ);
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 6b5ca90110..d48449fa81 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -85,10 +85,14 @@ circuit_is_acceptable(const origin_circuit_t *origin_circ,
}
if (purpose == CIRCUIT_PURPOSE_C_GENERAL ||
- purpose == CIRCUIT_PURPOSE_C_REND_JOINED)
+ purpose == CIRCUIT_PURPOSE_C_REND_JOINED) {
if (circ->timestamp_dirty &&
circ->timestamp_dirty+get_options()->MaxCircuitDirtiness <= now)
return 0;
+ }
+
+ if (origin_circ->unusable_for_new_conns)
+ return 0;
/* decide if this circ is suitable for this conn */
@@ -806,9 +810,12 @@ circuit_stream_is_being_handled(entry_connection_t *conn,
circ->purpose == CIRCUIT_PURPOSE_C_GENERAL &&
(!circ->timestamp_dirty ||
circ->timestamp_dirty + get_options()->MaxCircuitDirtiness > now)) {
- cpath_build_state_t *build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
+ origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
+ cpath_build_state_t *build_state = origin_circ->build_state;
if (build_state->is_internal || build_state->onehop_tunnel)
continue;
+ if (!origin_circ->unusable_for_new_conns)
+ continue;
exitnode = build_state_get_exit_node(build_state);
if (exitnode && (!need_uptime || build_state->need_uptime)) {
@@ -850,6 +857,7 @@ circuit_predict_and_launch_new(void)
/* First, count how many of each type of circuit we have already. */
for (circ=global_circuitlist;circ;circ = circ->next) {
cpath_build_state_t *build_state;
+ origin_circuit_t *origin_circ;
if (!CIRCUIT_IS_ORIGIN(circ))
continue;
if (circ->marked_for_close)
@@ -858,7 +866,10 @@ circuit_predict_and_launch_new(void)
continue; /* only count clean circs */
if (circ->purpose != CIRCUIT_PURPOSE_C_GENERAL)
continue; /* only pay attention to general-purpose circs */
- build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
+ origin_circ = TO_ORIGIN_CIRCUIT(circ);
+ if (origin_circ->unusable_for_new_conns)
+ continue;
+ build_state = origin_circ->build_state;
if (build_state->onehop_tunnel)
continue;
num++;
@@ -2282,3 +2293,22 @@ circuit_change_purpose(circuit_t *circ, uint8_t new_purpose)
}
}
+/** Mark <b>circ</b> so that no more connections can be attached to it. */
+void
+mark_circuit_unusable_for_new_conns(origin_circuit_t *circ)
+{
+ const or_options_t *options = get_options();
+ tor_assert(circ);
+
+ /* XXXX025 This is a kludge; we're only keeping it around in case there's
+ * something that doesn't check unusable_for_new_conns, and to avoid
+ * deeper refactoring of our expiration logic. */
+ if (! circ->base_.timestamp_dirty)
+ circ->base_.timestamp_dirty = approx_time();
+ if (options->MaxCircuitDirtiness >= circ->base_.timestamp_dirty)
+ circ->base_.timestamp_dirty = 1; /* prevent underflow */
+ else
+ circ->base_.timestamp_dirty -= options->MaxCircuitDirtiness;
+
+ circ->unusable_for_new_conns = 1;
+}
diff --git a/src/or/circuituse.h b/src/or/circuituse.h
index d4d68aad92..11e5a64163 100644
--- a/src/or/circuituse.h
+++ b/src/or/circuituse.h
@@ -55,6 +55,7 @@ void circuit_change_purpose(circuit_t *circ, uint8_t new_purpose);
int hostname_in_track_host_exits(const or_options_t *options,
const char *address);
+void mark_circuit_unusable_for_new_conns(origin_circuit_t *circ);
#endif
diff --git a/src/or/config.c b/src/or/config.c
index 15138f9d7b..0ebf3b6942 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2001 Matej Pfajfar.
+ /* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2013, The Tor Project, Inc. */
@@ -300,6 +300,7 @@ static config_var_t option_vars_[] = {
V(MaxClientCircuitsPending, UINT, "32"),
OBSOLETE("MaxOnionsPending"),
V(MaxOnionQueueDelay, MSEC_INTERVAL, "1750 msec"),
+ V(MinMeasuredBWsForAuthToIgnoreAdvertised, INT, "500"),
OBSOLETE("MonthlyAccountingStart"),
V(MyFamily, STRING, NULL),
V(NewCircuitPeriod, INTERVAL, "30 seconds"),
@@ -1502,7 +1503,7 @@ options_act(const or_options_t *old_options)
"preferred or excluded node lists. "
"Abandoning previous circuits.");
circuit_mark_all_unused_circs();
- circuit_expire_all_dirty_circs();
+ circuit_mark_all_dirty_circs_as_unusable();
revise_trackexithosts = 1;
}
@@ -2601,9 +2602,9 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (options->UseBridges && options->EntryNodes)
REJECT("You cannot set both UseBridges and EntryNodes.");
- if (options->EntryNodes && !options->UseEntryGuards)
- log_warn(LD_CONFIG, "EntryNodes is set, but UseEntryGuards is disabled. "
- "EntryNodes will be ignored.");
+ if (options->EntryNodes && !options->UseEntryGuards) {
+ REJECT("If EntryNodes is set, UseEntryGuards must be enabled.");
+ }
options->AllowInvalid_ = 0;
if (options->AllowInvalidNodes) {
diff --git a/src/or/connection.c b/src/or/connection.c
index c659e65fe5..622eadcff9 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -918,8 +918,11 @@ make_socket_reuseable(tor_socket_t sock)
* right after somebody else has let it go. But REUSEADDR on win32
* means you can bind to the port _even when somebody else
* already has it bound_. So, don't do that on Win32. */
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &one,
- (socklen_t)sizeof(one));
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &one,
+ (socklen_t)sizeof(one)) == -1) {
+ log_warn(LD_NET, "Error setting SO_REUSEADDR flag: %s",
+ tor_socket_strerror(errno));
+ }
#endif
}
@@ -1102,7 +1105,10 @@ connection_listener_new(const struct sockaddr *listensockaddr,
tor_assert(0);
}
- set_socket_nonblocking(s);
+ if (set_socket_nonblocking(s) == -1) {
+ tor_close_socket(s);
+ goto err;
+ }
lis_conn = listener_connection_new(type, listensockaddr->sa_family);
conn = TO_CONN(lis_conn);
@@ -1265,7 +1271,10 @@ connection_handle_listener_read(connection_t *conn, int new_type)
(int)news,(int)conn->s);
make_socket_reuseable(news);
- set_socket_nonblocking(news);
+ if (set_socket_nonblocking(news) == -1) {
+ tor_close_socket(news);
+ return 0;
+ }
if (options->ConstrainedSockets)
set_constrained_socket_buffers(news, (int)options->ConstrainedSockSize);
@@ -1494,7 +1503,11 @@ connection_connect(connection_t *conn, const char *address,
}
}
- set_socket_nonblocking(s);
+ if (set_socket_nonblocking(s) == -1) {
+ *socket_error = tor_socket_errno(s);
+ tor_close_socket(s);
+ return -1;
+ }
if (options->ConstrainedSockets)
set_constrained_socket_buffers(s, (int)options->ConstrainedSockSize);
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 84d556513c..9c39c25219 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -674,12 +674,10 @@ connection_ap_expire_beginning(void)
/* un-mark it as ending, since we're going to reuse it */
conn->edge_has_sent_end = 0;
conn->end_reason = 0;
- /* kludge to make us not try this circuit again, yet to allow
- * current streams on it to survive if they can: make it
- * unattractive to use for new streams */
- /* XXXX024 this is a kludgy way to do this. */
- tor_assert(circ->timestamp_dirty);
- circ->timestamp_dirty -= options->MaxCircuitDirtiness;
+ /* make us not try this circuit again, but allow
+ * current streams on it to survive if they can */
+ mark_circuit_unusable_for_new_conns(TO_ORIGIN_CIRCUIT(circ));
+
/* give our stream another 'cutoff' seconds to try */
conn->base_.timestamp_lastread += cutoff;
if (entry_conn->num_socks_retries < 250) /* avoid overflow */
@@ -1806,9 +1804,7 @@ connection_ap_handshake_send_begin(entry_connection_t *ap_conn)
connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
/* Mark this circuit "unusable for new streams". */
- /* XXXX024 this is a kludgy way to do this. */
- tor_assert(circ->base_.timestamp_dirty);
- circ->base_.timestamp_dirty -= get_options()->MaxCircuitDirtiness;
+ mark_circuit_unusable_for_new_conns(circ);
return -1;
}
@@ -1899,9 +1895,7 @@ connection_ap_handshake_send_resolve(entry_connection_t *ap_conn)
connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
/* Mark this circuit "unusable for new streams". */
- /* XXXX024 this is a kludgy way to do this. */
- tor_assert(circ->base_.timestamp_dirty);
- circ->base_.timestamp_dirty -= get_options()->MaxCircuitDirtiness;
+ mark_circuit_unusable_for_new_conns(circ);
return -1;
}
@@ -1945,13 +1939,14 @@ connection_ap_handshake_send_resolve(entry_connection_t *ap_conn)
string_addr, payload_len) < 0)
return -1; /* circuit is closed, don't continue */
- tor_free(base_conn->address); /* Maybe already set by dnsserv. */
- base_conn->address = tor_strdup("(Tor_internal)");
+ if (!base_conn->address) {
+ /* This might be unnecessary. XXXX */
+ base_conn->address = tor_dup_addr(&base_conn->addr);
+ }
base_conn->state = AP_CONN_STATE_RESOLVE_WAIT;
log_info(LD_APP,"Address sent for resolve, ap socket "TOR_SOCKET_T_FORMAT
", n_circ_id %u",
base_conn->s, (unsigned)circ->base_.n_circ_id);
- control_event_stream_status(ap_conn, STREAM_EVENT_NEW, 0);
control_event_stream_status(ap_conn, STREAM_EVENT_SENT_RESOLVE, 0);
return 0;
}
@@ -2201,9 +2196,11 @@ connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply,
tor_assert(conn->socks_request); /* make sure it's an AP stream */
- control_event_stream_status(conn,
- status==SOCKS5_SUCCEEDED ? STREAM_EVENT_SUCCEEDED : STREAM_EVENT_FAILED,
- endreason);
+ if (!SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)) {
+ control_event_stream_status(conn, status==SOCKS5_SUCCEEDED ?
+ STREAM_EVENT_SUCCEEDED : STREAM_EVENT_FAILED,
+ endreason);
+ }
/* Flag this stream's circuit as having completed a stream successfully
* (for path bias) */
diff --git a/src/or/control.c b/src/or/control.c
index 03e5d79c8e..2a68464189 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -2939,7 +2939,7 @@ handle_control_resolve(control_connection_t *conn, uint32_t len,
failed = smartlist_new();
SMARTLIST_FOREACH(args, const char *, arg, {
if (!is_keyval_pair(arg)) {
- if (dnsserv_launch_request(arg, is_reverse)<0)
+ if (dnsserv_launch_request(arg, is_reverse, conn)<0)
smartlist_add(failed, (char*)arg);
}
});
@@ -3742,7 +3742,7 @@ control_event_stream_status(entry_connection_t *conn, stream_status_event_t tp,
}
}
- if (tp == STREAM_EVENT_NEW) {
+ if (tp == STREAM_EVENT_NEW || tp == STREAM_EVENT_NEW_RESOLVE) {
tor_snprintf(addrport_buf,sizeof(addrport_buf), " SOURCE_ADDR=%s:%d",
ENTRY_TO_CONN(conn)->address, ENTRY_TO_CONN(conn)->port);
} else {
@@ -3752,11 +3752,7 @@ control_event_stream_status(entry_connection_t *conn, stream_status_event_t tp,
if (tp == STREAM_EVENT_NEW_RESOLVE) {
purpose = " PURPOSE=DNS_REQUEST";
} else if (tp == STREAM_EVENT_NEW) {
- if (ENTRY_TO_EDGE_CONN(conn)->is_dns_request ||
- (conn->socks_request &&
- SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)))
- purpose = " PURPOSE=DNS_REQUEST";
- else if (conn->use_begindir) {
+ if (conn->use_begindir) {
connection_t *linked = ENTRY_TO_CONN(conn)->linked_conn;
int linked_dir_purpose = -1;
if (linked && linked->type == CONN_TYPE_DIR)
diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c
index 38c6613f08..61f9faa394 100644
--- a/src/or/cpuworker.c
+++ b/src/or/cpuworker.c
@@ -535,13 +535,16 @@ spawn_cpuworker(void)
conn = connection_new(CONN_TYPE_CPUWORKER, AF_UNIX);
- set_socket_nonblocking(fd);
-
/* set up conn so it's got all the data we need to remember */
conn->s = fd;
conn->address = tor_strdup("localhost");
tor_addr_make_unspec(&conn->addr);
+ if (set_socket_nonblocking(fd) == -1) {
+ connection_free(conn); /* this closes fd */
+ return -1;
+ }
+
if (connection_add(conn) < 0) { /* no space, forget it */
log_warn(LD_NET,"connection_add for cpuworker failed. Giving up.");
connection_free(conn); /* this closes fd */
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index badacd683d..8e8f79a171 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -66,6 +66,13 @@ static cached_dir_t *the_directory = NULL;
/** For authoritative directories: the current (v1) network status. */
static cached_dir_t the_runningrouters;
+/** Total number of routers with measured bandwidth; this is set by
+ * dirserv_count_measured_bws() before the loop in
+ * dirserv_generate_networkstatus_vote_obj() and checked by
+ * dirserv_get_credible_bandwidth() and
+ * dirserv_compute_performance_thresholds() */
+static int routers_with_measured_bw = 0;
+
static void directory_remove_invalid(void);
static cached_dir_t *dirserv_regenerate_directory(void);
static char *format_versions_list(config_line_t *ln);
@@ -85,9 +92,8 @@ static const signed_descriptor_t *get_signed_descriptor_by_fp(
time_t publish_cutoff);
static was_router_added_t dirserv_add_extrainfo(extrainfo_t *ei,
const char **msg);
-
-/************** Measured Bandwidth parsing code ******/
-#define MAX_MEASUREMENT_AGE (3*24*60*60) /* 3 days */
+static uint32_t dirserv_get_bandwidth_for_router(const routerinfo_t *ri);
+static uint32_t dirserv_get_credible_bandwidth(const routerinfo_t *ri);
/************** Fingerprint handling code ************/
@@ -1824,7 +1830,7 @@ dirserv_thinks_router_is_unreliable(time_t now,
}
}
if (need_capacity) {
- uint32_t bw = router_get_advertised_bandwidth(router);
+ uint32_t bw = dirserv_get_bandwidth_for_router(router);
if (bw < fast_bandwidth)
return 1;
}
@@ -1876,15 +1882,23 @@ dirserv_thinks_router_is_hs_dir(const routerinfo_t *router,
#define ABSOLUTE_MIN_BW_VALUE_TO_CONSIDER 4096
/** Helper for dirserv_compute_performance_thresholds(): Decide whether to
- * include a router in our calculations, and return true iff we should. */
+ * include a router in our calculations, and return true iff we should; the
+ * require_mbw parameter is passed in by
+ * dirserv_compute_performance_thresholds() and controls whether we ever
+ * count routers with only advertised bandwidths */
static int
router_counts_toward_thresholds(const node_t *node, time_t now,
- const digestmap_t *omit_as_sybil)
+ const digestmap_t *omit_as_sybil,
+ int require_mbw)
{
+ /* Have measured bw? */
+ int have_mbw =
+ dirserv_has_measured_bw(node->ri->cache_info.identity_digest);
+
return node->ri && router_is_active(node->ri, node, now) &&
!digestmap_get(omit_as_sybil, node->ri->cache_info.identity_digest) &&
- (router_get_advertised_bandwidth(node->ri) >=
- ABSOLUTE_MIN_BW_VALUE_TO_CONSIDER);
+ (dirserv_get_credible_bandwidth(node->ri) >=
+ ABSOLUTE_MIN_BW_VALUE_TO_CONSIDER) && (have_mbw || !require_mbw);
}
/** Look through the routerlist, the Mean Time Between Failure history, and
@@ -1906,6 +1920,11 @@ dirserv_compute_performance_thresholds(routerlist_t *rl,
time_t now = time(NULL);
const or_options_t *options = get_options();
+ /* Require mbw? */
+ int require_mbw =
+ (routers_with_measured_bw >
+ options->MinMeasuredBWsForAuthToIgnoreAdvertised) ? 1 : 0;
+
/* initialize these all here, in case there are no routers */
stable_uptime = 0;
stable_mtbf = 0;
@@ -1938,7 +1957,8 @@ dirserv_compute_performance_thresholds(routerlist_t *rl,
/* Now, fill in the arrays. */
SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) {
- if (router_counts_toward_thresholds(node, now, omit_as_sybil)) {
+ if (router_counts_toward_thresholds(node, now, omit_as_sybil,
+ require_mbw)) {
routerinfo_t *ri = node->ri;
const char *id = ri->cache_info.identity_digest;
uint32_t bw;
@@ -1947,7 +1967,7 @@ dirserv_compute_performance_thresholds(routerlist_t *rl,
uptimes[n_active] = (uint32_t)real_uptime(ri, now);
mtbfs[n_active] = rep_hist_get_stability(id, now);
tks [n_active] = rep_hist_get_weighted_time_known(id, now);
- bandwidths[n_active] = bw = router_get_advertised_bandwidth(ri);
+ bandwidths[n_active] = bw = dirserv_get_credible_bandwidth(ri);
total_bandwidth += bw;
if (node->is_exit && !node->is_bad_exit) {
total_exit_bandwidth += bw;
@@ -2003,7 +2023,8 @@ dirserv_compute_performance_thresholds(routerlist_t *rl,
n_familiar = 0;
SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) {
- if (router_counts_toward_thresholds(node, now, omit_as_sybil)) {
+ if (router_counts_toward_thresholds(node, now,
+ omit_as_sybil, require_mbw)) {
routerinfo_t *ri = node->ri;
const char *id = ri->cache_info.identity_digest;
long tk = rep_hist_get_weighted_time_known(id, now);
@@ -2046,6 +2067,203 @@ dirserv_compute_performance_thresholds(routerlist_t *rl,
tor_free(wfus);
}
+/** Measured bandwidth cache entry */
+typedef struct mbw_cache_entry_s {
+ long mbw;
+ time_t as_of;
+} mbw_cache_entry_t;
+
+/** Measured bandwidth cache - keys are identity_digests, values are
+ * mbw_cache_entry_t *. */
+static digestmap_t *mbw_cache = NULL;
+
+/** Store a measured bandwidth cache entry when reading the measured
+ * bandwidths file. */
+void
+dirserv_cache_measured_bw(const measured_bw_line_t *parsed_line,
+ time_t as_of)
+{
+ mbw_cache_entry_t *e = NULL;
+
+ tor_assert(parsed_line);
+
+ /* Allocate a cache if we need */
+ if (!mbw_cache) mbw_cache = digestmap_new();
+
+ /* Check if we have an existing entry */
+ e = digestmap_get(mbw_cache, parsed_line->node_id);
+ /* If we do, we can re-use it */
+ if (e) {
+ /* Check that we really are newer, and update */
+ if (as_of > e->as_of) {
+ e->mbw = parsed_line->bw;
+ e->as_of = as_of;
+ }
+ } else {
+ /* We'll have to insert a new entry */
+ e = tor_malloc(sizeof(*e));
+ e->mbw = parsed_line->bw;
+ e->as_of = as_of;
+ digestmap_set(mbw_cache, parsed_line->node_id, e);
+ }
+}
+
+/** Clear and free the measured bandwidth cache */
+void
+dirserv_clear_measured_bw_cache(void)
+{
+ if (mbw_cache) {
+ /* Free the map and all entries */
+ digestmap_free(mbw_cache, tor_free_);
+ mbw_cache = NULL;
+ }
+}
+
+/** Scan the measured bandwidth cache and remove expired entries */
+void
+dirserv_expire_measured_bw_cache(time_t now)
+{
+
+ if (mbw_cache) {
+ /* Iterate through the cache and check each entry */
+ DIGESTMAP_FOREACH_MODIFY(mbw_cache, k, mbw_cache_entry_t *, e) {
+ if (now > e->as_of + MAX_MEASUREMENT_AGE) {
+ tor_free(e);
+ MAP_DEL_CURRENT(k);
+ }
+ } DIGESTMAP_FOREACH_END;
+
+ /* Check if we cleared the whole thing and free if so */
+ if (digestmap_size(mbw_cache) == 0) {
+ digestmap_free(mbw_cache, tor_free_);
+ mbw_cache = 0;
+ }
+ }
+}
+
+/** Get the current size of the measured bandwidth cache */
+int
+dirserv_get_measured_bw_cache_size(void)
+{
+ if (mbw_cache) return digestmap_size(mbw_cache);
+ else return 0;
+}
+
+/** Query the cache by identity digest, return value indicates whether
+ * we found it. The bw_out and as_of_out pointers receive the cached
+ * bandwidth value and the time it was cached if not NULL. */
+int
+dirserv_query_measured_bw_cache(const char *node_id, long *bw_out,
+ time_t *as_of_out)
+{
+ mbw_cache_entry_t *v = NULL;
+ int rv = 0;
+
+ if (mbw_cache && node_id) {
+ v = digestmap_get(mbw_cache, node_id);
+ if (v) {
+ /* Found something */
+ rv = 1;
+ if (bw_out) *bw_out = v->mbw;
+ if (as_of_out) *as_of_out = v->as_of;
+ }
+ }
+
+ return rv;
+}
+
+/** Predicate wrapper for dirserv_query_measured_bw_cache() */
+int
+dirserv_has_measured_bw(const char *node_id)
+{
+ return dirserv_query_measured_bw_cache(node_id, NULL, NULL);
+}
+
+/** Get the best estimate of a router's bandwidth for dirauth purposes,
+ * preferring measured to advertised values if available. */
+
+static uint32_t
+dirserv_get_bandwidth_for_router(const routerinfo_t *ri)
+{
+ uint32_t bw = 0;
+ /*
+ * Yeah, measured bandwidths in measured_bw_line_t are (implicitly
+ * signed) longs and the ones router_get_advertised_bandwidth() returns
+ * are uint32_t.
+ */
+ long mbw = 0;
+
+ if (ri) {
+ /*
+ * * First try to see if we have a measured bandwidth; don't bother with
+ * as_of_out here, on the theory that a stale measured bandwidth is still
+ * better to trust than an advertised one.
+ */
+ if (dirserv_query_measured_bw_cache(ri->cache_info.identity_digest,
+ &mbw, NULL)) {
+ /* Got one! */
+ bw = (uint32_t)mbw;
+ } else {
+ /* If not, fall back to advertised */
+ bw = router_get_advertised_bandwidth(ri);
+ }
+ }
+
+ return bw;
+}
+
+/** Look through the routerlist, and using the measured bandwidth cache count
+ * how many measured bandwidths we know. This is used to decide whether we
+ * ever trust advertised bandwidths for purposes of assigning flags. */
+static void
+dirserv_count_measured_bws(routerlist_t *rl)
+{
+ /* Initialize this first */
+ routers_with_measured_bw = 0;
+
+ tor_assert(rl);
+ tor_assert(rl->routers);
+
+ /* Iterate over the routerlist and count measured bandwidths */
+ SMARTLIST_FOREACH_BEGIN(rl->routers, routerinfo_t *, ri) {
+ /* Check if we know a measured bandwidth for this one */
+ if (dirserv_has_measured_bw(ri->cache_info.identity_digest)) {
+ ++routers_with_measured_bw;
+ }
+ } SMARTLIST_FOREACH_END(ri);
+}
+
+/** Return the bandwidth we believe for assigning flags; prefer measured
+ * over advertised, and if we have above a threshold quantity of measured
+ * bandwidths, we don't want to ever give flags to unmeasured routers, so
+ * return 0. */
+static uint32_t
+dirserv_get_credible_bandwidth(const routerinfo_t *ri)
+{
+ int threshold;
+ uint32_t bw = 0;
+ long mbw;
+
+ tor_assert(ri);
+ /* Check if we have a measured bandwidth, and check the threshold if not */
+ if (!(dirserv_query_measured_bw_cache(ri->cache_info.identity_digest,
+ &mbw, NULL))) {
+ threshold = get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised;
+ if (routers_with_measured_bw > threshold) {
+ /* Return zero for unmeasured bandwidth if we are above threshold */
+ bw = 0;
+ } else {
+ /* Return an advertised bandwidth otherwise */
+ bw = router_get_advertised_bandwidth(ri);
+ }
+ } else {
+ /* We have the measured bandwidth in mbw */
+ bw = (uint32_t)mbw;
+ }
+
+ return bw;
+}
+
/** Give a statement of our current performance thresholds for inclusion
* in a vote document. */
char *
@@ -2216,9 +2434,10 @@ routerstatus_format_entry(char *buf, size_t buf_len,
return -1;
}
- /* This assert can fire for the control port, because
+ /* This assert could fire for the control port, because
* it can request NS documents before all descriptors
- * have been fetched. */
+ * have been fetched. Therefore, we only do this test when
+ * format != NS_CONTROL_PORT. */
if (tor_memneq(desc->cache_info.signed_descriptor_digest,
rs->descriptor_digest,
DIGEST_LEN)) {
@@ -2327,8 +2546,8 @@ compare_routerinfo_by_ip_and_bw_(const void **a, const void **b)
else if (!first_is_running && second_is_running)
return 1;
- bw_first = router_get_advertised_bandwidth(first);
- bw_second = router_get_advertised_bandwidth(second);
+ bw_first = dirserv_get_bandwidth_for_router(first);
+ bw_second = dirserv_get_bandwidth_for_router(second);
if (bw_first > bw_second)
return -1;
@@ -2468,7 +2687,7 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs,
int listbaddirs, int vote_on_hsdirs)
{
const or_options_t *options = get_options();
- uint32_t routerbw = router_get_advertised_bandwidth(ri);
+ uint32_t routerbw = dirserv_get_credible_bandwidth(ri);
memset(rs, 0, sizeof(routerstatus_t));
@@ -2670,8 +2889,9 @@ dirserv_read_measured_bandwidths(const char *from_file,
char line[256];
FILE *fp = tor_fopen_cloexec(from_file, "r");
int applied_lines = 0;
- time_t file_time;
+ time_t file_time, now;
int ok;
+
if (fp == NULL) {
log_warn(LD_CONFIG, "Can't open bandwidth file at configured location: %s",
from_file);
@@ -2695,7 +2915,8 @@ dirserv_read_measured_bandwidths(const char *from_file,
return -1;
}
- if ((time(NULL) - file_time) > MAX_MEASUREMENT_AGE) {
+ now = time(NULL);
+ if ((now - file_time) > MAX_MEASUREMENT_AGE) {
log_warn(LD_DIRSERV, "Bandwidth measurement file stale. Age: %u",
(unsigned)(time(NULL) - file_time));
fclose(fp);
@@ -2709,12 +2930,17 @@ dirserv_read_measured_bandwidths(const char *from_file,
measured_bw_line_t parsed_line;
if (fgets(line, sizeof(line), fp) && strlen(line)) {
if (measured_bw_line_parse(&parsed_line, line) != -1) {
+ /* Also cache the line for dirserv_get_bandwidth_for_router() */
+ dirserv_cache_measured_bw(&parsed_line, file_time);
if (measured_bw_line_apply(&parsed_line, routerstatuses) > 0)
applied_lines++;
}
}
}
+ /* Now would be a nice time to clean the cache, too */
+ dirserv_expire_measured_bw_cache(now);
+
fclose(fp);
log_info(LD_DIRSERV,
"Bandwidth measurement file successfully read. "
@@ -2778,6 +3004,22 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
if (!contact)
contact = "(none)";
+ /*
+ * Do this so dirserv_compute_performance_thresholds() and
+ * set_routerstatus_from_routerinfo() see up-to-date bandwidth info.
+ */
+ if (options->V3BandwidthsFile) {
+ dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL);
+ } else {
+ /*
+ * No bandwidths file; clear the measured bandwidth cache in case we had
+ * one last time around.
+ */
+ if (dirserv_get_measured_bw_cache_size() > 0) {
+ dirserv_clear_measured_bw_cache();
+ }
+ }
+
/* precompute this part, since we need it to decide what "stable"
* means. */
SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
@@ -2794,6 +3036,10 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
rep_hist_make_router_pessimal(sybil_id, now);
} DIGESTMAP_FOREACH_END;
+ /* Count how many have measured bandwidths so we know how to assign flags;
+ * this must come before dirserv_compute_performance_thresholds() */
+ dirserv_count_measured_bws(rl);
+
dirserv_compute_performance_thresholds(rl, omit_as_sybil);
routerstatuses = smartlist_new();
@@ -2838,9 +3084,18 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
smartlist_free(routers);
digestmap_free(omit_as_sybil, NULL);
+ /* This pass through applies the measured bw lines to the routerstatuses */
if (options->V3BandwidthsFile) {
dirserv_read_measured_bandwidths(options->V3BandwidthsFile,
routerstatuses);
+ } else {
+ /*
+ * No bandwidths file; clear the measured bandwidth cache in case we had
+ * one last time around.
+ */
+ if (dirserv_get_measured_bw_cache_size() > 0) {
+ dirserv_clear_measured_bw_cache();
+ }
}
v3_out = tor_malloc_zero(sizeof(networkstatus_t));
@@ -3908,5 +4163,7 @@ dirserv_free_all(void)
cached_v2_networkstatus = NULL;
strmap_free(cached_consensuses, free_cached_dir_);
cached_consensuses = NULL;
+
+ dirserv_clear_measured_bw_cache();
}
diff --git a/src/or/dirserv.h b/src/or/dirserv.h
index 0caf55f830..a84ae964c9 100644
--- a/src/or/dirserv.h
+++ b/src/or/dirserv.h
@@ -76,7 +76,6 @@ int directory_fetches_from_authorities(const or_options_t *options);
int directory_fetches_dir_info_early(const or_options_t *options);
int directory_fetches_dir_info_later(const or_options_t *options);
int directory_caches_v2_dir_info(const or_options_t *options);
-#define directory_caches_v1_dir_info(o) directory_caches_v2_dir_info(o)
int directory_caches_unknown_auth_certs(const or_options_t *options);
int directory_caches_dir_info(const or_options_t *options);
int directory_permits_begindir_requests(const or_options_t *options);
@@ -138,10 +137,23 @@ void cached_dir_decref(cached_dir_t *d);
cached_dir_t *new_cached_dir(char *s, time_t published);
#ifdef DIRSERV_PRIVATE
+
+/* Put the MAX_MEASUREMENT_AGE #define here so unit tests can see it */
+#define MAX_MEASUREMENT_AGE (3*24*60*60) /* 3 days */
+
int measured_bw_line_parse(measured_bw_line_t *out, const char *line);
int measured_bw_line_apply(measured_bw_line_t *parsed_line,
smartlist_t *routerstatuses);
+
+void dirserv_cache_measured_bw(const measured_bw_line_t *parsed_line,
+ time_t as_of);
+void dirserv_clear_measured_bw_cache(void);
+void dirserv_expire_measured_bw_cache(time_t now);
+int dirserv_get_measured_bw_cache_size(void);
+int dirserv_query_measured_bw_cache(const char *node_id, long *bw_out,
+ time_t *as_of_out);
+int dirserv_has_measured_bw(const char *node_id);
#endif
int dirserv_read_measured_bandwidths(const char *from_file,
diff --git a/src/or/dnsserv.c b/src/or/dnsserv.c
index 7032b58145..a1275cf2b3 100644
--- a/src/or/dnsserv.c
+++ b/src/or/dnsserv.c
@@ -147,7 +147,7 @@ evdns_server_callback(struct evdns_server_request *req, void *data_)
return;
}
- control_event_stream_status(entry_conn, STREAM_EVENT_NEW, 0);
+ control_event_stream_status(entry_conn, STREAM_EVENT_NEW_RESOLVE, 0);
/* Now, unless a controller asked us to leave streams unattached,
* throw the connection over to get rewritten (which will
@@ -170,7 +170,8 @@ evdns_server_callback(struct evdns_server_request *req, void *data_)
* response; -1 if we couldn't launch the request.
*/
int
-dnsserv_launch_request(const char *name, int reverse)
+dnsserv_launch_request(const char *name, int reverse,
+ control_connection_t *control_conn)
{
entry_connection_t *entry_conn;
edge_connection_t *conn;
@@ -181,6 +182,10 @@ dnsserv_launch_request(const char *name, int reverse)
conn = ENTRY_TO_EDGE_CONN(entry_conn);
conn->base_.state = AP_CONN_STATE_RESOLVE_WAIT;
+ tor_addr_copy(&TO_CONN(conn)->addr, &control_conn->base_.addr);
+ TO_CONN(conn)->port = control_conn->base_.port;
+ TO_CONN(conn)->address = tor_dup_addr(&control_conn->base_.addr);
+
if (reverse)
entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR;
else
@@ -203,6 +208,8 @@ dnsserv_launch_request(const char *name, int reverse)
return -1;
}
+ control_event_stream_status(entry_conn, STREAM_EVENT_NEW_RESOLVE, 0);
+
/* Now, unless a controller asked us to leave streams unattached,
* throw the connection over to get rewritten (which will
* answer it immediately if it's in the cache, or completely bogus, or
diff --git a/src/or/dnsserv.h b/src/or/dnsserv.h
index 6bdb98de70..687a77e59e 100644
--- a/src/or/dnsserv.h
+++ b/src/or/dnsserv.h
@@ -20,7 +20,8 @@ void dnsserv_resolved(entry_connection_t *conn,
const char *answer,
int ttl);
void dnsserv_reject_request(entry_connection_t *conn);
-int dnsserv_launch_request(const char *name, int is_reverse);
+int dnsserv_launch_request(const char *name, int is_reverse,
+ control_connection_t *control_conn);
#endif
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 5d356b6231..e92c0c166d 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -367,13 +367,22 @@ add_an_entry_guard(const node_t *chosen, int reset_status, int prepend,
} else {
const routerstatus_t *rs;
rs = router_pick_directory_server(MICRODESC_DIRINFO|V3_DIRINFO,
- PDS_PREFER_TUNNELED_DIR_CONNS_);
+ PDS_PREFER_TUNNELED_DIR_CONNS_|PDS_FOR_GUARD);
if (!rs)
return NULL;
node = node_get_by_id(rs->identity_digest);
if (!node)
return NULL;
}
+ if (node->using_as_guard)
+ return NULL;
+ if (entry_guard_get_by_id_digest(node->identity) != NULL) {
+ log_info(LD_CIRC, "I was about to add a duplicate entry guard.");
+ /* This can happen if we choose a guard, then the node goes away, then
+ * comes back. */
+ ((node_t*) node)->using_as_guard = 1;
+ return NULL;
+ }
entry = tor_malloc_zero(sizeof(entry_guard_t));
log_info(LD_CIRC, "Chose %s as new entry guard.",
node_describe(node));
@@ -391,6 +400,7 @@ add_an_entry_guard(const node_t *chosen, int reset_status, int prepend,
* this guard. For details, see the Jan 2010 or-dev thread. */
entry->chosen_on_date = time(NULL) - crypto_rand_int(3600*24*30);
entry->chosen_by_version = tor_strdup(VERSION);
+ ((node_t*)node)->using_as_guard = 1;
if (prepend)
smartlist_insert(entry_guards, 0, entry);
else
@@ -730,6 +740,21 @@ entry_nodes_should_be_added(void)
should_add_entry_nodes = 1;
}
+/** Update the using_as_guard fields of all the nodes. We do this after we
+ * remove entry guards from the list: This is the only function that clears
+ * the using_as_guard field. */
+static void
+update_node_guard_status(void)
+{
+ smartlist_t *nodes = nodelist_get_list();
+ SMARTLIST_FOREACH(nodes, node_t *, node, node->using_as_guard = 0);
+ SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) {
+ node_t *node = node_get_mutable_by_id(entry->identity);
+ if (node)
+ node->using_as_guard = 1;
+ } SMARTLIST_FOREACH_END(entry);
+}
+
/** Adjust the entry guards list so that it only contains entries from
* EntryNodes, adding new entries from EntryNodes to the list as needed. */
static void
@@ -814,6 +839,8 @@ entry_guards_set_from_config(const or_options_t *options)
SMARTLIST_FOREACH(old_entry_guards_not_on_list, entry_guard_t *, e,
entry_guard_free(e));
+ update_node_guard_status();
+
smartlist_free(entry_nodes);
smartlist_free(worse_entry_nodes);
smartlist_free(entry_fps);
@@ -1269,6 +1296,8 @@ entry_guards_parse_state(or_state_t *state, int set, char **msg)
* few lines, so we don't have to re-dirty it */
if (remove_obsolete_entry_guards(now))
entry_guards_dirty = 1;
+
+ update_node_guard_status();
}
digestmap_free(added_by, tor_free_);
return *msg ? -1 : 0;
diff --git a/src/or/hibernate.c b/src/or/hibernate.c
index 36af4d8f83..a412571331 100644
--- a/src/or/hibernate.c
+++ b/src/or/hibernate.c
@@ -506,10 +506,6 @@ accounting_run_housekeeping(time_t now)
}
}
-/** When we have no idea how fast we are, how long do we assume it will take
- * us to exhaust our bandwidth? */
-#define GUESS_TIME_TO_USE_BANDWIDTH (24*60*60)
-
/** Based on our interval and our estimated bandwidth, choose a
* deterministic (but random-ish) time to wake up. */
static void
diff --git a/src/or/main.c b/src/or/main.c
index b5d1e2da34..fd8b6cf674 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -158,10 +158,6 @@ int can_complete_circuit=0;
/** How long do we let a directory connection stall before expiring it? */
#define DIR_CONN_MAX_STALL (5*60)
-/** How long do we let OR connections handshake before we decide that
- * they are obsolete? */
-#define TLS_HANDSHAKE_TIMEOUT (60)
-
/** Decides our behavior when no logs are configured/before any
* logs have been configured. For 0, we log notice to stdout as normal.
* For 1, we log warnings only. For 2, we log nothing.
@@ -1129,7 +1125,7 @@ signewnym_impl(time_t now)
return;
}
- circuit_expire_all_dirty_circs();
+ circuit_mark_all_dirty_circs_as_unusable();
addressmap_clear_transient();
rend_client_purge_state();
time_of_last_signewnym = now;
@@ -1848,7 +1844,7 @@ do_hup(void)
/* Rotate away from the old dirty circuits. This has to be done
* after we've read the new options, but before we start using
* circuits for directory fetches. */
- circuit_expire_all_dirty_circs();
+ circuit_mark_all_dirty_circs_as_unusable();
/* retry appropriate downloads */
router_reset_status_download_failures();
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index c63c76fccd..8846cd0634 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -1432,18 +1432,6 @@ consensus_is_waiting_for_certs(void)
? 1 : 0;
}
-/** Return the network status with a given identity digest. */
-networkstatus_v2_t *
-networkstatus_v2_get_by_digest(const char *digest)
-{
- SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
- {
- if (tor_memeq(ns->identity_digest, digest, DIGEST_LEN))
- return ns;
- });
- return NULL;
-}
-
/** Return the most recent consensus that we have downloaded, or NULL if we
* don't have one. */
networkstatus_t *
diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h
index b64e4b8e1a..761f8e7f0e 100644
--- a/src/or/networkstatus.h
+++ b/src/or/networkstatus.h
@@ -75,7 +75,6 @@ void update_certificate_downloads(time_t now);
int consensus_is_waiting_for_certs(void);
int client_would_use_router(const routerstatus_t *rs, time_t now,
const or_options_t *options);
-networkstatus_v2_t *networkstatus_v2_get_by_digest(const char *digest);
networkstatus_t *networkstatus_get_latest_consensus(void);
networkstatus_t *networkstatus_get_latest_consensus_by_flavor(
consensus_flavor_t f);
diff --git a/src/or/or.h b/src/or/or.h
index c893fba397..00f72adb8d 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1417,8 +1417,8 @@ typedef struct or_connection_t {
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." */
+ uint16_t link_proto; /**< What protocol version are we using? 0 for
+ * "none negotiated yet." */
or_handshake_state_t *handshake_state; /**< If we are setting this connection
* up, state information to do so. */
@@ -2249,6 +2249,9 @@ typedef struct node_t {
/** Local info: we treat this node as if it rejects everything */
unsigned int rejects_all:1;
+ /** Local info: this node is in our list of guards */
+ unsigned int using_as_guard:1;
+
/* Local info: derived. */
/** True if the IPv6 OR port is preferred over the IPv4 OR port. */
@@ -2942,6 +2945,10 @@ typedef struct origin_circuit_t {
*/
ENUM_BF(path_state_t) path_state : 3;
+ /* If this flag is set, we should not consider attaching any more
+ * connections to this circuit. */
+ unsigned int unusable_for_new_conns : 1;
+
/**
* Tristate variable to guard against pathbias miscounting
* due to circuit purpose transitions changing the decision
@@ -3872,6 +3879,10 @@ typedef struct {
* consensus vote on the 'params' line. */
char *ConsensusParams;
+ /** Authority only: minimum number of measured bandwidths we must see
+ * before we only beliee measured bandwidths to assign flags. */
+ int MinMeasuredBWsForAuthToIgnoreAdvertised;
+
/** The length of time that we think an initial consensus should be fresh.
* Only altered on testing networks. */
int TestingV3AuthInitialVotingInterval;
@@ -4469,15 +4480,6 @@ typedef struct vote_timing_t {
/********************************* geoip.c **************************/
-/** Round all GeoIP results to the next multiple of this value, to avoid
- * leaking information. */
-#define DIR_RECORD_USAGE_GRANULARITY 8
-/** Time interval: Flush geoip data to disk this often. */
-#define DIR_ENTRY_RECORD_USAGE_RETAIN_IPS (24*60*60)
-/** How long do we have to have observed per-country request history before
- * we are willing to talk about it? */
-#define DIR_RECORD_USAGE_MIN_OBSERVATION_TIME (12*60*60)
-
/** Indicates an action that we might be noting geoip statistics on.
* Note that if we're noticing CONNECT, we're a bridge, and if we're noticing
* the others, we're not.
@@ -4797,6 +4799,10 @@ typedef struct dir_server_t {
#define PDS_NO_EXISTING_SERVERDESC_FETCH (1<<3)
#define PDS_NO_EXISTING_MICRODESC_FETCH (1<<4)
+/** This node is to be chosen as a directory guard, so don't choose any
+ * node that's currently a guard. */
+#define PDS_FOR_GUARD (1<<5)
+
#define PDS_PREFER_TUNNELED_DIR_CONNS_ (1<<16)
/** Possible ways to weight routers when choosing one randomly. See
diff --git a/src/or/relay.c b/src/or/relay.c
index a4f402de44..1da993269d 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -17,6 +17,7 @@
#include "channel.h"
#include "circuitbuild.h"
#include "circuitlist.h"
+#include "circuituse.h"
#include "config.h"
#include "connection.h"
#include "connection_edge.h"
@@ -850,9 +851,7 @@ connection_ap_process_end_not_open(
/* We haven't retried too many times; reattach the connection. */
circuit_log_path(LOG_INFO,LD_APP,circ);
/* Mark this circuit "unusable for new streams". */
- /* XXXX024 this is a kludgy way to do this. */
- tor_assert(circ->base_.timestamp_dirty);
- circ->base_.timestamp_dirty -= get_options()->MaxCircuitDirtiness;
+ mark_circuit_unusable_for_new_conns(circ);
if (conn->chosen_exit_optional) {
/* stop wanting a specific exit */
@@ -1438,6 +1437,14 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
"'truncate' unsupported at origin. Dropping.");
return 0;
}
+ if (circ->n_hop) {
+ if (circ->n_chan)
+ log_warn(LD_BUG, "n_chan and n_hop set on the same circuit!");
+ extend_info_free(circ->n_hop);
+ circ->n_hop = NULL;
+ tor_free(circ->n_chan_create_cell);
+ circuit_set_state(circ, CIRCUIT_STATE_OPEN);
+ }
if (circ->n_chan) {
uint8_t trunc_reason = get_uint8(cell->payload + RELAY_HEADER_SIZE);
circuit_clear_cell_queue(circ, circ->n_chan);
diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c
index 79c1a724e4..2cfc364c3b 100644
--- a/src/or/rendcommon.c
+++ b/src/or/rendcommon.c
@@ -1452,13 +1452,6 @@ rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint,
command);
}
-/** Return the number of entries in our rendezvous descriptor cache. */
-int
-rend_cache_size(void)
-{
- return strmap_size(rend_cache);
-}
-
/** Allocate and return a new rend_data_t with the same
* contents as <b>query</b>. */
rend_data_t *
diff --git a/src/or/rendcommon.h b/src/or/rendcommon.h
index 189891b747..f476593d2b 100644
--- a/src/or/rendcommon.h
+++ b/src/or/rendcommon.h
@@ -49,7 +49,6 @@ int rend_cache_store(const char *desc, size_t desc_len, int published,
int rend_cache_store_v2_desc_as_client(const char *desc,
const rend_data_t *rend_query);
int rend_cache_store_v2_desc_as_dir(const char *desc);
-int rend_cache_size(void);
int rend_encode_v2_descriptors(smartlist_t *descs_out,
rend_service_descriptor_t *desc, time_t now,
uint8_t period, rend_auth_type_t auth_type,
diff --git a/src/or/router.c b/src/or/router.c
index 422fe5db2e..c8c9ce1a4f 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -2983,23 +2983,6 @@ router_get_verbose_nickname(char *buf, const routerinfo_t *router)
strlcpy(buf+1+HEX_DIGEST_LEN+1, router->nickname, MAX_NICKNAME_LEN+1);
}
-/** Set <b>buf</b> (which must have MAX_VERBOSE_NICKNAME_LEN+1 bytes) to the
- * verbose representation of the identity of <b>router</b>. The format is:
- * A dollar sign.
- * The upper-case hexadecimal encoding of the SHA1 hash of router's identity.
- * A "=" if the router is named; a "~" if it is not.
- * The router's nickname.
- **/
-void
-routerstatus_get_verbose_nickname(char *buf, const routerstatus_t *router)
-{
- buf[0] = '$';
- base16_encode(buf+1, HEX_DIGEST_LEN+1, router->identity_digest,
- DIGEST_LEN);
- buf[1+HEX_DIGEST_LEN] = router->is_named ? '=' : '~';
- strlcpy(buf+1+HEX_DIGEST_LEN+1, router->nickname, MAX_NICKNAME_LEN+1);
-}
-
/** Forget that we have issued any router-related warnings, so that we'll
* warn again if we see the same errors. */
void
diff --git a/src/or/router.h b/src/or/router.h
index fd2076af01..96749b53c0 100644
--- a/src/or/router.h
+++ b/src/or/router.h
@@ -132,8 +132,6 @@ const char *routerstatus_describe(const routerstatus_t *ri);
const char *extend_info_describe(const extend_info_t *ei);
void router_get_verbose_nickname(char *buf, const routerinfo_t *router);
-void routerstatus_get_verbose_nickname(char *buf,
- const routerstatus_t *router);
void router_reset_warnings(void);
void router_reset_reachability(void);
void router_free_all(void);
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 2f08167f18..0c978e9d00 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -54,8 +54,6 @@ static const routerstatus_t *router_pick_dirserver_generic(
smartlist_t *sourcelist,
dirinfo_type_t type, int flags);
static void mark_all_dirservers_up(smartlist_t *server_list);
-static int router_nickname_matches(const routerinfo_t *router,
- const char *nickname);
static void dir_server_free(dir_server_t *ds);
static int signed_desc_digest_is_recognized(signed_descriptor_t *desc);
static const char *signed_descriptor_get_body_impl(
@@ -339,7 +337,6 @@ trusted_dirs_remove_old_certs(void)
time_t now = time(NULL);
#define DEAD_CERT_LIFETIME (2*24*60*60)
#define OLD_CERT_LIFETIME (7*24*60*60)
-#define CERT_EXPIRY_SKEW (60*60)
if (!trusted_dir_certs)
return;
@@ -1153,6 +1150,7 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags)
int requireother = ! (flags & PDS_ALLOW_SELF);
int fascistfirewall = ! (flags & PDS_IGNORE_FASCISTFIREWALL);
int prefer_tunnel = (flags & PDS_PREFER_TUNNELED_DIR_CONNS_);
+ int for_guard = (flags & PDS_FOR_GUARD);
int try_excluding = 1, n_excluded = 0;
if (!consensus)
@@ -1192,6 +1190,8 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags)
if ((type & MICRODESC_DIRINFO) && !is_trusted &&
!node->rs->version_supports_microdesc_cache)
continue;
+ if (for_guard && node->using_as_guard)
+ continue; /* Don't make the same node a guard twice. */
if (try_excluding &&
routerset_contains_routerstatus(options->ExcludeNodes, status,
country)) {
@@ -1462,30 +1462,6 @@ routerlist_add_node_and_family(smartlist_t *sl, const routerinfo_t *router)
nodelist_add_node_and_family(sl, node);
}
-/** Return 1 iff any member of the (possibly NULL) comma-separated list
- * <b>list</b> is an acceptable nickname or hexdigest for <b>router</b>. Else
- * return 0.
- */
-int
-router_nickname_is_in_list(const routerinfo_t *router, const char *list)
-{
- smartlist_t *nickname_list;
- int v = 0;
-
- if (!list)
- return 0; /* definitely not */
- tor_assert(router);
-
- nickname_list = smartlist_new();
- smartlist_split_string(nickname_list, list, ",",
- SPLIT_SKIP_SPACE|SPLIT_STRIP_SPACE|SPLIT_IGNORE_BLANK, 0);
- SMARTLIST_FOREACH(nickname_list, const char *, cp,
- if (router_nickname_matches(router, cp)) {v=1;break;});
- SMARTLIST_FOREACH(nickname_list, char *, cp, tor_free(cp));
- smartlist_free(nickname_list);
- return v;
-}
-
/** Add every suitable node from our nodelist to <b>sl</b>, so that
* we can pick a node for a circuit.
*/
@@ -2312,18 +2288,6 @@ router_hex_digest_matches(const routerinfo_t *router, const char *hexdigest)
router_is_named(router));
}
-/** Return true if <b>router</b>'s nickname matches <b>nickname</b>
- * (case-insensitive), or if <b>router's</b> identity key digest
- * matches a hexadecimal value stored in <b>nickname</b>. Return
- * false otherwise. */
-static int
-router_nickname_matches(const routerinfo_t *router, const char *nickname)
-{
- if (nickname[0]!='$' && !strcasecmp(router->nickname, nickname))
- return 1;
- return router_hex_digest_matches(router, nickname);
-}
-
/** Return true iff <b>digest</b> is the digest of the identity key of a
* trusted directory matching at least one bit of <b>type</b>. If <b>type</b>
* is zero, any authority is okay. */
@@ -4052,17 +4016,6 @@ clear_dir_servers(void)
router_dir_info_changed();
}
-/** Return 1 if any trusted dir server supports v1 directories,
- * else return 0. */
-int
-any_trusted_dir_is_v1_authority(void)
-{
- if (trusted_dir_servers)
- return get_n_authorities(V1_DIRINFO) > 0;
-
- return 0;
-}
-
/** For every current directory connection whose purpose is <b>purpose</b>,
* and where the resource being downloaded begins with <b>prefix</b>, split
* rest of the resource into base16 fingerprints (or base64 fingerprints if
diff --git a/src/or/routerlist.h b/src/or/routerlist.h
index 1849fff31c..28b2f58935 100644
--- a/src/or/routerlist.h
+++ b/src/or/routerlist.h
@@ -42,7 +42,6 @@ int router_get_my_share_of_directory_requests(double *v2_share_out,
double *v3_share_out);
void router_reset_status_download_failures(void);
int routers_have_same_or_addrs(const routerinfo_t *r1, const routerinfo_t *r2);
-int router_nickname_is_in_list(const routerinfo_t *router, const char *list);
const routerinfo_t *routerlist_find_my_routerinfo(void);
uint32_t router_get_advertised_bandwidth(const routerinfo_t *router);
uint32_t router_get_advertised_bandwidth_capped(const routerinfo_t *router);
@@ -146,7 +145,6 @@ void dir_server_add(dir_server_t *ent);
void authority_cert_free(authority_cert_t *cert);
void clear_dir_servers(void);
-int any_trusted_dir_is_v1_authority(void);
void update_consensus_router_descriptor_downloads(time_t now, int is_vote,
networkstatus_t *consensus);
void update_router_descriptor_downloads(time_t now);
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index ce2cd5c513..b86864b5ee 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -1953,7 +1953,7 @@ routerstatus_parse_entry_from_string(memarea_t *area,
rs->version_supports_optimistic_data =
tor_version_as_new_as(tok->args[0], "0.2.3.1-alpha");
rs->version_supports_extend2_cells =
- tor_version_as_new_as(tok->args[0], "0.2.4.7-alpha");
+ tor_version_as_new_as(tok->args[0], "0.2.4.8-alpha");
}
if (vote_rs) {
vote_rs->version = tor_strdup(tok->args[0]);
diff --git a/src/or/transports.c b/src/or/transports.c
index 945d422f34..b5a00c90ec 100644
--- a/src/or/transports.c
+++ b/src/or/transports.c
@@ -124,10 +124,6 @@ static INLINE void free_execve_args(char **arg);
#define PROTO_CMETHODS_DONE "CMETHODS DONE"
#define PROTO_SMETHODS_DONE "SMETHODS DONE"
-/** Number of environment variables for managed proxy clients/servers. */
-#define ENVIRON_SIZE_CLIENT 3
-#define ENVIRON_SIZE_SERVER 7 /* XXX known to be too high, but that's ok */
-
/** The first and only supported - at the moment - configuration
protocol version. */
#define PROTO_VERSION_ONE 1
diff --git a/src/test/test.c b/src/test/test.c
index 6c64d35990..d3d3bd50bc 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -1979,11 +1979,6 @@ const struct testcase_setup_t legacy_setup = {
#define ENT(name) \
{ #name, legacy_test_helper, 0, &legacy_setup, test_ ## name }
-#define SUBENT(group, name) \
- { #group "_" #name, legacy_test_helper, 0, &legacy_setup, \
- test_ ## group ## _ ## name }
-#define DISABLED(name) \
- { #name, legacy_test_helper, TT_SKIP, &legacy_setup, test_ ## name }
#define FORK(name) \
{ #name, legacy_test_helper, TT_FORK, &legacy_setup, test_ ## name }
diff --git a/src/test/test_addr.c b/src/test/test_addr.c
index 890dfe4366..fec85a4696 100644
--- a/src/test/test_addr.c
+++ b/src/test/test_addr.c
@@ -843,6 +843,41 @@ test_virtaddrmap(void *data)
;
}
+static void
+test_addr_is_loopback(void *data)
+{
+ static const struct loopback_item {
+ const char *name;
+ int is_loopback;
+ } loopback_items[] = {
+ { "::1", 1 },
+ { "127.0.0.1", 1 },
+ { "127.99.100.101", 1 },
+ { "128.99.100.101", 0 },
+ { "8.8.8.8", 0 },
+ { "0.0.0.0", 0 },
+ { "::2", 0 },
+ { "::", 0 },
+ { "::1.0.0.0", 0 },
+ { NULL, 0 }
+ };
+
+ int i;
+ tor_addr_t addr;
+ (void)data;
+
+ for (i=0; loopback_items[i].name; ++i) {
+ tt_int_op(tor_addr_parse(&addr, loopback_items[i].name), >=, 0);
+ tt_int_op(tor_addr_is_loopback(&addr), ==, loopback_items[i].is_loopback);
+ }
+
+ tor_addr_make_unspec(&addr);
+ tt_int_op(tor_addr_is_loopback(&addr), ==, 0);
+
+ done:
+ ;
+}
+
#define ADDR_LEGACY(name) \
{ #name, legacy_test_helper, 0, &legacy_setup, test_addr_ ## name }
@@ -851,6 +886,7 @@ struct testcase_t addr_tests[] = {
ADDR_LEGACY(ip6_helpers),
ADDR_LEGACY(parse),
{ "virtaddr", test_virtaddrmap, 0, NULL, NULL },
+ { "is_loopback", test_addr_is_loopback, 0, NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c
index afb338a69c..c531c60838 100644
--- a/src/test/test_crypto.c
+++ b/src/test/test_crypto.c
@@ -636,22 +636,6 @@ test_crypto_formats(void)
tor_free(data2);
}
- /* Check fingerprint */
- {
- test_assert(crypto_pk_check_fingerprint_syntax(
- "ABCD 1234 ABCD 5678 0000 ABCD 1234 ABCD 5678 0000"));
- test_assert(!crypto_pk_check_fingerprint_syntax(
- "ABCD 1234 ABCD 5678 0000 ABCD 1234 ABCD 5678 000"));
- test_assert(!crypto_pk_check_fingerprint_syntax(
- "ABCD 1234 ABCD 5678 0000 ABCD 1234 ABCD 5678 00000"));
- test_assert(!crypto_pk_check_fingerprint_syntax(
- "ABCD 1234 ABCD 5678 0000 ABCD1234 ABCD 5678 0000"));
- test_assert(!crypto_pk_check_fingerprint_syntax(
- "ABCD 1234 ABCD 5678 0000 ABCD1234 ABCD 5678 00000"));
- test_assert(!crypto_pk_check_fingerprint_syntax(
- "ACD 1234 ABCD 5678 0000 ABCD 1234 ABCD 5678 00000"));
- }
-
done:
tor_free(data1);
tor_free(data2);
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index fbd49b7106..606dfe51ac 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -407,10 +407,8 @@ test_dir_split_fps(void *testdata)
"0123456789ABCdef0123456789ABCdef0123456789ABCdef0123456789ABCdef"
#define B64_1 "/g2v+JEnOJvGdVhpEjEjRVEZPu4"
#define B64_2 "3q2+75mZmZERERmZmRERERHwC6Q"
-#define B64_3 "sz/wDbM/8A2zP/ANsz/wDbM/8A0"
#define B64_256_1 "8/Pz8/u7vz8/Pz+7vz8/Pz+7u/Pz8/P7u/Pz8/P7u78"
#define B64_256_2 "zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMw"
-#define B64_256_3 "ASNFZ4mrze8BI0VniavN7wEjRWeJq83vASNFZ4mrze8"
/* no flags set */
dir_split_resource_into_fingerprints("A+C+B", sl, NULL, 0);
@@ -575,6 +573,83 @@ test_dir_measured_bw(void)
return;
}
+#define MBWC_INIT_TIME 1000
+
+/** Do the measured bandwidth cache unit test */
+static void
+test_dir_measured_bw_cache(void)
+{
+ /* Initial fake time_t for testing */
+ time_t curr = MBWC_INIT_TIME;
+ /* Some measured_bw_line_ts */
+ measured_bw_line_t mbwl[3];
+ /* For receiving output on cache queries */
+ long bw;
+ time_t as_of;
+
+ /* First, clear the cache and assert that it's empty */
+ dirserv_clear_measured_bw_cache();
+ test_eq(dirserv_get_measured_bw_cache_size(), 0);
+ /*
+ * Set up test mbwls; none of the dirserv_cache_*() functions care about
+ * the node_hex field.
+ */
+ memset(mbwl[0].node_id, 0x01, DIGEST_LEN);
+ mbwl[0].bw = 20;
+ memset(mbwl[1].node_id, 0x02, DIGEST_LEN);
+ mbwl[1].bw = 40;
+ memset(mbwl[2].node_id, 0x03, DIGEST_LEN);
+ mbwl[2].bw = 80;
+ /* Try caching something */
+ dirserv_cache_measured_bw(&(mbwl[0]), curr);
+ test_eq(dirserv_get_measured_bw_cache_size(), 1);
+ /* Okay, let's see if we can retrieve it */
+ test_assert(dirserv_query_measured_bw_cache(mbwl[0].node_id, &bw, &as_of));
+ test_eq(bw, 20);
+ test_eq(as_of, MBWC_INIT_TIME);
+ /* Try retrieving it without some outputs */
+ test_assert(dirserv_query_measured_bw_cache(mbwl[0].node_id, NULL, NULL));
+ test_assert(dirserv_query_measured_bw_cache(mbwl[0].node_id, &bw, NULL));
+ test_eq(bw, 20);
+ test_assert(dirserv_query_measured_bw_cache(mbwl[0].node_id, NULL, &as_of));
+ test_eq(as_of, MBWC_INIT_TIME);
+ /* Now expire it */
+ curr += MAX_MEASUREMENT_AGE + 1;
+ dirserv_expire_measured_bw_cache(curr);
+ /* Check that the cache is empty */
+ test_eq(dirserv_get_measured_bw_cache_size(), 0);
+ /* Check that we can't retrieve it */
+ test_assert(!dirserv_query_measured_bw_cache(mbwl[0].node_id, NULL, NULL));
+ /* Try caching a few things now */
+ dirserv_cache_measured_bw(&(mbwl[0]), curr);
+ test_eq(dirserv_get_measured_bw_cache_size(), 1);
+ curr += MAX_MEASUREMENT_AGE / 4;
+ dirserv_cache_measured_bw(&(mbwl[1]), curr);
+ test_eq(dirserv_get_measured_bw_cache_size(), 2);
+ curr += MAX_MEASUREMENT_AGE / 4;
+ dirserv_cache_measured_bw(&(mbwl[2]), curr);
+ test_eq(dirserv_get_measured_bw_cache_size(), 3);
+ curr += MAX_MEASUREMENT_AGE / 4 + 1;
+ /* Do an expire that's too soon to get any of them */
+ dirserv_expire_measured_bw_cache(curr);
+ test_eq(dirserv_get_measured_bw_cache_size(), 3);
+ /* Push the oldest one off the cliff */
+ curr += MAX_MEASUREMENT_AGE / 4;
+ dirserv_expire_measured_bw_cache(curr);
+ test_eq(dirserv_get_measured_bw_cache_size(), 2);
+ /* And another... */
+ curr += MAX_MEASUREMENT_AGE / 4;
+ dirserv_expire_measured_bw_cache(curr);
+ test_eq(dirserv_get_measured_bw_cache_size(), 1);
+ /* This should empty it out again */
+ curr += MAX_MEASUREMENT_AGE / 4;
+ dirserv_expire_measured_bw_cache(curr);
+ test_eq(dirserv_get_measured_bw_cache_size(), 0);
+
+ done:
+ return;
+}
+
static void
test_dir_param_voting(void)
{
@@ -2141,6 +2216,7 @@ struct testcase_t dir_tests[] = {
DIR(scale_bw),
DIR_LEGACY(clip_unmeasured_bw),
DIR_LEGACY(clip_unmeasured_bw_alt),
+ DIR_LEGACY(measured_bw_cache),
END_OF_TESTCASES
};
diff --git a/src/test/test_util.c b/src/test/test_util.c
index c2cb4448e6..7ab54e1530 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -1054,79 +1054,6 @@ test_util_strmisc(void)
test_assert(!tor_memstr(haystack, 7, "ababcade"));
}
- /* Test wrap_string */
- {
- smartlist_t *sl = smartlist_new();
- wrap_string(sl,
- "This is a test of string wrapping functionality: woot. "
- "a functionality? w00t w00t...!",
- 10, "", "");
- cp = smartlist_join_strings(sl, "", 0, NULL);
- test_streq(cp,
- "This is a\ntest of\nstring\nwrapping\nfunctional\nity: woot.\n"
- "a\nfunctional\nity? w00t\nw00t...!\n");
- tor_free(cp);
- SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
- smartlist_clear(sl);
-
- wrap_string(sl, "This is a test of string wrapping functionality: woot.",
- 16, "### ", "# ");
- cp = smartlist_join_strings(sl, "", 0, NULL);
- test_streq(cp,
- "### This is a\n# test of string\n# wrapping\n# functionality:\n"
- "# woot.\n");
- tor_free(cp);
- SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
- smartlist_clear(sl);
-
- wrap_string(sl, "A test of string wrapping...", 6, "### ", "# ");
- cp = smartlist_join_strings(sl, "", 0, NULL);
- test_streq(cp,
- "### A\n# test\n# of\n# stri\n# ng\n# wrap\n# ping\n# ...\n");
- tor_free(cp);
- SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
- smartlist_clear(sl);
-
- wrap_string(sl, "Wrapping test", 6, "#### ", "# ");
- cp = smartlist_join_strings(sl, "", 0, NULL);
- test_streq(cp, "#### W\n# rapp\n# ing\n# test\n");
- tor_free(cp);
- SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
- smartlist_clear(sl);
-
- wrap_string(sl, "Small test", 6, "### ", "#### ");
- cp = smartlist_join_strings(sl, "", 0, NULL);
- test_streq(cp, "### Sm\n#### a\n#### l\n#### l\n#### t\n#### e"
- "\n#### s\n#### t\n");
- tor_free(cp);
- SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
- smartlist_clear(sl);
-
- wrap_string(sl, "First null", 6, NULL, "> ");
- cp = smartlist_join_strings(sl, "", 0, NULL);
- test_streq(cp, "First\n> null\n");
- tor_free(cp);
- SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
- smartlist_clear(sl);
-
- wrap_string(sl, "Second null", 6, "> ", NULL);
- cp = smartlist_join_strings(sl, "", 0, NULL);
- test_streq(cp, "> Seco\nnd\nnull\n");
- tor_free(cp);
- SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
- smartlist_clear(sl);
-
- wrap_string(sl, "Both null", 6, NULL, NULL);
- cp = smartlist_join_strings(sl, "", 0, NULL);
- test_streq(cp, "Both\nnull\n");
- tor_free(cp);
- SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
- smartlist_free(sl);
-
- /* Can't test prefixes that have the same length as the line width, because
- the function has an assert */
- }
-
/* Test hex_str */
{
char binary_data[68];
diff --git a/src/tools/tor-fw-helper/tor-fw-helper-natpmp.c b/src/tools/tor-fw-helper/tor-fw-helper-natpmp.c
index e288a1ecf3..41eb9dcb76 100644
--- a/src/tools/tor-fw-helper/tor-fw-helper-natpmp.c
+++ b/src/tools/tor-fw-helper/tor-fw-helper-natpmp.c
@@ -93,16 +93,20 @@ wait_until_fd_readable(tor_socket_t fd, struct timeval *timeout)
{
int r;
fd_set fds;
+
+#ifndef WIN32
if (fd >= FD_SETSIZE) {
fprintf(stderr, "E: NAT-PMP FD_SETSIZE error %d\n", fd);
return -1;
}
+#endif
+
FD_ZERO(&fds);
FD_SET(fd, &fds);
r = select(fd+1, &fds, NULL, NULL, timeout);
if (r == -1) {
fprintf(stderr, "V: select failed in wait_until_fd_readable: %s\n",
- strerror(errno));
+ tor_socket_strerror(tor_socket_errno(fd)));
return -1;
}
/* XXXX we should really check to see whether fd was readable, or we timed
@@ -140,12 +144,12 @@ tor_natpmp_add_tcp_mapping(uint16_t internal_port, uint16_t external_port,
if (is_verbose)
fprintf(stderr, "V: attempting to readnatpmpreponseorretry...\n");
r = readnatpmpresponseorretry(&(state->natpmp), &(state->response));
- sav_errno = errno;
+ sav_errno = tor_socket_errno(state->natpmp.s);
if (r<0 && r!=NATPMP_TRYAGAIN) {
fprintf(stderr, "E: readnatpmpresponseorretry failed %d\n", r);
fprintf(stderr, "E: errno=%d '%s'\n", sav_errno,
- strerror(sav_errno));
+ tor_socket_strerror(sav_errno));
}
} while (r == NATPMP_TRYAGAIN);
@@ -198,7 +202,7 @@ tor_natpmp_fetch_public_ip(tor_fw_options_t *tor_fw_options,
if (tor_fw_options->verbose)
fprintf(stderr, "V: NAT-PMP attempting to read reponse...\n");
r = readnatpmpresponseorretry(&(state->natpmp), &(state->response));
- sav_errno = errno;
+ sav_errno = tor_socket_errno(state->natpmp.s);
if (tor_fw_options->verbose)
fprintf(stderr, "V: NAT-PMP readnatpmpresponseorretry returned"
@@ -208,7 +212,7 @@ tor_natpmp_fetch_public_ip(tor_fw_options_t *tor_fw_options,
fprintf(stderr, "E: NAT-PMP readnatpmpresponseorretry failed %d\n",
r);
fprintf(stderr, "E: NAT-PMP errno=%d '%s'\n", sav_errno,
- strerror(sav_errno));
+ tor_socket_strerror(sav_errno));
}
} while (r == NATPMP_TRYAGAIN );
diff --git a/src/tools/tor-fw-helper/tor-fw-helper.c b/src/tools/tor-fw-helper/tor-fw-helper.c
index d92445e08f..adeb63b736 100644
--- a/src/tools/tor-fw-helper/tor-fw-helper.c
+++ b/src/tools/tor-fw-helper/tor-fw-helper.c
@@ -100,7 +100,7 @@ usage(void)
" [-T|--Test]\n"
" [-v|--verbose]\n"
" [-g|--fetch-public-ip]\n"
- " [-p|--forward-port ([<external port>]:<internal port>])\n");
+ " [-p|--forward-port ([<external port>]:<internal port>)]\n");
}
/** Log commandline options to a hardcoded file <b>tor-fw-helper.log</b> in the