aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2006-09-24 17:20:41 +0000
committerNick Mathewson <nickm@torproject.org>2006-09-24 17:20:41 +0000
commit9006dbeb812168e0eb7ec707a61a7d539b18ecea (patch)
tree17eb1979d71a24c99cff0d87f047f3aaa8875c5d
parentbf738d30808190fcd20e8bcb3e75b17f7b730105 (diff)
downloadtor-9006dbeb812168e0eb7ec707a61a7d539b18ecea.tar.gz
tor-9006dbeb812168e0eb7ec707a61a7d539b18ecea.zip
Oops. My last commit to the 1.1 branch somehow merged the whole stable branch in. Bad idea. This should revert it.
svn:r8479
-rw-r--r--ChangeLog171
-rw-r--r--Doxyfile2
-rw-r--r--Makefile.am11
-rw-r--r--Win32Build/mingw/CHANGES-libevent80
-rw-r--r--Win32Build/mingw/README8
-rw-r--r--Win32Build/mingw/libevent-1.1b-mingw-custom.diff338
-rw-r--r--Win32Build/mingw/libevent-1.1b-mingw.diff221
-rw-r--r--Win32Build/mingw/libevent-svn-mingw.diff210
-rwxr-xr-x[-rw-r--r--]Win32Build/vc6/Tor.dsw0
-rwxr-xr-x[-rw-r--r--]Win32Build/vc6/tor/Tor.dsp8
-rwxr-xr-x[-rw-r--r--]Win32Build/vc6/tor_resolve/tor_resolve.dsp0
-rwxr-xr-x[-rw-r--r--]Win32Build/vc7/Tor/Tor.sln0
-rwxr-xr-x[-rw-r--r--]Win32Build/vc7/Tor/Tor.vcproj0
-rwxr-xr-x[-rw-r--r--]Win32Build/vc7/tor_resolve/tor_resolve.vcproj0
-rwxr-xr-x[-rw-r--r--]Win32Build/vc7/unittests/unittests.vcproj0
-rw-r--r--configure.in212
-rw-r--r--contrib/Makefile.am2
-rwxr-xr-xcontrib/add-tor115
-rwxr-xr-xcontrib/checkSpace.pl75
-rw-r--r--contrib/cross.sh150
-rwxr-xr-xcontrib/exitlist20
-rw-r--r--contrib/id_to_fp.c64
-rw-r--r--contrib/osx/Makefile.am3
-rw-r--r--contrib/osx/TorPostflight27
-rw-r--r--contrib/osx/TorPreFlight29
-rw-r--r--contrib/osx/Tor_Uninstaller.app.tar.gzbin20172 -> 0 bytes
-rw-r--r--contrib/osx/Tor_Uninstaller.applescript57
-rw-r--r--contrib/osx/package.sh3
-rwxr-xr-xcontrib/osx/uninstall_tor_bundle.sh2
-rw-r--r--contrib/package_nsis-mingw.sh59
-rw-r--r--contrib/tor-mingw.nsi.in212
-rwxr-xr-xcontrib/tor-resolve.py75
-rw-r--r--contrib/tor.nsi.in2
-rwxr-xr-xcontrib/torify.in42
-rw-r--r--debian/README.Debian7
-rw-r--r--debian/changelog23
-rw-r--r--debian/control2
-rw-r--r--debian/copyright2
-rw-r--r--debian/patches/00list1
-rwxr-xr-xdebian/patches/06_add_compile_time_defaults.dpatch124
-rwxr-xr-xdebian/patches/07_log_to_file_by_default.dpatch19
-rwxr-xr-xdebian/patches/11_tor_as_root_more_helpful.dpatch36
-rwxr-xr-xdebian/rules7
-rw-r--r--debian/tor.init92
-rw-r--r--doc/HACKING25
-rw-r--r--doc/TODO512
-rw-r--r--doc/control-spec-v0.txt5
-rw-r--r--doc/control-spec.txt24
-rw-r--r--doc/design-paper/blocking.tex352
-rw-r--r--doc/dir-spec-v1.txt315
-rw-r--r--doc/dir-spec.txt233
-rw-r--r--doc/incentives.txt2
-rw-r--r--doc/path-spec.txt551
-rw-r--r--doc/socks-extensions.txt6
-rw-r--r--doc/tor-osx-dmg-creation.txt3
-rw-r--r--doc/tor-rpm-creation.txt27
-rw-r--r--doc/tor-spec-udp.txt27
-rw-r--r--doc/tor-spec-v0.txt734
-rw-r--r--doc/tor-spec.txt580
-rw-r--r--doc/tor-win32-mingw-creation.txt120
-rw-r--r--doc/tor.1.in81
-rw-r--r--src/common/compat.c201
-rw-r--r--src/common/compat.h123
-rw-r--r--src/common/container.c174
-rw-r--r--src/common/container.h42
-rw-r--r--src/common/crypto.c74
-rw-r--r--src/common/crypto.h2
-rw-r--r--src/common/ht.h101
-rw-r--r--src/common/log.c9
-rw-r--r--src/common/log.h12
-rw-r--r--src/common/torgzip.c96
-rw-r--r--src/common/torgzip.h12
-rw-r--r--src/common/torint.h6
-rw-r--r--src/common/tortls.c159
-rw-r--r--src/common/tortls.h4
-rw-r--r--src/common/util.c163
-rw-r--r--src/common/util.h87
-rw-r--r--src/config/torrc.sample.in51
-rw-r--r--src/or/Makefile.am10
-rw-r--r--src/or/buffers.c114
-rw-r--r--src/or/circuitbuild.c293
-rw-r--r--src/or/circuitlist.c589
-rw-r--r--src/or/circuituse.c417
-rw-r--r--src/or/command.c111
-rw-r--r--src/or/config.c516
-rw-r--r--src/or/connection.c536
-rw-r--r--src/or/connection_edge.c684
-rw-r--r--src/or/connection_or.c286
-rw-r--r--src/or/control.c472
-rw-r--r--src/or/cpuworker.c27
-rw-r--r--src/or/directory.c612
-rw-r--r--src/or/dirserv.c497
-rw-r--r--src/or/dns.c1308
-rw-r--r--src/or/eventdns.c2292
-rw-r--r--src/or/eventdns.h73
-rw-r--r--src/or/eventdns_tor.h13
-rw-r--r--src/or/hibernate.c20
-rw-r--r--src/or/main.c328
-rw-r--r--src/or/onion.c12
-rw-r--r--src/or/or.h837
-rw-r--r--src/or/policies.c38
-rw-r--r--src/or/relay.c333
-rw-r--r--src/or/rendclient.c108
-rw-r--r--src/or/rendcommon.c27
-rw-r--r--src/or/rendmid.c84
-rw-r--r--src/or/rendservice.c109
-rw-r--r--src/or/rephist.c91
-rw-r--r--src/or/router.c308
-rw-r--r--src/or/routerlist.c452
-rw-r--r--src/or/routerparse.c102
-rw-r--r--src/or/test.c157
-rw-r--r--src/tools/tor-resolve.c2
-rw-r--r--src/win32/orconfig.h2
-rw-r--r--tor.spec.in6
114 files changed, 4703 insertions, 14587 deletions
diff --git a/ChangeLog b/ChangeLog
index 6912bfb788..8fe89f007e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,164 +1,22 @@
-Changes in version 0.1.2.2-alpha - 2006-??-??
- o Major features:
- - Add server-side support for "reverse" DNS lookups (using PTR
- records so clients can determine the canonical hostname for a given
- IPv4 address). This has been specified for a long time, but was
- previously never implemented. This is only supported by eventdns;
- servers now announce in their descriptors whether they support
- eventdns.
- - Specify and implement client-side SOCKS5 interface for reverse DNS
- lookups; see doc/socks-extensions.txt for full information.
-
- o Minor features:
- - Check for name servers (like Earthlink's) that hijack failing DNS
- requests and replace the 'no such server' answer with a "helpful"
- redirect to an advertising-driven search portal. We're a little clever
- about this, in order to work around DNS hijackers who "helpfully"
- decline to hijack known-invalid RFC2606 addresses. [Resolves bug 330.]
- - When asked to resolve a hostname, don't use non-exit servers unless
- requested to do so. This allows servers with broken DNS be useful to
- the network.
-
- o Security Fixes, minor
- - If a client asked for a server by name, and we didn't have a
- descriptor for a named server with that name, we might return an old
- one.
-
- o Minor Bugfixes
- - Small performance improvements on parsing descriptors (x2).
- - Major performance descriptor on inserting descriptors; change
- algorithm from O(n^2) to O(n).
- - Make the common memory allocation path faster on machines where
- malloc(0) returns a pointer.
- - Fix a debug log message in eventdns to say "X resolved to Y"
- instead of "X resolved to X".
- - Prevent the 'exitlist' script from printing the same result more
- than once.
-
- o Documentation
- - Documented (and renamed) ServerDNSSearchDomains and
- ServerDNSResolvConfFile options.
-
-Changes in version 0.1.2.1-alpha - 2006-08-27
- o Major features:
- - Add "eventdns" async dns library from Adam Langley, tweaked to
- build on OSX and Windows. Only enabled if you pass the
- --enable-eventdns argument to configure.
- - Allow servers with no hostname or IP address to learn their
- IP address by asking the directory authorities. This code only
- kicks in when you would normally have exited with a "no address"
- error. Nothing's authenticated, so use with care.
- - Rather than waiting a fixed amount of time between retrying
- application connections, we wait only 5 seconds for the first,
- 10 seconds for the second, and 15 seconds for each retry after
- that. Hopefully this will improve the expected user experience.
- - Patch from Tup to add support for transparent AP connections:
- this basically bundles the functionality of trans-proxy-tor
- into the Tor mainline. Now hosts with compliant pf/netfilter
- implementations can redirect TCP connections straight to Tor
- without diverting through SOCKS. Needs docs.
- - Busy directory servers save lots of memory by spooling server
- descriptors, v1 directories, and v2 networkstatus docs to buffers
- as needed rather than en masse. Also mmap the cached-routers
- files, so we don't need to keep the whole thing in memory too.
- - Automatically avoid picking more than one node from the same
- /16 network when constructing a circuit.
- - Revise and clean up the torrc.sample that we ship with; add
- a section for BandwidthRate and BandwidthBurst.
-
- o Minor features:
- - Split circuit_t into origin_circuit_t and or_circuit_t, and
- split connection_t into edge, or, dir, control, and base structs.
- These will save quite a bit of memory on busy servers, and they'll
- also help us track down bugs in the code and bugs in the spec.
- - Experimentally re-enable kqueue on OSX when using libevent 1.1b
- or later. Log when we are doing this, so we can diagnose it when
- it fails. (Also, recommend libevent 1.1b for kqueue and
- win32 methods; deprecate libevent 1.0b harder; make libevent
- recommendation system saner.)
- - Start being able to build universal binaries on OS X (thanks
- to Phobos).
- - Export the default exit policy via the control port, so controllers
- don't need to guess what it is / will be later.
- - Add a man page entry for ProtocolWarnings.
- - Add TestVia config option to the man page.
- - Remove even more protocol-related warnings from Tor server logs,
- such as bad TLS handshakes and malformed begin cells.
- - Stop fetching descriptors if you're not a dir mirror and you
- haven't tried to establish any circuits lately. [This currently
- causes some dangerous behavior, because when you start up again
- you'll use your ancient server descriptors.]
- - New DirPort behavior: if you have your dirport set, you download
- descriptors aggressively like a directory mirror, whether or not
- your ORPort is set.
- - Get rid of the router_retry_connections notion. Now routers
- no longer try to rebuild long-term connections to directory
- authorities, and directory authorities no longer try to rebuild
- long-term connections to all servers. We still don't hang up
- connections in these two cases though -- we need to look at it
- more carefully to avoid flapping, and we likely need to wait til
- 0.1.1.x is obsolete.
- - Drop compatibility with obsolete Tors that permit create cells
- to have the wrong circ_id_type.
- - Re-enable per-connection rate limiting. Get rid of the "OP
- bandwidth" concept. Lay groundwork for "bandwidth classes" --
- separate global buckets that apply depending on what sort of conn
- it is.
- - Start publishing one minute or so after we find our ORPort
- to be reachable. This will help reduce the number of descriptors
- we have for ourselves floating around, since it's quite likely
- other things (e.g. DirPort) will change during that minute too.
- - Fork the v1 directory protocol into its own spec document,
- and mark dir-spec.txt as the currently correct (v2) spec.
-
+Changes in version 0.1.1.24 - 2006-09-xx [ongoing]
o Major bugfixes:
- - When we find our DirPort to be reachable, publish a new descriptor
- so we'll tell the world (reported by pnx).
- - Publish a new descriptor after we hup/reload. This is important
- if our config has changed such that we'll want to start advertising
- our DirPort now, etc.
+ - Allow really slow clients to not hang up five minutes into their
+ directory downloads (suggested by Adam J. Richter).
+ - Fix major performance regression from 0.1.0.x: instead of checking
+ whether we have enough directory information every time we want to
+ do something, only check when the directory information has changed.
+ This should improve client CPU usage by 25-50%.
+
+ o Minor bugfixes:
- Allow Tor to start when RunAsDaemon is set but no logs are set.
- - When we have a state file we cannot parse, tell the user and
- move it aside. Now we avoid situations where the user starts
- Tor in 1904, Tor writes a state file with that timestamp in it,
- the user fixes her clock, and Tor refuses to start.
+ - Don't crash when the controller receives a third argument to an
+ "extendcircuit" request.
- Fix configure.in to not produce broken configure files with
more recent versions of autoconf. Thanks to Clint for his auto*
voodoo.
- - "tor --verify-config" now exits with -1(255) or 0 depending on
- whether the config options are bad or good.
- - Resolve bug 321 when using dnsworkers: append a period to every
- address we resolve at the exit node, so that we do not accidentally
- pick up local addresses, and so that failing searches are retried
- in the resolver search domains. (This is already solved for
- eventdns.) (This breaks Blossom servers for now.)
- - If we are using an exit enclave and we can't connect, e.g. because
- its webserver is misconfigured to not listen on localhost, then
- back off and try connecting from somewhere else before we fail.
-
- o Minor bugfixes:
- - Start compiling on MinGW on Windows (patches from Mike Chiussi).
- - Start compiling on MSVC6 on Windows (patches from Frediano Ziglio).
- - Fix bug 314: Tor clients issued "unsafe socks" warnings even
- when the IP address is mapped through MapAddress to a hostname.
- - Start passing "ipv4" hints to getaddrinfo(), so servers don't do
- useless IPv6 DNS resolves.
- - Patch suggested by Karsten Loesing: respond to SIGNAL command
- before we execute the signal, in case the signal shuts us down.
- - Clean up AllowInvalidNodes man page entry.
- - Claim a commonname of Tor, rather than TOR, in TLS handshakes.
- - Add more asserts to track down an assert error on a windows Tor
- server with connection_add being called with socket == -1.
- - Handle reporting OR_CONN_EVENT_NEW events to the controller.
- - Fix misleading log messages: an entry guard that is "unlisted",
- as well as not known to be "down" (because we've never heard
- of it), is not therefore "up".
- - Remove code to special-case "-cvs" ending, since it has not
- actually mattered since 0.0.9.
- - Make our socks5 handling more robust to broken socks clients:
- throw out everything waiting on the buffer in between socks
- handshake phases, since they can't possibly (so the theory
- goes) have predicted what we plan to respond to them.
+ - Fix NetBSD bug that could allow someone to force uninitialized RAM
+ to be sent to a server's DNS resolver. This only affects NetBSD and
+ other platforms that do not bounds-check tolower().
Changes in version 0.1.1.23 - 2006-07-30
@@ -199,6 +57,7 @@ Changes in version 0.1.1.22 - 2006-07-05
- Fix a rare bug that was causing some servers to complain about
"closing wedged cpuworkers" and skip some circuit create requests.
- Make the Exit flag in directory status documents actually work.
+ - Add a preliminary OSX binary un-installer, and fix permissions.
Changes in version 0.1.1.21 - 2006-06-10
diff --git a/Doxyfile b/Doxyfile
index 9cde9d6e13..e0726bb768 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -25,7 +25,7 @@ PROJECT_NAME = tor
# This could be handy for archiving the generated documentation or
# if some version control system is used.
-PROJECT_NUMBER = 0.1.2.1-alpha
+PROJECT_NUMBER = 0.1.1.16-rc
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
diff --git a/Makefile.am b/Makefile.am
index 6179291fd1..76be9982ca 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -15,7 +15,6 @@ EXTRA_DIST = INSTALL README AUTHORS LICENSE ChangeLog tor.spec tor.spec.in
#install-data-local:
# $(INSTALL) -m 755 -d $(LOCALSTATEDIR)/lib/tor
-# Assume a tarball is in .. for now.
dist-rpm:
RPM_BUILD_DIR="/tmp/tor-rpm-build-$$$$"; \
rm -rf $$RPM_BUILD_DIR; \
@@ -23,7 +22,7 @@ dist-rpm:
for subdir in BUILD RPMS SOURCES SPECS SRPMS; do \
mkdir $$RPM_BUILD_DIR/$$subdir; \
done; \
- mkdir $$RPM_BUILD_DIR/SOURCES/tor-$(VERSION); \
+ mkdir $$RPM_BUILD_DIR/SOURCES/tor-$(VERSION); \
cp -R ./ $$RPM_BUILD_DIR/SOURCES/tor-$(VERSION)/; \
pushd $$RPM_BUILD_DIR/SOURCES/; \
tar zcf tor-$(VERSION).tar.gz ./; \
@@ -55,8 +54,8 @@ doxygen:
# Avoid strlcpy.c, strlcat.c, tree.h
check-spaces:
- ./contrib/checkSpace.pl -C \
- src/common/*.h \
- src/common/[^as]*.c \
- src/or/[^et]*.[ch] src/or/t*.c src/or/eventdns_tor.h
+ ./contrib/checkSpace.pl -C \
+ src/common/*.h \
+ src/common/[^s]*.c \
+ src/or/[^t]*.[ch] src/or/t*.c
diff --git a/Win32Build/mingw/CHANGES-libevent b/Win32Build/mingw/CHANGES-libevent
deleted file mode 100644
index e723d9755f..0000000000
--- a/Win32Build/mingw/CHANGES-libevent
+++ /dev/null
@@ -1,80 +0,0 @@
-Changes related to compilation under MinGW/any sane win32 gcc
-=============================================================
-
-* event.c
-- If gcc include "WIN32-Code/misc.h" instead of "misc.h"
-
-* WIN32-Code/misc.h
-- Add struct prototypes for timeval and timezone
-
-* buffer.c
-- changed type of "i" from "u_int" to "unsigned int". My MinGW wasn't
- recognizing it. (u_int is normally typedef'ed to unsigned int, right?)
-
-* evbuffer.c
-- removed incorrect win32 error checking, see bufferevent_writecb().
- (this needs to be fixed by anyone planning to use evbuffer on win32)
-
-* log.c
-- If gcc include "WIN32-Code/misc.h" instead of "misc.h"
-
-* WIN32-Code/misc.c
-- if gcc, include "misc.h"
-- added newline at end of file to shut up gcc
-
-* WIN32-Code/win32.c
-- Altered the prototypes of win32_*() so their argument types didn't conflict
- with the function definitions.
-- Casted types of win32_* to void inside win32ops so that it didn't conflict
- with the definition of eventops (gcc doesn't like this)
-- Altered prototype of signal_handler to be static since definition is static
- (why wasn't it like this before)
-- Casted the second argument of signal() to be void*, some reason my MinGW
- doesn't have sighandler_t typedef'ed.
-
-* configure.in
-- some code to check if we are compiling for WIN32.
-
-* Makefile.am
-- if BUILD_WIN32 is defined, include WIN32-Code/misc.c and
- WIN32-Code/win32.c as source files.
-- if WIN32, do not build test stuff. (not windows friendly)
-- if WIN32, explicitly link to ws2_32.dll
-
-Notes
------
-- We assume that if __GNUC__ is undefined we are building with MSVC
-- If the user wishes to build a dll, they are on their own, the syntax is
- compiler specific.
-- Getting this warning from libtool, no idea why
- "libtool: link: warning: undefined symbols not allowed in i686-pc-mingw32
- shared libraries"
-
-
-Changes related to "custom eventops"
-====================================
-
-* configure.in
-- add argument --enable-custom-eventops, sets USE_CUSTOM_EVENTOPS in config.h
-- add argument --enable-custom-code, sets USE_CUSTOM_CODE in Makefile
-
-* Makefile.am
-- if USE_CUSTOM_CODE, include custom/custom.c as a source file.
- (I can't think of a way to pass a string to Makefile.am, so I'm stuck naming
- the new source file custom.c. It just seems simpler this way, but I'm open
- to suggestions)
-
-* event.c
-- if USE_CUSTOM_EVENTOPS, use eventops as defined in custom-eventops.h
-
-Notes
------
-Just in case it isn't completely obvious, the goal of "custom eventops" is to
-allow the user to include their own event processing system without requiring a
-fork. This is accomplished through two parts. Firstly, by allowing the user to
-redefine eventops. (for example, the user may wish to use epoll() exclusively).
-Secondly, by allowing the user to include their own code to support a private
-eventop (note, this may not be necessary, as the user may choose to include
-already defined eventop's.
-
-
diff --git a/Win32Build/mingw/README b/Win32Build/mingw/README
deleted file mode 100644
index 67e75cd27e..0000000000
--- a/Win32Build/mingw/README
+++ /dev/null
@@ -1,8 +0,0 @@
-The current SVN version of Tor should compile with MinGW.
-
-OpenSSL and libz both compile on MinGW out of the box.
-
-libevent 1.1b will not build unless you apply the diff in this directory.
-
-
-
diff --git a/Win32Build/mingw/libevent-1.1b-mingw-custom.diff b/Win32Build/mingw/libevent-1.1b-mingw-custom.diff
deleted file mode 100644
index 350586e35f..0000000000
--- a/Win32Build/mingw/libevent-1.1b-mingw-custom.diff
+++ /dev/null
@@ -1,338 +0,0 @@
-Only in libevent-1.1b: CHANGES
-Only in libevent-1.1b: Makefile
-diff -uwr libevent-1.1b-old/Makefile.am libevent-1.1b/Makefile.am
---- libevent-1.1b-old/Makefile.am Wed Aug 9 22:16:35 2006
-+++ libevent-1.1b/Makefile.am Sat Sep 2 03:49:26 2006
-@@ -1,6 +1,5 @@
- AUTOMAKE_OPTIONS = foreign no-dependencies
-
--SUBDIRS = . sample test
-
- EXTRA_DIST = acconfig.h event.h event-internal.h log.h evsignal.h event.3 \
- kqueue.c epoll_sub.c epoll.c select.c rtsig.c poll.c signal.c \
-@@ -20,8 +19,29 @@
-
- lib_LTLIBRARIES = libevent.la
-
--libevent_la_SOURCES = event.c buffer.c evbuffer.c log.c
--libevent_la_LIBADD = @LTLIBOBJS@
-+
-+if BUILD_WIN32
-+
-+SUBDIRS = . sample
-+SYS_LIBS = -lws2_32
-+SYS_SRC = WIN32-Code/misc.c WIN32-Code/win32.c
-+
-+else
-+
-+SUBDIRS = . sample test
-+SYS_LIBS =
-+SYS_SRC =
-+
-+endif
-+
-+if USE_CUSTOM_CODE
-+CUST_SRC = custom/custom.c
-+else
-+CUST_SRC =
-+endif
-+
-+libevent_la_SOURCES = event.c buffer.c evbuffer.c log.c $(CUST_SRC) $(SYS_SRC)
-+libevent_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS)
- libevent_la_LDFLAGS = -release @VERSION@ -version-info 1:2:0
-
- include_HEADERS = event.h
-Only in libevent-1.1b: Makefile.in
-diff -uwr libevent-1.1b-old/WIN32-Code/misc.c libevent-1.1b/WIN32-Code/misc.c
---- libevent-1.1b-old/WIN32-Code/misc.c Wed Aug 9 21:01:14 2006
-+++ libevent-1.1b/WIN32-Code/misc.c Fri Sep 1 22:21:31 2006
-@@ -4,6 +4,12 @@
- #include <sys/timeb.h>
- #include <time.h>
-
-+#ifdef __GNUC__
-+/*our prototypes for timeval and timezone are in here, just in case the above
-+ headers don't have them*/
-+#include "misc.h"
-+#endif
-+
- /****************************************************************************
- *
- * Function: gettimeofday(struct timeval *, struct timezone *)
-diff -uwr libevent-1.1b-old/WIN32-Code/misc.h libevent-1.1b/WIN32-Code/misc.h
---- libevent-1.1b-old/WIN32-Code/misc.h Wed Aug 9 21:01:14 2006
-+++ libevent-1.1b/WIN32-Code/misc.h Fri Sep 1 18:47:09 2006
-@@ -1,6 +1,9 @@
- #ifndef MISC_H
- #define MISC_H
-
-+struct timezone;
-+struct timeval;
-+
- int gettimeofday(struct timeval *,struct timezone *);
-
- #endif
-diff -uwr libevent-1.1b-old/WIN32-Code/win32.c libevent-1.1b/WIN32-Code/win32.c
---- libevent-1.1b-old/WIN32-Code/win32.c Wed Aug 9 21:25:48 2006
-+++ libevent-1.1b/WIN32-Code/win32.c Sat Sep 2 00:45:55 2006
-@@ -60,7 +60,8 @@
- /* MSDN says this is required to handle SIGFPE */
- volatile double SIGFPE_REQ = 0.0f;
-
--int signal_handler(int sig);
-+static int signal_handler(int sig);
-+
- void signal_process(void);
- int signal_recalc(void);
-
-@@ -77,20 +78,21 @@
- };
-
- void *win32_init (void);
--int win32_insert (void *, struct event *);
--int win32_del (void *, struct event *);
-+int win32_insert (struct win32op *, struct event *);
-+int win32_del (struct win32op *, struct event *);
- int win32_recalc (struct event_base *base, void *, int);
--int win32_dispatch (struct event_base *base, void *, struct timeval *);
-+int win32_dispatch (struct event_base *base, struct win32op *, struct timeval *);
-
- struct eventop win32ops = {
- "win32",
- win32_init,
-- win32_insert,
-- win32_del,
-+ (int (*) (void*, struct event*)) win32_insert,
-+ (int (*) (void*, struct event*)) win32_del,
- win32_recalc,
-- win32_dispatch
-+ (int (*) (struct event_base*, void*, struct timeval*)) win32_dispatch
- };
-
-+
- #define FD_SET_ALLOC_SIZE(n) ((sizeof(struct win_fd_set) + ((n)-1)*sizeof(SOCKET)))
-
- static int
-@@ -213,7 +215,13 @@
- if (ev->ev_events & (EV_READ|EV_WRITE))
- event_errx(1, "%s: EV_SIGNAL incompatible use",
- __func__);
-+
-+#ifndef __GNUC__
- if((int)signal(EVENT_SIGNAL(ev), signal_handler) == -1)
-+#else
-+ if((int)signal(EVENT_SIGNAL(ev), (void*) signal_handler) == -1)
-+#endif
-+
- return (-1);
-
- return (0);
-@@ -382,8 +390,13 @@
-
- /* Reinstall our signal handler. */
- TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
-+#ifndef __GNUC__
- if((int)signal(EVENT_SIGNAL(ev), signal_handler) == -1)
-+#else
-+ if((int)signal(EVENT_SIGNAL(ev), (void*) signal_handler) == -1)
-+#endif
- return (-1);
-+
- }
- return (0);
- }
-Only in libevent-1.1b-old/: aclocal.m4
-Only in libevent-1.1b: autom4te.cache
-diff -uwr libevent-1.1b-old/buffer.c libevent-1.1b/buffer.c
---- libevent-1.1b-old/buffer.c Wed Aug 9 22:01:40 2006
-+++ libevent-1.1b/buffer.c Fri Sep 1 18:52:56 2006
-@@ -197,7 +197,7 @@
- u_char *data = EVBUFFER_DATA(buffer);
- size_t len = EVBUFFER_LENGTH(buffer);
- char *line;
-- u_int i;
-+ unsigned int i;
-
- for (i = 0; i < len; i++) {
- if (data[i] == '\r' || data[i] == '\n')
-Only in libevent-1.1b: config.guess
-Only in libevent-1.1b: config.h
-diff -uwr libevent-1.1b-old/config.h.in libevent-1.1b/config.h.in
---- libevent-1.1b-old/config.h.in Wed Aug 9 21:27:37 2006
-+++ libevent-1.1b/config.h.in Sat Sep 2 02:23:17 2006
-@@ -223,6 +223,9 @@
- /* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
- #undef TIME_WITH_SYS_TIME
-
-+/* Define to 1 if you want to use a custom eventops variable */
-+#undef USE_CUSTOM_EVENTOPS
-+
- /* Version number of package */
- #undef VERSION
-
-@@ -232,11 +235,9 @@
- /* Define to empty if `const' does not conform to ANSI C. */
- #undef const
-
--/* Define to `__inline__' or `__inline' if that's what the C compiler
-- calls it, or to nothing if 'inline' is not supported under any name. */
--#ifndef __cplusplus
-+/* Define as `__inline' if that's what the C compiler calls it, or to nothing
-+ if it is not supported. */
- #undef inline
--#endif
-
- /* Define to `int' if <sys/types.h> does not define. */
- #undef pid_t
-Only in libevent-1.1b: config.h.in~
-Only in libevent-1.1b: config.log
-Only in libevent-1.1b: config.status
-Only in libevent-1.1b: configure
-diff -uwr libevent-1.1b-old/configure.in libevent-1.1b/configure.in
---- libevent-1.1b-old/configure.in Wed Aug 9 22:05:17 2006
-+++ libevent-1.1b/configure.in Sat Sep 2 03:40:15 2006
-@@ -21,6 +21,18 @@
- CFLAGS="$CFLAGS -Wall"
- fi
-
-+AC_ARG_ENABLE(custom-eventops,
-+ [ --enable-custom-eventops Use custom eventops variable],
-+ AC_DEFINE([USE_CUSTOM_EVENTOPS],[1],
-+ [Define to 1 to use a custom eventops variable])
-+ ,)
-+AC_ARG_ENABLE(custom-code,
-+ [ --enable-custom-code Use custom code from custom/],
-+ customcodev=true,
-+ customcodev=false)
-+
-+AM_CONDITIONAL(USE_CUSTOM_CODE, test x$customcodev = xtrue)
-+
- AC_PROG_LIBTOOL
-
- dnl Uncomment "AC_DISABLE_SHARED" to make shared librraries not get
-@@ -110,6 +122,22 @@
- AC_MSG_RESULT(yes)] ,AC_MSG_RESULT(no)
- )
- fi
-+
-+dnl - check if the macro WIN32 is defined on this compiler.
-+dnl - (this is how we check for a windows version of GCC)
-+AC_MSG_CHECKING(for WIN32)
-+AC_TRY_COMPILE(,
-+ [
-+ #ifndef WIN32
-+ #error
-+ #endif
-+ ],
-+ bwin32=true; AC_MSG_RESULT(yes),
-+ bwin32=false; AC_MSG_RESULT(no),
-+)
-+
-+AM_CONDITIONAL(BUILD_WIN32, test x$bwin32 = xtrue)
-+
-
- dnl Checks for typedefs, structures, and compiler characteristics.
- AC_C_CONST
-diff -uwr libevent-1.1b-old/evbuffer.c libevent-1.1b/evbuffer.c
---- libevent-1.1b-old/evbuffer.c Wed Aug 9 21:01:14 2006
-+++ libevent-1.1b/evbuffer.c Fri Sep 1 19:18:13 2006
-@@ -154,12 +154,20 @@
- if (EVBUFFER_LENGTH(bufev->output)) {
- res = evbuffer_write(bufev->output, fd);
- if (res == -1) {
-+#ifndef WIN32
-+/*todo. evbuffer uses WriteFile when WIN32 is set. WIN32 system calls do not
-+ *set errno. thus this error checking is not portable*/
- if (errno == EAGAIN ||
- errno == EINTR ||
- errno == EINPROGRESS)
- goto reschedule;
- /* error case */
- what |= EVBUFFER_ERROR;
-+
-+#else
-+ goto reschedule;
-+#endif
-+
- } else if (res == 0) {
- /* eof case */
- what |= EVBUFFER_EOF;
-@@ -181,6 +189,7 @@
- return;
-
- reschedule:
-+
- if (EVBUFFER_LENGTH(bufev->output) != 0)
- bufferevent_add(&bufev->ev_write, bufev->timeout_write);
- return;
-diff -uwr libevent-1.1b-old/event.c libevent-1.1b/event.c
---- libevent-1.1b-old/event.c Wed Aug 9 21:25:48 2006
-+++ libevent-1.1b/event.c Sat Sep 2 04:22:05 2006
-@@ -30,8 +30,14 @@
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- #undef WIN32_LEAN_AND_MEAN
-+
-+#ifdef __GNUC__
-+#include "WIN32-Code/misc.h"
-+#else
- #include "misc.h"
- #endif
-+
-+#endif
- #include <sys/types.h>
- #include <sys/tree.h>
- #ifdef HAVE_SYS_TIME_H
-@@ -53,6 +59,7 @@
- #include "event-internal.h"
- #include "log.h"
-
-+
- #ifdef HAVE_SELECT
- extern const struct eventop selectops;
- #endif
-@@ -75,6 +82,8 @@
- extern const struct eventop win32ops;
- #endif
-
-+#ifndef USE_CUSTOM_EVENTOPS
-+
- /* In order of preference */
- const struct eventop *eventops[] = {
- #ifdef HAVE_WORKING_KQUEUE
-@@ -101,6 +110,11 @@
- NULL
- };
-
-+#else
-+#include "custom-eventops.h"
-+#endif //USE_CUSTOM_EVENTOPS
-+
-+
- /* Global state */
- struct event_list signalqueue;
-
-Only in libevent-1.1b: libtool
-diff -uwr libevent-1.1b-old/log.c libevent-1.1b/log.c
---- libevent-1.1b-old/log.c Wed Aug 9 21:01:14 2006
-+++ libevent-1.1b/log.c Fri Sep 1 19:09:45 2006
-@@ -45,8 +45,14 @@
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- #undef WIN32_LEAN_AND_MEAN
-+
-+#ifdef __GNUC__
-+#include "WIN32-Code/misc.h"
-+#else
- #include "misc.h"
- #endif
-+
-+#endif
- #include <sys/types.h>
- #include <sys/tree.h>
- #ifdef HAVE_SYS_TIME_H
-Only in libevent-1.1b/sample: Makefile
-Only in libevent-1.1b/sample: Makefile.in
-Only in libevent-1.1b: stamp-h1
-Only in libevent-1.1b/test: Makefile
-Only in libevent-1.1b/test: Makefile.in
diff --git a/Win32Build/mingw/libevent-1.1b-mingw.diff b/Win32Build/mingw/libevent-1.1b-mingw.diff
deleted file mode 100644
index c7cea5b326..0000000000
--- a/Win32Build/mingw/libevent-1.1b-mingw.diff
+++ /dev/null
@@ -1,221 +0,0 @@
-=== Makefile.am
-==================================================================
---- Makefile.am (revision 8794)
-+++ Makefile.am (local)
-@@ -1,6 +1,5 @@
- AUTOMAKE_OPTIONS = foreign no-dependencies
-
--SUBDIRS = . sample test
-
- EXTRA_DIST = acconfig.h event.h event-internal.h log.h evsignal.h event.3 \
- kqueue.c epoll_sub.c epoll.c select.c rtsig.c poll.c signal.c \
-@@ -20,13 +19,29 @@
-
- lib_LTLIBRARIES = libevent.la
-
--libevent_la_SOURCES = event.c buffer.c evbuffer.c log.c
--libevent_la_LIBADD = @LTLIBOBJS@
-+if BUILD_WIN32
-+
-+SUBDIRS = . sample
-+SYS_LIBS = -lws2_32
-+SYS_SRC = WIN32-Code/misc.c WIN32-Code/win32.c
-+SYS_INCLUDES = -IWIN32-Code
-+
-+else
-+
-+SUBDIRS = . sample test
-+SYS_LIBS =
-+SYS_SRC =
-+SYS_INCLUDES =
-+
-+endif
-+
-+libevent_la_SOURCES = event.c buffer.c evbuffer.c log.c $(SYS_SRC)
-+libevent_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS)
- libevent_la_LDFLAGS = -release @VERSION@ -version-info 1:2:0
-
- include_HEADERS = event.h
-
--INCLUDES = -Icompat
-+INCLUDES = -Icompat $(SYS_INCLUDES)
-
- man_MANS = event.3
-
-=== WIN32-Code/misc.c
-==================================================================
---- WIN32-Code/misc.c (revision 8794)
-+++ WIN32-Code/misc.c (local)
-@@ -4,6 +4,12 @@
- #include <sys/timeb.h>
- #include <time.h>
-
-+#ifdef __GNUC__
-+/*our prototypes for timeval and timezone are in here, just in case the above
-+ headers don't have them*/
-+#include "misc.h"
-+#endif
-+
- /****************************************************************************
- *
- * Function: gettimeofday(struct timeval *, struct timezone *)
-@@ -17,6 +23,7 @@
- *
- ****************************************************************************/
-
-+#ifndef HAVE_GETTIMEOFDAY
- int gettimeofday(struct timeval *tv, struct timezone *tz) {
- struct _timeb tb;
-
-@@ -28,6 +35,7 @@
- tv->tv_usec = ((int) tb.millitm) * 1000;
- return 0;
- }
-+#endif
-
- int
- win_read(int fd, void *buf, unsigned int length)
-=== WIN32-Code/misc.h
-==================================================================
---- WIN32-Code/misc.h (revision 8794)
-+++ WIN32-Code/misc.h (local)
-@@ -1,6 +1,11 @@
- #ifndef MISC_H
- #define MISC_H
-
-+struct timezone;
-+struct timeval;
-+
-+#ifndef HAVE_GETTIMEOFDAY
- int gettimeofday(struct timeval *,struct timezone *);
-+#endif
-
- #endif
-=== WIN32-Code/win32.c
-==================================================================
---- WIN32-Code/win32.c (revision 8794)
-+++ WIN32-Code/win32.c (local)
-@@ -60,7 +60,8 @@
- /* MSDN says this is required to handle SIGFPE */
- volatile double SIGFPE_REQ = 0.0f;
-
--int signal_handler(int sig);
-+static void signal_handler(int sig);
-+
- void signal_process(void);
- int signal_recalc(void);
-
-@@ -205,8 +206,9 @@
- }
-
- int
--win32_insert(struct win32op *win32op, struct event *ev)
-+win32_insert(void *op, struct event *ev)
- {
-+ struct win32op *win32op = op;
- int i;
-
- if (ev->ev_events & EV_SIGNAL) {
-@@ -251,8 +253,9 @@
- }
-
- int
--win32_del(struct win32op *win32op, struct event *ev)
-+win32_del(void *op, struct event *ev)
- {
-+ struct win32op *win32op = op;
- int i, found;
-
- if (ev->ev_events & EV_SIGNAL)
-@@ -302,9 +305,10 @@
- */
-
- int
--win32_dispatch(struct event_base *base, struct win32op *win32op,
-+win32_dispatch(struct event_base *base, void *op,
- struct timeval *tv)
- {
-+ struct win32op *win32op = op;
- int res = 0;
- int i;
- int fd_count;
-@@ -366,13 +370,11 @@
- }
-
-
--static int
-+static void
- signal_handler(int sig)
- {
- evsigcaught[sig]++;
- signal_caught = 1;
--
-- return 0;
- }
-
- int
-=== buffer.c
-==================================================================
---- buffer.c (revision 8794)
-+++ buffer.c (local)
-@@ -197,7 +197,7 @@
- u_char *data = EVBUFFER_DATA(buffer);
- size_t len = EVBUFFER_LENGTH(buffer);
- char *line;
-- u_int i;
-+ unsigned int i;
-
- for (i = 0; i < len; i++) {
- if (data[i] == '\r' || data[i] == '\n')
-=== configure.in
-==================================================================
---- configure.in (revision 8794)
-+++ configure.in (local)
-@@ -111,6 +111,21 @@
- )
- fi
-
-+dnl - check if the macro WIN32 is defined on this compiler.
-+dnl - (this is how we check for a windows version of GCC)
-+AC_MSG_CHECKING(for WIN32)
-+AC_TRY_COMPILE(,
-+ [
-+ #ifndef WIN32
-+ #error
-+ #endif
-+ ],
-+ bwin32=true; AC_MSG_RESULT(yes),
-+ bwin32=false; AC_MSG_RESULT(no),
-+)
-+
-+AM_CONDITIONAL(BUILD_WIN32, test x$bwin32 = xtrue)
-+
- dnl Checks for typedefs, structures, and compiler characteristics.
- AC_C_CONST
- AC_C_INLINE
-=== evbuffer.c
-==================================================================
---- evbuffer.c (revision 8794)
-+++ evbuffer.c (local)
-@@ -154,12 +154,20 @@
- if (EVBUFFER_LENGTH(bufev->output)) {
- res = evbuffer_write(bufev->output, fd);
- if (res == -1) {
-+#ifndef WIN32
-+/*todo. evbuffer uses WriteFile when WIN32 is set. WIN32 system calls do not
-+ *set errno. thus this error checking is not portable*/
- if (errno == EAGAIN ||
- errno == EINTR ||
- errno == EINPROGRESS)
- goto reschedule;
- /* error case */
- what |= EVBUFFER_ERROR;
-+
-+#else
-+ goto reschedule;
-+#endif
-+
- } else if (res == 0) {
- /* eof case */
- what |= EVBUFFER_EOF;
-
diff --git a/Win32Build/mingw/libevent-svn-mingw.diff b/Win32Build/mingw/libevent-svn-mingw.diff
deleted file mode 100644
index af4ffbbbb5..0000000000
--- a/Win32Build/mingw/libevent-svn-mingw.diff
+++ /dev/null
@@ -1,210 +0,0 @@
-=== Makefile.am
-==================================================================
---- Makefile.am (revision 8794)
-+++ Makefile.am (local)
-@@ -1,6 +1,5 @@
- AUTOMAKE_OPTIONS = foreign no-dependencies
-
--SUBDIRS = . sample test
-
- bin_SCRIPTS = event_rpcgen.py
-
-@@ -22,18 +21,34 @@
-
- lib_LTLIBRARIES = libevent.la
-
-+if BUILD_WIN32
-+
-+SUBDIRS = . sample
-+SYS_LIBS = -lws2_32
-+SYS_SRC = WIN32-Code/misc.c WIN32-Code/win32.c
-+SYS_INCLUDES = -IWIN32-Code
-+
-+else
-+
-+SUBDIRS = . sample test
-+SYS_LIBS =
-+SYS_SRC =
-+SYS_INCLUDES =
-+
-+endif
-+
- libevent_la_SOURCES = event.c buffer.c evbuffer.c log.c event_tagging.c \
-- http.c evhttp.h http-internal.h evdns.c evdns.h
--libevent_la_LIBADD = @LTLIBOBJS@
-+ http.c evhttp.h http-internal.h evdns.c evdns.h $(SYS_SRC)
-+libevent_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS)
- libevent_la_LDFLAGS = -release @VERSION@ -version-info 1:3:0
-
- include_HEADERS = event.h evhttp.h evdns.h
-
--INCLUDES = -Icompat
-+INCLUDES = -Icompat $(SYS_INCLUDES)
-
- man_MANS = event.3
-
- verify: libevent.la
-- cd $(srcdir)/test && make verify
-+ cd $(srcdir)/test && make verify
-
- DISTCLEANFILES = *~
-=== WIN32-Code/misc.c
-==================================================================
---- WIN32-Code/misc.c (revision 8794)
-+++ WIN32-Code/misc.c (local)
-@@ -4,6 +4,12 @@
- #include <sys/timeb.h>
- #include <time.h>
-
-+#ifdef __GNUC__
-+/*our prototypes for timeval and timezone are in here, just in case the above
-+ headers don't have them*/
-+#include "misc.h"
-+#endif
-+
- /****************************************************************************
- *
- * Function: gettimeofday(struct timeval *, struct timezone *)
-=== WIN32-Code/misc.h
-==================================================================
---- WIN32-Code/misc.h (revision 8794)
-+++ WIN32-Code/misc.h (local)
-@@ -1,6 +1,9 @@
- #ifndef MISC_H
- #define MISC_H
-
-+struct timezone;
-+struct timeval;
-+
- int gettimeofday(struct timeval *,struct timezone *);
-
- #endif
-=== WIN32-Code/win32.c
-==================================================================
---- WIN32-Code/win32.c (revision 8794)
-+++ WIN32-Code/win32.c (local)
-@@ -60,7 +60,8 @@
- /* MSDN says this is required to handle SIGFPE */
- volatile double SIGFPE_REQ = 0.0f;
-
--int signal_handler(int sig);
-+static void signal_handler(int sig);
-+
- void signal_process(void);
- int signal_recalc(void);
-
-@@ -207,8 +208,9 @@
- }
-
- int
--win32_insert(struct win32op *win32op, struct event *ev)
-+win32_insert(void *op, struct event *ev)
- {
-+ struct win32op *win32op = op;
- int i;
-
- if (ev->ev_events & EV_SIGNAL) {
-@@ -253,8 +255,9 @@
- }
-
- int
--win32_del(struct win32op *win32op, struct event *ev)
-+win32_del(void *op, struct event *ev)
- {
-+ struct win32op *win32op = op;
- int i, found;
-
- if (ev->ev_events & EV_SIGNAL)
-@@ -304,9 +307,10 @@
- */
-
- int
--win32_dispatch(struct event_base *base, struct win32op *win32op,
-+win32_dispatch(struct event_base *base, void *op,
- struct timeval *tv)
- {
-+ struct win32op *win32op = op;
- int res = 0;
- int i;
- int fd_count;
-@@ -389,13 +393,11 @@
- free(win32op);
- }
-
--static int
-+static void
- signal_handler(int sig)
- {
- evsigcaught[sig]++;
- signal_caught = 1;
--
-- return 0;
- }
-
- int
-=== buffer.c
-==================================================================
---- buffer.c (revision 8794)
-+++ buffer.c (local)
-@@ -197,7 +197,7 @@
- u_char *data = EVBUFFER_DATA(buffer);
- size_t len = EVBUFFER_LENGTH(buffer);
- char *line;
-- u_int i;
-+ unsigned int i;
-
- for (i = 0; i < len; i++) {
- if (data[i] == '\r' || data[i] == '\n')
-=== configure.in
-==================================================================
---- configure.in (revision 8794)
-+++ configure.in (local)
-@@ -111,6 +111,22 @@
- )
- fi
-
-+dnl - check if the macro WIN32 is defined on this compiler.
-+dnl - (this is how we check for a windows version of GCC)
-+AC_MSG_CHECKING(for WIN32)
-+AC_TRY_COMPILE(,
-+ [
-+ #ifndef WIN32
-+ #error
-+ #endif
-+ ],
-+ bwin32=true; AC_MSG_RESULT(yes),
-+ bwin32=false; AC_MSG_RESULT(no),
-+)
-+
-+AM_CONDITIONAL(BUILD_WIN32, test x$bwin32 = xtrue)
-+
-+
- dnl Checks for typedefs, structures, and compiler characteristics.
- AC_C_CONST
- AC_C_INLINE
-=== evbuffer.c
-==================================================================
---- evbuffer.c (revision 8794)
-+++ evbuffer.c (local)
-@@ -163,12 +162,20 @@
- if (EVBUFFER_LENGTH(bufev->output)) {
- res = evbuffer_write(bufev->output, fd);
- if (res == -1) {
-+#ifndef WIN32
-+/*todo. evbuffer uses WriteFile when WIN32 is set. WIN32 system calls do not
-+ *set errno. thus this error checking is not portable*/
- if (errno == EAGAIN ||
- errno == EINTR ||
- errno == EINPROGRESS)
- goto reschedule;
- /* error case */
- what |= EVBUFFER_ERROR;
-+
-+#else
-+ goto reschedule;
-+#endif
-+
- } else if (res == 0) {
- /* eof case */
- what |= EVBUFFER_EOF;
-
diff --git a/Win32Build/vc6/Tor.dsw b/Win32Build/vc6/Tor.dsw
index 3999da18c2..3999da18c2 100644..100755
--- a/Win32Build/vc6/Tor.dsw
+++ b/Win32Build/vc6/Tor.dsw
diff --git a/Win32Build/vc6/tor/Tor.dsp b/Win32Build/vc6/tor/Tor.dsp
index f05e04931d..4df3052ecc 100644..100755
--- a/Win32Build/vc6/tor/Tor.dsp
+++ b/Win32Build/vc6/tor/Tor.dsp
@@ -106,6 +106,10 @@ SOURCE=..\..\..\src\common\crypto.c
# End Source File
# Begin Source File
+SOURCE=..\..\..\src\common\fakepoll.c
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\src\common\log.c
# End Source File
# Begin Source File
@@ -290,10 +294,6 @@ SOURCE=..\..\..\src\or\onion.c
# End Source File
# Begin Source File
-SOURCE=..\..\..\src\or\policies.c
-# End Source File
-# Begin Source File
-
SOURCE=..\..\..\src\or\relay.c
# End Source File
# Begin Source File
diff --git a/Win32Build/vc6/tor_resolve/tor_resolve.dsp b/Win32Build/vc6/tor_resolve/tor_resolve.dsp
index 63f406b9e1..63f406b9e1 100644..100755
--- a/Win32Build/vc6/tor_resolve/tor_resolve.dsp
+++ b/Win32Build/vc6/tor_resolve/tor_resolve.dsp
diff --git a/Win32Build/vc7/Tor/Tor.sln b/Win32Build/vc7/Tor/Tor.sln
index 3087e26cc1..3087e26cc1 100644..100755
--- a/Win32Build/vc7/Tor/Tor.sln
+++ b/Win32Build/vc7/Tor/Tor.sln
diff --git a/Win32Build/vc7/Tor/Tor.vcproj b/Win32Build/vc7/Tor/Tor.vcproj
index 307521e89d..307521e89d 100644..100755
--- a/Win32Build/vc7/Tor/Tor.vcproj
+++ b/Win32Build/vc7/Tor/Tor.vcproj
diff --git a/Win32Build/vc7/tor_resolve/tor_resolve.vcproj b/Win32Build/vc7/tor_resolve/tor_resolve.vcproj
index a44f1ac66a..a44f1ac66a 100644..100755
--- a/Win32Build/vc7/tor_resolve/tor_resolve.vcproj
+++ b/Win32Build/vc7/tor_resolve/tor_resolve.vcproj
diff --git a/Win32Build/vc7/unittests/unittests.vcproj b/Win32Build/vc7/unittests/unittests.vcproj
index 3dffa786cc..3dffa786cc 100644..100755
--- a/Win32Build/vc7/unittests/unittests.vcproj
+++ b/Win32Build/vc7/unittests/unittests.vcproj
diff --git a/configure.in b/configure.in
index 7527bed5cc..eadbd09d3d 100644
--- a/configure.in
+++ b/configure.in
@@ -4,7 +4,7 @@ dnl Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson
dnl See LICENSE for licensing information
AC_INIT
-AM_INIT_AUTOMAKE(tor, 0.1.2.1-alpha-dev)
+AM_INIT_AUTOMAKE(tor, 0.1.1.23)
AM_CONFIG_HEADER(orconfig.h)
AC_CANONICAL_HOST
@@ -44,26 +44,6 @@ if test $enable_threads = "yes"; then
AC_DEFINE(ENABLE_THREADS, 1, [Defined if we will try to use multithreading])
fi
-AC_ARG_ENABLE(eventdns,
- AC_HELP_STRING(--enable-eventdns, enable asynchronous dns module),
- [case "${enableval}" in
- yes) eventdns=true ;;
- no) eventdns=false ;;
- *) AC_MSG_ERROR(bad value for --enable-eventdns) ;;
- esac], [eventdns=true])
-AM_CONDITIONAL(EVENTDNS, test x$eventdns = xtrue)
-if test x$eventdns = xtrue; then
- AC_DEFINE([USE_EVENTDNS], 1, "Define to 1 if we'll be using eventdns.c")
-fi
-
-AC_ARG_ENABLE(transparent,
- AC_HELP_STRING(--disable-transparent, disable transparent proxy support),
- [case "${enableval}" in
- yes) transparent=true ;;
- no) transparent=false ;;
- *) AC_MSG_ERROR(bad value for --enable-transparent) ;;
- esac], [transparent=true])
-
case $host in
*-*-solaris* )
AC_DEFINE(_REENTRANT, 1, [Define on some platforms to activate x_r() functions in time.h])
@@ -74,31 +54,6 @@ AC_PROG_CC
AC_PROG_MAKE_SET
AC_PROG_RANLIB
-# If WIN32 is defined and non-zero, we are building for win32
-AC_MSG_CHECKING([for win32])
-AC_TRY_COMPILE(,
-[
-#ifdef WIN32
-#if WIN32
-//all is well
-#else
-#error
-#endif
-#else
-#error
-#endif
-],
-bwin32=true; AC_MSG_RESULT([yes]),
-bwin32=false; AC_MSG_RESULT([no])
-)
-
-if test $bwin32 = true; then
-
-AC_DEFINE(MS_WINDOWS,1, [Define to 1 if we are building for a Windows platform.])
-
-
-fi
-
# The big search for OpenSSL
# copied from openssh's configure.ac
tryssldir=""
@@ -158,12 +113,7 @@ AC_CACHE_CHECK([for libevent directory], ac_cv_libevent_dir, [
le_found=no
for ledir in $trylibeventdir "" $prefix /usr/local ; do
LDFLAGS="$saved_LDFLAGS"
-
- if test $bwin32 = true; then
- LIBS="$saved_LIBS -levent -lws2_32"
- else
- LIBS="$saved_LIBS -levent"
- fi
+ LIBS="$saved_LIBS -levent"
# Skip the directory if it isn't there.
if test ! -z "$ledir" -a ! -d "$ledir" ; then
@@ -203,12 +153,7 @@ AC_CACHE_CHECK([for libevent directory], ac_cv_libevent_dir, [
AC_MSG_ERROR([Could not find a linkable libevent. You can specify an explicit path using --with-libevent-dir])
fi
])
-
-if test $bwin32 = true; then
-LIBS="$LIBS -levent -lws2_32"
-else
LIBS="$LIBS -levent"
-fi
if test $ac_cv_libevent_dir != "(system)"; then
if test -d "$ac_cv_libevent_dir/lib" ; then
LDFLAGS="-L$ac_cv_libevent_dir/lib $LDFLAGS"
@@ -224,7 +169,6 @@ if test $ac_cv_libevent_dir != "(system)"; then
fi
fi
-if test -z "$CROSS_COMPILE"; then
AC_CACHE_CHECK([whether we need extra options to link libevent],
ac_cv_libevent_linker_option, [
saved_LDFLAGS="$LDFLAGS"
@@ -256,7 +200,6 @@ AC_CACHE_CHECK([whether we need extra options to link libevent],
if test $ac_cv_libevent_linker_option != '(none)' ; then
LDFLAGS="$ac_cv_libevent_linker_option $LDFLAGS"
fi
-fi
dnl ------------------------------------------------------
dnl Where do you live, openssl? And how do we call you?
@@ -268,12 +211,7 @@ AC_CACHE_CHECK([for OpenSSL directory], ac_cv_openssl_dir, [
ssl_found=no
for ssldir in $tryssldir "" $prefix /usr/local/openssl /usr/lib/openssl /usr/local/ssl /usr/lib/ssl /usr/local /usr/athena /usr/pkg /opt /opt/openssl ; do
LDFLAGS="$saved_LDFLAGS"
-
- if test $bwin32 = true; then
- LIBS="$saved_LIBS -lssl -lcrypto -lws2_32 -lgdi32"
- else
- LIBS="$saved_LIBS -lssl -lcrypto"
- fi
+ LIBS="$saved_LIBS -lssl -lcrypto"
# Skip the directory if it isn't there.
if test ! -z "$ssldir" -a ! -d "$ssldir" ; then
@@ -312,13 +250,7 @@ AC_CACHE_CHECK([for OpenSSL directory], ac_cv_openssl_dir, [
AC_MSG_ERROR([Could not find a linkable OpenSSL. You can specify an explicit path using --with-ssl-dir])
fi
])
-
-if test $bwin32 = true; then
-LIBS="$LIBS -lssl -lcrypto -lws2_32 -lgdi32"
-else
LIBS="$LIBS -lssl -lcrypto"
-fi
-
if test "$ac_cv_openssl_dir" != "(system)"; then
if test -d "$ac_cv_openssl_dir/lib" ; then
LDFLAGS="-L$ac_cv_openssl_dir/lib $LDFLAGS"
@@ -334,8 +266,6 @@ if test "$ac_cv_openssl_dir" != "(system)"; then
fi
fi
-if test -z $CROSS_COMPILE
-then
AC_CACHE_CHECK([whether we need extra options to link OpenSSL],
ac_cv_openssl_linker_option, [
saved_LDFLAGS="$LDFLAGS"
@@ -395,7 +325,6 @@ return (OPENSSL_VERSION_NUMBER == SSLeay()) == 0;
if test "$ac_cv_openssl_linker_option" != '(none)' ; then
LDFLAGS="$ac_cv_openssl_linker_option $LDFLAGS"
fi
-fi
dnl Make sure to enable support for large off_t if avalable.
@@ -405,74 +334,21 @@ dnl The warning message here is no longer strictly accurate.
AC_CHECK_HEADERS(unistd.h string.h signal.h netdb.h ctype.h sys/stat.h sys/types.h fcntl.h sys/fcntl.h sys/ioctl.h sys/socket.h sys/time.h netinet/in.h arpa/inet.h errno.h assert.h time.h pwd.h grp.h, , AC_MSG_WARN(some headers were not found, compilation may fail))
-AC_CHECK_HEADERS(event.h, , AC_MSG_ERROR(Libevent header (event.h) not found. Tor requires libevent to build.),
-[#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
- struct timeval {
- long tv_sec;
- long tv_usec;
- };
-#endif])
+AC_CHECK_HEADERS(event.h, , AC_MSG_ERROR(Libevent header (event.h) not found. Tor requires libevent to build.))
AC_CHECK_HEADERS(zlib.h, , AC_MSG_ERROR(Zlib header (zlib.h) not found. Tor requires zlib to build. You may need to install a zlib development package.))
dnl These headers are not essential
-AC_CHECK_HEADERS(stdint.h sys/types.h inttypes.h sys/param.h sys/wait.h limits.h sys/limits.h netinet/in.h arpa/inet.h machine/limits.h syslog.h sys/time.h sys/resource.h inttypes.h utime.h sys/utime.h sys/mman.h)
+AC_CHECK_HEADERS(stdint.h sys/types.h inttypes.h sys/param.h sys/wait.h sys/limits.h netinet/in.h arpa/inet.h machine/limits.h syslog.h sys/time.h sys/resource.h stddef.h inttypes.h utime.h sys/utime.h)
-AC_CHECK_HEADERS(net/if.h, [net_if_found=1], [net_if_found=0],
-[#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif])
-AC_CHECK_HEADERS(net/pfvar.h, [net_pfvar_found=1], [net_pfvar_found=0],
-[#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef HAVE_NET_IF_H
-#include <net/if.h>
-#endif])
-AC_CHECK_HEADERS(linux/netfilter_ipv4.h,
- [linux_netfilter_ipv4=1], [linux_netfilter_ipv4=0],
-[#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif])
-
-AC_CHECK_FUNCS(gettimeofday ftime socketpair uname inet_aton strptime getrlimit strlcat strlcpy strtoull ftello getaddrinfo localtime_r gmtime_r event_get_version event_get_method event_set_log_callback memmem strtok_r)
+AC_CHECK_FUNCS(gettimeofday ftime socketpair uname inet_aton strptime getrlimit setrlimit strlcat strlcpy strtoull getpwnam getpwuid ftello getaddrinfo localtime_r gmtime_r event_get_version event_get_method event_set_log_callback memmem)
if test $enable_threads = "yes"; then
AC_CHECK_HEADERS(pthread.h)
AC_CHECK_FUNCS(pthread_create)
fi
-if test x$transparent = xtrue ; then
- transparent_ok=0
- if test x$net_if_found = x1 -a x$net_pfvar_found = x1 ; then
- transparent_ok=1
- fi
- if test x$linux_netfilter_ipv4 = x1 ; then
- transparent_ok=1
- fi
- if test x$transparent_ok = x1 ; then
- AC_DEFINE(USE_TRANSPARENT, 1, "Define to enable transparent proxy support")
- case $host in
- *-*-openbsd*)
- AC_DEFINE(OPENBSD, 1, "Define to handle pf on OpenBSD properly") ;;
- esac
- else
- AC_MSG_NOTICE([Transparent proxy support enabled, but missing headers.])
- fi
-fi
-
AC_FUNC_FSEEKO
AC_CHECK_MEMBERS([struct timeval.tv_sec])
@@ -501,20 +377,11 @@ AC_CHECK_SIZEOF(long long)
AC_CHECK_SIZEOF(__int64)
AC_CHECK_SIZEOF(void *)
AC_CHECK_SIZEOF(time_t)
-
-AC_CHECK_TYPES([uint, u_char])
-
-if test -z "$CROSS_COMPILE"; then
AC_CACHE_CHECK([whether time_t is signed], tor_cv_time_t_signed, [
AC_TRY_RUN([
int main(int c, char**v) { if (((time_t)-1)<0) return 1; else return 0; }],
tor_cv_time_t_signed=no, tor_cv_time_t_signed=yes)
])
-else
- # Cross-compiling; let's hope the target platform isn't loony.
- AC_MSG_NOTICE([Cross compiling: assuming that time_t is signed.])
- tor_cv_time_t_signed=yes
-fi
if test $tor_cv_time_t_signed = yes; then
AC_DEFINE([TIME_T_IS_SIGNED], 1,
@@ -531,8 +398,36 @@ AC_CHECK_SIZEOF(socklen_t, , [AC_INCLUDES_DEFAULT()
AC_CHECK_SIZEOF(cell_t)
+# Now, let's see about alignment requirements. On some platforms, we override
+# the default.
+case $host in
+ ia64-*-* | arm-*-* | sparc-*-* | sparc64-*-* )
+ tor_cv_unaligned_ok=no
+ ;;
+ # On the following architectures unaligned access works, but is not done in
+ # hardware. This means that when you try to do unaligned access the kernel
+ # gets to sort out an exception and then work around to somehow make your
+ # reqest work, which is quite expensive. Therefore it's probably better to
+ # not even do it.
+ alpha-*-* | mips-*-* | mipsel-*-* )
+ tor_cv_unaligned_ok=no
+ ;;
+ *)
+AC_CACHE_CHECK([whether unaligned int access is allowed], tor_cv_unaligned_ok,
+[AC_RUN_IFELSE([AC_LANG_SOURCE(
+[[int main () { char s[] = "A\x00\x00\x00\x00\x00\x00\x00";
+return *(int*)(&s[1]); }]])],
+ [tor_cv_unaligned_ok=yes],
+ [tor_cv_unaligned_ok=no],
+ [tor_cv_unaligned_ok=cross])])
+esac
+
+if test $tor_cv_unaligned_ok = yes; then
+ AC_DEFINE([UNALIGNED_INT_ACCESS_OK], 1,
+ [Define to 1 iff unaligned int access is allowed])
+fi
+
# Now make sure that NULL can be represented as zero bytes.
-if test -z "$CROSS_COMPILE"; then
AC_CACHE_CHECK([whether memset(0) sets pointers to NULL], tor_cv_null_is_zero,
[AC_RUN_IFELSE([AC_LANG_SOURCE(
[[#include <stdlib.h>
@@ -547,44 +442,11 @@ return memcmp(&p1,&p2,sizeof(char*))?1:0; }]])],
[tor_cv_null_is_zero=no],
[tor_cv_null_is_zero=cross])])
-else
- # Cross-compiling; let's hope that the target isn't raving mad.
- AC_MSG_NOTICE([Cross-compiling: we'll assume that NULL is represented as a sequence of 0-valued bytes.])
- tor_cv_null_is_zero=yes
-fi
-
if test $tor_cv_null_is_zero = yes; then
AC_DEFINE([NULL_REP_IS_ZERO_BYTES], 1,
[Define to 1 iff memset(0) sets pointers to NULL])
fi
-# And what happens when we malloc zero?
-
-if test -z "$CROSS_COMPILE"; then
-AC_CACHE_CHECK([whether we can malloc(0) safely.], tor_cv_malloc_zero_works,
-[AC_RUN_IFELSE([AC_LANG_SOURCE(
-[[#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#ifdef HAVE_STDDEF_H
-#include <stddef.h>
-#endif
-int main () { return malloc(0)?0:1; }]])],
- [tor_cv_malloc_zero_works=yes],
- [tor_cv_malloc_zero_works=no],
- [tor_cv_malloc_zero_works=cross])])
-
-else
- # Cross-compiling; let's hope that the target isn't raving mad.
- AC_MSG_NOTICE([Cross-compiling: we'll assume that we need to check malloc() arguments for 0.])
- tor_cv_malloc_zero_works=no
-fi
-
-if test $tor_cv_malloc_zero_works = yes; then
- AC_DEFINE([MALLOC_ZERO_WORKS], 1,
- [Define to 1 iff malloc(0) returns a pointer])
-fi
-
# Whether we should use the dmalloc memory allocation debugging library.
AC_MSG_CHECKING(whether to use dmalloc (debug memory allocation library))
AC_ARG_WITH(dmalloc,
@@ -695,6 +557,7 @@ if test $ac_cv_have_func_macro = 'yes'; then
AC_DEFINE(HAVE_MACRO__func__, 1, [Defined if the compiler supports __func__])
fi
+
if test $ac_cv_have_FUNC_macro = 'yes'; then
AC_DEFINE(HAVE_MACRO__FUNC__, 1, [Defined if the compiler supports __FUNC__])
fi
@@ -704,6 +567,7 @@ if test $ac_cv_have_FUNCTION_macro = 'yes'; then
[Defined if the compiler supports __FUNCTION__])
fi
+
# $prefix stores the value of the --prefix command line option, or
# NONE if the option wasn't set. In the case that it wasn't set, make
# it be the default, so that we can use it to expand directories now.
@@ -738,7 +602,7 @@ else
fi
# Add some more warnings which we use in the cvs version but not in the
# released versions. (Some relevant gcc versions can't handle these.)
-#CFLAGS="$CFLAGS -W -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wchar-subscripts -Wcomment -Wformat=2 -Winit-self -Wwrite-strings -Waggregate-return -Wmissing-declarations -Wmissing-field-initializers -Wredundant-decls -Winline -Wnested-externs -Wswitch-enums"
+#CFLAGS="$CFLAGS -W -Wno-unused-parameter -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wchar-subscripts -Wcomment -Wformat=2 -Winit-self -Wwrite-strings -Waggregate-return -Wmissing-declarations -Wmissing-field-initializers -Wredundant-decls -Winline"
# Add these in when you feel like fun.
#CFLAGS="$CFLAGS -Wbad-function-cast -Werror -Wdeclaration-after-statement -Wold-style-definition"
diff --git a/contrib/Makefile.am b/contrib/Makefile.am
index d8ae4c06d6..16e9158cd9 100644
--- a/contrib/Makefile.am
+++ b/contrib/Makefile.am
@@ -3,7 +3,7 @@ DIST_SUBDIRS = osx suse
confdir = $(sysconfdir)/tor
-EXTRA_DIST = exitlist tor-tsocks.conf torify.1 TorControl.py tor.nsi.in tor.sh torctl rc.subr ExerciseServer.py PathDemo.py cross.sh
+EXTRA_DIST = exitlist tor-tsocks.conf torify.1 TorControl.py tor.nsi.in tor.sh torctl rc.subr ExerciseServer.py PathDemo.py
conf_DATA = tor-tsocks.conf
diff --git a/contrib/add-tor b/contrib/add-tor
deleted file mode 100755
index 5a12abca80..0000000000
--- a/contrib/add-tor
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/usr/bin/ruby
-
-# add-tor - Add a tor fingerprint line to the approved-routers file
-#
-# Tor's approved-routers file is expected to be versioned using RCS.
-# This script checks for uncommitted changes, does a checkout of the
-# file, adds the new fingerprint with a comment stating the server's
-# operator, and commits the file to RCS again (using -u so that the
-# working copy is not removed.
-#
-# Operator and fingerprint line are read from stdin.
-#
-# Before adding a fingerprint line, approved-routers is checked for
-# rough syntactical correctness. This script also checks that the
-# nickname and fingerprint to be added do not already exist in the
-# binding list.
-
-
-# Copyright (c) 2006 by Peter Palfrader
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-BINDING = '/etc/tor/approved-routers'
-
-def mysys(cmd)
- unless system(cmd)
- STDERR.puts "ERROR: #{cmd} failed"
- exit 1
- end
-end
-
-def check_nick(n)
- n =~ /^[a-zA-Z0-9]+$/
-end
-
-def check_fpr(fpr)
- fpr =~ /^([0-9A-F]{4} ){9}[0-9A-F]{4}$/
-end
-
-def parse_fprline(fprline)
- n = fprline[0 ... fprline.index(' ')]
- f = fprline[fprline.index(' ') + 1 .. -1 ]
- unless check_nick(n) and check_fpr(f)
- STDERR.puts "Invalid fpr syntax '#{fprline}'"
- exit 1
- end
- [n, f]
-end
-
-
-
-unless system("rcsdiff -q -u #{BINDING}")
- STDERR.puts "Uncommitted changes in #{BINDING}. Aborting."
- exit 1
-end
-
-puts "Checking out #{BINDING}..."
-mysys("co -l #{BINDING}")
-
-print "Operator: "
-@operator = readline.chop
-unless @operator.index('@')
- STDERR.puts "ERROR: No @ found"
- exit 1
-end
-
-print "FPR Line: "
-@fprline = readline.chop
-(@nickname, @fpr) = parse_fprline(@fprline)
-
-binding = File.new(BINDING, "r+")
-binding.readlines.each do |line|
- line.chop!
- next if line[0..0] == "#"
- (n,f) = parse_fprline(line)
- if (n == @nickname)
- STDERR.puts
- STDERR.puts "ERROR: Nickname #{n} already exists in #{BINDING} (fpr: #{f})"
- exit 1
- end
- if (f == @fpr)
- STDERR.puts
- STDERR.puts "ERROR: Fpr #{f} already exists in #{BINDING} (nickname: #{n})"
- exit 1
- end
-end
-
-puts
-puts '| # ' + @operator
-puts '| ' + @fprline
-puts
-
-binding.puts '# '+@operator
-binding.puts @fprline
-binding.close
-
-puts "Committing #{BINDING}..."
-mysys("ci -u -m'Add #{@nickname}' #{BINDING}")
diff --git a/contrib/checkSpace.pl b/contrib/checkSpace.pl
index aff96861a9..30c243e09f 100755
--- a/contrib/checkSpace.pl
+++ b/contrib/checkSpace.pl
@@ -11,23 +11,23 @@ for $fn (@ARGV) {
$lastnil = 0;
$incomment = 0;
while (<F>) {
- ## Warn about windows-style newlines.
+ ## Warn about windows-style newlines.
if (/\r/) {
print " CR:$fn:$.\n";
}
- ## Warn about tabs.
+ ## Warn about tabs.
if (/\t/) {
print " TAB:$fn:$.\n";
}
- ## Warn about trailing whitespace.
+ ## Warn about trailing whitespace.
if (/ +$/) {
print "Space\@EOL:$fn:$.\n";
}
- ## Warn about control keywords without following space.
- if ($C && /\s(?:if|while|for|switch)\(/) {
- print " KW(:$fn:$.\n";
- }
- ## Warn about multiple empty lines.
+ ## Warn about control keywords without following space.
+ if ($C && /\s(?:if|while|for|switch)\(/) {
+ print " KW(:$fn:$.\n";
+ }
+ ## Warn about multiple empty lines.
if ($lastnil && /^$/) {
print " DoubleNL:$fn:$.\n";
} elsif (/^$/) {
@@ -35,15 +35,15 @@ for $fn (@ARGV) {
} else {
$lastnil = 0;
}
- ## Terminals are still 80 columns wide in my world. I refuse to
- ## accept double-line lines. Except, of course, svn Id tags
- ## can make us go long.
- if (/^.{80}/ && !/\$Id: /) {
- print " Wide:$fn:$.\n";
- }
- ### Juju to skip over comments and strings, since the tests
- ### we're about to do are okay there.
- if ($C) {
+ ## Terminals are still 80 columns wide in my world. I refuse to
+ ## accept double-line lines.
+ if (/^.{80}/) {
+ print " Wide:$fn:$.\n";
+ }
+
+ ### Juju to skip over comments and strings, since the tests
+ ### we're about to do are okay there.
+ if ($C) {
if ($incomment) {
if (m!\*/!) {
s!.*?\*/!!;
@@ -83,30 +83,30 @@ for $fn (@ARGV) {
if (/(\w+)\s\(/) {
if ($1 ne "if" and $1 ne "while" and $1 ne "for" and
$1 ne "switch" and $1 ne "return" and $1 ne "int" and
- $1 ne "elsif" and
$1 ne "void" and $1 ne "__attribute__") {
print " fn ():$fn:$.\n";
}
}
- ## Warn about functions not declared at start of line.
- if ($in_func_head ||
- ($fn !~ /\.h$/ && /^[a-zA-Z0-9_]/ &&
- ! /^(?:const |static )*(?:typedef|struct|union)[^\(]*$/ &&
- ! /= *\{$/ && ! /;$/)) {
- if (/.\{$/){
- print "fn() {:$fn:$.\n";
- $in_func_head = 0;
- } elsif (/^\S[^\(]* +\**[a-zA-Z0-9_]+\(/) {
- $in_func_head = -1; # started with tp fn
- } elsif (/;$/) {
- $in_func_head = 0;
- } elsif (/\{/) {
- if ($in_func_head == -1) {
- print "tp fn():$fn:$.\n";
- }
- $in_func_head = 0;
- }
- }
+ ## Warn about functions not declared at start of line.
+ if ($in_func_head ||
+ ($fn !~ /\.h$/ && /^[a-zA-Z0-9_]/ &&
+ ! /^(?:static )?(?:typedef|struct|union)[^\(]*$/ &&
+ ! /= *\{$/ && ! /;$/)) {
+
+ if (/.\{$/){
+ print "fn() {:$fn:$.\n";
+ $in_func_head = 0;
+ } elsif (/^\S[^\(]* +\**[a-zA-Z0-9_]+\(/) {
+ $in_func_head = -1; # started with tp fn
+ } elsif (/;$/) {
+ $in_func_head = 0;
+ } elsif (/\{/) {
+ if ($in_func_head == -1) {
+ print "tp fn():$fn:$.\n";
+ }
+ $in_func_head = 0;
+ }
+ }
}
}
if (! $lastnil) {
@@ -114,4 +114,3 @@ for $fn (@ARGV) {
}
close(F);
}
-
diff --git a/contrib/cross.sh b/contrib/cross.sh
deleted file mode 100644
index 890e4496de..0000000000
--- a/contrib/cross.sh
+++ /dev/null
@@ -1,150 +0,0 @@
-#!/bin/bash
-# $Id$
-# Copyright 2006 Michael Mohr with modifications by Roger Dingledine
-# See LICENSE for licensing information.
-
-#######################################################################
-# Tor-cross: a tool to help cross-compile Tor
-#
-# The purpose of a cross-compiler is to produce an executable for
-# one system (CPU) on another. This is useful, for example, when
-# the target system does not have a native compiler available.
-# You might, for example, wish to cross-compile a program on your
-# host (the computer you're working on now) for a target such as
-# a router or handheld computer.
-#
-# A number of environment variables must be set in order for this
-# script to work:
-# $PREFIX, $CROSSPATH, $ARCH_PREFIX, $HOST,
-# and (optionally) $BUILD
-# Please run the script for a description of each one. If automated
-# builds are desired, the above variables can be exported at the top
-# of this script.
-#
-# Recent releases of Tor include test programs in configure. Normally
-# this is a good thing, since it catches a number of problems.
-# However, this also presents a problem when cross compiling, since
-# you can't run binary images for the target system on the host.
-#
-# Tor-cross assumes that you know what you're doing and removes a
-# number of checks known to cause problems with this process.
-# Note that this does not guarantee that the program will run or
-# even compile; it simply allows configure to generate the Makefiles.
-#
-# Stripping the binaries should almost always be done for an
-# embedded environment where space is at an exacting premium.
-# However, the default is NOT to strip them since they are useful for
-# debugging. If you do not plan to do any debugging and you
-# don't care about the debugging symbols, set $STRIP to "yes" before
-# running this script.
-#
-# Tor-cross was written by Michael Mohr. He can be contacted at
-# m(dot)mohr(at)laposte(dot)net. Comments are appreciated, but
-# flames go to /dev/null.
-#
-# The target with which this script is tested is little-endian
-# MIPS Linux, built on an Athlon-based Linux desktop.
-#
-#######################################################################
-
-# disable the platform-specific tests in configure
-export CROSS_COMPILE=yes
-
-if [ ! -f configure ]
-then
- echo "Please run this script from the root of the Tor distribution."
- exit -1
-fi
-
-if [ -z $PREFIX ]
-then
- echo "You must define \$PREFIX since you are cross-compiling."
- echo "Select a non-system location (i.e. /tmp/tor-cross):"
- echo " export PREFIX=/tmp/tor-cross"
- exit -1
-fi
-
-if [ -z $CROSSPATH ]
-then
- echo "You must define the location of your cross-compiler's"
- echo "directory using \$CROSSPATH; for example,"
- echo " export CROSSPATH=/opt/cross/staging_dir_mipsel/bin"
- exit -1
-fi
-
-if [ -z $ARCH_PREFIX ]
-then
- echo "You must define \$ARCH_PREFIX to continue. For example,"
- echo "if you normally cross-compile applications using"
- echo "mipsel-linux-uclibc-gcc, you would set \$ARCH_PREFIX like so:"
- echo " export ARCH_PREFIX=mipsel-linux-uclibc-"
- exit -1
-fi
-
-if [ -z $HOST ]
-then
- echo "You must specify a target processor with \$HOST; for example:"
- echo " export HOST=mipsel-unknown-elf"
- exit -1
-fi
-
-if [ -z $BUILD ]
-then
- echo "You should specify the host machine's type with \$BUILD; for example:"
- echo " export BUILD=i686-pc-linux-gnu"
- echo "If you wish to let configure autodetect the host, set \$BUILD to 'auto':"
- echo " export BUILD=auto"
- exit -1
-fi
-
-# clean up any existing object files
-if [ -f src/or/tor ]
-then
- make clean
-fi
-
-# Set up the build environment and try to run configure
-export PATH=$PATH:$CROSSPATH
-export RANLIB=${ARCH_PREFIX}ranlib
-export CC=${ARCH_PREFIX}gcc
-
-if [ $BUILD == "auto" ]
-then
- ./configure \
- --prefix=$PREFIX \
- --host=$HOST
-else
- ./configure \
- --prefix=$PREFIX \
- --host=$HOST \
- --build=$BUILD
-fi
-
-# has a problem occurred?
-if [ $? -ne 0 ]
-then
- echo ""
- echo "A problem has been detected with configure."
- echo "Please check the output above and rerun cross.sh"
- echo ""
- exit -1
-fi
-
-# Now we're cookin'
-
-make
-
-# if $STRIP has length (i.e. STRIP=yes), strip the binaries
-if [ ! -z $STRIP ]
-then
-${ARCH_PREFIX}strip \
- src/or/tor \
- src/or/test \
- src/tools/tor-resolve
-fi
-
-echo ""
-echo "Tor should be compiled at this point. Now run 'make install' to"
-echo "install to $PREFIX"
-echo ""
-
diff --git a/contrib/exitlist b/contrib/exitlist
index de26dab89c..96be25a7fa 100755
--- a/contrib/exitlist
+++ b/contrib/exitlist
@@ -19,10 +19,6 @@
If you're using Tor 0.1.1.18-rc or later, you should look at
the "FetchUselessDescriptors" config option in the man page.
- Note that this script won't give you a perfect list of IP addresses
- that might connect to you using Tor, since some Tor servers might exit
- from other addresses than the one they publish.
-
"""
#
@@ -200,13 +196,6 @@ class Server:
self.ip = ip
self.policy = policy
-def uniq_sort(lst):
- d = {}
- for item in lst: d[item] = 1
- lst = d.keys()
- lst.sort()
- return lst
-
def run():
servers = []
policy = []
@@ -244,13 +233,12 @@ def run():
else:
printlist = accepters
- ents = []
if VERBOSE:
- ents = uniq_sort([ "%s\t%s"%(s.ip,s.name) for s in printlist ])
+ for s in printlist:
+ print "%s\t%s"%(s.ip,s.name)
else:
- ents = uniq_sort([ s.ip for s in printlist ])
- for e in ents:
- print e
+ for s in printlist:
+ print s.ip
def _test():
import doctest, exitparse
diff --git a/contrib/id_to_fp.c b/contrib/id_to_fp.c
deleted file mode 100644
index e6f9f46279..0000000000
--- a/contrib/id_to_fp.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/* Copyright 2006 Nick Mathewson; see LICENSE for licensing information */
-/* $Id$ */
-
-/* id_to_fp.c : Helper for directory authority ops. When somebody sends us
- * a private key, this utility converts the private key into a fingerprint
- * so you can de-list that fingerprint.
- */
-
-#include <openssl/rsa.h>
-#include <openssl/bio.h>
-#include <openssl/sha.h>
-#include <openssl/pem.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#define die(s) do { fprintf(stderr, "%s\n", s); goto err; } while (0)
-
-int
-main(int argc, char **argv)
-{
- BIO *b = NULL;
- RSA *key = NULL;
- unsigned char *buf = NULL, *bufp;
- int len, i;
- unsigned char digest[20];
- int status = 1;
-
- if (argc != 2)
- die("I want a filename");
- if (!(b = BIO_new_file(argv[1], "r")))
- die("couldn't open file");
-
- if (!(key = PEM_read_bio_RSAPrivateKey(b, NULL, NULL, NULL)))
- die("couldn't parse key");
-
- len = i2d_RSAPublicKey(key, NULL);
- if (len < 0)
- die("Bizarre key");
- bufp = buf = malloc(len+1);
- if (!buf)
- die("Out of memory");
- len = i2d_RSAPublicKey(key, &bufp);
- if (len < 0)
- die("Bizarre key");
-
- SHA1(buf, len, digest);
- for (i=0; i < 20; i += 2) {
- printf("%02X%02X ", (int)digest[i], (int)digest[i+1]);
- }
- printf("\n");
-
- status = 0;
-
-err:
- if (buf)
- free(buf);
- if (key)
- RSA_free(key);
- if (b)
- BIO_free(b);
- return status;
-}
-
diff --git a/contrib/osx/Makefile.am b/contrib/osx/Makefile.am
index 3fa7047ee1..f26148593f 100644
--- a/contrib/osx/Makefile.am
+++ b/contrib/osx/Makefile.am
@@ -6,5 +6,4 @@ EXTRA_DIST = PrivoxyConfDesc.plist PrivoxyConfInfo.plist \
TorInfo.plist.in TorStartupDesc.plist.in TorStartupInfo.plist \
package.sh privoxy.config TorPostflight addsysuser \
Tor_Uninstaller.applescript uninstall_tor_bundle.sh \
- package_list.txt tor_logo.gif Tor_Uninstaller.app.tar.gz \
- TorPreFlight
+ package_list.txt tor_logo.gif
diff --git a/contrib/osx/TorPostflight b/contrib/osx/TorPostflight
index 8c8c32aa4f..cd49924947 100644
--- a/contrib/osx/TorPostflight
+++ b/contrib/osx/TorPostflight
@@ -37,7 +37,7 @@ chown $TORUSER $LOGDIR
chgrp daemon $LOGDIR
chmod 700 $LOGDIR
-# Create the configuration file only if there wasn't one already.
+# Create the configuration file only if there wan't one already.
if [ ! -f $TARGET/torrc ]; then
cp $TARGET/torrc.sample $TARGET/torrc
fi
@@ -63,6 +63,11 @@ if [ ! -e /var/log/tor -o -L /var/log/tor ]; then
ln -sf $LOGDIR tor
fi
+if [ -d /Library/StartupItems/Tor ]; then
+ rm -f /Library/StartupItems/Tor/Tor.loc
+ echo "$TARGET" > /Library/StartupItems/Tor/Tor.loc
+fi
+
if [ -d /Library/StartupItems/Privoxy ]; then
find /Library/StartupItems/Privoxy -print0 | xargs -0 chown root:wheel
fi
@@ -78,14 +83,6 @@ if [ -f $PACKAGE_PATH/Contents/Resources/Tor_Uninstaller.applescript ]; then
chmod 755 $TARGET/Tor_Uninstaller.applescript
fi
-if [ -f $PACKAGE_PATH/Contents/Resources/Tor_Uninstaller.app.tar.gz ]; then
- cp $PACKAGE_PATH/Contents/Resources/Tor_Uninstaller.app.tar.gz $TARGET/Tor_Uninstaller.app.tar.gz
- cd $TARGET && tar zxf Tor_Uninstaller.app.tar.gz
- chmod -R 755 $TARGET/Tor_Uninstaller.app
- chown -R _tor:_tor Tor_Uninstaller.app
- rm $TARGET/Tor_Uninstaller.app.tar.gz
-fi
-
if [ -f $PACKAGE_PATH/Contents/Resources/uninstall_tor_bundle.sh ]; then
cp $PACKAGE_PATH/Contents/Resources/uninstall_tor_bundle.sh $TARGET/uninstall_tor_bundle.sh
chmod 755 $TARGET/uninstall_tor_bundle.sh
@@ -94,15 +91,3 @@ fi
if [ -f $PACKAGE_PATH/Contents/Resources/package_list.txt ]; then
cp $PACKAGE_PATH/Contents/Resources/package_list.txt $TARGET/package_list.txt
fi
-
-# If the pre-install script did it's thing, it should have saved the
-# config and server keys; put these back and clean up
-if [ -f /tmp/TorSavedMe.tar.gz ]; then
- tar zxf /tmp/TorSavedMe.tar.gz -C /
- rm /tmp/TorSavedMe.tar.gz
-fi
-
-if [ -d /Library/StartupItems/Tor ]; then
- rm -f /Library/StartupItems/Tor/Tor.loc
- echo "$TARGET" > /Library/StartupItems/Tor/Tor.loc
-fi
diff --git a/contrib/osx/TorPreFlight b/contrib/osx/TorPreFlight
deleted file mode 100644
index b147264861..0000000000
--- a/contrib/osx/TorPreFlight
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/sh
-# TorPreFlight is invoked before the install begins
-
-# Figure out where Tor is installed
-if [ -f /Library/StartupItems/Tor/Tor.loc ]; then
- TORPATH=`cat /Library/StartupItems/Tor/Tor.loc`
-else
- TORPATH="/Library/Tor/"
-fi
-
-if [ -f /Library/StartupItems/Privoxy/Privoxy.loc ]; then
- PRIVOXYPATH=`cat /Library/StartupItems/Privoxy/Privoxy.loc`
-else
- PRIVOXYPATH="/Library/Privoxy/"
-fi
-
-# Backup all of Tor, just in case
-if [ -d $TORPATH ]; then
- tar zcf /tmp/TorSavedMe.tar.gz $TORPATH/var/lib/tor $TORPATH/torrc $PRIVOXYPATH/config $PRIVOXYPATH/user.action
-fi
-
-# Remove Tor and everything to do with it
-if [ -f $TORPATH/uninstall_tor_bundle.sh ]; then
- $TORPATH/uninstall_tor_bundle.sh
-else
- $PACKAGE_PATH/Contents/Resources/uninstall_tor_bundle.sh
-fi
-
-# This is complete, we have a fresh system on which to install Tor
diff --git a/contrib/osx/Tor_Uninstaller.app.tar.gz b/contrib/osx/Tor_Uninstaller.app.tar.gz
deleted file mode 100644
index add053a1fe..0000000000
--- a/contrib/osx/Tor_Uninstaller.app.tar.gz
+++ /dev/null
Binary files differ
diff --git a/contrib/osx/Tor_Uninstaller.applescript b/contrib/osx/Tor_Uninstaller.applescript
index 246e265bbe..79ac46f9aa 100644
--- a/contrib/osx/Tor_Uninstaller.applescript
+++ b/contrib/osx/Tor_Uninstaller.applescript
@@ -35,34 +35,31 @@
-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- ===============================================================================
-on run
-
- -- Validate & find disk paths
- set boot_disk to (path to startup disk) as string
- set default_tor_path to boot_disk & "Library:Tor"
- set default_privoxy_path to boot_disk & "Library:Privoxy"
- set default_tor_startup_path to boot_disk & "Library:StartupItems:Tor"
- set default_privoxy_startup_path to boot_disk & "Library:StartupItems:Privoxy"
- set shell_script to default_tor_path & ":uninstall_tor_bundle.sh"
- set doomed_path_list to {default_tor_path, default_privoxy_path, default_tor_startup_path, default_privoxy_startup_path}
-
- -- Display what we're removing and ask for validation
- -- this is the simplest way to do this
- set remove_me to display dialog "Welcome to the Tor + Privoxy Uninstaller. This program will remove:" & return & return & POSIX path of default_tor_path & return & POSIX path of default_privoxy_path & return & POSIX path of default_tor_startup_path & return & POSIX path of default_privoxy_startup_path & return & return & "If this looks correct, choose Yes. Otherwise, choose No." buttons {"Yes", "No"} default button "No"
-
- -- Run a shell script to do all the unix work since applescript can't see it at all
- if button returned of result is "Yes" then
- try
- do shell script (POSIX path of shell_script) with administrator privileges
- on error
- display dialog "Too many errors, quitting." buttons {"Quit"} default button "Quit" with icon stop giving up after 3
- quit
- end try
- -- So Long and Thanks for all the Fish!
- display dialog "Thank you for using tor!" buttons {"Ok"} giving up after 3
- else
- display dialog "Thank you for your continued use of Tor & Privoxy" buttons {"You're welcome."} giving up after 3
- end if
-
-end run
+-- Validate & find disk paths
+set boot_disk to (path to startup disk) as string
+set default_tor_path to boot_disk & "Library:Tor"
+set default_privoxy_path to boot_disk & "Library:Privoxy"
+set default_tor_startup_path to boot_disk & "Library:StartupItems:Tor"
+set default_privoxy_startup_path to boot_disk & "Library:StartupItems:Privoxy"
+set shell_script to default_tor_path & ":uninstall_tor_bundle.sh"
+set doomed_path_list to {default_tor_path, default_privoxy_path, default_tor_startup_path, default_privoxy_startup_path}
+
+-- Display what we're removing and ask for validation
+-- this is the simplest way to do this
+set remove_me to display dialog "Welcome to the Tor + Privoxy Uninstaller. This program will remove:" & return & default_tor_path & return & default_privoxy_path & return & default_tor_startup_path & return & default_privoxy_startup_path & return & return & "If this does not look right, choose Yes. Otherwise, choose No." buttons {"Yes", "No"} default button "No"
+
+-- Run a shell script to do all the unix work since applescript can't see it at all
+if button returned of result is "Yes" then
+ try
+ do shell script (shell_script) with administrator privileges
+ on error
+ display dialog "Too many errors, quitting." buttons {"Quit"} default button "Quit" with icon stop giving up after 5
+ quit
+ end try
+ -- So Long and Thanks for all the Fish!
+ display dialog "Thank you for using tor!" buttons {"Ok"} giving up after 5
+else
+ display dialog "Thank you for your continued use of Tor & Privoxy" buttons {"You're welcome."}
+end if
+
-- We're done \ No newline at end of file
diff --git a/contrib/osx/package.sh b/contrib/osx/package.sh
index 85b0e43660..d63c3efab4 100644
--- a/contrib/osx/package.sh
+++ b/contrib/osx/package.sh
@@ -26,7 +26,7 @@ PRIVOXY_PKG_ZIP=~/tmp/privoxyosx_setup_3.0.3.zip
# man packagemaker
# Make sure VERSION is set, so we don't name the package
-# "Tor--$OS-Bundle.dmg"
+# "Tor--$OS-$ARCH-Bundle.dmg"
if [ "XX$VERSION" = 'XX' ]; then
echo "VERSION not set."
exit 1
@@ -83,7 +83,6 @@ cp contrib/osx/ReadMe.rtf $BUILD_DIR/tor_resources
#cp contrib/osx/License.rtf $BUILD_DIR/tor_resources
chmod 755 contrib/osx/TorPostflight
cp contrib/osx/TorPostflight $BUILD_DIR/tor_resources/postflight
-cp contrib/osx/TorPreFlight $BUILD_DIR/tor_resources/preflight
cp contrib/osx/addsysuser $BUILD_DIR/tor_resources/addsysuser
cp contrib/osx/Tor_Uninstaller.applescript $BUILD_DIR/tor_resources/Tor_Uninstaller.applescript
cp contrib/osx/Tor_Uninstaller.app.tar.gz $BUILD_DIR/tor_resources/Tor_Uninstaller.app.tar.gz
diff --git a/contrib/osx/uninstall_tor_bundle.sh b/contrib/osx/uninstall_tor_bundle.sh
index 18b346005c..9d69d09e54 100755
--- a/contrib/osx/uninstall_tor_bundle.sh
+++ b/contrib/osx/uninstall_tor_bundle.sh
@@ -134,7 +134,7 @@ niutil -destroy . /users/$TOR_USER
## clean up
echo ". Cleaning up"
rm -rf $TEMP_BOM_CONTENTS
-rm -rf /Library/Privoxy/ /Library/StartupItems/Privoxy/ /Library/Tor/ /Library/StartupItems/Tor/
+rm -rf /Library/Privoxy/ /Library/StartupItems/Tor/ /Library/StartupItems/Privoxy/ /Library/Tor/
echo ". Finished"
diff --git a/contrib/package_nsis-mingw.sh b/contrib/package_nsis-mingw.sh
deleted file mode 100644
index 661bdbb403..0000000000
--- a/contrib/package_nsis-mingw.sh
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/bin/sh
-#
-# Script to package a Tor installer on win32. This script assumes that
-# you have already built Tor, that you are running msys/mingw, and that
-# you know what you are doing.
-
-# Start in the tor source directory after you've compiled tor.exe
-
-rm -rf win_tmp
-mkdir win_tmp
-mkdir win_tmp/bin
-mkdir win_tmp/contrib
-mkdir win_tmp/doc
-mkdir win_tmp/doc/design-paper
-mkdir win_tmp/doc/contrib
-mkdir win_tmp/src
-mkdir win_tmp/src/config
-mkdir win_tmp/tmp
-
-cp src/or/tor.exe win_tmp/bin/tor.exe
-cp src/tools/tor_resolve.exe win_tmp/bin
-cp /usr/local/ssl/lib/libcrypto.a win_tmp/bin
-cp /usr/local/ssl/lib/libssl.a win_tmp/bin
-
-# There is no man2html in mingw.
-# Maybe we should add this into make dist instead.
-man2html doc/tor.1.in > win_tmp/tmp/tor-reference.html
-man2html doc/tor-resolve.1 > win_tmp/tmp/tor-resolve.html
-
-clean_newlines() {
- perl -pe 's/^\n$/\r\n/mg; s/([^\r])\n$/\1\r\n/mg;' $1 >$2
-}
-
-clean_localstatedir() {
- perl -pe 's/^\n$/\r\n/mg; s/([^\r])\n$/\1\r\n/mg; s{\@LOCALSTATEDIR\@/(lib|log)/tor/}{C:\\Documents and Settings\\Application Data\\Tor\\}' $1 >$2
-}
-
-for fn in tor-spec.txt HACKING rend-spec.txt control-spec.txt \
- tor-doc.html tor-doc.css version-spec.txt; do
- clean_newlines doc/$fn win_tmp/doc/$fn
-done
-
-cp doc/design-paper/tor-design.pdf win_tmp/doc/design-paper/tor-design.pdf
-
-for fn in tor-reference.html tor-resolve.html; do \
- clean_newlines win_tmp/tmp/$fn win_tmp/doc/$fn
-done
-
-for fn in README AUTHORS ChangeLog LICENSE; do \
- clean_newlines $fn win_tmp/$fn
-done
-
-clean_localstatedir src/config/torrc.sample.in win_tmp/src/config/torrc.sample
-
-cp contrib/tor.nsi win_tmp/contrib
-
-cd win_tmp/contrib
-C:\Program Files\NSIS\makensis.exe tor.nsi
-mv tor-*.exe ../..
diff --git a/contrib/tor-mingw.nsi.in b/contrib/tor-mingw.nsi.in
deleted file mode 100644
index d83aa5ca5e..0000000000
--- a/contrib/tor-mingw.nsi.in
+++ /dev/null
@@ -1,212 +0,0 @@
-;tor.nsi - A basic win32 installer for Tor
-; Originally written by J Doe.
-; See LICENSE for licencing information
-;-----------------------------------------
-;
-; How to make an installer:
-; Step 0. If you are a Tor maintainer, make sure that tor.nsi and
-; src/win32/orconfig.h all have the correct version number.
-; Step 1. Download and install OpenSSL. Make sure that the OpenSSL
-; version listed below matches the one you downloaded.
-; Step 2. Download and install NSIS (http://nsis.sourceforge.net)
-; Step 3. Make a directory under the main tor directory called "bin".
-; Step 4. Copy ssleay32.dll and libeay32.dll from OpenSSL into "bin".
-; Step 5. Run man2html on tor.1.in; call the result tor-reference.html
-; Run man2html on tor-resolve.1; call the result tor-resolve.html
-; Step 6. Copy torrc.sample.in to torrc.sample.
-; Step 7. Build tor.exe and tor_resolve.exe; save the result into bin.
-; Step 8. cd into contrib and run "makensis tor.nsi".
-;
-; Problems:
-; - Copying torrc.sample.in to torrc.sample and tor.1.in (implicitly)
-; to tor.1 is a Bad Thing, and leaves us with @autoconf@ vars in the final
-; result.
-; - Building Tor requires too much windows C clue.
-; - We should have actual makefiles for VC that do the right thing.
-; - I need to learn more NSIS juju to solve these:
-; - There should be a batteries-included installer that comes with
-; privoxy too. (Check privoxy license on this; be sure to include
-; all privoxy documents.)
-; - The filename should probably have a revision number.
-
-!include "MUI.nsh"
-
-!define VERSION "0.1.2.1-alpha-dev"
-!define INSTALLER "tor-${VERSION}-win32.exe"
-!define WEBSITE "http://tor.eff.org/"
-
-!define LICENSE "..\LICENSE"
-;BIN is where it expects to find tor.exe, tor_resolve.exe, libcrypto.a
-;and libssl.a
-!define BIN "..\bin"
-
-SetCompressor lzma
-;SetCompressor zlib
-OutFile ${INSTALLER}
-InstallDir $PROGRAMFILES\Tor
-SetOverWrite ifnewer
-
-Name "Tor"
-Caption "Tor ${VERSION} Setup"
-BrandingText "The Onion Router"
-CRCCheck on
-
-;Use upx on the installer header to shrink the size.
-!packhdr header.dat "upx --best header.dat"
-
-!define MUI_WELCOMEPAGE_TITLE "Welcome to the Tor ${VERSION} Setup Wizard"
-!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of Tor ${VERSION}.\r\n\r\nIf you have previously installed Tor and it is currently running, please exit Tor first before continuing this installation.\r\n\r\n$_CLICK"
-!define MUI_ABORTWARNING
-!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\win-install.ico"
-!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\win-uninstall.ico"
-!define MUI_HEADERIMAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Header\win.bmp"
-!define MUI_HEADERIMAGE
-!define MUI_FINISHPAGE_RUN "$INSTDIR\tor.exe"
-!define MUI_FINISHPAGE_LINK "Visit the Tor website for the latest updates."
-!define MUI_FINISHPAGE_LINK_LOCATION ${WEBSITE}
-
-!insertmacro MUI_PAGE_WELCOME
-; There's no point in having a clickthrough license: Our license adds
-; certain rights, but doesn't remove them.
-; !insertmacro MUI_PAGE_LICENSE "${LICENSE}"
-!insertmacro MUI_PAGE_COMPONENTS
-!insertmacro MUI_PAGE_DIRECTORY
-!insertmacro MUI_PAGE_INSTFILES
-!insertmacro MUI_PAGE_FINISH
-!insertmacro MUI_UNPAGE_WELCOME
-!insertmacro MUI_UNPAGE_CONFIRM
-!insertmacro MUI_UNPAGE_INSTFILES
-!insertmacro MUI_UNPAGE_FINISH
-!insertmacro MUI_LANGUAGE "English"
-
-Var configdir
-Var configfile
-
-;Sections
-;--------
-
-Section "Tor" Tor
-;Files that have to be installed for tor to run and that the user
-;cannot choose not to install
- SectionIn RO
- SetOutPath $INSTDIR
- File "${BIN}\tor.exe"
- File "${BIN}\tor_resolve.exe"
- WriteIniStr "$INSTDIR\Tor Website.url" "InternetShortcut" "URL" ${WEBSITE}
-
- StrCpy $configfile "torrc"
- StrCpy $configdir $APPDATA\Tor
-; ;If $APPDATA isn't valid here (Early win95 releases with no updated
-; ; shfolder.dll) then we put it in the program directory instead.
-; StrCmp $APPDATA "" "" +2
-; StrCpy $configdir $INSTDIR
- SetOutPath $configdir
- ;If there's already a torrc config file, ask if they want to
- ;overwrite it with the new one.
- IfFileExists "$configdir\torrc" "" endiftorrc
- MessageBox MB_ICONQUESTION|MB_YESNO "You already have a Tor config file.$\r$\nDo you want to overwrite it with the default sample config file?" IDNO yesreplace
- Delete $configdir\torrc
- Goto endiftorrc
- yesreplace:
- StrCpy $configfile "torrc.sample"
- endiftorrc:
- File /oname=$configfile "..\src\config\torrc.sample"
-SectionEnd
-
-Section "OpenSSL 0.9.8c" OpenSSL
- SetOutPath $INSTDIR
- File "${BIN}\libcrypto.a"
- File "${BIN}\libssl.a"
-SectionEnd
-
-Section "Documents" Docs
- SetOutPath "$INSTDIR\Documents"
- ;File "..\doc\FAQ"
- File "..\doc\HACKING"
- File "..\doc\control-spec.txt"
- File "..\doc\dir-spec.txt"
- File "..\doc\rend-spec.txt"
- File "..\doc\socks-extensions.txt"
- File "..\doc\version-spec.txt"
- ;
- ; WEBSITE-FILES-HERE
- ;
- File "..\doc\tor-resolve.html"
- File "..\doc\tor-reference.html"
- ;
- File "..\doc\design-paper\tor-design.pdf"
- ;
- File "..\README"
- File "..\AUTHORS"
- File "..\ChangeLog"
- File "..\LICENSE"
-SectionEnd
-
-SubSection /e "Shortcuts" Shortcuts
-
-Section "Start Menu" StartMenu
- SetOutPath $INSTDIR
- IfFileExists "$SMPROGRAMS\Tor\*.*" "" +2
- RMDir /r "$SMPROGRAMS\Tor"
- CreateDirectory "$SMPROGRAMS\Tor"
- CreateShortCut "$SMPROGRAMS\Tor\Tor.lnk" "$INSTDIR\tor.exe"
- CreateShortCut "$SMPROGRAMS\Tor\Torrc.lnk" "Notepad.exe" "$configdir\torrc"
- CreateShortCut "$SMPROGRAMS\Tor\Tor Website.lnk" "$INSTDIR\Tor Website.url"
- CreateShortCut "$SMPROGRAMS\Tor\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
- IfFileExists "$INSTDIR\Documents\*.*" "" endifdocs
- CreateDirectory "$SMPROGRAMS\Tor\Documents"
- CreateShortCut "$SMPROGRAMS\Tor\Documents\Tor Manual.lnk" "$INSTDIR\Documents\tor-doc.html"
- CreateShortCut "$SMPROGRAMS\Tor\Documents\Tor Documentation.lnk" "$INSTDIR\Documents"
- CreateShortCut "$SMPROGRAMS\Tor\Documents\Tor Specification.lnk" "$INSTDIR\Documents\tor-spec.txt"
- endifdocs:
-SectionEnd
-
-Section "Desktop" Desktop
- SetOutPath $INSTDIR
- CreateShortCut "$DESKTOP\Tor.lnk" "$INSTDIR\tor.exe"
-SectionEnd
-
-Section /o "Run at startup" Startup
- SetOutPath $INSTDIR
- CreateShortCut "$SMSTARTUP\Tor.lnk" "$INSTDIR\tor.exe" "" "" 0 SW_SHOWMINIMIZED
-SectionEnd
-
-SubSectionEnd
-
-Section "Uninstall"
- Delete "$DESKTOP\Tor.lnk"
- Delete "$INSTDIR\libcrypto.a"
- Delete "$INSTDIR\libssl.a"
- Delete "$INSTDIR\tor.exe"
- Delete "$INSTDIR\tor_resolve.exe"
- Delete "$INSTDIR\Tor Website.url"
- Delete "$INSTDIR\torrc"
- Delete "$INSTDIR\torrc.sample"
- StrCmp $configdir $INSTDIR +2 ""
- RMDir /r $configdir
- Delete "$INSTDIR\Uninstall.exe"
- RMDir /r "$INSTDIR\Documents"
- RMDir $INSTDIR
- RMDir /r "$SMPROGRAMS\Tor"
- Delete "$SMSTARTUP\Tor.lnk"
- DeleteRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Tor"
-SectionEnd
-
-Section -End
- WriteUninstaller "$INSTDIR\Uninstall.exe"
- ;The registry entries simply add the Tor uninstaller to the Windows
- ;uninstall list.
- WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Tor" "DisplayName" "Tor (remove only)"
- WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Tor" "UninstallString" '"$INSTDIR\Uninstall.exe"'
-SectionEnd
-
-!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
- !insertmacro MUI_DESCRIPTION_TEXT ${Tor} "The core executable and config files needed for Tor to run."
- !insertmacro MUI_DESCRIPTION_TEXT ${OpenSSL} "OpenSSL libraries required by Tor."
- !insertmacro MUI_DESCRIPTION_TEXT ${Docs} "Documentation about Tor."
- !insertmacro MUI_DESCRIPTION_TEXT ${ShortCuts} "Shortcuts to easily start Tor"
- !insertmacro MUI_DESCRIPTION_TEXT ${StartMenu} "Shortcuts to access Tor and it's documentation from the Start Menu"
- !insertmacro MUI_DESCRIPTION_TEXT ${Desktop} "A shortcut to start Tor from the desktop"
- !insertmacro MUI_DESCRIPTION_TEXT ${Startup} "Launches Tor automatically at startup in a minimized window"
-!insertmacro MUI_FUNCTION_DESCRIPTION_END
-
diff --git a/contrib/tor-resolve.py b/contrib/tor-resolve.py
index 919bc876cc..dd44255bc1 100755
--- a/contrib/tor-resolve.py
+++ b/contrib/tor-resolve.py
@@ -32,16 +32,15 @@ def socks5Hello():
def socks5ParseHello(response):
if response != "\x05\x00":
raise ValueError("Bizarre socks5 response")
-def socks5ResolveRequest(hostname, atype=0x03, command=0xF0):
+def socks5ResolveRequest(hostname):
version = 5
+ command = 0xF0
rsv = 0
port = 0
- reqheader = struct.pack("!BBBB",version, command, rsv, atype)
- if atype == 0x03:
- reqheader += struct.pack("!B", len(hostname))
+ atype = 0x03
+ reqheader = struct.pack("!BBBBB",version, command, rsv, atype, len(hostname))
portstr = struct.pack("!H",port)
return "%s%s%s"%(reqheader,hostname,portstr)
-
def socks5ParseResponse(r):
if len(r)<8:
return None
@@ -50,30 +49,18 @@ def socks5ParseResponse(r):
assert rsv==0
if reply != 0x00:
return "ERROR",reply
- assert atype in (0x01,0x03,0x04)
- if atype != 0x03:
- expected_len = 4 + ({1:4,4:16}[atype]) + 2
- if len(r) < expected_len:
- return None
- elif len(r) > expected_len:
- raise ValueError("Overlong socks5 reply!")
- addr = r[4:-2]
- if atype == 0x01:
- return "%d.%d.%d.%d"%tuple(map(ord,addr))
- else:
- # not really the right way to format IPv6
- return "IPv6: %s"%(":".join([hex(ord(c)) for c in addr]))
+ assert atype in (0x01,0x04)
+ expected_len = 4 + ({1:4,4:16}[atype]) + 2
+ if len(r) < expected_len:
+ return None
+ elif len(r) > expected_len:
+ raise ValueError("Overlong socks5 reply!")
+ addr = r[4:-2]
+ if atype == 0x01:
+ return "%d.%d.%d.%d"%tuple(map(ord,addr))
else:
- hlen, = struct.unpack("!B", r[4])
- expected_len = 5 + hlen + 2
- if len(r) < expected_len:
- return None
- return r[5:-2]
-
-def socks5ResolvePTRRequest(hostname):
- return socks5ResolveRequest(socket.inet_aton(hostname),
- atype=1, command = 0xF1)
-
+ # not really the right way to format IPv6
+ return "IPv6: %s"%(":".join([hex(ord(c)) for c in addr]))
def parseHostAndPort(h):
host, port = "localhost", 9050
@@ -93,23 +80,20 @@ def parseHostAndPort(h):
return host, port
-def resolve(hostname, sockshost, socksport, socksver=4, reverse=0):
+def resolve(hostname, sockshost, socksport, socksver=4):
assert socksver in (4,5)
if socksver == 4:
fmt = socks4AResolveRequest
parse = socks4AParseResponse
- elif not reverse:
- fmt = socks5ResolveRequest
- parse = socks5ParseResponse
else:
- fmt = socks5ResolvePTRRequest
+ fmt = socks5ResolveRequest
parse = socks5ParseResponse
-
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((sockshost,socksport))
if socksver == 5:
s.send(socks5Hello())
socks5ParseHello(s.recv(2))
+ print len(fmt(hostname)), len(hostname)
s.send(fmt(hostname))
answer = s.recv(6)
result = parse(answer)
@@ -130,25 +114,14 @@ if __name__ == '__main__':
print "Syntax: resolve.py [-4|-5] hostname [sockshost:socksport]"
sys.exit(0)
socksver = 4
- reverse = 0
- while sys.argv[1][0] == '-':
- if sys.argv[1] in ("-4", "-5"):
- socksver = int(sys.argv[1][1])
- del sys.argv[1]
- elif sys.argv[1] == '-x':
- reverse = 1
- del sys.argv[1]
- elif sys.argv[1] == '--':
- break
-
- if len(sys.argv) >= 4:
- print "Syntax: resolve.py [-x] [-4|-5] hostname [sockshost:socksport]"
+ if sys.argv[1] in ("-4", "-5"):
+ socksver = int(sys.argv[1][1])
+ del sys.argv[1]
+ if len(sys.argv) == 4:
+ print "Syntax: resolve.py [-4|-5] hostname [sockshost:socksport]"
sys.exit(0)
if len(sys.argv) == 3:
sh,sp = parseHostAndPort(sys.argv[2])
else:
sh,sp = parseHostAndPort("")
-
- if reverse and socksver == 4:
- socksver = 5
- resolve(sys.argv[1], sh, sp, socksver, reverse)
+ resolve(sys.argv[1], sh, sp, socksver)
diff --git a/contrib/tor.nsi.in b/contrib/tor.nsi.in
index 4fc8d34c1a..295a8ec21c 100644
--- a/contrib/tor.nsi.in
+++ b/contrib/tor.nsi.in
@@ -31,7 +31,7 @@
!include "MUI.nsh"
-!define VERSION "0.1.2.1-alpha-dev"
+!define VERSION "0.1.1.23"
!define INSTALLER "tor-${VERSION}-win32.exe"
!define WEBSITE "http://tor.eff.org/"
diff --git a/contrib/torify.in b/contrib/torify.in
index 05645fd07c..f9162a19fe 100755
--- a/contrib/torify.in
+++ b/contrib/torify.in
@@ -1,45 +1,7 @@
#! /bin/sh
-
# Wrapper script for use of the tsocks(8) transparent socksification library
# See the tsocks(1) and torify(1) manpages.
-# Copyright (c) 2004, 2006 Peter Palfrader
-# Modified by Jacob Appelbaum <jacob@appelbaum.net> April 16th 2006
-# May be distributed under the same terms as Tor itself
-
-
-# Define and ensure we have tsocks
-# XXX: what if we don't have which?
-TSOCKS="`which tsocks`"
-if [ ! -x "$TSOCKS" ]
-then
- echo "$0: Can't find tsocks in PATH. Perhaps you haven't installed it?" >&2
- exit 1
-fi
-
-# Check for any argument list
-if [ "$#" = 0 ]
-then
- echo "Usage: $0 <command> [<options>...]" >&2
- exit 1
-fi
-if [ "$#" = 1 ] && ( [ "$1" = "-h" ] || [ "$1" = "--help" ] )
-then
- echo "Usage: $0 <command> [<options>...]"
- exit 0
-fi
-
-# Define our tsocks config file
-TSOCKS_CONF_FILE="@CONFDIR@/tor-tsocks.conf"
+TSOCKS_CONF_FILE=@CONFDIR@/tor-tsocks.conf
export TSOCKS_CONF_FILE
-
-# Check that we've got a tsocks config file
-if [ -r "$TSOCKS_CONF_FILE" ]
-then
- exec tsocks "$@"
- echo "$0: Failed to exec tsocks $@" >&2
- exit 1
-else
- echo "$0: Missing tsocks configuration file \"$TSOCKS_CONF_FILE\"." >&2
- exit 1
-fi
+exec tsocks "$@"
diff --git a/debian/README.Debian b/debian/README.Debian
index cda020b9e7..6c9730d6c3 100644
--- a/debian/README.Debian
+++ b/debian/README.Debian
@@ -1,14 +1,13 @@
This is the Debian package for Tor, The Onion Router.
-Some changes have been made to the Tor source to integrate it better into
-Debian. If Tor is started as the 'debian-tor' user, then:
+The following changes have been made to the Tor source to integrate it better
+into Debian:
- RunAsDaemon is enabled by default.
- PidFile is set to /var/run/tor/tor.pid. No default upstream.
- default logging goes to /var/log/tor/log instead of stdout.
- DataDirectory is set to /var/lib/tor by default. Uses $HOME/.tor upstream.
-If Tor is started as any other user it behaves just like upstream's.
--
-Peter Palfrader, Mon, 24 Jul 2006 05:20:30 +0200
+Peter Palfrader, Fri, 12 Nov 2004 18:08:54 +0100
diff --git a/debian/changelog b/debian/changelog
index 615802d61b..c84079444e 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,26 +1,3 @@
-tor (0.1.2.1-alpha-XXXX) XXXerimental; urgency=low
-
- * Minor update of debian/copyright [arma].
-
- -- Peter Palfrader <weasel@debian.org> Sun, 3 Sep 2006 19:53:45 +0200
-
-tor (0.1.2.1-alpha-1) experimental; urgency=low
-
- * Forward port 07_log_to_file_by_default.dpatch.
- * Previously our defaults for DataDirectory, PidFile, RunAsDaemon, and
- Log differed from upstreams. Now Tor behaves just like before (with
- our own DataDirectory and all) only when run as the debian-tor user.
- If invoked as any other user, Tor will behave just like the pristine
- upstream version.
- * Tell users about the init script when they try to run Tor as root.
- Should we also do this when they try to run their Tor as any other
- (non root, non debian-tor) user? - add 11_tor_as_root_more_helpful
- * Use tor --verify-config before start and reload. Abort init script
- with exit 1 if config does not verify.
- * Change Standards-Version to 3.7.2. No changes required.
-
- -- Peter Palfrader <weasel@debian.org> Tue, 29 Aug 2006 22:38:29 +0200
-
tor (0.1.1.23-XXXXXX) unstable; urgency=low
* Update debian/copyright:
diff --git a/debian/control b/debian/control
index 7820f3c4a1..7599169fcc 100644
--- a/debian/control
+++ b/debian/control
@@ -3,7 +3,7 @@ Section: comm
Priority: optional
Maintainer: Peter Palfrader <weasel@debian.org>
Build-Depends: debhelper (>= 4.1.65), libssl-dev, dpatch, zlib1g-dev, libevent-dev (>= 1.1), tetex-bin, tetex-extra, transfig, gs, binutils (>= 2.14.90.0.7)
-Standards-Version: 3.7.2
+Standards-Version: 3.6.2
Package: tor
Architecture: any
diff --git a/debian/copyright b/debian/copyright
index f010a4580f..6ce5c8ab8c 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -13,7 +13,7 @@ strlcat, strlcpy: Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
ht.h: Copyright (c) 2002, Christopher Clark, 2006 Nick Mathewson
Modifications for Debian: Copyright (c) 2004, 2005, 2006 Peter Palfrader
-Tor is distributed under this license:
+The tor code is under this license:
===============================================================================
Copyright (c) 2001-2004, Roger Dingledine
Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson
diff --git a/debian/patches/00list b/debian/patches/00list
index 0c2be8424f..cd17cd1dca 100644
--- a/debian/patches/00list
+++ b/debian/patches/00list
@@ -2,4 +2,3 @@
03_tor_manpage_in_section_8.dpatch
06_add_compile_time_defaults.dpatch
07_log_to_file_by_default.dpatch
-11_tor_as_root_more_helpful.dpatch
diff --git a/debian/patches/06_add_compile_time_defaults.dpatch b/debian/patches/06_add_compile_time_defaults.dpatch
index 8b4e494246..81e6034d3c 100755
--- a/debian/patches/06_add_compile_time_defaults.dpatch
+++ b/debian/patches/06_add_compile_time_defaults.dpatch
@@ -23,97 +23,33 @@ esac
exit 0
@DPATCH@
-diff -urNad tor~/src/or/config.c tor/src/or/config.c
---- tor~/src/or/config.c 2006-07-23 19:31:29.000000000 +0200
-+++ tor/src/or/config.c 2006-07-24 05:13:19.924871985 +0200
-@@ -12,6 +12,7 @@
- **/
-
- #include "or.h"
-+#include <pwd.h>
- #ifdef MS_WINDOWS
- #include <shlobj.h>
- #endif
-@@ -396,6 +397,10 @@
- static void check_libevent_version(const char *m, const char *v, int server);
- #endif
-
-+static int debian_running_as_debiantor();
-+static int debian_config_fix_defaults();
-+
-+
- /*static*/ or_options_t *options_new(void);
-
- #define OR_OPTIONS_MAGIC 9090909
-@@ -2663,7 +2668,7 @@
- int
- options_init_from_torrc(int argc, char **argv)
- {
-- or_options_t *oldoptions, *newoptions;
-+ or_options_t *oldoptions, *newoptions = NULL;
- config_line_t *cl;
- char *cf=NULL, *fname=NULL, *errmsg=NULL;
- int i, retval;
-@@ -2671,6 +2676,9 @@
- static char **backup_argv;
- static int backup_argc;
-
-+ if (debian_config_fix_defaults() < 0)
-+ goto err;
-+
- if (argv) { /* first time we're called. save commandline args */
- backup_argv = argv;
- backup_argc = argc;
-@@ -3948,3 +3956,52 @@
- puts(routerparse_c_id);
- }
-
-+/* Checks whether we are running as the debian-tor user.
-+ * Returns -1 on error, 1 if we are debian-tor, 0 if not */
-+static int
-+debian_running_as_debiantor()
-+{
-+ struct passwd *pw = NULL;
-+ int uid;
-+
-+ uid = getuid();
-+ pw = getpwuid(uid);
-+ if (!pw) {
-+ log(LOG_WARN, LD_GENERAL, "Could not get passwd information for %d.", uid);
-+ return -1;
-+ }
-+ assert(pw->pw_name);
-+ if (strcmp(pw->pw_name, "debian-tor") == 0)
-+ return 1;
-+ else
-+ return 0;
-+}
-+
-+static int
-+debian_config_fix_defaults()
-+{
-+ config_var_t *var;
-+ static int fixed = 0;
-+ int running_as_debian;
-+
-+ if (fixed) return 0;
-+ fixed = 1;
-+
-+ running_as_debian = debian_running_as_debiantor();
-+ if (running_as_debian < 0) return -1;
-+ if (!running_as_debian) return 0;
-+
-+ var = config_find_option(&options_format, "DataDirectory");
-+ tor_assert(var);
-+ var->initvalue = tor_strdup("/var/lib/tor");
-+
-+ var = config_find_option(&options_format, "PidFile");
-+ tor_assert(var);
-+ var->initvalue = tor_strdup("/var/run/tor/tor.pid");
-+
-+ var = config_find_option(&options_format, "RunAsDaemon");
-+ tor_assert(var);
-+ var->initvalue = tor_strdup("1");
-+
-+ return 0;
-+}
+diff -urNad tor-0.1.1.5/src/or/config.c /tmp/dpep.Xv4cHn/tor-0.1.1.5/src/or/config.c
+--- tor-0.1.1.9/src/or/config.c 2005-10-17 03:54:24.917618642 +0200
++++ /tmp/foo/tor/src/or/config.c 2005-10-17 03:57:52.040022393 +0200
+@@ -111,7 +111,7 @@
+ VAR("ContactInfo", STRING, ContactInfo, NULL),
+ VAR("ControlPort", UINT, ControlPort, "0"),
+ VAR("CookieAuthentication",BOOL, CookieAuthentication, "0"),
+- VAR("DataDirectory", STRING, DataDirectory, NULL),
++ VAR("DataDirectory", STRING, DataDirectory, "/var/lib/tor"),
+ VAR("DebugLogFile", STRING, DebugLogFile, NULL),
+ VAR("DirAllowPrivateAddresses",BOOL, DirAllowPrivateAddresses, NULL),
+ VAR("DirBindAddress", LINELIST, DirBindAddress, NULL),
+@@ -162,7 +162,7 @@
+ VAR("ORPort", UINT, ORPort, "0"),
+ VAR("OutboundBindAddress", STRING, OutboundBindAddress, NULL),
+ VAR("PathlenCoinWeight", DOUBLE, PathlenCoinWeight, "0.3"),
+- VAR("PidFile", STRING, PidFile, NULL),
++ VAR("PidFile", STRING, PidFile, "/var/run/tor/tor.pid"),
+ VAR("ProtocolWarnings", BOOL, ProtocolWarnings, "0"),
+ VAR("ReachableAddresses", LINELIST, ReachableAddresses, NULL),
+ VAR("RecommendedVersions", LINELIST, RecommendedVersions, NULL),
+@@ -174,7 +174,7 @@
+ VAR("RendPostPeriod", INTERVAL, RendPostPeriod, "20 minutes"),
+ VAR("RephistTrackTime", INTERVAL, RephistTrackTime, "24 hours"),
+ OBSOLETE("RouterFile"),
+- VAR("RunAsDaemon", BOOL, RunAsDaemon, "0"),
++ VAR("RunAsDaemon", BOOL, RunAsDaemon, "1"),
+ VAR("RunTesting", BOOL, RunTesting, "0"),
+ VAR("SafeLogging", BOOL, SafeLogging, "1"),
+ VAR("ShutdownWaitLength", INTERVAL, ShutdownWaitLength, "30 seconds"),
diff --git a/debian/patches/07_log_to_file_by_default.dpatch b/debian/patches/07_log_to_file_by_default.dpatch
index 809c5ddcf3..da9aaf4324 100755
--- a/debian/patches/07_log_to_file_by_default.dpatch
+++ b/debian/patches/07_log_to_file_by_default.dpatch
@@ -23,22 +23,15 @@ esac
exit 0
@DPATCH@
-diff -urNad tor~/src/or/config.c tor/src/or/config.c
---- tor~/src/or/config.c 2006-07-24 05:15:02.576170550 +0200
-+++ tor/src/or/config.c 2006-07-24 05:18:45.286651501 +0200
-@@ -2118,8 +2118,13 @@
- REJECT("Failed to normalize old Log options. See logs for details.");
+diff -urNad tor-0.1.1.17/src/or/config.c /tmp/dpep.YwfNhI/tor-0.1.1.17/src/or/config.c
+--- tor-0.1.1.17/src/or/config.c
++++ /tmp/dpep.YwfNhI/tor-0.1.1.17/src/or/config.c
+@@ -2079,7 +2079,7 @@
/* Special case on first boot if no Log options are given. */
-- if (!options->Logs && !options->RunAsDaemon && !from_setconf)
+ if (!options->Logs && !from_setconf)
- config_line_append(&options->Logs, "Log", "notice stdout");
-+ if (debian_running_as_debiantor()) {
-+ if (!options->Logs && !from_setconf)
-+ config_line_append(&options->Logs, "Log", "notice file /var/log/tor/log");
-+ } else {
-+ if (!options->Logs && !options->RunAsDaemon && !from_setconf)
-+ config_line_append(&options->Logs, "Log", "notice stdout");
-+ }
++ config_line_append(&options->Logs, "Log", "notice file /var/log/tor/log");
if (options_init_logs(options, 1)<0) /* Validate the log(s) */
REJECT("Failed to validate Log options. See logs for details.");
diff --git a/debian/patches/11_tor_as_root_more_helpful.dpatch b/debian/patches/11_tor_as_root_more_helpful.dpatch
deleted file mode 100755
index 96e42d5316..0000000000
--- a/debian/patches/11_tor_as_root_more_helpful.dpatch
+++ /dev/null
@@ -1,36 +0,0 @@
-#! /bin/sh -e
-## 08_no_run_as_root.dpatch by <weasel@debian.org>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: No description.
-
-if [ $# -lt 1 ]; then
- echo "`basename $0`: script expects -patch|-unpatch as argument" >&2
- exit 1
-fi
-
-[ -f debian/patches/00patch-opts ] && . debian/patches/00patch-opts
-patch_opts="${patch_opts:--f --no-backup-if-mismatch} ${2:+-d $2}"
-
-case "$1" in
- -patch) patch -p1 ${patch_opts} < $0;;
- -unpatch) patch -R -p1 ${patch_opts} < $0;;
- *)
- echo "`basename $0`: script expects -patch|-unpatch as argument" >&2
- exit 1;;
-esac
-
-exit 0
-
-@DPATCH@
---- tor~/src/or/main.c 2006-07-23 19:31:29.000000000 +0200
-+++ tor/src/or/main.c 2006-07-24 05:34:30.696138870 +0200
-@@ -1483,7 +1483,7 @@
- #ifndef MS_WINDOWS
- if (geteuid()==0)
- log_warn(LD_GENERAL,"You are running Tor as root. You don't need to, "
-- "and you probably shouldn't.");
-+ "and you probably shouldn't. Maybe you are looking for the init script? '/etc/init.d/tor start'");
- #endif
-
- crypto_global_init(get_options()->HardwareAccel);
diff --git a/debian/rules b/debian/rules
index e52aae5a35..c593860b51 100755
--- a/debian/rules
+++ b/debian/rules
@@ -11,20 +11,15 @@ include /usr/share/dpatch/dpatch.make
# These are used for cross-compiling and for saving the configure script
# from having to guess our platform (since we know it already)
-#
-# See /usr/share/doc/autotools-dev/README.Debian.gz which suggests
-# this way of passing --build and --host. Also see the thread on
-# debian-devel './configure in debian/rules' from February/March 2006,
-# starting with <43FF212C.5020800@xs4all.nl> by Pjotr Kourzanov.
export DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
export DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+CFLAGS ?= -Wall -g
ifeq ($(DEB_BUILD_GNU_TYPE), $(DEB_HOST_GNU_TYPE))
confflags += --build $(DEB_HOST_GNU_TYPE)
else
confflags += --build $(DEB_BUILD_GNU_TYPE) --host $(DEB_HOST_GNU_TYPE)
endif
-CFLAGS ?= -Wall -g
LOCALHOST_IP ?= $(shell getent hosts localhost | awk '{print $$1}')
diff --git a/debian/tor.init b/debian/tor.init
index 7a69ae621a..e930b496ff 100644
--- a/debian/tor.init
+++ b/debian/tor.init
@@ -60,59 +60,46 @@ wait_for_deaddaemon () {
return 0
}
-
-if test ! -d $TORPIDDIR; then
- echo "There is no $TORPIDDIR directory. Creating one for you."
- mkdir -m 02700 "$TORPIDDIR"
- chown debian-tor:debian-tor "$TORPIDDIR"
-fi
-
-if test ! -x $TORPIDDIR; then
- echo "Cannot access $TORPIDDIR directory, are you root?" >&2
- exit 1
-fi
-
-
case "$1" in
start)
if [ "$RUN_DAEMON" != "yes" ]; then
echo "Not starting $DESC (Disabled in $DEFAULTSFILE)."
- exit 0
- fi
-
- if [ -n "$MAX_FILEDESCRIPTORS" ]; then
- echo -n "Raising maximum number of filedescriptors (ulimit -n) to $MAX_FILEDESCRIPTORS"
- if ulimit -n "$MAX_FILEDESCRIPTORS" ; then
- echo "."
+ else
+ if test ! -d $TORPIDDIR; then
+ echo "There is no $TORPIDDIR directory. Creating one for you."
+ mkdir -m 02700 "$TORPIDDIR"
+ chown debian-tor:debian-tor "$TORPIDDIR"
+ fi
+ if test ! -x $TORPIDDIR; then echo "Cannot access $TORPIDDIR directory, are you root?" >&2; exit 1;
else
- echo ": FAILED."
+ if [ -n "$MAX_FILEDESCRIPTORS" ]; then
+ echo -n "Raising maximum number of filedescriptors (ulimit -n) to $MAX_FILEDESCRIPTORS"
+ if ulimit -n "$MAX_FILEDESCRIPTORS" ; then
+ echo "."
+ else
+ echo ": FAILED."
+ fi
+ fi
+ echo "Starting $DESC: $NAME..."
+ start-stop-daemon --start --quiet --oknodo \
+ --chuid debian-tor:debian-tor \
+ --pidfile $TORPID \
+ $NICE \
+ --exec $DAEMON -- $ARGS
+ echo "done."
fi
fi
-
- echo "Starting $DESC: $NAME..."
- if ! su -c "$DAEMON --verify-config" debian-tor > /dev/null; then
- echo "ABORTED: Tor configuration invalid:" >&2
- su -c "$DAEMON --verify-config" debian-tor >&2
- exit 1
- fi
-
- start-stop-daemon --start --quiet --oknodo \
- --chuid debian-tor:debian-tor \
- --pidfile $TORPID \
- $NICE \
- --exec $DAEMON -- $ARGS
- echo "done."
;;
stop)
echo -n "Stopping $DESC: "
pid=`cat $TORPID 2>/dev/null` || true
-
- if test ! -f $TORPID -o -z "$pid"; then
+ if test ! -d $TORPIDDIR; then echo "There is no $TORPIDDIR directory." >&2; exit 1
+ elif test ! -x $TORPIDDIR; then echo "Cannot access $TORPIDDIR directory, are you root?" >&2; exit 1;
+ elif test ! -f $TORPID -o -z "$pid"
+ then
echo "not running (there is no $TORPID)."
- exit 0
- fi
-
- if start-stop-daemon --stop --signal INT --quiet --pidfile $TORPID --exec $DAEMON; then
+ elif start-stop-daemon --stop --signal INT --quiet --pidfile $TORPID --exec $DAEMON
+ then
wait_for_deaddaemon $pid
echo "$NAME."
elif kill -0 $pid 2>/dev/null
@@ -125,19 +112,12 @@ case "$1" in
reload|force-reload)
echo -n "Reloading $DESC configuration: "
pid=`cat $TORPID 2>/dev/null` || true
-
- if test ! -f $TORPID -o -z "$pid"; then
+ if test ! -d $TORPIDDIR; then echo "There is no $TORPIDDIR directory." >&2; exit 1
+ elif test ! -x $TORPIDDIR; then echo "Cannot access $TORPIDDIR directory, are you root?" >&2; exit 1;
+ elif test ! -f $TORPID -o -z "$pid"
+ then
echo "not running (there is no $TORPID)."
- exit 0
- fi
-
- if ! su -c "$DAEMON --verify-config" debian-tor > /dev/null; then
- echo "ABORTED: Tor configuration invalid:" >&2
- su -c "$DAEMON --verify-config" debian-tor >&2
- exit 1
- fi
-
- if start-stop-daemon --stop --signal 1 --quiet --pidfile $TORPID --exec $DAEMON
+ elif start-stop-daemon --stop --signal 1 --quiet --pidfile $TORPID --exec $DAEMON
then
echo "$NAME."
elif kill -0 $pid 2>/dev/null
@@ -148,12 +128,6 @@ case "$1" in
fi
;;
restart)
- if ! su -c "$DAEMON --verify-config" debian-tor > /dev/null; then
- echo "Restarting Tor ABORTED: Tor configuration invalid:" >&2
- su -c "$DAEMON --verify-config" debian-tor >&2
- exit 1
- fi
-
$0 stop
sleep 1
$0 start
diff --git a/doc/HACKING b/doc/HACKING
index 81424a26b5..23253cb341 100644
--- a/doc/HACKING
+++ b/doc/HACKING
@@ -6,14 +6,12 @@
Use tor_malloc, tor_free, tor_snprintf, tor_strdup, and tor_gettimeofday
instead of their generic equivalents. (They always succeed or exit.)
- You can get a full list of the compatibility functions that Tor provides
- by looking through src/common/util.h and src/common/compat.h.
-
- Use 'INLINE' instead of 'inline', so that we work properly on Windows.
+ Use INLINE instead of 'inline', so that we work properly on windows.
1.2. Calling and naming conventions
- Whenever possible, functions should return -1 on error and 0 on success.
+ Whenever possible, functions should return -1 on error and and 0 on
+ success.
For multi-word identifiers, use lowercase words combined with
underscores. (e.g., "multi_word_identifier"). Use ALL_CAPS for macros and
@@ -54,7 +52,7 @@
you need to (or can) do about it.
DEBUG is for everything louder than INFO.
- [XXX Proposed convention: every message of severity INFO or higher should
+ [XXX Proposed convention: every messages of severity INFO or higher should
either (A) be intelligible to end-users who don't know the Tor source; or
(B) somehow inform the end-users that they aren't expected to understand
the message (perhaps with a string like "internal error"). Option (A) is
@@ -62,8 +60,8 @@
1.5. Doxygen
- We use the 'doxygen' utility to generate documentation from our
- source code. Here's how to use it:
+ We use the 'doxygen' utility to generate documentation from our source code.
+ Here's how to use it:
1. Begin every file that should be documented with
/**
@@ -100,17 +98,16 @@
struct foo {
/** You can put the comment before an element; */
int a;
- int b; /**< Or use the less-than symbol to put the comment
- * after the element. */
+ int b; /**< Or use the less-than symbol to put the comment after the element. */
};
5. To generate documentation from the Tor source code, type:
$ doxygen -g
- To generate a file called 'Doxyfile'. Edit that file and run
- 'doxygen' to generate the API documentation.
+ To generate a file called 'Doxyfile'. Edit that file and run 'doxygen' to
+ generate the API documentation.
- 6. See the Doxygen manual for more information; this summary just
- scratches the surface.
+ 6. See the Doxygen manual for more information; this summary just scratches
+ the surface.
diff --git a/doc/TODO b/doc/TODO
index bfb55c96e7..e3fc7bc86e 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -12,312 +12,130 @@ P - phobos claims
D Deferred
X Abandoned
+Non-Coding, Soon:
+N - Mark up spec; note unclear points about servers
+N - Mention controller libs someplace.
+ D FAQ entry: why gnutls is bad/not good for tor
+P - flesh out the rest of the section 6 of the faq
+R . more pictures from ren. he wants to describe the tor handshake
+R - make a page with the hidden service diagrams.
+NR- write a spec appendix for 'being nice with tor'
+ - tor-in-the-media page
+ - Remove need for HACKING file.
+
+Website:
+ - and remove home and make the "Tor" picture be the link to home.
+ - put the logo on the website, in source form, so people can put it on
+ stickers directly, etc.
+
+for 0.1.1.x-final:
+N - building on freebsd 6.0: (with multiple openssl installations)
. <nickm> "Let's try to find a way to make it run and make the version
match, but if not, let's just make it run."
- - <arma> "should we detect if we have a --with-ssl-dir and try the -R
- by default, if it works?"
-
-Items for 0.1.2.x, real soon now:
-x - When we've been idle a long time, we stop fetching server
- descriptors. When we then get a socks request, we build circuits
- immediately using whatever descriptors we have, rather than waiting
- until we've fetched correct ones.
-x - If the client's clock is too far in the past, it will drop (or
- just not try to get) descriptors, so it'll never build circuits.
-N - when we start, remove any entryguards that are listed in excludenodes.
-N - Remember the last time we saw one of our entry guards labelled with
- the GUARD flag. If it's been too long, it is not suitable for use.
- If it's been really too long, remove it from the list.
- . Figure out avoiding duplicate /24 lines
- o automatically add /16 servers to family
- D do it in an efficient way. keep a list of something somewhere?
- - The right thing here is to revamp our node selection implementation.
-N - make it configurable, so people can turn it on or off.
-N - Clients stop dumping old descriptors if the network-statuses
- claim they're still valid.
-R . If we fail to connect via an exit enclave, (warn and) try again
- without demanding that exit node.
- - And recognize when extending to the enclave node is failing,
- so we can abandon then too.
-N - We need a separate list of "hidserv authorities" if we want to
- retire moria1 from the main list.
-P - Figure out why dll's compiled in mingw don't work right in Winxp.
-P - Figure out why openssl 0.9.8c "make test" fails at sha256t test.
-
-Items for 0.1.2.x:
- o re-enable blossom functionality: let tor servers decide if they
- will use local search when resolving, or not.
-N - Document it.
- - enumerate events of important things that occur in tor, so vidalia can
- react.
-N - Backend implementation
-R - Actually list all the events (notice and warn log messages are a good
- place to look.) Divide messages into categories, perhaps.
-N - Specify general event system
-R - Specify actual events.
-
-x - We should ship with a list of stable dir mirrors -- they're not
- trusted like the authorities, but they'll provide more robustness
- and diversity for bootstrapping clients.
-
-N - Simplify authority operation
- - Follow weasel's proposal, crossed with mixminion dir config format
- - Reject/invalidate by IP.
-
- - Servers are easy to setup and run: being a relay is about as easy as
- being a client.
- - Reduce resource load
-N - Come up with good 'nicknames' automatically, or make no-nickname
- routers workable. [Make a magic nickname "Unnamed" that can't be
- registered and can't be looked up by nickname.]
-d - Tolerate clock skew on bridge relays.
-d - A way to examine and twiddle router flags from controller.
- - A way to export server descriptors to controllers
-N - Event / getinfo for "when did routerdesc last change".
-d - a way to pick entries based wholly on extend_info equivalent;
- a way to export extend_info equivalent.
-R - option to dl directory info via tor
- - Make an option like __AllDirActionsPrivate that falls back to
- non-Tor DL when not enough info present.
- D Count TLS bandwidth more accurately
-
- - Improvements to bandwidth counting
-R - look into "uncounting" bytes spent on local connections, so
- we can bandwidthrate but still have fast downloads.
-R - "bandwidth classes", for incoming vs initiated-here conns.
-d - Write limiting; separate token bucket for write
- - Write-limit directory responses (need to research)
-
-N - DNS improvements
- o Option to deal with broken DNS of the "ggoogle.com? Ah, you meant
- ads.me.com!" variety.
- o Autodetect whether DNS is broken in this way.
- o Don't ask reject *:* nodes for DNS unless client wants you to.
- . Asynchronous DNS
- o Document and rename SearchDomains, ResolvConf options
- D Make API closer to getaddrinfo()
- - Teach it to be able to listen for A and PTR requests to be processed.
- Interface should be set_request_listener(sock, cb); [ cb(request) ]
- send_reply(request, answer);
-d - Add option to use /etc/hosts?
-d - Special-case localhost?
- - Verify that it works on windows
- . Make reverse DNS work.
- o Specify
- X Implement with dnsworkers
- (There's no point doing this, since we will throw away dnsworkers once
- eventdns is confirmed to work everywhere.)
- o Implement in eventdns
- o Connect to resolve cells, server-side.
- o Add element to routerinfo to note routers that aren't using eventdns,
- so we can avoid sending them reverse DNS etc.
- - Fix the bug with server-side caching, whatever is causing it.
- . Add client-side interface
- o SOCKS interface: specify
- o SOCKS interface: implement
- - Cache answers client-side
- o Add to Tor-resolve.py
- - Add to tor-resolve
-
- - Performance improvements
-
-x - Better estimates in the directory of whether servers have good uptime
- (high expected time to failure) or good guard qualities (high
- fractional uptime).
- - AKA Track uptime as %-of-time-up, as well as time-since-last-down
-
- - Clients should prefer to avoid exit nodes for non-exit path positions.
- (bug 200)
-R - spec
-x - implement
-
- - Have a "Faster" status flag that means it. Fast2, Fast4, Fast8?
-x - spec
-d - implement
-
- - A more efficient dir protocol.
-N - Later, servers will stop generating new descriptors simply
- because 18 hours have passed: we must start tolerating this now.
-
- - Critical but minor bugs, backport candidates.
-d - Failed rend desc fetches sometimes don't get retried. True/false?
-R - non-v1 authorities should not accept rend descs.
-R - support dir 503s better
- o clients don't log as loudly when they receive them
- - they don't count toward the 3-strikes rule
- - should there be some threshold of 503's after which we give up?
- - Delay when we get a lot of 503s.
-N - split "router is down" from "dirport shouldn't be tried for a while"?
- Just a separate bit.
- - authorities should *never* 503 a cache, but *should* 503 clients
- when they feel like it.
- - update dir-spec with what we decided for each of these
-
-N - provide no-cache no-index headers from the dirport?
-
- - Windows server usability
- - Solve the ENOBUFS problem.
- - make tor's use of openssl operate on buffers rather than sockets,
- so we can make use of libevent's buffer paradigm once it has one.
- - make tor's use of libevent tolerate either the socket or the
- buffer paradigm; includes unifying the functions in connect.c.
- - We need a getrlimit equivalent on Windows so we can reserve some
- file descriptors for saving files, etc. Otherwise we'll trigger
- asserts when we're out of file descriptors and crash.
-M - rewrite how libevent does select() on win32 so it's not so very slow.
- - Add overlapped IO
-
- o Exitlist should avoid outputting the same IP address twice.
-
-Nd- Have a mode that doesn't write to disk much, so we can run Tor on
- flash memory (e.g. Linksys routers or USB keys).
- o Add AvoidDiskWrites config option.
- - only write state file when it's "changed"
- - stop writing identity key / fingerprint / etc every restart
- - stop caching directory stuff -- and disable mmap?
- - more?
-
-NR- Write path-spec.txt
-
- - Packaging
- - Tell people about OSX Uninstaller
- - Quietly document NT Service options
- - Switch canonical win32 compiler to mingw.
-
- - Docs
- - More prominently, we should have a recommended apps list.
- - recommend gaim.
- - unrecommend IE because of ftp:// bug.
- - torrc.complete.in needs attention?
- - we should add a preamble to tor-design saying it's out of date.
+ - <arma> should we detect if we have a --with-ssl-dir and try the -R
+ by default, if it works?
+
+ - support dir 503s better
+ o clients don't log as loudly when they receive them
+ - they don't count toward the 3-strikes rule
+ - should there be some threshold of 503's after which we give up?
+ - think about how to split "router is down" from "dirport shouldn't
+ be tried for a while"?
+ - authorities should *never* 503 a cache, but *should* 503 clients
+ when they feel like it.
+ - update dir-spec with what we decided for each of these
+
+ o find N dirservers.
+ o Make it no longer default for v2 dirservers to support v1.
+ o non-versioning dirservers don't need to set recommended*versions.
+ o non-naming dirservers don't need to have an approved-routers file.
+ o What are criteria to be a dirserver? Write a policy.
+ - are there other options that we haven't documented so far?
+ . look at the proposed os x uninstaller:
+ http://archives.seul.org/or/talk/Jan-2006/msg00038.html
+
+- Interim things:
+ - provide no-cache no-index headers from the dirport?
+ o remove down/useless descriptors from v1 directory?
+ - exitlist should avoid outputting the same IP address twice.
+
+Deferred from 0.1.1.x:
-Topics to think about during 0.1.2.x development:
- * Figure out incentives.
- - (How can we make this tolerant of a bad v0?)
- * Figure out non-clique.
- * Figure out China.
- - Figure out partial network knowledge.
- - Figure out hidden services.
- - Design next-version protocol for directories
- - Design next-version protocol for connections
-
-For blocking-resistance scheme:
- X allow ordinary-looking ssl for dir connections. need a new dirport
- for this, or can we handle both ssl and non-ssl, or should we
- entirely switch to ssl in certain cases?
-Rd- Official way to do authenticated dir conns: connect to OR port,
- and exit to 'localhost:dir-port'.
- - Make everybody with a dir-port implicitly accept exit to
- localhost:dir-port.
- - Check whether this works with one-hop circ case.
-d - need to figure out how to fetch status of a few servers from the BDA
- without fetching all statuses. A new URL to fetch I presume?
-
-Deferred from 0.1.2.x:
- - Directory guards
- - RAM use in directory authorities.
- - Memory use improvements:
- - Look into pulling serverdescs off buffers as they arrive.
- - Save and mmap v1 directories, and networkstatus docs; store them
- zipped, not uncompressed.
- - Switch cached_router_t to use mmap.
- - What to do about reference counts on windows? (On Unix, this is
- easy: unlink works fine. (Right?) On Windows, I have doubts. Do we
- need to keep multiple files?)
- - What do we do about the fact that people can't read zlib-
- compressed files manually?
-
- - Add IPv6 support to eventdns.c
-
- - Refactor DNS resolve implementation
- - Refactor exit side of resolve: do we need a connection_t?
- - Refactor entry side of resolve: do we need a connection_t?
-
- - A more efficient dir protocol.
- - Authorities should fetch the network-statuses amongst each
- other, consensus them, and advertise a communal network-status.
- This is not so much for safety/complexity as it is to reduce
- bandwidth requirements for Alice.
- - How does this interact with our goal of being able to choose
- your own dir authorities? I guess we're now assuming that all
- dir authorities know all the other authorities in their "group"?
- - Should we also look into a "delta since last network-status
- checkpoint" scheme, to reduce overhead further?
- - Extend the "r" line in network-status to give a set of buckets (say,
- comma-separated) for that router.
- - Buckets are deterministic based on IP address.
- - Then clients can choose a bucket (or set of buckets) to
- download and use.
-
- - Improvements to versioning.
- - When we connect to a Tor server, it sends back a cell listing
- the IP it believes it is using. Use this to block dvorak's attack.
- Also, this is a fine time to say what time you think it is.
- o Verify that a new cell type is okay with deployed codebase
- . Specify HELLO cells
- . Figure out v0 compatibility.
- - Implement
-
-Minor items for 0.1.2.x as time permits:
- X If we try to publish as a nickname that's already claimed, should
- we append a number (or increment the number) and try again? This
- way people who read their logs can fix it as before, but people
- who don't read their logs will still offer Tor servers.
- - Fall back to unnamed; warn user; sent controller event.
-! - Tor should bind its ports before dropping privs, so users don't
- have to do the ipchains dance.
- - Rate limit exit connections to a given destination -- this helps
- us play nice with websites when Tor users want to crawl them; it
- also introduces DoS opportunities.
-! - The bw_accounting file should get merged into the state file.
-R - Streamline how we pick entry nodes.
-! - Better installers and build processes.
- - Commit edmanm's win32 makefile to tor contrib, or write a new one.
- - Christian Grothoff's attack of infinite-length circuit.
+ - We need a way for the authorities to declare that nodes are
+ in a family. Needs design.
+
+R - streamline how we define a guard node as 'up'. document it
+ somewhere.
+ - Make "setconf" and "hup" behavior cleaner for LINELIST config
+ options (e.g. Log). Bug 238.
+N - commit edmanm's win32 makefile to tor cvs contrib
+
+R - look into "uncounting" bytes spent on local connections. so
+ we can bandwidthrate but still have fast downloads.
+
+R - Christian Grothoff's attack of infinite-length circuit.
the solution is to have a separate 'extend-data' cell type
which is used for the first N data cells, and only
extend-data cells can be extend requests.
- - Specify, including thought about anonymity implications.
- - Display the reasons in 'destroy' and 'truncated' cells under some
+ - Specify, including thought about
+ - Implement
+
+R - When we connect to a Tor server, it sends back a cell listing
+ the IP it believes it is using. Use this to block dvorak's attack.
+ Also, this is a fine time to say what time you think it is.
+ - Verify that a new cell type is okay with deployed codebase
+ - Specify
+ - Implement
+
+R - failed rend desc fetches sometimes don't get retried.
+
+N - Display the reasons in 'destroy' and 'truncated' cells under some
circumstances?
- - We need a way for the authorities to declare that nodes are
- in a family. Also, it kinda sucks that family declarations use O(N^2)
- space in the descriptors.
+
- If the server is spewing complaints about raising your ulimit -n,
we should add a note about this to the server descriptor so other
people can notice too.
- - cpu fixes:
- - see if we should make use of truncate to retry
- X kill dns workers more slowly
- . Directory changes
- . Some back-out mechanism for auto-approval
- - a way of rolling back approvals to before a timestamp
- - Consider minion-like fingerprint file/log combination.
- - packaging and ui stuff:
- . multiple sample torrc files
- . figure out how to make nt service stuff work?
- . Document it.
- - Vet all pending installer patches
- - Win32 installer plus privoxy, sockscap/freecap, etc.
- - Vet win32 systray helper code
- - Improve controller
- - a NEWSTATUS event similar to NEWDESC.
+ - We need a getrlimit equivalent on Windows so we can reserve some
+ file descriptors for saving files, etc. Otherwise we'll trigger
+ asserts when we're out of file descriptors and crash.
+
+ X <weasel> it would be nice to support a unix socket for the control thing.
+ The main motivation behind this was that we could let unix permissions
+ take care of the authentication step: everybody who can connect to the
+ socket is authenticated. However, the linux unix(7) manual page suggests
+ that requiring read/write permissions on the socket in order to use it
+ is Linux specific, and that many BSD-derived systems ignore the permissions
+ on the socket file. Portable programs should not rely on this feature for
+ security, therefore the motivation for this feature is gone.
+
+ - the tor client can do the "automatic proxy config url" thing?
+
+R - clients prefer to avoid exit nodes for non-exit path positions.
+
+ - Automatically determine what ports are reachable and start using
+ those, if circuits aren't working and it's a pattern we recognize
+ ("port 443 worked once and port 9001 keeps not working").
+
+N - Should router info have a pointer to routerstatus?
+ - We should at least do something about the duplicated fields.
+
+N . Additional controller features
- change circuit status events to give more details, like purpose,
whether they're internal, when they become dirty, when they become
too dirty for further circuits, etc.
- - What do we want here, exactly?
- - Specify and implement it.
+R - What do we want here, exactly?
+N - Specify and implement it.
- Change stream status events analogously.
- - What do we want here, exactly?
- - Specify and implement it.
+R - What do we want here, exactly?
+N - Specify and implement it.
- Make other events "better".
- Change stream status events analogously.
- - What do we want here, exactly?
- - Specify and implement it.
+R - What do we want here, exactly?
+N - Specify and implement it.
- Make other events "better" analogously
- - What do we want here, exactly?
- - Specify and implement it.
+R - What do we want here, exactly?
+N - Specify and implement it.
. Expose more information via getinfo:
- import and export rendezvous descriptors
- Review all static fields for additional candidates
@@ -327,19 +145,57 @@ R - Streamline how we pick entry nodes.
- It would be nice to request address lookups from the controller
without using SOCKS.
- Make everything work with hidden services
- - Directory system improvements
+
+ X switch accountingmax to count total in+out, not either in or
+ out. it's easy to move in this direction (not risky), but hard to
+ back out if we decide we prefer it the way it already is. hm.
+
+ - cpu fixes:
+ - see if we should make use of truncate to retry
+R - kill dns workers more slowly
+
+ . Directory changes
+ . Some back-out mechanism for auto-approval
+ - a way of rolling back approvals to before a timestamp
+ - Consider minion-like fingerprint file/log combination.
+
- config option to publish what ports you listen on, beyond
ORPort/DirPort. It should support ranges and bit prefixes (?) too.
- Parse this.
- Relay this in networkstatus.
- o smartlist_uniq(): We have at least 3 places that check a smartlist for
- duplicates and then removes them: networkstatus_parse_from_string(),
- sort_version_list(), and router_rebuild_descriptor(). This should probably
- get its own function that takes a comparator and a delete function.
-Future version:
- - Configuration format really wants sections.
- - Good RBL substitute.
+ - Non-directories don't need to keep descriptors in memory.
+ o Make descriptor-fetching happen via an indirection function.
+ - Remember file and offset.
+ - Keep a journal FD for appending router descriptors.
+
+ - packaging and ui stuff:
+ . multiple sample torrc files
+ - uninstallers
+ . for os x
+ . figure out how to make nt service stuff work?
+ . Document it.
+ o Add version number to directory.
+N - Vet all pending installer patches
+ - Win32 installer plus privoxy, sockscap/freecap, etc.
+ - Vet win32 systray helper code
+
+ - document:
+ o torcp needs more attention in the tor-doc-win32.
+ - recommend gaim.
+ - unrecommend IE because of ftp:// bug.
+ - torrc.complete.in needs attention?
+
+ - Bind to random port when making outgoing connections to Tor servers,
+ to reduce remote sniping attacks.
+ - Have new people be in limbo and need to demonstrate usefulness
+ before we approve them.
+ - Clients should estimate their skew as median of skew from servers
+ over last N seconds.
+ - Security
+ - Alices avoid duplicate class C nodes.
+ - Analyze how bad the partitioning is or isn't.
+
. Update the hidden service stuff for the new dir approach.
- switch to an ascii format, maybe sexpr?
- authdirservers publish blobs of them.
@@ -351,20 +207,45 @@ Future version:
- come up with a few more auth mechanisms.
- auth mechanisms to let hidden service midpoint and responder filter
connection requests.
- - Bind to random port when making outgoing connections to Tor servers,
- to reduce remote sniping attacks.
- - Have new people be in limbo and need to demonstrate usefulness
- before we approve them.
- - Clients should estimate their skew as median of skew from servers
- over last N seconds.
+
+ . Come up with a coherent strategy for bandwidth buckets and TLS. (The
+ logic for reading from TLS sockets is likely to overrun the bandwidth
+ buckets under heavy load. (Really, the logic was never right in the
+ first place.) Also, we should audit all users of get_pending_bytes().)
+ - Make it harder to circumvent bandwidth caps: look at number of bytes
+ sent across sockets, not number sent inside TLS stream.
+
- Make router_is_general_exit() a bit smarter once we're sure what it's for.
+
+ - rewrite how libevent does select() on win32 so it's not so very slow.
+ - Write limiting; separate token bucket for write
- Audit everything to make sure rend and intro points are just as likely to
be us as not.
- Do something to prevent spurious EXTEND cells from making middleman
nodes connect all over. Rate-limit failed connections, perhaps?
- - Automatically determine what ports are reachable and start using
- those, if circuits aren't working and it's a pattern we recognize
- ("port 443 worked once and port 9001 keeps not working").
+
+
+Major items for 0.1.2.x:
+
+ - Directory guards
+R - Server usability
+N - Better hidden service performance
+ - Improve controller
+ - Asynchronous DNS
+ - Better estimates in the directory of whether servers have good uptime
+ (high expected time to failure) or good guard qualities (high
+ fractional uptime).
+ - memory usage on dir servers.
+ copy less!
+N - oprofile including kernel time.
+
+Topics to think about during 0.1.2.x development:
+ - Figure out non-clique.
+ - Figure out partial network knowledge.
+ - Figure out incentives.
+
+
+Future version:
- Limit to 2 dir, 2 OR, N SOCKS connections per IP.
- Handle full buffers without totally borking
- Rate-limit OR and directory connections overall and per-IP and
@@ -374,11 +255,13 @@ Future version:
- DoS protection: TLS puzzles, public key ops, bandwidth exhaustion.
- Specify?
- tor-resolve script should use socks5 to get better error messages.
+ - Track uptime as %-of-time-up, as well as time-since-last-down.
- hidserv offerers shouldn't need to define a SocksPort
* figure out what breaks for this, and do it.
+ - Relax clique assumptions.
+ X start handling server descriptors without a socksport?
- tor should be able to have a pool of outgoing IP addresses
that it is able to rotate through. (maybe)
- - Specify; implement.
- let each hidden service (or other thing) specify its own
OutboundBindAddress?
@@ -401,20 +284,3 @@ Blue-sky:
we've seen in the wild.
(Pending a user who needs this)
-Non-Coding:
- - Mark up spec; note unclear points about servers
- - Mention controller libs someplace.
- . more pictures from ren. he wants to describe the tor handshake
-NR- write a spec appendix for 'being nice with tor'
- - tor-in-the-media page
- - Remove need for HACKING file.
- - Figure out licenses for website material.
-
-Website:
- - and remove home and make the "Tor" picture be the link to home.
- - put the logo on the website, in source form, so people can put it on
- stickers directly, etc.
-R - make a page with the hidden service diagrams.
-
- - ask Jan to be the translation coordinator? add to volunteer page.
-
diff --git a/doc/control-spec-v0.txt b/doc/control-spec-v0.txt
index 4c64040acb..df2c054010 100644
--- a/doc/control-spec-v0.txt
+++ b/doc/control-spec-v0.txt
@@ -4,9 +4,8 @@ $Id$
-1. Deprecation
-THIS PROTOCOL IS DEPRECATED. It is still documented here because Tor
-0.1.1.x happens to support much of it; but the support for v0 is not
-maintained, so you should expect it to rot in unpredictable ways.
+THIS PROTOCOL IS DEPRECATED. It is still documented here because it is the
+only Tor control protocol supported in the Tor implementation right now.
0. Scope
diff --git a/doc/control-spec.txt b/doc/control-spec.txt
index a79973e3e0..8cfc36ceba 100644
--- a/doc/control-spec.txt
+++ b/doc/control-spec.txt
@@ -188,8 +188,6 @@ $Id$
or none.
NOTE: "EXTENDED" is only supported in Tor 0.1.1.9-alpha or later.
- XXX Need to describe what each event does and is for -RD
-
3.5. AUTHENTICATE
Sent from the client to the server. The syntax is:
@@ -318,13 +316,6 @@ $Id$
"config-file" -- The location of Tor's configuration file ("torrc").
- ["exit-policy/prepend" -- The default exit policy lines that Tor will
- *prepend* to the ExitPolicy config option.
- -- Never implemented. Useful?]
-
- "exit-policy/default" -- The default exit policy lines that Tor will
- *append* to the ExitPolicy config option.
-
"desc/id/<OR identity>" or "desc/name/<OR nickname>" -- the latest
server descriptor for a given OR, NUL-terminated.
@@ -346,13 +337,10 @@ $Id$
via the control interface; the 'all' target returns the mappings
set through any mechanism.
- "address" -- the best guess at our external IP address. If we
- have no guess, return a 551 error.
-
"circuit-status"
A series of lines as for a circuit status event. Each line is of
the form:
- CircuitID SP CircStatus [SP Path] CRLF
+ CircuitID SP CircStatus SP Path CRLF
"stream-status"
A series of lines as for a stream status event. Each is of the form:
@@ -687,7 +675,7 @@ $Id$
The syntax is:
- "650" SP "CIRC" SP CircuitID SP CircStatus [SP Path]
+ "650" SP "CIRC" SP CircuitID SP CircStatus SP Path
CircStatus =
"LAUNCHED" / ; circuit ID assigned to new circuit
@@ -698,9 +686,6 @@ $Id$
Path = ServerID *("," ServerID)
- The path is provided only when the circuit has been extended at least one
- hop.
-
4.1.2. Stream status changed
The syntax is:
@@ -783,11 +768,6 @@ $Id$
file named "control_auth_cookie" into its data directory. To authenticate,
the controller must send the contents of this file.
- [With the v1 controller protocol, what we really mean is that you should
- send the base16 of the contents of this file. Is this it, or is there
- more to it? Should we write a control_auth_cookie.asc file too that
- makes this step easier for people doing it manually? -RD]
-
If the 'HashedControlPassword' option is set, it must contain the salted
hash of a secret password. The salted hash is computed according to the
S2K algorithm in RFC 2440 (OpenPGP), and prefixed with the s2k specifier.
diff --git a/doc/design-paper/blocking.tex b/doc/design-paper/blocking.tex
deleted file mode 100644
index ebc677ab82..0000000000
--- a/doc/design-paper/blocking.tex
+++ /dev/null
@@ -1,352 +0,0 @@
-\documentclass{llncs}
-
-\usepackage{url}
-\usepackage{amsmath}
-\usepackage{epsfig}
-
-%\setlength{\textwidth}{5.9in}
-%\setlength{\textheight}{8.4in}
-%\setlength{\topmargin}{.5cm}
-%\setlength{\oddsidemargin}{1cm}
-%\setlength{\evensidemargin}{1cm}
-
-\newenvironment{tightlist}{\begin{list}{$\bullet$}{
- \setlength{\itemsep}{0mm}
- \setlength{\parsep}{0mm}
- % \setlength{\labelsep}{0mm}
- % \setlength{\labelwidth}{0mm}
- % \setlength{\topsep}{0mm}
- }}{\end{list}}
-
-\begin{document}
-
-\title{Design of a blocking-resistant anonymity system}
-
-\author{}
-
-\maketitle
-\pagestyle{plain}
-
-\begin{abstract}
-
-Websites around the world are increasingly being blocked by
-government-level firewalls. Many people use anonymizing networks like
-Tor to contact sites without letting an attacker trace their activities,
-and as an added benefit they are no longer affected by local censorship.
-But if the attacker simply denies access to the Tor network itself,
-blocked users can no longer benefit from the security Tor offers.
-
-Here we describe a design that uses the current Tor network as a
-building block to provide an anonymizing network that resists blocking
-by government-level attackers.
-
-\end{abstract}
-
-\section{Introduction and Goals}
-
-Websites like Wikipedia and Blogspot are increasingly being blocked by
-government-level firewalls around the world.
-
-China is the third largest user base for Tor clients~\cite{geoip-tor}.
-Many people already want it, and the current Tor design is easy to block
-(by blocking the directory authorities, by blocking all the server
-IP addresses, or by filtering the signature of the Tor TLS handshake).
-
-Now that we've got an overlay network, we're most of the way there in
-terms of building a blocking-resistant tool.
-
-And it improves the anonymity that Tor can provide to add more different
-classes of users and goals to the Tor network.
-
-\subsection{A single system that works for multiple blocked domains}
-
-We want this to work for people in China, people in Iran, people in
-Thailand, people in firewalled corporate networks, etc. The blocking
-censor will be at different stages of the arms race in different places;
-and likely the list of blocked addresses will be different in each
-location too.
-
-
-\section{Adversary assumptions}
-\label{sec:adversary}
-
-Three main network attacks by censors currently:
-
-\begin{tightlist}
-\item Block destination by string matches in TCP packets.
-
-\item Block destination by IP address.
-
-\item Intercept DNS requests.
-\end{tightlist}
-
-Assume the network firewall has very limited CPU~\cite{clayton06}.
-
-Assume that readers of blocked content will not be punished much
-(relative to writers).
-
-Assume that while various different adversaries can coordinate and share
-notes, there will be a significant time lag between one attacker learning
-how to overcome a facet of our design and other attackers picking it up.
-
-
-
-
-\section{Related schemes}
-
-\subsection{public single-hop proxies}
-
-\subsection{personal single-hop proxies}
-
-Easier to deploy; might not require client-side software.
-
-\subsection{break your sensitive strings into multiple tcp packets}
-
-\subsection{steganography}
-
-% \subsection{}
-
-\section{Useful building blocks}
-
-\subsection{Tor}
-
-Anonymizing networks such as
-Tor~\cite{tor-design}
-aim to hide not only what is being said, but also who is
-communicating with whom, which users are using which websites, and so on.
-These systems have a broad range of users, including ordinary citizens
-who want to avoid being profiled for targeted advertisements, corporations
-who don't want to reveal information to their competitors, and law
-enforcement and government intelligence agencies who need
-to do operations on the Internet without being noticed.
-
-Tor provides three security properties:
-\begin{tightlist}
-\item A local observer can't learn, or influence, your destination.
-\item The destination, or somebody watching the destination, can't learn
-your location.
-\item No single piece of the infrastructure can link you to your
-destination.
-\end{tightlist}
-
-We care most clearly about property number 1. But when the arms race
-progresses, property 2 will become important -- so the blocking adversary
-can't learn user+destination just by volunteering a relay. It's not so
-clear to see that property 3 is important, but consider websites and
-services that are pressured into treating clients from certain network
-locations differently.
-
-Other benefits:
-
-\begin{tightlist}
-\item Separates the role of relay from the role of exit node.
-
-\item (Re)builds circuits automatically in the background, based on
-whichever paths work.
-\end{tightlist}
-
-\subsection{Tor circuits}
-
-can build arbitrary overlay paths given a set of descriptors~\cite{blossom}
-
-\subsection{Tor directory servers}
-
-\subsection{Tor user base}
-
-\section{The Design, version one}
-
-\subsection{Bridge relays}
-
-Some Tor users on the free side of the network will opt to become
-bridge relays. They will relay a bit of traffic and won't need to allow
-exits. They sign up on the bridge directory authorities, below.
-
-...need to outline instructions for a Tor config that will publish
-to an alternate directory authority, and for controller commands
-that will do this cleanly.
-
-\subsection{The bridge directory authority (BDA)}
-
-They aggregate server descriptors just like the main authorities, and
-answer all queries as usual, except they don't publish network statuses.
-
-So once you know a bridge relay's key, you can get the most recent
-server descriptor for it.
-
-XXX need to figure out how to fetch some server statuses from the BDA
-without fetching all statuses. A new URL to fetch I presume?
-
-\subsection{Blocked users}
-
-If a blocked user has a server descriptor for one working bridge relay,
-then he can make secure connections to the BDA to update his knowledge
-about other bridge
-relays, and he can make secure connections to the main Tor network
-and directory servers to build circuits and connect to the rest of
-the Internet.
-
-So now we've reduced the problem from how to circumvent the firewall
-for all transactions (and how to know that the pages you get have not
-been modified by the local attacker) to how to learn about a working
-bridge relay.
-
-The simplest format for communicating information about a bridge relay
-is as an IP address and port for its directory cache. From there, the
-user can ask the directory cache for an up-to-date copy of that bridge
-relay's server descriptor, including its current circuit keys, the port
-it uses for Tor connections, and so on.
-
-However, connecting directly to the directory cache involves a plaintext
-http request, so the censor could create a firewall signature for the
-request and/or its response, thus preventing these connections. If that
-happens, the first fix is to use SSL -- not for authentication, but
-just for encryption so requests look different every time.
-
-There's another possible attack here: since we only learn an IP address
-and port, a local attacker could intercept our directory request and
-give us some other server descriptor. But notice that we don't need
-strong authentication for the bridge relay. Since the Tor client will
-ship with trusted keys for the bridge directory authority and the Tor
-network directory authorities, the user can decide if the bridge relays
-are lying to him or not.
-
-Once the Tor client has fetched the server descriptor at least once,
-it should remember the identity key fingerprint for that bridge relay.
-If the bridge relay moves to a new IP address, the client can then
-use the bridge directory authority to look up a fresh server descriptor
-using this fingerprint.
-
-another option is to conclude
-that it will be better to tunnel through a Tor circuit when fetching them.
-
-The following section describes ways to bootstrap knowledge of your first
-bridge relay, and ways to maintain connectivity once you know a few
-bridge relays.
-
-\section{Discovering and maintaining working bridge relays}
-
-\subsection{Initial network discovery}
-
-We make the assumption that the firewall is not perfect. People can
-get around it through the usual means, or they know a friend who can.
-If they can't get around it at all, then we can't help them -- they
-should go meet more people.
-
-Thus they can reach the BDA. From here we either assume a social
-network or other mechanism for learning IP:dirport or key fingerprints
-as above, or we assume an account server that allows us to limit the
-number of new bridge relays an external attacker can discover.
-
-
-
-\section{The Design, version two}
-
-\item A blinded token, which can be exchanged at the BDA (assuming you
-can reach it) for a new IP:dirport or server descriptor.
-
-\subsection{The account server}
-
-Users can establish reputations, perhaps based on social network
-connectivity, perhaps based on not getting their bridge relays blocked,
-
-
-
-\section{Other issues}
-
-\subsection{How many bridge relays should you know about?}
-
-If they're ordinary Tor users on cable modem or DSL, many of them will
-disappear periodically. How many bridge relays should a blockee know
-about before he's likely to have at least one up at any given point?
-
-The related question is: if the bridge relays change IP addresses
-periodically, how often does the blockee need to "check in" in order
-to keep from being cut out of the loop?
-
-\subsection{How do we know if a bridge relay has been blocked?}
-
-We need some mechanism for testing reachability from inside the
-blocked area. The easiest answer is for certain users inside
-the area to sign up as testing relays, and then we can route through
-them and see if it works.
-
-First problem is that different network areas block different net masks,
-and it will likely be hard to know which users are in which areas. So
-if a bridge relay isn't reachable, is that because of a network block
-somewhere, because of a problem at the bridge relay, or just a temporary
-outage?
-
-Second problem is that if we pick random users to test random relays, the
-adversary should sign up users on the inside, and enumerate the relays
-we test. But it seems dangerous to just let people come forward and
-declare that things are blocked for them, since they could be tricking
-us. (This matters even moreso if our reputation system above relies on
-whether things get blocked to punish or reward.)
-
-
-
-
-\subsection{Tunneling directory lookups through Tor}
-
-All you need to do is bootstrap, and then you can use
-your Tor connection to maintain your Tor connection,
-including doing secure directory fetches.
-
-\subsection{Predictable SSL ports}
-
-We should encourage most servers to listen on port 443, which is
-where SSL normally listens.
-
-Is that all it will take, or should we set things up so some fraction
-of them pick random ports? I can see that both helping and hurting.
-
-\subsection{Predictable TLS handshakes}
-
-Right now Tor has some predictable strings in its TLS handshakes.
-These can be removed; but should they be replaced with nothing, or
-should we try to emulate some popular browser? In any case our
-protocol demands a pair of certs on both sides -- how much will this
-make Tor handshakes stand out?
-
-\section{Anonymity issues from becoming a bridge relay}
-
-You can actually harm your anonymity by relaying traffic in Tor. This is
-the same issue that ordinary Tor servers face. On the other hand, it
-provides improved anonymity against some attacks too:
-
-\begin{verbatim}
-http://wiki.noreply.org/noreply/TheOnionRouter/TorFAQ#ServerAnonymity
-\end{verbatim}
-
-\subsection{Cablemodem users don't provide important websites}
-
-...so our adversary could just block all DSL and cablemodem networks,
-and for the most part only our bridge relays would be affected.
-
-The first answer is to aim to get volunteers both from traditionally
-``consumer'' networks and also from traditionally ``producer'' networks.
-
-The second answer (not so good) would be to encourage more use of consumer
-networks for popular and useful websites.
-
-\section{Future designs}
-
-\subsection{Bridges inside the blocked network too}
-
-Assuming actually crossing the firewall is the risky part of the
-operation, can we have some bridge relays inside the blocked area too,
-and more established users can use them as relays so they don't need to
-communicate over the firewall directly at all? A simple example here is
-to make new blocked users into internal bridges also -- so they sign up
-on the BDA as part of doing their query, and we give out their addresses
-rather than (or along with) the external bridge addresses. This design
-is a lot trickier because it brings in the complexity of whether the
-internal bridges will remain available, can maintain reachability with
-the outside world, etc.
-
-Hidden services as bridges.
-
-%\bibliographystyle{plain} \bibliography{tor-design}
-
-\end{document}
-
diff --git a/doc/dir-spec-v1.txt b/doc/dir-spec-v1.txt
deleted file mode 100644
index d5381c0cbe..0000000000
--- a/doc/dir-spec-v1.txt
+++ /dev/null
@@ -1,315 +0,0 @@
-$Id$
-
- Tor Protocol Specification
-
- Roger Dingledine
- Nick Mathewson
-
-0. Prelimaries
-
- THIS SPECIFICATION IS OBSOLETE.
-
- This document specifies the Tor directory protocol as used in version
- 0.1.0.x and earlier. See dir-spec.txt for a current version.
-
-1. Basic operation
-
- There is a small number of directory authorities, and a larger number of
- caches. Client and servers know public keys for the directory authorities.
- Tor servers periodically upload self-signed "router descriptors" to the
- directory authorities. Each authority publishes a self-signed "directory"
- (containing all the router descriptors it knows, and a statement on which
- are running) and a self-signed "running routers" document containing only
- the statement on which routers are running.
-
- All Tors periodically download these documents, downloading the directory
- less frequently than they do the "running routers" document. Clients
- preferentially download from caches rather than authorities.
-
-1.1. Document format
-
- Router descriptors, directories, and running-routers documents all obey the
- following lightweight extensible information format.
-
- The highest level object is a Document, which consists of one or more
- Items. Every Item begins with a KeywordLine, followed by one or more
- Objects. A KeywordLine begins with a Keyword, optionally followed by
- whitespace and more non-newline characters, and ends with a newline. A
- Keyword is a sequence of one or more characters in the set [A-Za-z0-9-].
- An Object is a block of encoded data in pseudo-Open-PGP-style
- armor. (cf. RFC 2440)
-
- More formally:
-
- Document ::= (Item | NL)+
- Item ::= KeywordLine Object*
- KeywordLine ::= Keyword NL | Keyword WS ArgumentsChar+ NL
- Keyword = KeywordChar+
- KeywordChar ::= 'A' ... 'Z' | 'a' ... 'z' | '0' ... '9' | '-'
- ArgumentChar ::= any printing ASCII character except NL.
- WS = (SP | TAB)+
- Object ::= BeginLine Base-64-encoded-data EndLine
- BeginLine ::= "-----BEGIN " Keyword "-----" NL
- EndLine ::= "-----END " Keyword "-----" NL
-
- The BeginLine and EndLine of an Object must use the same keyword.
-
- When interpreting a Document, software MUST reject any document containing a
- KeywordLine that starts with a keyword it doesn't recognize.
-
- The "opt" keyword is reserved for non-critical future extensions. All
- implementations MUST ignore any item of the form "opt keyword ....." when
- they would not recognize "keyword ....."; and MUST treat "opt keyword ....."
- as synonymous with "keyword ......" when keyword is recognized.
-
-8.2. Router descriptor format.
-
- Every router descriptor MUST start with a "router" Item; MUST end with a
- "router-signature" Item and an extra NL; and MUST contain exactly one
- instance of each of the following Items: "published" "onion-key" "link-key"
- "signing-key" "bandwidth". Additionally, a router descriptor MAY contain
- any number of "accept", "reject", "fingerprint", "uptime", and "opt" Items.
- Other than "router" and "router-signature", the items may appear in any
- order.
-
- The items' formats are as follows:
- "router" nickname address ORPort SocksPort DirPort
-
- Indicates the beginning of a router descriptor. "address"
- must be an IPv4 address in dotted-quad format. The last
- three numbers indicate the TCP ports at which this OR exposes
- functionality. ORPort is a port at which this OR accepts TLS
- connections for the main OR protocol; SocksPort is deprecated and
- should always be 0; and DirPort is the port at which this OR accepts
- directory-related HTTP connections. If any port is not supported,
- the value 0 is given instead of a port number.
-
- "bandwidth" bandwidth-avg bandwidth-burst bandwidth-observed
-
- Estimated bandwidth for this router, in bytes per second. The
- "average" bandwidth is the volume per second that the OR is willing
- to sustain over long periods; the "burst" bandwidth is the volume
- that the OR is willing to sustain in very short intervals. The
- "observed" value is an estimate of the capacity this server can
- handle. The server remembers the max bandwidth sustained output
- over any ten second period in the past day, and another sustained
- input. The "observed" value is the lesser of these two numbers.
-
- "platform" string
-
- A human-readable string describing the system on which this OR is
- running. This MAY include the operating system, and SHOULD include
- the name and version of the software implementing the Tor protocol.
-
- "published" YYYY-MM-DD HH:MM:SS
-
- The time, in GMT, when this descriptor was generated.
-
- "fingerprint"
-
- A fingerprint (a HASH_LEN-byte of asn1 encoded public key, encoded
- in hex, with a single space after every 4 characters) for this router's
- identity key. A descriptor is considered invalid (and MUST be
- rejected) if the fingerprint line does not match the public key.
-
- [We didn't start parsing this line until Tor 0.1.0.6-rc; it should
- be marked with "opt" until earlier versions of Tor are obsolete.]
-
- "hibernating" 0|1
-
- If the value is 1, then the Tor server was hibernating when the
- descriptor was published, and shouldn't be used to build circuits.
-
- [We didn't start parsing this line until Tor 0.1.0.6-rc; it should
- be marked with "opt" until earlier versions of Tor are obsolete.]
-
- "uptime"
-
- The number of seconds that this OR process has been running.
-
- "onion-key" NL a public key in PEM format
-
- This key is used to encrypt EXTEND cells for this OR. The key MUST
- be accepted for at least XXXX hours after any new key is published in
- a subsequent descriptor.
-
- "signing-key" NL a public key in PEM format
-
- The OR's long-term identity key.
-
- "accept" exitpattern
- "reject" exitpattern
-
- These lines, in order, describe the rules that an OR follows when
- deciding whether to allow a new stream to a given address. The
- 'exitpattern' syntax is described below.
-
- "router-signature" NL Signature NL
-
- The "SIGNATURE" object contains a signature of the PKCS1-padded
- hash of the entire router descriptor, taken from the beginning of the
- "router" line, through the newline after the "router-signature" line.
- The router descriptor is invalid unless the signature is performed
- with the router's identity key.
-
- "contact" info NL
-
- Describes a way to contact the server's administrator, preferably
- including an email address and a PGP key fingerprint.
-
- "family" names NL
-
- 'Names' is a whitespace-separated list of server nicknames. If two ORs
- list one another in their "family" entries, then OPs should treat them
- as a single OR for the purpose of path selection.
-
- For example, if node A's descriptor contains "family B", and node B's
- descriptor contains "family A", then node A and node B should never
- be used on the same circuit.
-
- "read-history" YYYY-MM-DD HH:MM:SS (NSEC s) NUM,NUM,NUM,NUM,NUM... NL
- "write-history" YYYY-MM-DD HH:MM:SS (NSEC s) NUM,NUM,NUM,NUM,NUM... NL
-
- Declare how much bandwidth the OR has used recently. Usage is divided
- into intervals of NSEC seconds. The YYYY-MM-DD HH:MM:SS field defines
- the end of the most recent interval. The numbers are the number of
- bytes used in the most recent intervals, ordered from oldest to newest.
-
- [We didn't start parsing these lines until Tor 0.1.0.6-rc; they should
- be marked with "opt" until earlier versions of Tor are obsolete.]
-
-2.1. Nonterminals in routerdescriptors
-
- nickname ::= between 1 and 19 alphanumeric characters, case-insensitive.
-
- exitpattern ::= addrspec ":" portspec
- portspec ::= "*" | port | port "-" port
- port ::= an integer between 1 and 65535, inclusive.
- addrspec ::= "*" | ip4spec | ip6spec
- ipv4spec ::= ip4 | ip4 "/" num_ip4_bits | ip4 "/" ip4mask
- ip4 ::= an IPv4 address in dotted-quad format
- ip4mask ::= an IPv4 mask in dotted-quad format
- num_ip4_bits ::= an integer between 0 and 32
- ip6spec ::= ip6 | ip6 "/" num_ip6_bits
- ip6 ::= an IPv6 address, surrounded by square brackets.
- num_ip6_bits ::= an integer between 0 and 128
-
- Ports are required; if they are not included in the router
- line, they must appear in the "ports" lines.
-
-3. Directory format
-
- A Directory begins with a "signed-directory" item, followed by one each of
- the following, in any order: "recommended-software", "published",
- "router-status", "dir-signing-key". It may include any number of "opt"
- items. After these items, a directory includes any number of router
- descriptors, and a single "directory-signature" item.
-
- "signed-directory"
-
- Indicates the start of a directory.
-
- "published" YYYY-MM-DD HH:MM:SS
-
- The time at which this directory was generated and signed, in GMT.
-
- "dir-signing-key"
-
- The key used to sign this directory; see "signing-key" for format.
-
- "recommended-software" comma-separated-version-list
-
- A list of which versions of which implementations are currently
- believed to be secure and compatible with the network.
-
- "running-routers" whitespace-separated-list
-
- A description of which routers are currently believed to be up or
- down. Every entry consists of an optional "!", followed by either an
- OR's nickname, or "$" followed by a hexadecimal encoding of the hash
- of an OR's identity key. If the "!" is included, the router is
- believed not to be running; otherwise, it is believed to be running.
- If a router's nickname is given, exactly one router of that nickname
- will appear in the directory, and that router is "approved" by the
- directory server. If a hashed identity key is given, that OR is not
- "approved". [XXXX The 'running-routers' line is only provided for
- backward compatibility. New code should parse 'router-status'
- instead.]
-
- "router-status" whitespace-separated-list
-
- A description of which routers are currently believed to be up or
- down, and which are verified or unverified. Contains one entry for
- every router that the directory server knows. Each entry is of the
- format:
-
- !name=$digest [Verified router, currently not live.]
- name=$digest [Verified router, currently live.]
- !$digest [Unverified router, currently not live.]
- or $digest [Unverified router, currently live.]
-
- (where 'name' is the router's nickname and 'digest' is a hexadecimal
- encoding of the hash of the routers' identity key).
-
- When parsing this line, clients should only mark a router as
- 'verified' if its nickname AND digest match the one provided.
-
- "directory-signature" nickname-of-dirserver NL Signature
-
- The signature is computed by computing the digest of the
- directory, from the characters "signed-directory", through the newline
- after "directory-signature". This digest is then padded with PKCS.1,
- and signed with the directory server's signing key.
-
- If software encounters an unrecognized keyword in a single router descriptor,
- it MUST reject only that router descriptor, and continue using the
- others. Because this mechanism is used to add 'critical' extensions to
- future versions of the router descriptor format, implementation should treat
- it as a normal occurrence and not, for example, report it to the user as an
- error. [Versions of Tor prior to 0.1.1 did this.]
-
- If software encounters an unrecognized keyword in the directory header,
- it SHOULD reject the entire directory.
-
-4. Network-status descriptor
-
- A "network-status" (a.k.a "running-routers") document is a truncated
- directory that contains only the current status of a list of nodes, not
- their actual descriptors. It contains exactly one of each of the following
- entries.
-
- "network-status"
-
- Must appear first.
-
- "published" YYYY-MM-DD HH:MM:SS
-
- (see 8.3 above)
-
- "router-status" list
-
- (see 8.3 above)
-
- "directory-signature" NL signature
-
- (see 8.3 above)
-
-5. Behavior of a directory server
-
- lists nodes that are connected currently
- speaks HTTP on a socket, spits out directory on request
-
- Directory servers listen on a certain port (the DirPort), and speak a
- limited version of HTTP 1.0. Clients send either GET or POST commands.
- The basic interactions are:
- "%s %s HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s\r\n\r\n",
- command, url, content-length, host.
- Get "/tor/" to fetch a full directory.
- Get "/tor/dir.z" to fetch a compressed full directory.
- Get "/tor/running-routers" to fetch a network-status descriptor.
- Post "/tor/" to post a server descriptor, with the body of the
- request containing the descriptor.
-
- "host" is used to specify the address:port of the dirserver, so
- the request can survive going through HTTP proxies.
-
diff --git a/doc/dir-spec.txt b/doc/dir-spec.txt
index a211ebc095..b97eb7fe94 100644
--- a/doc/dir-spec.txt
+++ b/doc/dir-spec.txt
@@ -1,26 +1,28 @@
$Id$
- Tor directory protocol, version 2
+ Tor directory protocol for 0.1.1.x series
0. Scope and preliminaries
- This directory protocol is used by Tor version 0.1.1.x and later. See
- dir-spec-v1.txt for information on earlier versions.
+ This document should eventually be merged to replace and supplement the
+ existing notes on directories in tor-spec.txt.
-0.1. Goals and motivation
+ This is not a finalized version; what we actually wind up implementing
+ may be different from the system described here.
- There were several problems with the way Tor handles directory information
+0.1. Goals
+
+ There are several problems with the way Tor handles directory information
in version 0.1.0.x and earlier. Here are the problems we try to fix with
- this new design, already implemented in 0.1.1.x:
- 1. Directories were very large and use up a lot of bandwidth: clients
- downloaded descriptors for all router several times an hour.
- 2. Every directory authority was a trust bottleneck: if a single
- directory authority lied, it could make clients believe for a time an
+ this new design, already partially implemented in 0.1.1.x:
+ 1. Directories are very large and use up a lot of bandwidth: clients
+ download descriptors for all router several times an hour.
+ 2. Every directory authority is a trust bottleneck: if a single
+ directory authority lies, it can make clients believe for a time an
arbitrarily distorted view of the Tor network.
3. Our current "verified server" system is kind of nonsensical.
-
- 4. Getting more directory authorities would add more points of failure
- and worsen possible partitioning attacks.
+ 4. Getting more directory authorities adds more points of failure and
+ worsens possible partitioning attacks.
There are two problems that remain unaddressed by this design.
5. Requiring every client to know about every router won't scale.
@@ -80,44 +82,10 @@ $Id$
Routers used to upload fresh descriptors all the time, whether their keys
and other information had changed or not.
-1.2. Document meta-format
-
- Router descriptors, directories, and running-routers documents all obey the
- following lightweight extensible information format.
-
- The highest level object is a Document, which consists of one or more
- Items. Every Item begins with a KeywordLine, followed by one or more
- Objects. A KeywordLine begins with a Keyword, optionally followed by
- whitespace and more non-newline characters, and ends with a newline. A
- Keyword is a sequence of one or more characters in the set [A-Za-z0-9-].
- An Object is a block of encoded data in pseudo-Open-PGP-style
- armor. (cf. RFC 2440)
-
- More formally:
-
- Document ::= (Item | NL)+
- Item ::= KeywordLine Object*
- KeywordLine ::= Keyword NL | Keyword WS ArgumentsChar+ NL
- Keyword = KeywordChar+
- KeywordChar ::= 'A' ... 'Z' | 'a' ... 'z' | '0' ... '9' | '-'
- ArgumentChar ::= any printing ASCII character except NL.
- WS = (SP | TAB)+
- Object ::= BeginLine Base-64-encoded-data EndLine
- BeginLine ::= "-----BEGIN " Keyword "-----" NL
- EndLine ::= "-----END " Keyword "-----" NL
-
- The BeginLine and EndLine of an Object must use the same keyword.
-
- When interpreting a Document, software MUST reject any document containing a
- KeywordLine that starts with a keyword it doesn't recognize.
-
- The "opt" keyword is reserved for non-critical future extensions. All
- implementations MUST ignore any item of the form "opt keyword ....." when
- they would not recognize "keyword ....."; and MUST treat "opt keyword ....."
- as synonymous with "keyword ......" when keyword is recognized.
-
2. Router operation
+ The router descriptor format is unchanged from tor-spec.txt.
+
ORs SHOULD generate a new router descriptor whenever any of the
following events have occurred:
@@ -137,159 +105,6 @@ $Id$
http://<hostname:port>/tor/
-2.1. Router descriptor format
-
- Every router descriptor MUST start with a "router" Item; MUST end with a
- "router-signature" Item and an extra NL; and MUST contain exactly one
- instance of each of the following Items: "published" "onion-key"
- "link-key" "signing-key" "bandwidth". Additionally, a router descriptor
- MAY contain any number of "accept", "reject", "fingerprint", "uptime", and
- "opt" Items. Other than "router" and "router-signature", the items may
- appear in any order.
-
- The items' formats are as follows:
- "router" nickname address ORPort SocksPort DirPort
-
- Indicates the beginning of a router descriptor. "address" must be an
- IPv4 address in dotted-quad format. The last three numbers indicate
- the TCP ports at which this OR exposes functionality. ORPort is a port
- at which this OR accepts TLS connections for the main OR protocol;
- SocksPort is deprecated and should always be 0; and DirPort is the
- port at which this OR accepts directory-related HTTP connections. If
- any port is not supported, the value 0 is given instead of a port
- number.
-
- "bandwidth" bandwidth-avg bandwidth-burst bandwidth-observed
-
- Estimated bandwidth for this router, in bytes per second. The
- "average" bandwidth is the volume per second that the OR is willing to
- sustain over long periods; the "burst" bandwidth is the volume that
- the OR is willing to sustain in very short intervals. The "observed"
- value is an estimate of the capacity this server can handle. The
- server remembers the max bandwidth sustained output over any ten
- second period in the past day, and another sustained input. The
- "observed" value is the lesser of these two numbers.
-
- "platform" string
-
- A human-readable string describing the system on which this OR is
- running. This MAY include the operating system, and SHOULD include
- the name and version of the software implementing the Tor protocol.
-
- "published" YYYY-MM-DD HH:MM:SS
-
- The time, in GMT, when this descriptor was generated.
-
- "fingerprint"
-
- A fingerprint (a HASH_LEN-byte of asn1 encoded public key, encoded in
- hex, with a single space after every 4 characters) for this router's
- identity key. A descriptor is considered invalid (and MUST be
- rejected) if the fingerprint line does not match the public key.
-
- [We didn't start parsing this line until Tor 0.1.0.6-rc; it should
- be marked with "opt" until earlier versions of Tor are obsolete.]
-
- "hibernating" 0|1
-
- If the value is 1, then the Tor server was hibernating when the
- descriptor was published, and shouldn't be used to build circuits.
-
- [We didn't start parsing this line until Tor 0.1.0.6-rc; it should be
- marked with "opt" until earlier versions of Tor are obsolete.]
-
- "uptime"
-
- The number of seconds that this OR process has been running.
-
- "onion-key" NL a public key in PEM format
-
- This key is used to encrypt EXTEND cells for this OR. The key MUST be
- accepted for at least XXXX hours after any new key is published in a
- subsequent descriptor.
-
- "signing-key" NL a public key in PEM format
-
- The OR's long-term identity key.
-
- "accept" exitpattern
- "reject" exitpattern
-
- These lines, in order, describe the rules that an OR follows when
- deciding whether to allow a new stream to a given address. The
- 'exitpattern' syntax is described below.
-
- "router-signature" NL Signature NL
-
- The "SIGNATURE" object contains a signature of the PKCS1-padded
- hash of the entire router descriptor, taken from the beginning of the
- "router" line, through the newline after the "router-signature" line.
- The router descriptor is invalid unless the signature is performed
- with the router's identity key.
-
- "contact" info NL
-
- Describes a way to contact the server's administrator, preferably
- including an email address and a PGP key fingerprint.
-
- "family" names NL
-
- 'Names' is a whitespace-separated list of server nicknames. If two
- ORs list one another in their "family" entries, then OPs should treat
- them as a single OR for the purpose of path selection.
-
- For example, if node A's descriptor contains "family B", and node B's
- descriptor contains "family A", then node A and node B should never
- be used on the same circuit.
-
- "read-history" YYYY-MM-DD HH:MM:SS (NSEC s) NUM,NUM,NUM,NUM,NUM... NL
- "write-history" YYYY-MM-DD HH:MM:SS (NSEC s) NUM,NUM,NUM,NUM,NUM... NL
-
- Declare how much bandwidth the OR has used recently. Usage is divided
- into intervals of NSEC seconds. The YYYY-MM-DD HH:MM:SS field
- defines the end of the most recent interval. The numbers are the
- number of bytes used in the most recent intervals, ordered from
- oldest to newest.
-
- [We didn't start parsing these lines until Tor 0.1.0.6-rc; they should
- be marked with "opt" until earlier versions of Tor are obsolete.]
-
- "eventdns" bool NL
-
- Declare whether this version of Tor is using the newer enhanced
- dns logic. Versions of Tor without eventdns SHOULD not be used for
- reverse hostname lookups.
-
- [All versions of Tor before 0.1.2.2-alpha should be assumed to have
- this option set to 0 if it is not present. All Tor versions at
- 0.1.2.2-alpha or later should be assumed to have this option set to
- 1 if it is not present. Until 0.1.2.1-alpha-dev, this option was
- not generated, even when eventdns was in use. Versions of Tor
- before 0.1.2.1-alpha-dev did not parse this option, so it should be
- marked "opt". With some future version, the old 'dnsworker' logic
- will be removed, rendering this option of historical interest only.]
-
-2.1. Nonterminals in router descriptors
-
- nickname ::= between 1 and 19 alphanumeric characters, case-insensitive.
-
- exitpattern ::= addrspec ":" portspec
- portspec ::= "*" | port | port "-" port
- port ::= an integer between 1 and 65535, inclusive.
- addrspec ::= "*" | ip4spec | ip6spec
- ipv4spec ::= ip4 | ip4 "/" num_ip4_bits | ip4 "/" ip4mask
- ip4 ::= an IPv4 address in dotted-quad format
- ip4mask ::= an IPv4 mask in dotted-quad format
- num_ip4_bits ::= an integer between 0 and 32
- ip6spec ::= ip6 | ip6 "/" num_ip6_bits
- ip6 ::= an IPv6 address, surrounded by square brackets.
- num_ip6_bits ::= an integer between 0 and 128
-
- bool ::= "0" | "1"
-
- Ports are required; if they are not included in the router
- line, they must appear in the "ports" lines.
-
3. Network status format
Directory authorities generate, sign, and compress network-status
@@ -368,15 +183,13 @@ $Id$
"V2Dir" if the router implements this protocol.
The "r" entry for each router must appear first and is required. The
- "s" entry is optional. Unrecognized flags on the "s" line and extra
- elements on the "r" line must be ignored.
+ 's" entry is optional. Unrecognized flags and extra elements on the
+ "r" line must be ignored.
The signature section contains:
- "directory-signature". A signature of the rest of the document
- (the document up until the signature, including the line
- "directory-signature <nick>\n") using the directory authority's
- signing key.
+ "directory-signature". A signature of the rest of the document using
+ the directory authority's signing key.
We compress the network status list with zlib before transmitting it.
@@ -573,7 +386,7 @@ $Id$
5. Client operation: downloading information
- Every Tor that is not a directory server (that is, those that do
+ Every Tor that is not a directory server (that is, clients and ORs that do
not have a DirPort set) implements this section.
5.1. Downloading network-status documents
@@ -778,7 +591,7 @@ $Id$
consecutive times) a network-status for every authority, and at
least one of the authorities is "Naming", and no live "Naming"
authorities publish a binding for the router's nickname, the
- router MAY remind the operator that the chosen nickname is not
+ router SHOULD remind the operator that the chosen nickname is not
bound to this key at the authorities, and suggest contacting the
authority operators.
diff --git a/doc/incentives.txt b/doc/incentives.txt
index 994310025d..5b805549d1 100644
--- a/doc/incentives.txt
+++ b/doc/incentives.txt
@@ -177,7 +177,7 @@
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
+ otherwise wouldn't need to spend is 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
diff --git a/doc/path-spec.txt b/doc/path-spec.txt
deleted file mode 100644
index fde40f4299..0000000000
--- a/doc/path-spec.txt
+++ /dev/null
@@ -1,551 +0,0 @@
-$Id$
-
- Tor Path Specification
-
- Roger Dingledine
- Nick Mathewson
-
-Note: This is an attempt to specify Tor as currently implemented. Future
-versions of Tor will implement improved algorithms.
-
-This document tries to cover how Tor chooses to build circuits and assign
-streams to circuits. Other implementations MAY take other approaches, but
-implementors should be aware of the anonymity and load-balancing implications
-of their choices.
-
- THIS SPEC ISN'T DONE OR CORRECT.
-I'm just copying in relevant info so far. The starred points are things we
-should cover, but not an exhaustive list. -NM
-
-1. General operation
-
- Tor begins building circuits as soon as it has enough directory
- information to do so (see section 5.1 of dir-spec.txt). Some circuits are
- built preemptively because we expect to need them later (for user
- traffic), and some are build because of immediate need (for user traffic
- that no current circuit can handle, for testing the network or our
- availability, and so on).
-
- When a client application creates a new stream (by opening a SOCKS
- connection or launching a resolve request), we attach it to an appropriate
- open (or in-progress) circuit if one exists, and launch a new circuit only
- if no current circuit can handle the request. We rotate circuits over
- time to avoid some profiling attacks.
-
- To build a circuit, we choose all the nodes we want to use, and then
- construct the circuit. Sometimes, when we want a circuit that ends at a
- given hop, and we have an appropriate unused circuit, we "cannibalize" the
- existing circuit and extend it to the new terminus.
-
- These processes are described in more detail below.
-
- This document describes Tor's automatic path selection logic only; path
- selection can be overridden by a controller (with the EXTENDCIRCUIT and
- ATTACHSTREAM commands). Paths constructed through these means will
- violate some constraints given below.
-
-1b. Types of circuits.
-
-* Stable / Ordinary
-* Internal / Exit
-
- XXXX
-
-1c. Terminology
-
- A "path" is an ordered sequence of nodes, not yet built as a circuit.
-
- A "clean" circuit is one that has not yet been used for any traffic.
-
- A "stable" node is one that we believe to have the 'Stable' flag set on
- the basis of our current directory information. A "stable" circuit is one
- that consists entirely of "stable" nodes.
-
- A "fast" or "stable" node is one that we believe to have the 'Fast' or
- 'Stable' flag set on the basis of our current directory information. A
- "fast" or "stable" circuit is one consisting only of "fast" or "stable"
- nodes.
-
- A "request" is a client-side connection or DNS resolve that needs to be
- served by a circuit.
-
- A "pending" circuit is one that we have started to build, but which has
- not yet completed.
-
- A circuit or path "supports" a request if it is okay to use the
- circuit/path to fulfill the request, according to the rules given below.
- A circuit or path "might support" a request if some aspect of the request
- is unknown (usually its target IP), but we believe the path probably
- supports the request according to the rules given below.
-
-2. Building circuits
-
-2.1. When we build.
-
-2.1.1. When clients build circuits
-
- When running as a client, Tor tries to maintain at least 3 clean circuits,
- so that new streams can be handled quickly. To increase the likelihood of
- success, Tor tries to predict what exit nodes will be useful by choosing
- from among nodes that support the ports we have used in the recent past.
- (see 2.4). [XXXX describe in detail how predicted ports work.]
-
- Additionally, when a client request exists that no circuit (built or
- pending) might support, we cannibalize an existing circuit (2.1.4) or
- create a new circuit to support the request. We do so by picking a
- request at random, building or cannibalizing a circuit to support it, and
- repeating until every unattached request might be supported by a pending
- or built circuit.
-
- XXXX when long idle, we build nothing.
-
-2.1.2. When servers build circuits
-
- XXXX
-
-2.1.3. When authorities build circuits
-
- XXXX
-
-2.1.4. Hidden-service circuits
-
- See section 4 below.
-
-2.1.4. Cannibalizing circuits
-
- When Tor has a request (either an unattached stream or unattached resolve
- request) that no current circuit can support, it looks for an existing
- clean circuit to cannibalize. If it finds one, it tries to extend it
- another hop to an exit node that might support the stream. [Must be
- internal???]
-
- If no circuit exists, or is currently being built, along a path that
- might support a stream, we begin building a new circuit that might support
- the stream.
-
- [XXXX always? really?]
-
-2.2. Path selection and constraints
-
- We choose the path for each new circuit before we build it. We choose the
- exit node first, followed by the other nodes in the circuit. All paths
- we generate obey the following constraints:
- - We do not choose the same router twice for the same path.
- - We do not choose any router in the same family as another in the same
- circuit.
- - We do not choose any router in the same /16 subnet as another in the
- same circuit.
- - We don't choose any non-running or non-valid router unless we have
- been configured to do so.
- - If we're using Guard nodes, the first node must be a Guard (see 5
- below)
- - XXXX Choosing the length
-
- When choosing among multiple candidates for a path element, we choose
- a given router with probability proportional to its advertised bandwidth
- [the smaller of the 'rate' and 'observed' arguments to the "bandwidth"
- element in its descriptor]. If a router's advertised bandwidth is greater
- than MAX_BELIEVEABLE_BANDWIDTH (1.5 MB/sec), we clip to that value.
-
- (XXXX We should do something to shift traffic away from exit nodes.)
-
- Additionally, we may be building circuits with one or more requests in
- mind. Each kind of request puts certain constraints on paths:
-
- - All service-side introduction circuits and all rendezvous paths
- should be Stable.
- - All connection requests for connections that we think will need to
- stay open a long time require Stable circuits. Currently, Tor decides
- this by examining the request's target port, and comparing it to a
- list of "long-lived" ports. (Default: 21, 22, 706, 1863, 5050, 5190,
- 5222, 5223, 6667, 8300, 8888.)
- - DNS resolves require an exit node whose exit policy is not equivalent
- to "reject *:*".
- - Reverse DNS resolves require a version of Tor with advertised eventdns
- support, running 0.1.2.1-alpha-dev or later.
- - All connection requests require an exit node whose exit policy
- supports their target address and port (if known), or which "might
- support it" (if the address isn't known). See 2.2.1.
- - Rules for Fast? XXXXX
-
-2.2.1. Choosing an exit
-
- If we know what IP we want to resolve, we can trivially tell whether a
- given router will support it by simulating its declared exit policy.
-
- Because we often connect to addresses of the form hostname:port, we do not
- always know the target IP address when we select an exit node. In these
- cases, we need to pick an exit node that "might support" connections to a
- given address port with an unknown address. An exit node "might support"
- such a connection if any clause that accepts any connections to that port
- precedes all clauses (if any) that reject all connections to that port.
-
-2.2.2. User configuration
-
- Users can alter the default behavior for path selection with configuration
- options.
-
- - If "ExitNodes" is provided, then every request requires an exit node on
- the ExitNodes list. (If a request is supported by no nodes on that list,
- and StrictExitNodes is false, then Tor treats that request as if
- ExitNodes were not provided.)
-
- - "EntryNodes" and "StrictEntryNodes" behave analagously.
-
- - If a user tries to connect to or resolve a hostname of the form
- <target>.<servername>.exit, the request is rewritten to a request for
- <target>, and the request is only supported by the exit whose nickname
- or fingerprint is <servername>.
-
-2.3. Handling failure
-
- If an attempt to extend a circuit fails (either because the first create
- failed or a subsequent extend failed) then the circuit is torn down and is
- no longer pending. (XXXX really?) Requests that might have been
- supported by the pending circuit thus become unsupported, and a new
- circuit needs to be constructed.
-
- If we fail to being a circuit with an EXITPOLICY error, we decide that the
- exit node's exit policy is not correctly advertised, so we treat the exit
- node as if it were a non-exit until we retrieve a fresh descriptor for it.
-
- XXXX
-
-2.4. Tracking "predicted" ports
-
- A Tor client tracks how much time has passed since it last received a
- request for a connection on each port. (For the purposes of this section,
- requests for hostname resolves are considered requests to a separate
- port). Tor forgets about ports that haven't been used for an hour
- [PREDICTED_CIRCS_RELEVANCE_TIME].
-
- The ports that have been used in the last hour are considered "predicted",
- and Tor will try to maintain a clean circuits to them as described in 2.1.
-
- For bootstrapping purposes, port 80 is treated as used at startup time.
-
- Tor clients SHOULD NOT store predicted ports to a persistent medium.
-
-3. Attaching streams to circuits
-
- When a circuit that might support a request is built, Tor tries to attach
- the request's stream to the circuit and sends a BEGIN or RESOLVE relay
- cell as appropriate. If the request completes unsuccessfully, Tor
- considers the reason given in the CLOSE relay cell. [XXX yes, and?]
-
-
- After a request has remained unattached for [XXXX retries? interval?], Tor
- abandons the attempt and signals an error to the client as appropriate
- (e.g., by closing the SOCKS connection).
-
- XXX Timeouts and when Tor auto-retries.
- * What stream-end-reasons are appropriate for retrying.
-
- XXX What if no reply to BEGIN/RESOLVE?
-
-4. Hidden-service related circuits
-
- XXX Tracking expected hidden service use (client-side and hidserv-side)
-
-5. Guard nodes
-
- XXX writeme
-
-6. Testing circuits
-
-
-
-
-(From some emails by arma)
-
-Hi folks,
-
-I've gotten the codebase to the point that I'm going to start trying
-to make helper nodes work well. With luck they will be on by default in
-the final 0.1.1.x release.
-
-For background on helper nodes, read
-http://wiki.noreply.org/noreply/TheOnionRouter/TorFAQ#RestrictedEntry
-
-First order of business: the phrase "helper node" sucks. We always have
-to define it after we say it to somebody. Nick likes the phrase "contact
-node", because they are your point-of-contact into the network. That is
-better than phrases like "bridge node". The phrase "fixed entry node"
-doesn't seem to work with non-math people, because they wonder what was
-broken about it. I'm sort of partial to the phrase "entry node" or maybe
-"restricted entry node". In any case, if you have ideas on names, please
-mail me off-list and I'll collate them.
-
-Right now the code exists to pick helper nodes, store our choices to
-disk, and use them for our entry nodes. But there are three topics
-to tackle before I'm comfortable turning them on by default. First,
-how to handle churn: since Tor nodes are not always up, and sometimes
-disappear forever, we need a plan for replacing missing helpers in a
-safe way. Second, we need a way to distinguish "the network is down"
-from "all my helpers are down", also in a safe way. Lastly, we need to
-examine the situation where a client picks three crummy helper nodes
-and is forever doomed to a lousy Tor experience. Here's my plan:
-
-How to handle churn.
- - Keep track of whether you have ever actually established a
- connection to each helper. Any helper node in your list that you've
- never used is ok to drop immediately. Also, we don't save that
- one to disk.
- - If all our helpers are down, we need more helper nodes: add a new
- one to the *end*of our list. Only remove dead ones when they have
- been gone for a very long time (months).
- - Pick from the first n (by default 3) helper nodes in your list
- that are up (according to the network-statuses) and reachable
- (according to your local firewall config).
- - This means that order matters when writing/reading them to disk.
-
-How to deal with network down.
- - While all helpers are down/unreachable and there are no established
- or on-the-way testing circuits, launch a testing circuit. (Do this
- periodically in the same way we try to establish normal circuits
- when things are working normally.)
- (Testing circuits are a special type of circuit, that streams won't
- attach to by accident.)
- - When a testing circuit succeeds, mark all helpers up and hold
- the testing circuit open.
- - If a connection to a helper succeeds, close all testing circuits.
- Else mark that helper down and try another.
- - If the last helper is marked down and we already have a testing
- circuit established, then add the first hop of that testing circuit
- to the end of our helper node list, close that testing circuit,
- and go back to square one. (Actually, rather than closing the
- testing circuit, can we get away with converting it to a normal
- circuit and beginning to use it immediately?)
-
-How to pick non-sucky helpers.
- - When we're picking a new helper nodes, don't use ones which aren't
- reachable according to our local ReachableAddresses configuration.
- (There's an attack here: if I pick my helper nodes in a very
- restrictive environment, say "ReachableAddresses 18.0.0.0/255.0.0.0:*",
- then somebody watching me use the network from another location will
- guess where I first joined the network. But let's ignore it for now.)
- - Right now we choose new helpers just like we'd choose any entry
- node: they must be "stable" (claim >1day uptime) and "fast" (advertise
- >10kB capacity). In 0.1.1.11-alpha, clients let dirservers define
- "stable" and "fast" however they like, and they just believe them.
- So the next step is to make them a function of the current network:
- e.g. line up all the 'up' nodes in order and declare the top
- three-quarter to be stable, fast, etc, as long as they meet some
- minimum too.
- - If that's not sufficient (it won't be), dirservers should introduce
- a new status flag: in additional to "stable" and "fast", we should
- also describe certain nodes as "entry", meaning they are suitable
- to be chosen as a helper. The first difference would be that we'd
- demand the top half rather than the top three-quarters. Another
- requirement would be to look at "mean time between returning" to
- ensure that these nodes spend most of their time available. (Up for
- two days straight, once a month, is not good enough.)
- - Lastly, we need a function, given our current set of helpers and a
- directory of the rest of the network, that decides when our helper
- set has become "too crummy" and we need to add more. For example,
- this could be based on currently advertised capacity of each of
- our helpers, and it would also be based on the user's preferences
- of speed vs. security.
-
-***
-
-Lasse wrote:
-> I am a bit concerned with performance if we are to have e.g. two out of
-> three helper nodes down or unreachable. How often should Tor check if
-> they are back up and running?
-
-Right now Tor believes a threshold of directory servers when deciding
-whether each server is up. When Tor observes a server to be down
-(connection failed or building the first hop of the circuit failed),
-it marks it as down and doesn't try it again, until it gets a new
-network-status from somebody, at which point it takes a new concensus
-and marks the appropriate servers as up.
-
-According to sec 5.1 of dir-spec.txt, the client will try to fetch a new
-network-status at least every 30 minutes, and more often in certain cases.
-
-With the proposed scheme, we'll also mark all our helpers as up shortly
-after the last one is marked down.
-
-> When should there be
-> added an extra node to the helper node list? This is kind of an
-> important threshold?
-
-I agree, this is an important question. I don't have a good answer yet. Is
-it terrible, anonymity-wise, to add a new helper every time only one of
-your helpers is up? Notice that I say add rather than replace -- so you'd
-only use this fourth helper when one of your main three helpers is down,
-and if three of your four are down, you'd add a fifth, but only use it
-when two of the first four are down, etc.
-
-In fact, this may be smarter than just picking a random node for your
-testing circuit, because if your network goes up and down a lot, then
-eventually you have a chance of using any entry node in the network for
-your testing circuit.
-
-We have a design choice here. Do we only try to use helpers for the
-connections that will have streams on them (revealing our communication
-partners), or do we also want to restrict the overall set of nodes that
-we'll connect to, to discourage people from enumerating all Tor clients?
-
-I'm increasingly of the belief that we want to hide our presence too,
-based on the fact that Steven and George and others keep coming up with
-attacks that start with "Assuming we know the set of users".
-
-If so, then here's a revised "How to deal with network down" section:
-
- 1) When a helper is marked down or the helper list shrinks, and as
- a result the total number of helpers that are either (up and
- reachable) or (reachable but never connected to) is <= 1, then pick
- a new helper and add it to the end of the list.
- [We count nodes that have never been connected to, since otherwise
- we might keep on adding new nodes before trying any of them. By
- "reachable" I mean "is allowed by ReachableAddresses".]
- 2) When you fail to connect to a helper that has never been connected
- to, you remove him from the list right then (and the above rule
- might kick in).
- 3) When you succeed at connecting to a helper that you've never
- connected to before, mark all reachable helpers earlier in the list
- as up, and close that circuit.
- [We close the circuit, since if the other helpers are now up, we
- prefer to use them for circuits that will reveal communication
- partners.]
-
-This certainly seems simpler. Are there holes that I'm missing?
-
-> If running from a laptop you will meet different firewall settings, so
-> how should Helper Nodes settings keep up with moving from an open
-> ReachableAddresses to a FascistFirewall setting after the helper nodes
-> have been selected?
-
-I added the word "reachable" to three places in the above list, and I
-believe that totally solves this question.
-
-And as a bonus, it leads to an answer to Nick's attack ("If I pick
-my helper nodes all on 18.0.0.0:*, then I move, you'll know where I
-bootstrapped") -- the answer is to pick your original three helper nodes
-without regard for reachability. Then the above algorithm will add some
-more that are reachable for you, and if you move somewhere, it's more
-likely (though not certain) that some of the originals will become useful.
-Is that smart or just complex?
-
-> What happens if(when?) performance of the third node is bad?
-
-My above solution solves this a little bit, in that we always try to
-have two nodes available. But what if they are both up but bad? I'm not
-sure. As my previous mail said, we need some function, given our list
-of helpers and the network directory, that will tell us when we're in a
-bad situation. I can imagine some simple versions of this function --
-for example, when both our working helpers are in the bottom half of
-the nodes, ranked by capacity.
-
-But the hard part: what's the remedy when we decide there's something
-to fix? Do we add a third, and now we have two crummy ones and a new
-one? Or do we drop one or both of the bad ones?
-
-Perhaps we believe the latest claim from the network-status concensus,
-and we count a helper the dirservers believe is crummy as "not worth
-trying" (equivalent to "not reachable under our current ReachableAddresses
-config") -- and then the above algorithm would end up adding good ones,
-but we'd go back to the originals if they resume being acceptable? That's
-an appealing design. I wonder if it will cause the typical Tor user to
-have a helper node list that comprises most of the network, though. I'm
-ok with this.
-
-> Another point you might want to keep in mind, is the possibility to
-> reuse the code in order to add a second layer helper node (meaning node
-> number two) to "protect" the first layer (node number one) helper nodes.
-> These nodes should be tied to each of the first layer nodes. E.g. there
-> is one helper node list, as described in your mail, for each of the
-> first layer nodes, following their create/destroy.
-
-True. Does that require us to add a fourth hop to our path length,
-since the first hop is from a limited set, the second hop is from a
-limited set, and the third hop might also be constrained because, say,
-we're asking for an unusual exit port?
-
-> Another of the things might worth adding to the to do list is
-> localization of server (helper) nodes. Making it possible to pick
-> countries/regions where you do (not) want your helper nodes located. (As
-> in "HelperNodesLocated us,!eu" etc.) I know this requires the use of
-> external data and may not be worth it, but it _could_ be integrated at
-> the directory servers only -- adding a list of node IP's and e.g. a
-> country/region code to the directory and thus reduce the overhead. (?)
-> Maybe extending the Family-term?
-
-I think we are heading towards doing path selection based on geography,
-but I don't have a good sense yet of how that will actually turn out --
-that is, with what mechanism Tor clients will learn the information they
-need. But this seems to be something that is orthogonal to the rest of
-this discussion, so I look forward to having somebody else solve it for
-us, and fitting it in when it's ready. :)
-
-> And I would like to keep an option to pick the first X helper nodes
-> myself and then let Tor extend this list if these nodes are down (like
-> EntryNodes in current code). Even if this opens up for some new types of
-> "relationship" attacks.
-
-Good idea. Here's how I'd like to name these:
-
-The "EntryNodes" config option is a list of seed helper nodes. When we
-read EntryNodes, any node listed in entrynodes but not in the current
-helper node list gets *pre*pended to the helper node list.
-
-The "NumEntryNodes" config option (currently called NumHelperNodes)
-specifies the number of up, reachable, good-enough helper nodes that
-will make up the pool of possible choices for first hop, counted from
-the front of the helper node list until we have enough.
-
-The "UseEntryNodes" config option (currently called UseHelperNodes)
-tells us to turn on all this helper node behavior. If you set EntryNodes,
-then this option is implied.
-
-The "StrictEntryNodes" config option, provided for backward compatibility
-and for debugging, means a) we replace the helper node list with the
-current EntryNodes list, and b) whenever we would do an operation that
-alters the helper node list, we don't. (Yes, this means that if all the
-helper nodes are down, we lose until we mark them up again. But this is
-how it behaves now.)
-
-> I am sure my next point has been asked before, but what about testing
-> the current speed of the connections when looking for new helper nodes,
-> not only testing the connectivity? I know this might contribute to a lot
-> of overhead in the network, but if this only occur e.g. when using
-> helper nodes as a Hidden Service it might not have that large an impact,
-> but could help availability for the services?
-
-If we're just going to be testing them when we're first picking them,
-then it seems we can do the same thing by letting the directory servers
-test them. This has the added benefit that all the (behaving) clients
-use the same data, so they don't end up partitioned by a node that
-(for example) performs selectively for his victims.
-
-Another idea would be to periodically keep track of what speeds you get
-through your helpers, and make decisions from this. The reason we haven't
-done this yet is because there are a lot of variables -- perhaps the
-web site is slow, perhaps some other node in the path is slow, perhaps
-your local network is slow briefly, perhaps you got unlucky, etc. I
-believe that over time (assuming the user has roughly the same browsing
-habits) all of these would average out and you'd get a usable answer,
-but I don't have a good sense of how long it would take to converge,
-so I don't know whether this would be worthwhile.
-
-> BTW. I feel confortable with all the terms helper/entry/contact nodes,
-> but I think you (the developers) should just pick one and stay with it
-> to avoid confusion.
-
-I think I'm going to try to co-opt the term 'Entry' node for this
-purpose. We're going to have to keep referring to helper nodes for the
-research community for a while though, so they realize that Tor does
-more than just let users ask for certain entry nodes.
-
-
-
-============================================================
-Some stuff that worries me about entry guards. 2006 Jun, Nickm.
-
-1. It is unlikely for two users to have the same set of entry guards.
-
-2. Observing a user is sufficient to learn its entry guards.
-
-3. So, as we move around, we leak our
diff --git a/doc/socks-extensions.txt b/doc/socks-extensions.txt
index 8040a8b03f..7022af14fc 100644
--- a/doc/socks-extensions.txt
+++ b/doc/socks-extensions.txt
@@ -46,12 +46,6 @@ Tor's extensions to the SOCKS protocol
(We support RESOLVE in SOCKS4 too, even though it is unnecessary.)
- For SOCKS5 only, we support reverse resolution with a new command value,
- "RESOLVE_PTR". In response to a "RESOLVE_PTR" SOCKS5 command with an IPv4
- address as its target, Tor attempts to find the canonical hostname for that
- IPv4 record, and returns it in the "server bound address" portion of the
- reply. (This was not supported before Tor 0.1.2.2-alpha)
-
3. HTTP-resistance
Tor checks the first byte of each SOCKS request to see whether it looks
diff --git a/doc/tor-osx-dmg-creation.txt b/doc/tor-osx-dmg-creation.txt
index c7db886b4a..95a0414f89 100644
--- a/doc/tor-osx-dmg-creation.txt
+++ b/doc/tor-osx-dmg-creation.txt
@@ -1,6 +1,3 @@
-## Instructions for building the official dmgs for OSX.
-##
-
The following steps are the exact steps used to produce the "official"
OSX builds of tor
diff --git a/doc/tor-rpm-creation.txt b/doc/tor-rpm-creation.txt
index 9597cca5f6..9af2556b79 100644
--- a/doc/tor-rpm-creation.txt
+++ b/doc/tor-rpm-creation.txt
@@ -1,15 +1,13 @@
-## Instructions for building the official rpms.
-##
-These are instructions for building Tor binaries in the rpm format on
+These are instructions for building Tor binaries in the rpm format on
various cpu architectures and operating systems. Each rpm will require
-glibc on the target system. It is believed that any rpm-based linux
-distribution should have semi-current glibc installed by default.
-If you run into a distribution that does not work with glibc, or does
-not contain it, please let us know the details.
+glibc on the target system. It is believed that any rpm-based linux
+distribution should have semi-current glibc installed by default.
+If you run into a distribution that does not work with glibc, or does
+not contain it, please let us know the details.
-These are the exact steps used to build the official rpms of Tor.
+These are the exact same steps used to build the official rpms of Tor.
-If you wish to further tune Tor binaries in rpm format beyond this list,
+If you wish to further tune Tor binaries in rpm format beyond this list,
see the GCC doc page for further options:
http://gcc.gnu.org/onlinedocs/gcc-4.0.2/gcc/
@@ -25,13 +23,14 @@ this:
%define target_cpu i386
%define target_os linux
+
The three parameters: target, target_cpu, and target_os are used
throughout the "make dist-rpm" process. They control the parameters
-passed to "configure" and the final tuning of the binaries produced.
+passed to "configure" and the final tuning of the binaries produced.
The default settings, as shown above, create binaries for the widest
-range of Intel x86 or x86-compatible architectures.
+range of Intel x86 or compatible architectures.
-The parameters can be set as follows:
+The paramters can be set as follows:
The "target" parameter:
This should be "gnu", "redhat", or the short name of your linux distribution.
@@ -40,6 +39,7 @@ Other possibilities are "mandrake" or "suse". This is passed to
Therefore, this "target" parameter must be a valid OS for "configure" as
well.
+
The "target_cpu" parameter:
This parameter controls the optimization and tuning of your binaries via
gcc and "configure". This parameter is passed to gcc via the -mtune= or
@@ -49,7 +49,10 @@ through the --host, --build, and --target parameters. Therefore, this
few common options for this parameter may be "athlon64, i686, pentium4" or
others.
+
The "target_os" parameter:
This parameter controls the target operating system. Normally, this is
only "linux". If you wish to build rpms for a non-linux operating
system, you can replace "linux" with your operating system.
+
+
diff --git a/doc/tor-spec-udp.txt b/doc/tor-spec-udp.txt
index 9e4966c8c4..59d05342c0 100644
--- a/doc/tor-spec-udp.txt
+++ b/doc/tor-spec-udp.txt
@@ -383,32 +383,5 @@ Other sections:
What changes need to happen to each node's exit policy to support this? -RD
-Switching to UDP means managing the queues of incoming packets better,
-so we don't miss packets. How does this interact with doing large public
-key operations (handshakes) in the same thread?
-========================================================================
-COMMENTS
-========================================================================
-[16 May 2006]
-
-I don't favor this approach; it makes packet traffic partitioned from
-stream traffic end-to-end. The architecture I'd like to see is:
-
- A *All* Tor-to-Tor traffic is UDP/DTLS, unless we need to fall back on
- TCP/TLS for firewall penetration or something. (This also gives us an
- upgrade path for routing through legacy servers.)
-
- B Stream traffic is handled with end-to-end per-stream acks/naks and
- retries. On failure, the data is retransmitted in a new RELAY_DATA cell;
- a cell isn't retransmitted.
-
-We'll need to do A anyway, to fix our behavior on packet-loss. Once we've
-done so, B is more or less inevitable, and we can support end-to-end UDP
-traffic "for free".
-
-(Also, there are some details that this draft spec doesn't address. For
-example, what happens when a UDP packet doesn't fit in a single cell?)
-
--NM
diff --git a/doc/tor-spec-v0.txt b/doc/tor-spec-v0.txt
deleted file mode 100644
index d64647d7d8..0000000000
--- a/doc/tor-spec-v0.txt
+++ /dev/null
@@ -1,734 +0,0 @@
-$Id$
-
- Tor Protocol Specification
-
- Roger Dingledine
- Nick Mathewson
-
-Note: This document specifies Tor as currently implemented in versions
-0.1.2.1-alpha and earlier. Current protocol designs are described in
-tor-spec.txt.
-
-0. Preliminaries
-
-0.1. Notation and encoding
-
- PK -- a public key.
- SK -- a private key.
- K -- a key for a symmetric cypher.
-
- a|b -- concatenation of 'a' and 'b'.
-
- [A0 B1 C2] -- a three-byte sequence, containing the bytes with
- hexadecimal values A0, B1, and C2, in that order.
-
- All numeric values are encoded in network (big-endian) order.
-
- H(m) -- a cryptographic hash of m.
-
-0.2. Security parameters
-
- Tor uses a stream cipher, a public-key cipher, the Diffie-Hellman
- protocol, and a hash function.
-
- KEY_LEN -- the length of the stream cipher's key, in bytes.
-
- PK_ENC_LEN -- the length of a public-key encrypted message, in bytes.
- PK_PAD_LEN -- the number of bytes added in padding for public-key
- encryption, in bytes. (The largest number of bytes that can be encrypted
- in a single public-key operation is therefore PK_ENC_LEN-PK_PAD_LEN.)
-
- DH_LEN -- the number of bytes used to represent a member of the
- Diffie-Hellman group.
- DH_SEC_LEN -- the number of bytes used in a Diffie-Hellman private key (x).
-
- HASH_LEN -- the length of the hash function's output, in bytes.
-
- CELL_LEN -- The length of a Tor cell, in bytes.
-
-0.3. Ciphers
-
- For a stream cipher, we use 128-bit AES in counter mode, with an IV of all
- 0 bytes.
-
- For a public-key cipher, we use RSA with 1024-bit keys and a fixed
- exponent of 65537. We use OAEP padding, with SHA-1 as its digest
- function. (For OAEP padding, see
- ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf)
-
- For Diffie-Hellman, we use a generator (g) of 2. For the modulus (p), we
- use the 1024-bit safe prime from rfc2409, (section 6.2) whose hex
- representation is:
-
- "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
- "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
- "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
- "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
- "49286651ECE65381FFFFFFFFFFFFFFFF"
-
- As an optimization, implementations SHOULD choose DH private keys (x) of
- 320 bits. Implementations that do this MUST never use any DH key more
- than once.
-
- For a hash function, we use SHA-1.
-
- KEY_LEN=16.
- DH_LEN=128; DH_GROUP_LEN=40.
- PK_ENC_LEN=128; PK_PAD_LEN=42.
- HASH_LEN=20.
-
- When we refer to "the hash of a public key", we mean the SHA-1 hash of the
- DER encoding of an ASN.1 RSA public key (as specified in PKCS.1).
-
- All "random" values should be generated with a cryptographically strong
- random number generator, unless otherwise noted.
-
- The "hybrid encryption" of a byte sequence M with a public key PK is
- computed as follows:
- 1. If M is less than PK_ENC_LEN-PK_PAD_LEN, pad and encrypt M with PK.
- 2. Otherwise, generate a KEY_LEN byte random key K.
- Let M1 = the first PK_ENC_LEN-PK_PAD_LEN-KEY_LEN bytes of M,
- and let M2 = the rest of M.
- Pad and encrypt K|M1 with PK. Encrypt M2 with our stream cipher,
- using the key K. Concatenate these encrypted values.
- [XXX Note that this "hybrid encryption" approach does not prevent
- an attacker from adding or removing bytes to the end of M. It also
- allows attackers to modify the bytes not covered by the OAEP --
- see Goldberg's PET2006 paper for details. We will add a MAC to this
- scheme one day. -RD]
-
-0.4. Other parameter values
-
- CELL_LEN=512
-
-1. System overview
-
- Tor is a distributed overlay network designed to anonymize
- low-latency TCP-based applications such as web browsing, secure shell,
- and instant messaging. Clients choose a path through the network and
- build a ``circuit'', in which each node (or ``onion router'' or ``OR'')
- in the path knows its predecessor and successor, but no other nodes in
- the circuit. Traffic flowing down the circuit is sent in fixed-size
- ``cells'', which are unwrapped by a symmetric key at each node (like
- the layers of an onion) and relayed downstream.
-
-2. Connections
-
- There are two ways to connect to an onion router (OR). The first is
- as an onion proxy (OP), which allows the OP to authenticate the OR
- without authenticating itself. The second is as another OR, which
- allows mutual authentication.
-
- Tor uses TLS for link encryption. All implementations MUST support
- the TLS ciphersuite "TLS_EDH_RSA_WITH_DES_192_CBC3_SHA", and SHOULD
- support "TLS_DHE_RSA_WITH_AES_128_CBC_SHA" if it is available.
- Implementations MAY support other ciphersuites, but MUST NOT
- support any suite without ephemeral keys, symmetric keys of at
- least KEY_LEN bits, and digests of at least HASH_LEN bits.
-
- An OP or OR always sends a two-certificate chain, consisting of a
- certificate using a short-term connection key and a second, self-
- signed certificate containing the OR's identity key. The commonName of the
- first certificate is the OR's nickname, and the commonName of the second
- certificate is the OR's nickname, followed by a space and the string
- "<identity>".
-
- All parties receiving certificates must confirm that the identity key is
- as expected. (When initiating a connection, the expected identity key is
- the one given in the directory; when creating a connection because of an
- EXTEND cell, the expected identity key is the one given in the cell.) If
- the key is not as expected, the party must close the connection.
-
- All parties SHOULD reject connections to or from ORs that have malformed
- or missing certificates. ORs MAY accept or reject connections from OPs
- with malformed or missing certificates.
-
- Once a TLS connection is established, the two sides send cells
- (specified below) to one another. Cells are sent serially. All
- cells are CELL_LEN bytes long. Cells may be sent embedded in TLS
- records of any size or divided across TLS records, but the framing
- of TLS records MUST NOT leak information about the type or contents
- of the cells.
-
- TLS connections are not permanent. An OP or an OR may close a
- connection to an OR if there are no circuits running over the
- connection, and an amount of time (KeepalivePeriod, defaults to 5
- minutes) has passed.
-
- (As an exception, directory servers may try to stay connected to all of
- the ORs -- though this will be phased out for the Tor 0.1.2.x release.)
-
-3. Cell Packet format
-
- The basic unit of communication for onion routers and onion
- proxies is a fixed-width "cell". Each cell contains the following
- fields:
-
- CircID [2 bytes]
- Command [1 byte]
- Payload (padded with 0 bytes) [CELL_LEN-3 bytes]
- [Total size: CELL_LEN bytes]
-
- The CircID field determines which circuit, if any, the cell is
- associated with.
-
- The 'Command' field holds one of the following values:
- 0 -- PADDING (Padding) (See Sec 6.2)
- 1 -- CREATE (Create a circuit) (See Sec 4.1)
- 2 -- CREATED (Acknowledge create) (See Sec 4.1)
- 3 -- RELAY (End-to-end data) (See Sec 4.5 and 5)
- 4 -- DESTROY (Stop using a circuit) (See Sec 4.4)
- 5 -- CREATE_FAST (Create a circuit, no PK) (See Sec 4.1)
- 6 -- CREATED_FAST (Circuit created, no PK) (See Sec 4.1)
- 7 -- HELLO (Introduce the OR) (See Sec 7.1)
-
- The interpretation of 'Payload' depends on the type of the cell.
- PADDING: Payload is unused.
- CREATE: Payload contains the handshake challenge.
- CREATED: Payload contains the handshake response.
- RELAY: Payload contains the relay header and relay body.
- DESTROY: Payload contains a reason for closing the circuit.
- (see 4.4)
- Upon receiving any other value for the command field, an OR must
- drop the cell.
-
- The payload is padded with 0 bytes.
-
- PADDING cells are currently used to implement connection keepalive.
- If there is no other traffic, ORs and OPs send one another a PADDING
- cell every few minutes.
-
- CREATE, CREATED, and DESTROY cells are used to manage circuits;
- see section 4 below.
-
- RELAY cells are used to send commands and data along a circuit; see
- section 5 below.
-
- HELLO cells are used to introduce parameters and characteristics of
- Tor clients and servers when connections are established.
-
-4. Circuit management
-
-4.1. CREATE and CREATED cells
-
- Users set up circuits incrementally, one hop at a time. To create a
- new circuit, OPs send a CREATE cell to the first node, with the
- first half of the DH handshake; that node responds with a CREATED
- cell with the second half of the DH handshake plus the first 20 bytes
- of derivative key data (see section 4.2). To extend a circuit past
- the first hop, the OP sends an EXTEND relay cell (see section 5)
- which instructs the last node in the circuit to send a CREATE cell
- to extend the circuit.
-
- The payload for a CREATE cell is an 'onion skin', which consists
- of the first step of the DH handshake data (also known as g^x).
- This value is hybrid-encrypted (see 0.3) to Bob's public key, giving
- an onion-skin of:
- PK-encrypted:
- Padding padding [PK_PAD_LEN bytes]
- Symmetric key [KEY_LEN bytes]
- First part of g^x [PK_ENC_LEN-PK_PAD_LEN-KEY_LEN bytes]
- Symmetrically encrypted:
- Second part of g^x [DH_LEN-(PK_ENC_LEN-PK_PAD_LEN-KEY_LEN)
- bytes]
-
- The relay payload for an EXTEND relay cell consists of:
- Address [4 bytes]
- Port [2 bytes]
- Onion skin [DH_LEN+KEY_LEN+PK_PAD_LEN bytes]
- Identity fingerprint [HASH_LEN bytes]
-
- The port and address field denote the IPV4 address and port of the next
- onion router in the circuit; the public key hash is the hash of the PKCS#1
- ASN1 encoding of the next onion router's identity (signing) key. (See 0.3
- above.) (Including this hash allows the extending OR verify that it is
- indeed connected to the correct target OR, and prevents certain
- man-in-the-middle attacks.)
-
- The payload for a CREATED cell, or the relay payload for an
- EXTENDED cell, contains:
- DH data (g^y) [DH_LEN bytes]
- Derivative key data (KH) [HASH_LEN bytes] <see 4.2 below>
-
- The CircID for a CREATE cell is an arbitrarily chosen 2-byte integer,
- selected by the node (OP or OR) that sends the CREATE cell. To prevent
- CircID collisions, when one OR sends a CREATE cell to another, it chooses
- from only one half of the possible values based on the ORs' public
- identity keys: if the sending OR has a lower key, it chooses a CircID with
- an MSB of 0; otherwise, it chooses a CircID with an MSB of 1.
-
- Public keys are compared numerically by modulus.
-
- As usual with DH, x and y MUST be generated randomly.
-
-4.1.1. CREATE_FAST/CREATED_FAST cells
-
- When initializing the first hop of a circuit, the OP has already
- established the OR's identity and negotiated a secret key using TLS.
- Because of this, it is not always necessary for the OP to perform the
- public key operations to create a circuit. In this case, the
- OP MAY send a CREATE_FAST cell instead of a CREATE cell for the first
- hop only. The OR responds with a CREATED_FAST cell, and the circuit is
- created.
-
- A CREATE_FAST cell contains:
-
- Key material (X) [HASH_LEN bytes]
-
- A CREATED_FAST cell contains:
-
- Key material (Y) [HASH_LEN bytes]
- Derivative key data [HASH_LEN bytes] (See 4.2 below)
-
- The values of X and Y must be generated randomly.
-
- [Versions of Tor before 0.1.0.6-rc did not support these cell types;
- clients should not send CREATE_FAST cells to older Tor servers.]
-
-4.2. Setting circuit keys
-
- Once the handshake between the OP and an OR is completed, both can
- now calculate g^xy with ordinary DH. Before computing g^xy, both client
- and server MUST verify that the received g^x or g^y value is not degenerate;
- that is, it must be strictly greater than 1 and strictly less than p-1
- where p is the DH modulus. Implementations MUST NOT complete a handshake
- with degenerate keys. Implementations MUST NOT discard other "weak"
- g^x values.
-
- (Discarding degenerate keys is critical for security; if bad keys
- are not discarded, an attacker can substitute the server's CREATED
- cell's g^y with 0 or 1, thus creating a known g^xy and impersonating
- the server. Discarding other keys may allow attacks to learn bits of
- the private key.)
-
- (The mainline Tor implementation, in the 0.1.1.x-alpha series, discarded
- all g^x values less than 2^24, greater than p-2^24, or having more than
- 1024-16 identical bits. This served no useful purpose, and we stopped.)
-
- If CREATE or EXTEND is used to extend a circuit, the client and server
- base their key material on K0=g^xy, represented as a big-endian unsigned
- integer.
-
- If CREATE_FAST is used, the client and server base their key material on
- K0=X|Y.
-
- From the base key material K0, they compute KEY_LEN*2+HASH_LEN*3 bytes of
- derivative key data as
- K = H(K0 | [00]) | H(K0 | [01]) | H(K0 | [02]) | ...
-
- The first HASH_LEN bytes of K form KH; the next HASH_LEN form the forward
- digest Df; the next HASH_LEN 41-60 form the backward digest Db; the next
- KEY_LEN 61-76 form Kf, and the final KEY_LEN form Kb. Excess bytes from K
- are discarded.
-
- KH is used in the handshake response to demonstrate knowledge of the
- computed shared key. Df is used to seed the integrity-checking hash
- for the stream of data going from the OP to the OR, and Db seeds the
- integrity-checking hash for the data stream from the OR to the OP. Kf
- is used to encrypt the stream of data going from the OP to the OR, and
- Kb is used to encrypt the stream of data going from the OR to the OP.
-
-4.3. Creating circuits
-
- When creating a circuit through the network, the circuit creator
- (OP) performs the following steps:
-
- 1. Choose an onion router as an exit node (R_N), such that the onion
- router's exit policy includes at least one pending stream that
- needs a circuit (if there are any).
-
- 2. Choose a chain of (N-1) onion routers
- (R_1...R_N-1) to constitute the path, such that no router
- appears in the path twice.
-
- 3. If not already connected to the first router in the chain,
- open a new connection to that router.
-
- 4. Choose a circID not already in use on the connection with the
- first router in the chain; send a CREATE cell along the
- connection, to be received by the first onion router.
-
- 5. Wait until a CREATED cell is received; finish the handshake
- and extract the forward key Kf_1 and the backward key Kb_1.
-
- 6. For each subsequent onion router R (R_2 through R_N), extend
- the circuit to R.
-
- To extend the circuit by a single onion router R_M, the OP performs
- these steps:
-
- 1. Create an onion skin, encrypted to R_M's public key.
-
- 2. Send the onion skin in a relay EXTEND cell along
- the circuit (see section 5).
-
- 3. When a relay EXTENDED cell is received, verify KH, and
- calculate the shared keys. The circuit is now extended.
-
- When an onion router receives an EXTEND relay cell, it sends a CREATE
- cell to the next onion router, with the enclosed onion skin as its
- payload. The initiating onion router chooses some circID not yet
- used on the connection between the two onion routers. (But see
- section 4.1. above, concerning choosing circIDs based on
- lexicographic order of nicknames.)
-
- When an onion router receives a CREATE cell, if it already has a
- circuit on the given connection with the given circID, it drops the
- cell. Otherwise, after receiving the CREATE cell, it completes the
- DH handshake, and replies with a CREATED cell. Upon receiving a
- CREATED cell, an onion router packs it payload into an EXTENDED relay
- cell (see section 5), and sends that cell up the circuit. Upon
- receiving the EXTENDED relay cell, the OP can retrieve g^y.
-
- (As an optimization, OR implementations may delay processing onions
- until a break in traffic allows time to do so without harming
- network latency too greatly.)
-
-4.4. Tearing down circuits
-
- Circuits are torn down when an unrecoverable error occurs along
- the circuit, or when all streams on a circuit are closed and the
- circuit's intended lifetime is over. Circuits may be torn down
- either completely or hop-by-hop.
-
- To tear down a circuit completely, an OR or OP sends a DESTROY
- cell to the adjacent nodes on that circuit, using the appropriate
- direction's circID.
-
- Upon receiving an outgoing DESTROY cell, an OR frees resources
- associated with the corresponding circuit. If it's not the end of
- the circuit, it sends a DESTROY cell for that circuit to the next OR
- in the circuit. If the node is the end of the circuit, then it tears
- down any associated edge connections (see section 5.1).
-
- After a DESTROY cell has been processed, an OR ignores all data or
- destroy cells for the corresponding circuit.
-
- To tear down part of a circuit, the OP may send a RELAY_TRUNCATE cell
- signaling a given OR (Stream ID zero). That OR sends a DESTROY
- cell to the next node in the circuit, and replies to the OP with a
- RELAY_TRUNCATED cell.
-
- When an unrecoverable error occurs along one connection in a
- circuit, the nodes on either side of the connection should, if they
- are able, act as follows: the node closer to the OP should send a
- RELAY_TRUNCATED cell towards the OP; the node farther from the OP
- should send a DESTROY cell down the circuit.
-
- The payload of a RELAY_TRUNCATED or DESTROY cell contains a single octet,
- describing why the circuit is being closed or truncated. When sending a
- TRUNCATED or DESTROY cell because of another TRUNCATED or DESTROY cell,
- the error code should be propagated. The origin of a circuit always sets
- this error code to 0, to avoid leaking its version.
-
- The error codes are:
- 0 -- NONE (No reason given.)
- 1 -- PROTOCOL (Tor protocol violation.)
- 2 -- INTERNAL (Internal error.)
- 3 -- REQUESTED (A client sent a TRUNCATE command.)
- 4 -- HIBERNATING (Not currently operating; trying to save bandwidth.)
- 5 -- RESOURCELIMIT (Out of memory, sockets, or circuit IDs.)
- 6 -- CONNECTFAILED (Unable to reach server.)
- 7 -- OR_IDENTITY (Connected to server, but its OR identity was not
- as expected.)
- 8 -- OR_CONN_CLOSED (The OR connection that was carrying this circuit
- died.)
-
- [Versions of Tor prior to 0.1.0.11 didn't send reasons; implementations
- MUST accept empty TRUNCATED and DESTROY cells.]
-
-4.5. Routing relay cells
-
- When an OR receives a RELAY cell, it checks the cell's circID and
- determines whether it has a corresponding circuit along that
- connection. If not, the OR drops the RELAY cell.
-
- Otherwise, if the OR is not at the OP edge of the circuit (that is,
- either an 'exit node' or a non-edge node), it de/encrypts the payload
- with the stream cipher, as follows:
- 'Forward' relay cell (same direction as CREATE):
- Use Kf as key; decrypt.
- 'Back' relay cell (opposite direction from CREATE):
- Use Kb as key; encrypt.
- Note that in counter mode, decrypt and encrypt are the same operation.
-
- The OR then decides whether it recognizes the relay cell, by
- inspecting the payload as described in section 5.1 below. If the OR
- recognizes the cell, it processes the contents of the relay cell.
- Otherwise, it passes the decrypted relay cell along the circuit if
- the circuit continues. If the OR at the end of the circuit
- encounters an unrecognized relay cell, an error has occurred: the OR
- sends a DESTROY cell to tear down the circuit.
-
- When a relay cell arrives at an OP, the OP decrypts the payload
- with the stream cipher as follows:
- OP receives data cell:
- For I=N...1,
- Decrypt with Kb_I. If the payload is recognized (see
- section 5.1), then stop and process the payload.
-
- For more information, see section 5 below.
-
-5. Application connections and stream management
-
-5.1. Relay cells
-
- Within a circuit, the OP and the exit node use the contents of
- RELAY packets to tunnel end-to-end commands and TCP connections
- ("Streams") across circuits. End-to-end commands can be initiated
- by either edge; streams are initiated by the OP.
-
- The payload of each unencrypted RELAY cell consists of:
- Relay command [1 byte]
- 'Recognized' [2 bytes]
- StreamID [2 bytes]
- Digest [4 bytes]
- Length [2 bytes]
- Data [CELL_LEN-14 bytes]
-
- The relay commands are:
- 1 -- RELAY_BEGIN [forward]
- 2 -- RELAY_DATA [forward or backward]
- 3 -- RELAY_END [forward or backward]
- 4 -- RELAY_CONNECTED [backward]
- 5 -- RELAY_SENDME [forward or backward]
- 6 -- RELAY_EXTEND [forward]
- 7 -- RELAY_EXTENDED [backward]
- 8 -- RELAY_TRUNCATE [forward]
- 9 -- RELAY_TRUNCATED [backward]
- 10 -- RELAY_DROP [forward or backward]
- 11 -- RELAY_RESOLVE [forward]
- 12 -- RELAY_RESOLVED [backward]
-
- Commands labelled as "forward" must only be sent by the originator
- of the circuit. Commands labelled as "backward" must only be sent by
- other nodes in the circuit back to the originator. Commands marked
- as either can be sent either by the originator or other nodes.
-
- The 'recognized' field in any unencrypted relay payload is always set
- to zero; the 'digest' field is computed as the first four bytes of
- the running digest of all the bytes that have been destined for
- this hop of the circuit or originated from this hop of the circuit,
- seeded from Df or Db respectively (obtained in section 4.2 above),
- and including this RELAY cell's entire payload (taken with the digest
- field set to zero).
-
- When the 'recognized' field of a RELAY cell is zero, and the digest
- is correct, the cell is considered "recognized" for the purposes of
- decryption (see section 4.5 above).
-
- (The digest does not include any bytes from relay cells that do
- not start or end at this hop of the circuit. That is, it does not
- include forwarded data. Therefore if 'recognized' is zero but the
- digest does not match, the running digest at that node should
- not be updated, and the cell should be forwarded on.)
-
- All RELAY cells pertaining to the same tunneled stream have the
- same stream ID. StreamIDs are chosen arbitrarily by the OP. RELAY
- cells that affect the entire circuit rather than a particular
- stream use a StreamID of zero.
-
- The 'Length' field of a relay cell contains the number of bytes in
- the relay payload which contain real payload data. The remainder of
- the payload is padded with NUL bytes.
-
- If the RELAY cell is recognized but the relay command is not
- understood, the cell must be dropped and ignored. Its contents
- still count with respect to the digests, though. [Before
- 0.1.1.10, Tor closed circuits when it received an unknown relay
- command. Perhaps this will be more forward-compatible. -RD]
-
-5.2. Opening streams and transferring data
-
- To open a new anonymized TCP connection, the OP chooses an open
- circuit to an exit that may be able to connect to the destination
- address, selects an arbitrary StreamID not yet used on that circuit,
- and constructs a RELAY_BEGIN cell with a payload encoding the address
- and port of the destination host. The payload format is:
-
- ADDRESS | ':' | PORT | [00]
-
- where ADDRESS can be a DNS hostname, or an IPv4 address in
- dotted-quad format, or an IPv6 address surrounded by square brackets;
- and where PORT is encoded in decimal.
-
- [What is the [00] for? -NM]
- [It's so the payload is easy to parse out with string funcs -RD]
-
- Upon receiving this cell, the exit node resolves the address as
- necessary, and opens a new TCP connection to the target port. If the
- address cannot be resolved, or a connection can't be established, the
- exit node replies with a RELAY_END cell. (See 5.4 below.)
- Otherwise, the exit node replies with a RELAY_CONNECTED cell, whose
- payload is in one of the following formats:
- The IPv4 address to which the connection was made [4 octets]
- A number of seconds (TTL) for which the address may be cached [4 octets]
- or
- Four zero-valued octets [4 octets]
- An address type (6) [1 octet]
- The IPv6 address to which the connection was made [16 octets]
- A number of seconds (TTL) for which the address may be cached [4 octets]
- [XXXX Versions of Tor before 0.1.1.6 ignore and do not generate the TTL
- field. No version of Tor currently generates the IPv6 format.
-
- Tor servers before 0.1.2.0 set the TTL field to a fixed value. Later
- versions set the TTL to the last value seen from a DNS server, and expire
- their own cached entries after a fixed interval. This prevents certain
- attacks.]
-
- The OP waits for a RELAY_CONNECTED cell before sending any data.
- Once a connection has been established, the OP and exit node
- package stream data in RELAY_DATA cells, and upon receiving such
- cells, echo their contents to the corresponding TCP stream.
- RELAY_DATA cells sent to unrecognized streams are dropped.
-
- Relay RELAY_DROP cells are long-range dummies; upon receiving such
- a cell, the OR or OP must drop it.
-
-5.3. Closing streams
-
- When an anonymized TCP connection is closed, or an edge node
- encounters error on any stream, it sends a 'RELAY_END' cell along the
- circuit (if possible) and closes the TCP connection immediately. If
- an edge node receives a 'RELAY_END' cell for any stream, it closes
- the TCP connection completely, and sends nothing more along the
- circuit for that stream.
-
- The payload of a RELAY_END cell begins with a single 'reason' byte to
- describe why the stream is closing, plus optional data (depending on
- the reason.) The values are:
-
- 1 -- REASON_MISC (catch-all for unlisted reasons)
- 2 -- REASON_RESOLVEFAILED (couldn't look up hostname)
- 3 -- REASON_CONNECTREFUSED (remote host refused connection) [*]
- 4 -- REASON_EXITPOLICY (OR refuses to connect to host or port)
- 5 -- REASON_DESTROY (Circuit is being destroyed)
- 6 -- REASON_DONE (Anonymized TCP connection was closed)
- 7 -- REASON_TIMEOUT (Connection timed out, or OR timed out
- while connecting)
- 8 -- (unallocated) [**]
- 9 -- REASON_HIBERNATING (OR is temporarily hibernating)
- 10 -- REASON_INTERNAL (Internal error at the OR)
- 11 -- REASON_RESOURCELIMIT (OR has no resources to fulfill request)
- 12 -- REASON_CONNRESET (Connection was unexpectedly reset)
- 13 -- REASON_TORPROTOCOL (Sent when closing connection because of
- Tor protocol violations.)
-
- (With REASON_EXITPOLICY, the 4-byte IPv4 address or 16-byte IPv6 address
- forms the optional data; no other reason currently has extra data.
- As of 0.1.1.6, the body also contains a 4-byte TTL.)
-
- OPs and ORs MUST accept reasons not on the above list, since future
- versions of Tor may provide more fine-grained reasons.
-
- [*] Older versions of Tor also send this reason when connections are
- reset.
- [**] Due to a bug in versions of Tor through 0095, error reason 8 must
- remain allocated until that version is obsolete.
-
- --- [The rest of this section describes unimplemented functionality.]
-
- Because TCP connections can be half-open, we follow an equivalent
- to TCP's FIN/FIN-ACK/ACK protocol to close streams.
-
- An exit connection can have a TCP stream in one of three states:
- 'OPEN', 'DONE_PACKAGING', and 'DONE_DELIVERING'. For the purposes
- of modeling transitions, we treat 'CLOSED' as a fourth state,
- although connections in this state are not, in fact, tracked by the
- onion router.
-
- A stream begins in the 'OPEN' state. Upon receiving a 'FIN' from
- the corresponding TCP connection, the edge node sends a 'RELAY_FIN'
- cell along the circuit and changes its state to 'DONE_PACKAGING'.
- Upon receiving a 'RELAY_FIN' cell, an edge node sends a 'FIN' to
- the corresponding TCP connection (e.g., by calling
- shutdown(SHUT_WR)) and changing its state to 'DONE_DELIVERING'.
-
- When a stream in already in 'DONE_DELIVERING' receives a 'FIN', it
- also sends a 'RELAY_FIN' along the circuit, and changes its state
- to 'CLOSED'. When a stream already in 'DONE_PACKAGING' receives a
- 'RELAY_FIN' cell, it sends a 'FIN' and changes its state to
- 'CLOSED'.
-
- If an edge node encounters an error on any stream, it sends a
- 'RELAY_END' cell (if possible) and closes the stream immediately.
-
-5.4. Remote hostname lookup
-
- To find the address associated with a hostname, the OP sends a
- RELAY_RESOLVE cell containing the hostname to be resolved. (For a reverse
- lookup, the OP sends a RELAY_RESOLVE cell containing an in-addr.arpa
- address.) The OR replies with a RELAY_RESOLVED cell containing a status
- byte, and any number of answers. Each answer is of the form:
- Type (1 octet)
- Length (1 octet)
- Value (variable-width)
- TTL (4 octets)
- "Length" is the length of the Value field.
- "Type" is one of:
- 0x00 -- Hostname
- 0x04 -- IPv4 address
- 0x06 -- IPv6 address
- 0xF0 -- Error, transient
- 0xF1 -- Error, nontransient
-
- If any answer has a type of 'Error', then no other answer may be given.
-
- The RELAY_RESOLVE cell must use a nonzero, distinct streamID; the
- corresponding RELAY_RESOLVED cell must use the same streamID. No stream
- is actually created by the OR when resolving the name.
-
-6. Flow control
-
-6.1. Link throttling
-
- Each node should do appropriate bandwidth throttling to keep its
- user happy.
-
- Communicants rely on TCP's default flow control to push back when they
- stop reading.
-
-6.2. Link padding
-
- Currently nodes are not required to do any sort of link padding or
- dummy traffic. Because strong attacks exist even with link padding,
- and because link padding greatly increases the bandwidth requirements
- for running a node, we plan to leave out link padding until this
- tradeoff is better understood.
-
-6.3. Circuit-level flow control
-
- To control a circuit's bandwidth usage, each OR keeps track of
- two 'windows', consisting of how many RELAY_DATA cells it is
- allowed to package for transmission, and how many RELAY_DATA cells
- it is willing to deliver to streams outside the network.
- Each 'window' value is initially set to 1000 data cells
- in each direction (cells that are not data cells do not affect
- the window). When an OR is willing to deliver more cells, it sends a
- RELAY_SENDME cell towards the OP, with Stream ID zero. When an OR
- receives a RELAY_SENDME cell with stream ID zero, it increments its
- packaging window.
-
- Each of these cells increments the corresponding window by 100.
-
- The OP behaves identically, except that it must track a packaging
- window and a delivery window for every OR in the circuit.
-
- An OR or OP sends cells to increment its delivery window when the
- corresponding window value falls under some threshold (900).
-
- If a packaging window reaches 0, the OR or OP stops reading from
- TCP connections for all streams on the corresponding circuit, and
- sends no more RELAY_DATA cells until receiving a RELAY_SENDME cell.
-[this stuff is badly worded; copy in the tor-design section -RD]
-
-6.4. Stream-level flow control
-
- Edge nodes use RELAY_SENDME cells to implement end-to-end flow
- control for individual connections across circuits. Similarly to
- circuit-level flow control, edge nodes begin with a window of cells
- (500) per stream, and increment the window by a fixed value (50)
- upon receiving a RELAY_SENDME cell. Edge nodes initiate RELAY_SENDME
- cells when both a) the window is <= 450, and b) there are less than
- ten cell payloads remaining to be flushed at that edge.
-
diff --git a/doc/tor-spec.txt b/doc/tor-spec.txt
index 61f5fd7f15..347397ce64 100644
--- a/doc/tor-spec.txt
+++ b/doc/tor-spec.txt
@@ -5,41 +5,25 @@ $Id$
Roger Dingledine
Nick Mathewson
-Note: This document aims to specify Tor as implemented in 0.1.2.1-alpha-dev
-and later. Future versions of Tor will implement improved protocols, and
-compatibility is not guaranteed.
-
-THIS DOCUMENT IS UNSTABLE. Right now, we're revising the protocol to remove
-a few long-standing limitations. For the most stable current version of the
-protocol, see tor-spec-v0.txt; current versions of Tor are backward-compatible.
-
-This specification is not a design document; most design criteria
-are not examined. For more information on why Tor acts as it does,
-see tor-design.pdf.
-
-TODO for v1 revision:
- - Fix onionskin handshake scheme to be more mainstream, less nutty.
- Can we just do
- E(HMAC(g^x), g^x) rather than just E(g^x) ?
- No, that has the same flaws as before. We should send
- E(g^x, C) with random C and expect g^y, HMAC_C(K=g^xy).
- Better ask Ian; probably Stephen too.
- - Versioned CREATE and friends
- - Length on CREATE and friends
- - Versioning on circuits
-
-TODO:
+Note: This is an attempt to specify Tor as currently implemented. Future
+versions of Tor will implement improved protocols, and compatibility is not
+guaranteed.
+
+This is not a design document; most design criteria are not examined. For
+more information on why Tor acts as it does, see tor-design.pdf.
+
+TODO: (very soon)
- REASON_CONNECTFAILED should include an IP.
- Copy prose from tor-design to make everything more readable.
- - Spec when we should rotate which keys (tls, link, etc)?
+when do we rotate which keys (tls, link, etc)?
0. Preliminaries
0.1. Notation and encoding
PK -- a public key.
- SK -- a private key.
- K -- a key for a symmetric cypher.
+ SK -- a private key
+ K -- a key for a symmetric cypher
a|b -- concatenation of 'a' and 'b'.
@@ -53,7 +37,7 @@ TODO:
0.2. Security parameters
Tor uses a stream cipher, a public-key cipher, the Diffie-Hellman
- protocol, and a hash function.
+ protocol, and and a hash function.
KEY_LEN -- the length of the stream cipher's key, in bytes.
@@ -68,8 +52,6 @@ TODO:
HASH_LEN -- the length of the hash function's output, in bytes.
- PAYLOAD_LEN -- The longest allowable cell payload, in bytes. (509)
-
CELL_LEN -- The length of a Tor cell, in bytes.
0.3. Ciphers
@@ -82,20 +64,18 @@ TODO:
function. (For OAEP padding, see
ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf)
- For Diffie-Hellman, we use a generator (g) of 2. For the modulus (p), we
- use the 1024-bit safe prime from rfc2409 section 6.2 whose hex
- representation is:
+ For Diffie-Hellman, we use a generator (g) of 2. For the modulus (p), the
+ 1024-bit safe prime from rfc2409, (section 6.2) whose hex representation
+ is:
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
"8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
"302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
"A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
"49286651ECE65381FFFFFFFFFFFFFFFF"
-
As an optimization, implementations SHOULD choose DH private keys (x) of
320 bits. Implementations that do this MUST never use any DH key more
than once.
- [May other implementations reuse their DH keys?? -RD]
For a hash function, we use SHA-1.
@@ -118,11 +98,8 @@ TODO:
and let M2 = the rest of M.
Pad and encrypt K|M1 with PK. Encrypt M2 with our stream cipher,
using the key K. Concatenate these encrypted values.
- [XXX Note that this "hybrid encryption" approach does not prevent
- an attacker from adding or removing bytes to the end of M. It also
- allows attackers to modify the bytes not covered by the OAEP --
- see Goldberg's PET2006 paper for details. We will add a MAC to this
- scheme one day. -RD]
+ (Note that this "hybrid encryption" approach does not prevent an attacker
+ from adding or removing bytes to the end of M.)
0.4. Other parameter values
@@ -130,7 +107,7 @@ TODO:
1. System overview
- Tor is a distributed overlay network designed to anonymize
+ Onion Routing is a distributed overlay network designed to anonymize
low-latency TCP-based applications such as web browsing, secure shell,
and instant messaging. Clients choose a path through the network and
build a ``circuit'', in which each node (or ``onion router'' or ``OR'')
@@ -139,23 +116,13 @@ TODO:
``cells'', which are unwrapped by a symmetric key at each node (like
the layers of an onion) and relayed downstream.
-1.1. Protocol Versioning
-
- The node-to-node TLS-based "OR connection" protocol and the multi-hop
- "circuit" protocol are versioned quasi-independently. (Certain versions
- of the circuit protocol may require a minimum version of the connection
- protocol to be used.)
-
- Version numbers are incremented for backward-incompatible protocol changes
- only. Backward-compatible changes are generally implemented by adding
- additional fields to existing structures; implementations MUST ignore
- fields they do not expect.
-
- Parties negotiate OR connection versions as described below in sections
- 4.1 and 4.2.
-
2. Connections
+ There are two ways to connect to an onion router (OR). The first is
+ as an onion proxy (OP), which allows the OP to authenticate the OR
+ without authenticating itself. The second is as another OR, which
+ allows mutual authentication.
+
Tor uses TLS for link encryption. All implementations MUST support
the TLS ciphersuite "TLS_EDH_RSA_WITH_DES_192_CBC3_SHA", and SHOULD
support "TLS_DHE_RSA_WITH_AES_128_CBC_SHA" if it is available.
@@ -163,25 +130,13 @@ TODO:
support any suite without ephemeral keys, symmetric keys of at
least KEY_LEN bits, and digests of at least HASH_LEN bits.
- Even though the connection protocol is identical, we think of the
- initiator as either an onion router (OR) if it is willing to relay
- traffic for other Tor users, or an onion proxy (OP) if it only handles
- local requests. Onion proxies SHOULD NOT provide long-term-trackable
- identifiers in their handshakes.
-
- The connection initiator always sends a two-certificate chain,
- consisting of a
+ An OP or OR always sends a two-certificate chain, consisting of a
certificate using a short-term connection key and a second, self-
signed certificate containing the OR's identity key. The commonName of the
first certificate is the OR's nickname, and the commonName of the second
certificate is the OR's nickname, followed by a space and the string
"<identity>".
- Implementations running 0.2.1.0-alpha-dev and earlier used an
- organizationName of "Tor" or "TOR". Current implementations (which
- support the version negotiation protocol in section 4.1) MUST NOT
- have either of these values for their organizationName.
-
All parties receiving certificates must confirm that the identity key is
as expected. (When initiating a connection, the expected identity key is
the one given in the directory; when creating a connection because of an
@@ -199,44 +154,36 @@ TODO:
of TLS records MUST NOT leak information about the type or contents
of the cells.
- TLS connections are not permanent. Either side may close a connection
- if there are no circuits running over it and an amount of time
- (KeepalivePeriod, defaults to 5 minutes) has passed.
+ TLS connections are not permanent. An OP or an OR may close a
+ connection to an OR if there are no circuits running over the
+ connection, and an amount of time (KeepalivePeriod, defaults to 5
+ minutes) has passed.
(As an exception, directory servers may try to stay connected to all of
- the ORs -- though this will be phased out for the Tor 0.1.2.x release.)
+ the ORs.)
3. Cell Packet format
The basic unit of communication for onion routers and onion
- proxies is a fixed-width "cell".
-
- On a version 0 connection, each cell contains the following
+ proxies is a fixed-width "cell". Each cell contains the following
fields:
CircID [2 bytes]
Command [1 byte]
- Payload (padded with 0 bytes) [PAYLOAD_LEN bytes]
-
- On a version 1 connection, each cell contains the following fields:
-
- CircID [3 bytes]
- Command [1 byte]
- Payload (padded with 0 bytes) [PAYLOAD_LEN bytes]
+ Payload (padded with 0 bytes) [CELL_LEN-3 bytes]
+ [Total size: CELL_LEN bytes]
The CircID field determines which circuit, if any, the cell is
associated with.
The 'Command' field holds one of the following values:
- 0 -- PADDING (Padding) (See Sec 7.2)
- 1 -- CREATE (Create a circuit) (See Sec 5.1)
- 2 -- CREATED (Acknowledge create) (See Sec 5.1)
- 3 -- RELAY (End-to-end data) (See Sec 5.5 and 6)
- 4 -- DESTROY (Stop using a circuit) (See Sec 5.4)
- 5 -- CREATE_FAST (Create a circuit, no PK) (See Sec 5.1)
- 6 -- CREATED_FAST (Circuit created, no PK) (See Sec 5.1)
- 7 -- VERSIONS (Negotiate versions) (See Sec 4.1)
- 8 -- NETINFO (Time and MITM-prevention) (See Sec 4.2)
+ 0 -- PADDING (Padding) (See Sec 6.2)
+ 1 -- CREATE (Create a circuit) (See Sec 4)
+ 2 -- CREATED (Acknowledge create) (See Sec 4)
+ 3 -- RELAY (End-to-end data) (See Sec 5)
+ 4 -- DESTROY (Stop using a circuit) (See Sec 4)
+ 5 -- CREATE_FAST (Create a circuit, no PK) (See sec 4)
+ 6 -- CREATED_FAST (Circtuit created, no PK) (See Sec 4)
The interpretation of 'Payload' depends on the type of the cell.
PADDING: Payload is unused.
@@ -244,10 +191,9 @@ TODO:
CREATED: Payload contains the handshake response.
RELAY: Payload contains the relay header and relay body.
DESTROY: Payload contains a reason for closing the circuit.
- (see 5.4)
+ (see 4.4)
Upon receiving any other value for the command field, an OR must
- drop the cell. [XXXX Versions prior to 0.1.0.?? logged a warning
- when dropping the cell; this is bad behavior. -NM]
+ drop the cell.
The payload is padded with 0 bytes.
@@ -261,81 +207,15 @@ TODO:
RELAY cells are used to send commands and data along a circuit; see
section 5 below.
- VERSIONS cells are used to introduce parameters and characteristics of
- Tor clients and servers when connections are established.
-
-4, Connection management
-
- Upon establishing a TLS connection, both parties immediately begin
- negotiating a connection protocol version and other connection parameters.
-
-4.1. VERSIONS cells
-
- When a Tor connection is established, both parties normally send a
- VERSIONS cell before sending any other cells. (But see below.)
-
- NumVersions [1 byte]
- Versions [NumVersions bytes]
-
- "Versions" is a sequence of NumVersions link connection protocol versions,
- each one byte long. Parties should list all of the versions which they
- are able and willing to support. Parties can only communicate if they
- have some connection protocol version in common.
-
- Version 0.1.2.0-alpha and earlier don't understand VERSIONS cells,
- and therefore don't support version negotiation. Thus, waiting until
- the other side has sent a VERSIONS cell won't work for these servers:
- if they send no cells back, it is impossible to tell whether they
- have sent a VERSIONS cell that has been stalled, or whether they have
- dropped our own VERSIONS cell as unrecognized. Thus, immediately after
- a TLS connection has been established, the parties check whether the
- other side has an obsolete certificate (organizationName equal to "Tor"
- or "TOR"). If the other party presented an obsolete certificate,
- we assume a v0 connection. Otherwise, both parties send VERSIONS
- cells listing all their supported versions. Upon receiving the
- other party's VERSIONS cell, the implementation begins using the
- highest-valued version common to both cells. If the first cell from
- the other party is _not_ a VERSIONS cell, we assume a v0 protocol.
-
- Implementations MUST discard cells that are not the first cells sent on a
- connection.
-
-4.2. MITM-prevention and time checking
-
- If we negotiate a v1 connection or higher, the first cell we send SHOULD
- be a NETINFO cell. Implementations SHOULD NOT send NETINFO cells at other
- times.
-
- A NETINFO cell contains:
- Timestamp [4 bytes]
- This OR's address [variable]
- Other OR's address [variable]
-
- Timestamp is the OR's current Unix time, in seconds since the epoch. If
- an implementation receives time values from many validated ORs that
- indicate that its clock is skewed, it SHOULD try to warn the
- administrator.
-
- Each address contains Type/Length/Value as used in Section 6.4. The first
- address is the address of the interface the party sending the VERSIONS cell
- used to connect to or accept connections from the other -- we include it
- to block a man-in-the-middle attack on TLS that lets an attacker bounce
- traffic through his own computers to enable timing and packet-counting
- attacks.
+4. Circuit management
- The second address is the one that the party sending the VERSIONS cell
- believes the other has -- it can be used to learn what your IP address
- is if you have no other hints.
-
-5. Circuit management
-
-5.1. CREATE and CREATED cells
+4.1. CREATE and CREATED cells
Users set up circuits incrementally, one hop at a time. To create a
new circuit, OPs send a CREATE cell to the first node, with the
first half of the DH handshake; that node responds with a CREATED
cell with the second half of the DH handshake plus the first 20 bytes
- of derivative key data (see section 5.2). To extend a circuit past
+ of derivative key data (see section 4.2). To extend a circuit past
the first hop, the OP sends an EXTEND relay cell (see section 5)
which instructs the last node in the circuit to send a CREATE cell
to extend the circuit.
@@ -368,7 +248,7 @@ TODO:
The payload for a CREATED cell, or the relay payload for an
EXTENDED cell, contains:
DH data (g^y) [DH_LEN bytes]
- Derivative key data (KH) [HASH_LEN bytes] <see 5.2 below>
+ Derivative key data (KH) [HASH_LEN bytes] <see 4.2 below>
The CircID for a CREATE cell is an arbitrarily chosen 2-byte integer,
selected by the node (OP or OR) that sends the CREATE cell. To prevent
@@ -381,12 +261,12 @@ TODO:
As usual with DH, x and y MUST be generated randomly.
-[
- To implement backward-compatible version negotiation, parties MUST
- drop CREATE cells with all-[00] onion-skins.
-]
+ (Older versions of Tor compared OR nicknames, and did it in a broken and
+ unreliable way. To support versions of Tor earlier than 0.0.9pre6,
+ implementations should notice when the other side of a connection is
+ sending CREATE cells with the "wrong" MSB, and switch accordingly.)
-5.1.1. CREATE_FAST/CREATED_FAST cells
+4.1.1. CREATE_FAST/CREATED_FAST cells
When initializing the first hop of a circuit, the OP has already
established the OR's identity and negotiated a secret key using TLS.
@@ -403,28 +283,25 @@ TODO:
A CREATED_FAST cell contains:
Key material (Y) [HASH_LEN bytes]
- Derivative key data [HASH_LEN bytes] (See 5.2 below)
+ Derivative key data [HASH_LEN bytes] (See 4.2 below)
The values of X and Y must be generated randomly.
[Versions of Tor before 0.1.0.6-rc did not support these cell types;
clients should not send CREATE_FAST cells to older Tor servers.]
-5.2. Setting circuit keys
+4.2. Setting circuit keys
Once the handshake between the OP and an OR is completed, both can
now calculate g^xy with ordinary DH. Before computing g^xy, both client
and server MUST verify that the received g^x or g^y value is not degenerate;
that is, it must be strictly greater than 1 and strictly less than p-1
where p is the DH modulus. Implementations MUST NOT complete a handshake
- with degenerate keys. Implementations MUST NOT discard other "weak"
- g^x values.
+ with degenerate keys. Implementations MAY discard other "weak" g^x values.
- (Discarding degenerate keys is critical for security; if bad keys
- are not discarded, an attacker can substitute the server's CREATED
- cell's g^y with 0 or 1, thus creating a known g^xy and impersonating
- the server. Discarding other keys may allow attacks to learn bits of
- the private key.)
+ (Discarding degenerate keys is critical for security; if bad keys are not
+ discarded, an attacker can substitute the server's CREATED cell's g^y with
+ 0 or 1, thus creating a known g^xy and impersonating the server.)
(The mainline Tor implementation, in the 0.1.1.x-alpha series, discarded
all g^x values less than 2^24, greater than p-2^24, or having more than
@@ -453,7 +330,7 @@ TODO:
is used to encrypt the stream of data going from the OP to the OR, and
Kb is used to encrypt the stream of data going from the OR to the OP.
-5.3. Creating circuits
+4.3. Creating circuits
When creating a circuit through the network, the circuit creator
(OP) performs the following steps:
@@ -494,7 +371,7 @@ TODO:
cell to the next onion router, with the enclosed onion skin as its
payload. The initiating onion router chooses some circID not yet
used on the connection between the two onion routers. (But see
- section 5.1. above, concerning choosing circIDs based on
+ section 4.1. above, concerning choosing circIDs based on
lexicographic order of nicknames.)
When an onion router receives a CREATE cell, if it already has a
@@ -509,7 +386,7 @@ TODO:
until a break in traffic allows time to do so without harming
network latency too greatly.)
-5.4. Tearing down circuits
+4.4. Tearing down circuits
Circuits are torn down when an unrecoverable error occurs along
the circuit, or when all streams on a circuit are closed and the
@@ -524,7 +401,7 @@ TODO:
associated with the corresponding circuit. If it's not the end of
the circuit, it sends a DESTROY cell for that circuit to the next OR
in the circuit. If the node is the end of the circuit, then it tears
- down any associated edge connections (see section 6.1).
+ down any associated edge connections (see section 5.1).
After a DESTROY cell has been processed, an OR ignores all data or
destroy cells for the corresponding circuit.
@@ -552,17 +429,17 @@ TODO:
2 -- INTERNAL (Internal error.)
3 -- REQUESTED (A client sent a TRUNCATE command.)
4 -- HIBERNATING (Not currently operating; trying to save bandwidth.)
- 5 -- RESOURCELIMIT (Out of memory, sockets, or circuit IDs.)
- 6 -- CONNECTFAILED (Unable to reach server.)
+ 5 -- RESOURCELIMIT (Out of memory, sockets, or circuit IDs.)
+ 6 -- CONNECTFAILED (Unable to reach server.)
7 -- OR_IDENTITY (Connected to server, but its OR identity was not
as expected.)
8 -- OR_CONN_CLOSED (The OR connection that was carrying this circuit
died.)
- [Versions of Tor prior to 0.1.0.11 didn't send reasons; implementations
+ [Versions of Tor prior to 0.1.0.11 didn't sent versions; implementations
MUST accept empty TRUNCATED and DESTROY cells.]
-5.5. Routing relay cells
+4.5. Routing relay cells
When an OR receives a RELAY cell, it checks the cell's circID and
determines whether it has a corresponding circuit along that
@@ -578,7 +455,7 @@ TODO:
Note that in counter mode, decrypt and encrypt are the same operation.
The OR then decides whether it recognizes the relay cell, by
- inspecting the payload as described in section 6.1 below. If the OR
+ inspecting the payload as described in section 5.1 below. If the OR
recognizes the cell, it processes the contents of the relay cell.
Otherwise, it passes the decrypted relay cell along the circuit if
the circuit continues. If the OR at the end of the circuit
@@ -590,13 +467,13 @@ TODO:
OP receives data cell:
For I=N...1,
Decrypt with Kb_I. If the payload is recognized (see
- section 6..1), then stop and process the payload.
+ section 5.1), then stop and process the payload.
- For more information, see section 6 below.
+ For more information, see section 5 below.
-6. Application connections and stream management
+5. Application connections and stream management
-6.1. Relay cells
+5.1. Relay cells
Within a circuit, the OP and the exit node use the contents of
RELAY packets to tunnel end-to-end commands and TCP connections
@@ -634,13 +511,13 @@ TODO:
to zero; the 'digest' field is computed as the first four bytes of
the running digest of all the bytes that have been destined for
this hop of the circuit or originated from this hop of the circuit,
- seeded from Df or Db respectively (obtained in section 5.2 above),
+ seeded from Df or Db respectively (obtained in section 4.2 above),
and including this RELAY cell's entire payload (taken with the digest
field set to zero).
When the 'recognized' field of a RELAY cell is zero, and the digest
is correct, the cell is considered "recognized" for the purposes of
- decryption (see section 5.5 above).
+ decryption (see section 4.5 above).
(The digest does not include any bytes from relay cells that do
not start or end at this hop of the circuit. That is, it does not
@@ -663,7 +540,7 @@ TODO:
0.1.1.10, Tor closed circuits when it received an unknown relay
command. Perhaps this will be more forward-compatible. -RD]
-6.2. Opening streams and transferring data
+5.2. Opening streams and transferring data
To open a new anonymized TCP connection, the OP chooses an open
circuit to an exit that may be able to connect to the destination
@@ -683,7 +560,7 @@ TODO:
Upon receiving this cell, the exit node resolves the address as
necessary, and opens a new TCP connection to the target port. If the
address cannot be resolved, or a connection can't be established, the
- exit node replies with a RELAY_END cell. (See 6.4 below.)
+ exit node replies with a RELAY_END cell. (See 5.4 below.)
Otherwise, the exit node replies with a RELAY_CONNECTED cell, whose
payload is in one of the following formats:
The IPv4 address to which the connection was made [4 octets]
@@ -694,12 +571,7 @@ TODO:
The IPv6 address to which the connection was made [16 octets]
A number of seconds (TTL) for which the address may be cached [4 octets]
[XXXX Versions of Tor before 0.1.1.6 ignore and do not generate the TTL
- field. No version of Tor currently generates the IPv6 format.
-
- Tor servers before 0.1.2.0 set the TTL field to a fixed value. Later
- versions set the TTL to the last value seen from a DNS server, and expire
- their own cached entries after a fixed interval. This prevents certain
- attacks.]
+ field. No version of Tor currently generates the IPv6 format.]
The OP waits for a RELAY_CONNECTED cell before sending any data.
Once a connection has been established, the OP and exit node
@@ -710,7 +582,7 @@ TODO:
Relay RELAY_DROP cells are long-range dummies; upon receiving such
a cell, the OR or OP must drop it.
-6.3. Closing streams
+5.3. Closing streams
When an anonymized TCP connection is closed, or an edge node
encounters error on any stream, it sends a 'RELAY_END' cell along the
@@ -778,7 +650,7 @@ TODO:
If an edge node encounters an error on any stream, it sends a
'RELAY_END' cell (if possible) and closes the stream immediately.
-6.4. Remote hostname lookup
+5.4. Remote hostname lookup
To find the address associated with a hostname, the OP sends a
RELAY_RESOLVE cell containing the hostname to be resolved. (For a reverse
@@ -803,9 +675,9 @@ TODO:
corresponding RELAY_RESOLVED cell must use the same streamID. No stream
is actually created by the OR when resolving the name.
-7. Flow control
+6. Flow control
-7.1. Link throttling
+6.1. Link throttling
Each node should do appropriate bandwidth throttling to keep its
user happy.
@@ -813,11 +685,7 @@ TODO:
Communicants rely on TCP's default flow control to push back when they
stop reading.
-7.2. Link padding
-
- Link padding can be created by sending PADDING cells along the
- connection; relay cells of type "DROP" can be used for long-range
- padding.
+6.2. Link padding
Currently nodes are not required to do any sort of link padding or
dummy traffic. Because strong attacks exist even with link padding,
@@ -825,7 +693,7 @@ TODO:
for running a node, we plan to leave out link padding until this
tradeoff is better understood.
-7.3. Circuit-level flow control
+6.3. Circuit-level flow control
To control a circuit's bandwidth usage, each OR keeps track of
two 'windows', consisting of how many RELAY_DATA cells it is
@@ -851,7 +719,7 @@ TODO:
sends no more RELAY_DATA cells until receiving a RELAY_SENDME cell.
[this stuff is badly worded; copy in the tor-design section -RD]
-7.4. Stream-level flow control
+6.4. Stream-level flow control
Edge nodes use RELAY_SENDME cells to implement end-to-end flow
control for individual connections across circuits. Similarly to
@@ -861,6 +729,290 @@ TODO:
cells when both a) the window is <= 450, and b) there are less than
ten cell payloads remaining to be flushed at that edge.
+7. Directories and routers
+
+7.1. Extensible information format
+
+Router descriptors and directories both obey the following lightweight
+extensible information format.
+
+The highest level object is a Document, which consists of one or more Items.
+Every Item begins with a KeywordLine, followed by one or more Objects. A
+KeywordLine begins with a Keyword, optionally followed by whitespace and more
+non-newline characters, and ends with a newline. A Keyword is a sequence of
+one or more characters in the set [A-Za-z0-9-]. An Object is a block of
+encoded data in pseudo-Open-PGP-style armor. (cf. RFC 2440)
+
+More formally:
+
+ Document ::= (Item | NL)+
+ Item ::= KeywordLine Object*
+ KeywordLine ::= Keyword NL | Keyword WS ArgumentsChar+ NL
+ Keyword = KeywordChar+
+ KeywordChar ::= 'A' ... 'Z' | 'a' ... 'z' | '0' ... '9' | '-'
+ ArgumentChar ::= any printing ASCII character except NL.
+ WS = (SP | TAB)+
+ Object ::= BeginLine Base-64-encoded-data EndLine
+ BeginLine ::= "-----BEGIN " Keyword "-----" NL
+ EndLine ::= "-----END " Keyword "-----" NL
+
+ The BeginLine and EndLine of an Object must use the same keyword.
+
+When interpreting a Document, software MUST reject any document containing a
+KeywordLine that starts with a keyword it doesn't recognize.
+
+The "opt" keyword is reserved for non-critical future extensions. All
+implementations MUST ignore any item of the form "opt keyword ....." when
+they would not recognize "keyword ....."; and MUST treat "opt keyword ....."
+as synonymous with "keyword ......" when keyword is recognized.
+
+7.2. Router descriptor format.
+
+Every router descriptor MUST start with a "router" Item; MUST end with a
+"router-signature" Item and an extra NL; and MUST contain exactly one
+instance of each of the following Items: "published" "onion-key" "link-key"
+"signing-key" "bandwidth". Additionally, a router descriptor MAY contain any
+number of "accept", "reject", "fingerprint", "uptime", and "opt" Items.
+Other than "router" and "router-signature", the items may appear in any
+order.
+
+The items' formats are as follows:
+ "router" nickname address ORPort SocksPort DirPort
+
+ Indicates the beginning of a router descriptor. "address"
+ must be an IPv4 address in dotted-quad format. The last
+ three numbers indicate the TCP ports at which this OR exposes
+ functionality. ORPort is a port at which this OR accepts TLS
+ connections for the main OR protocol; SocksPort is deprecated and
+ should always be 0; and DirPort is the port at which this OR accepts
+ directory-related HTTP connections. If any port is not supported,
+ the value 0 is given instead of a port number.
+
+ "bandwidth" bandwidth-avg bandwidth-burst bandwidth-observed
+
+ Estimated bandwidth for this router, in bytes per second. The
+ "average" bandwidth is the volume per second that the OR is willing
+ to sustain over long periods; the "burst" bandwidth is the volume
+ that the OR is willing to sustain in very short intervals. The
+ "observed" value is an estimate of the capacity this server can
+ handle. The server remembers the max bandwidth sustained output
+ over any ten second period in the past day, and another sustained
+ input. The "observed" value is the lesser of these two numbers.
+
+ "platform" string
+
+ A human-readable string describing the system on which this OR is
+ running. This MAY include the operating system, and SHOULD include
+ the name and version of the software implementing the Tor protocol.
+
+ "published" YYYY-MM-DD HH:MM:SS
+
+ The time, in GMT, when this descriptor was generated.
+
+ "fingerprint"
+
+ A fingerprint (a HASH_LEN-byte of asn1 encoded public key, encoded
+ in hex, with a single space after every 4 characters) for this router's
+ identity key.
+
+ [We didn't start parsing this line until Tor 0.1.0.6-rc; it should
+ be marked with "opt" until earlier versions of Tor are obsolete.]
+
+ "hibernating" 0|1
+
+ If the value is 1, then the Tor server was hibernating when the
+ descriptor was published, and shouldn't be used to build circuits.
+
+ [We didn't start parsing this line until Tor 0.1.0.6-rc; it should
+ be marked with "opt" until earlier versions of Tor are obsolete.]
+
+ "uptime"
+
+ The number of seconds that this OR process has been running.
+
+ "onion-key" NL a public key in PEM format
+
+ This key is used to encrypt EXTEND cells for this OR. The key MUST
+ be accepted for at least XXXX hours after any new key is published in
+ a subsequent descriptor.
+
+ "signing-key" NL a public key in PEM format
+
+ The OR's long-term identity key.
+
+ "accept" exitpattern
+ "reject" exitpattern
+
+ These lines, in order, describe the rules that an OR follows when
+ deciding whether to allow a new stream to a given address. The
+ 'exitpattern' syntax is described below.
+
+ "router-signature" NL Signature NL
+
+ The "SIGNATURE" object contains a signature of the PKCS1-padded
+ hash of the entire router descriptor, taken from the beginning of the
+ "router" line, through the newline after the "router-signature" line.
+ The router descriptor is invalid unless the signature is performed
+ with the router's identity key.
+
+ "contact" info NL
+
+ Describes a way to contact the server's administrator, preferably
+ including an email address and a PGP key fingerprint.
+
+ "family" names NL
+
+ 'Names' is a whitespace-separated list of server nicknames. If two ORs
+ list one another in their "family" entries, then OPs should treat them
+ as a single OR for the purpose of path selection.
+
+ For example, if node A's descriptor contains "family B", and node B's
+ descriptor contains "family A", then node A and node B should never
+ be used on the same circuit.
+
+ "read-history" YYYY-MM-DD HH:MM:SS (NSEC s) NUM,NUM,NUM,NUM,NUM... NL
+ "write-history" YYYY-MM-DD HH:MM:SS (NSEC s) NUM,NUM,NUM,NUM,NUM... NL
+
+ Declare how much bandwidth the OR has used recently. Usage is divided
+ into intervals of NSEC seconds. The YYYY-MM-DD HH:MM:SS field defines
+ the end of the most recent interval. The numbers are the number of
+ bytes used in the most recent intervals, ordered from oldest to newest.
+
+ [We didn't start parsing these lines until Tor 0.1.0.6-rc; they should
+ be marked with "opt" until earlier versions of Tor are obsolete.]
+
+nickname ::= between 1 and 19 alphanumeric characters, case-insensitive.
+
+exitpattern ::= addrspec ":" portspec
+portspec ::= "*" | port | port "-" port
+port ::= an integer between 1 and 65535, inclusive.
+addrspec ::= "*" | ip4spec | ip6spec
+ipv4spec ::= ip4 | ip4 "/" num_ip4_bits | ip4 "/" ip4mask
+ip4 ::= an IPv4 address in dotted-quad format
+ip4mask ::= an IPv4 mask in dotted-quad format
+num_ip4_bits ::= an integer between 0 and 32
+ip6spec ::= ip6 | ip6 "/" num_ip6_bits
+ip6 ::= an IPv6 address, surrounded by square brackets.
+num_ip6_bits ::= an integer between 0 and 128
+
+Ports are required; if they are not included in the router
+line, they must appear in the "ports" lines.
+
+7.3. Directory format
+
+A Directory begins with a "signed-directory" item, followed by one each of
+the following, in any order: "recommended-software", "published",
+"router-status", "dir-signing-key". It may include any number of "opt"
+items. After these items, a directory includes any number of router
+descriptors, and a single "directory-signature" item.
+
+ "signed-directory"
+
+ Indicates the start of a directory.
+
+ "published" YYYY-MM-DD HH:MM:SS
+
+ The time at which this directory was generated and signed, in GMT.
+
+ "dir-signing-key"
+
+ The key used to sign this directory; see "signing-key" for format.
+
+ "recommended-software" comma-separated-version-list
+
+ A list of which versions of which implementations are currently
+ believed to be secure and compatible with the network.
+
+ "running-routers" whitespace-separated-list
+
+ A description of which routers are currently believed to be up or
+ down. Every entry consists of an optional "!", followed by either an
+ OR's nickname, or "$" followed by a hexadecimal encoding of the hash
+ of an OR's identity key. If the "!" is included, the router is
+ believed not to be running; otherwise, it is believed to be running.
+ If a router's nickname is given, exactly one router of that nickname
+ will appear in the directory, and that router is "approved" by the
+ directory server. If a hashed identity key is given, that OR is not
+ "approved". [XXXX The 'running-routers' line is only provided for
+ backward compatibility. New code should parse 'router-status'
+ instead.]
+
+ "router-status" whitespace-separated-list
+
+ A description of which routers are currently believed to be up or
+ down, and which are verified or unverified. Contains one entry for
+ every router that the directory server knows. Each entry is of the
+ format:
+
+ !name=$digest [Verified router, currently not live.]
+ name=$digest [Verified router, currently live.]
+ !$digest [Unverified router, currently not live.]
+ or $digest [Unverified router, currently live.]
+
+ (where 'name' is the router's nickname and 'digest' is a hexadecimal
+ encoding of the hash of the routers' identity key).
+
+ When parsing this line, clients should only mark a router as
+ 'verified' if its nickname AND digest match the one provided.
+
+ "directory-signature" nickname-of-dirserver NL Signature
+
+The signature is computed by computing the digest of the
+directory, from the characters "signed-directory", through the newline
+after "directory-signature". This digest is then padded with PKCS.1,
+and signed with the directory server's signing key.
+
+If software encounters an unrecognized keyword in a single router descriptor,
+it MUST reject only that router descriptor, and continue using the
+others. Because this mechanism is used to add 'critical' extensions to
+future versions of the router descriptor format, implementation should treat
+it as a normal occurrence and not, for example, report it to the user as an
+error. [Versions of Tor prior to 0.1.1 did this.]
+
+If software encounters an unrecognized keyword in the directory header,
+it SHOULD reject the entire directory.
+
+7.4. Network-status descriptor
+
+A "network-status" (a.k.a "running-routers") document is a truncated
+directory that contains only the current status of a list of nodes, not
+their actual descriptors. It contains exactly one of each of the following
+entries.
+
+ "network-status"
+
+ Must appear first.
+
+ "published" YYYY-MM-DD HH:MM:SS
+
+ (see 7.3 above)
+
+ "router-status" list
+
+ (see 7.3 above)
+
+ "directory-signature" NL signature
+
+ (see 7.3 above)
+
+7.5. Behavior of a directory server
+
+lists nodes that are connected currently
+speaks HTTP on a socket, spits out directory on request
+
+Directory servers listen on a certain port (the DirPort), and speak a
+limited version of HTTP 1.0. Clients send either GET or POST commands.
+The basic interactions are:
+ "%s %s HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s\r\n\r\n",
+ command, url, content-length, host.
+ Get "/tor/" to fetch a full directory.
+ Get "/tor/dir.z" to fetch a compressed full directory.
+ Get "/tor/running-routers" to fetch a network-status descriptor.
+ Post "/tor/" to post a server descriptor, with the body of the
+ request containing the descriptor.
+
+ "host" is used to specify the address:port of the dirserver, so
+ the request can survive going through HTTP proxies.
A.1. Differences between spec and implementation
@@ -881,7 +1033,7 @@ B.1. ... but which will require backward-incompatible change
- Drop backward compatibility.
- We should use a 128-bit subgroup of our DH prime.
- Handshake should use HMAC.
- - Multiple cell lengths.
+ - Multiple cell lengths
- Ability to split circuits across paths (If this is useful.)
- SENDME windows should be dynamic.
diff --git a/doc/tor-win32-mingw-creation.txt b/doc/tor-win32-mingw-creation.txt
deleted file mode 100644
index a17d37a806..0000000000
--- a/doc/tor-win32-mingw-creation.txt
+++ /dev/null
@@ -1,120 +0,0 @@
-## Instructions for building Tor with MinGW (http://www.mingw.org/)
-##
-
-Stage One: Download and Install MinGW.
----------------------------------------
-
-Download mingw:
-http://prdownloads.sf.net/mingw/MinGW-5.0.3.exe?download
-
-Download msys:
-http://prdownloads.sf.net/mingw/MSYS-1.0.10.exe?download
-
-Download the mingw developer tool kit:
-http://prdownloads.sf.net/mingw/msysDTK-1.0.1.exe?download
-
-Download the mingw win32api:
-http://prdownloads.sf.net/mingw/w32api-3.6.tar.gz?download
-
-Install mingw, msys and mingw-dtk.
-
-Create a directory called "tor-mingw".
-
-Stage Two: Download, extract, compile openssl
-----------------------------------------------
-
-Download openssl:
-http://www.openssl.org/source/openssl-0.9.8c.tar.gz
-
-Extract openssl:
-Copy the openssl tarball into the "tor-mingw" directory.
-Type "cd tor-mingw/"
-Type "tar zxf openssl-0.9.8c.tar.gz"
-
-Make openssl libraries:
-Type "cd tor-mingw/openssl-0.9.8c/"
-Type "./Configure mingw"
-Edit Makefile and remove the "test:" and "tests:" sections.
-Type "rm -rf ./test"
-Type "cd crypto/"
-Type "find ./ -name "*.h" -exec cp {} ../include/openssl/ \;"
-Type "cd ../ssl/"
-Type "find ./ -name "*.h" -exec cp {} ../include/openssl/ \;
-Type "cd .."
-Type "cp *.h include/openssl/"
-# The next steps can take up to 30 minutes to complete.
-Type "make"
-Type "make install"
-
-Alternatively:
-Download the pre-compiled openssl for win32.
-Install and proceed.
-
-
-Stage Three: Download, extract, compile zlib
----------------------------------------------
-
-Download zlib source:
-http://www.zlib.net/zlib-1.2.3.tar.gz
-
-Extract zlib:
-Copy the zlib tarball into the "tor-mingw" directory
-Type "cd tor-mingw/"
-Type "tar zxf zlib-1.2.3.tar.gz"
-
-CHOICE:
-
-Make zlib.a:
-Type "cd tor-mingw/zlib-1.2.3/"
-Type "./configure"
-Type "make"
-Type "make install"
-
-OR
-
-Make zlib1.dll:
-Type "cd tor-mingw/zlib-1.2.3"/
-Type "./configure"
-Type "make -f win32/Makefile.gcc"
-
-Done.
-
-
-Stage Four: Download, extract, and patch libevent-1.1b.
-------------------------------------------------------
-
-Download libevent-1.1b:
-http://www.monkey.org/~provos/libevent/
-
-Copy the libevent tarball into the "tor-mingw" directory.
-Type "cd tor-mingw"
-
-Extract libevent:
-Type "tar zxf libevent-1.1b.tar.gz"
-
-Download the libevent-1.1b-mingw.diff from
-http://cvsview.seul.org/tor/something/path.
-Copy the libevent-1.1b diff into the libevent-1.1b directory.
-Type "patch -p0 < libevent-1.1b-mingw.diff"
-
-Type "aclocal && autoheader && automake && autoconf".
-There may be WARNING messages. There will be no output if all runs successfuly.
-
-Type "./configure --enable-static --disable-shared"
-Type "make"
-Type "make install"
-
-Stage Five: Build Tor
-----------------------
-
-Download the current Tor alpha release from http://tor.eff.org/download.html.
-Copy the Tor tarball into the "tor-mingw" directory.
-Extract Tor:
-Type "tar zxf latest-tor-alpha.tar.gz"
-
-cd tor-<version>
-Type "./configure --enable-static --disable-shared"
-Type "make"
-
-You now have a tor.exe in src/or/. This is Tor.
-You now have a tor_resolve.exe in src/tools/.
diff --git a/doc/tor.1.in b/doc/tor.1.in
index effd59b7ef..656a259249 100644
--- a/doc/tor.1.in
+++ b/doc/tor.1.in
@@ -198,12 +198,6 @@ of Tor's outgoing connections to use a single one.
On startup, write our PID to FILE. On clean shutdown, remove FILE.
.LP
.TP
-\fBProtocolWarnings \fR\fB0\fR|\fB1\fR\fP
-If 1, Tor will log with severity 'warn' various cases of other parties
-not following the Tor specification. Otherwise, they are logged with
-severity 'info'. (Default: 0)
-.LP
-.TP
\fBRunAsDaemon \fR\fB0\fR|\fB1\fR\fP
If 1, Tor forks and daemonizes to the background. This option has
no effect on Windows; instead you should use the --service command-line
@@ -221,7 +215,7 @@ about what sites a user might have visited. (Default: 1)
On startup, setuid to this user.
.LP
.TP
-\fBHardwareAccel \fR\fB0\fR|\fB1\fP
+\fBHardwareAccel \fR\fI0|1\fP
If non-zero, try to use crypto hardware acceleration when
available. This is untested and probably buggy. (Default: 0)
@@ -231,11 +225,10 @@ The following options are useful only for clients (that is, if \fBSocksPort\fP i
.LP
.TP
\fBAllowInvalidNodes\fR \fBentry\fR|\fBexit\fR|\fBmiddle\fR|\fBintroduction\fR|\fBrendezvous\fR|...\fP
-If some Tor servers are obviously not working right, the directory
-authorities can manually mark them as invalid, meaning that it's not
-recommended you use them for entry or exit positions in your circuits. You
-can opt to use them in some circuit positions, though. The default is
-"middle,rendezvous", and other choices are not advised.
+Allow routers that the dirserver operators consider invalid (not
+trustworthy or otherwise not working right) in only these positions in
+your circuits.
+The default is "middle,rendezvous", and other choices are not advised.
.LP
.TP
\fBCircuitBuildTimeout \fR\fINUM\fP
@@ -317,7 +310,7 @@ firewall allows connections to everything inside net 99, rejects port
\fBReachableDirAddresses \fR\fIADDR\fP[\fB/\fP\fIMASK\fP][:\fIPORT\fP]...\fP
Like \fBReachableAddresses\fP, a list of addresses and ports. Tor will obey
these restrictions when fetching directory information, using standard HTTP
-GET requests. If not set explicitly then the value of \fBReachableAddresses\fP
+GET requests. If not set explicitly then the value of \fBfBReachableAddresses\fP
is used. If \fBHttpProxy\fR is set then these connections will go through that
proxy.
.LP
@@ -325,7 +318,7 @@ proxy.
\fBReachableORAddresses \fR\fIADDR\fP[\fB/\fP\fIMASK\fP][:\fIPORT\fP]...\fP
Like \fBReachableAddresses\fP, a list of addresses and ports. Tor will obey
these restrictions when connecting to Onion Routers, using TLS/SSL. If not set
-explicitly then the value of \fBReachableAddresses\fP is used. If
+explicitly then the value of \fBfBReachableAddresses\fP is used. If
\fBHttpsProxy\fR is set then these connections will go through that proxy.
The separation between \fBReachableORAddresses\fP and
@@ -340,15 +333,14 @@ port 80.
A list of ports for services that tend to have long-running connections
(e.g. chat and interactive shells). Circuits for streams that use these
ports will contain only high-uptime nodes, to reduce the chance that a
-node will go down before the stream is finished.
-(Default: 21, 22, 706, 1863, 5050, 5190, 5222, 5223, 6667, 8300)
+node will go down before the stream is finished. (Default: 21, 22, 706, 1863, 5050,
+5190, 5222, 5223, 6667, 8300, 8888)
.LP
.TP
\fBMapAddress\fR \fIaddress\fR \fInewaddress\fR
-When a request for address arrives to Tor, it will rewrite it to
-newaddress before processing it. For example, if you always want
-connections to www.indymedia.org to exit via \fItorserver\fR (where
-\fItorserver\fR is the nickname of the server),
+When a request for address arrives to Tor, it will rewrite it to newaddress before
+processing it. For example, if you always want connections to www.indymedia.org to
+exit via \fItorserver\fR (where \fItorserver\fR is the nickname of the server),
use "MapAddress www.indymedia.org www.indymedia.org.torserver.exit".
.LP
.TP
@@ -357,9 +349,8 @@ Every NUM seconds consider whether to build a new circuit. (Default: 30 seconds)
.LP
.TP
\fBMaxCircuitDirtiness \fR\fINUM\fP
-Feel free to reuse a circuit that was first used at most NUM seconds ago,
-but never attach a new stream to a circuit that is too old.
-(Default: 10 minutes)
+Feel free to reuse a circuit that was first used at most NUM seconds
+ago, but never attach a new stream to a circuit that is too old. (Default: 10 minutes)
.LP
.TP
\fBNodeFamily \fR\fInickname\fR,\fInickname\fR,\fI...\fP
@@ -370,7 +361,7 @@ NodeFamily is only needed when a server doesn't list the family itself
.LP
.TP
.\" \fBPathlenCoinWeight \fR\fI0.0-1.0\fP
-.\" Paths are 3 hops plus a geometric distribution centered around this coinweight.
+.\" Paths are 3 hops plus a geometric distribution centered around this coinweight.
.\" Must be >=0.0 and <1.0. (Default: 0.3) NOT USED CURRENTLY
.\" .TP
\fBRendNodes \fR\fInickname\fR,\fInickname\fR,\fI...\fP
@@ -405,11 +396,6 @@ Let a socks connection wait NUM seconds unattached before we fail it.
(Default: 2 minutes.)
.LP
.TP
-\fBTestVia \fR\fInickname\fR,\fInickname\fR,\fI...\fP
-A list of nodes to prefer for your middle hop when building testing
-circuits. This option is mainly for debugging reachability problems.
-.LP
-.TP
\fBTrackHostExits \fR\fIhost\fR,\fI.domain\fR,\fI...\fR\fP
For each value in the comma separated list, Tor will track recent connections
to hosts that match this value and attempt to
@@ -429,7 +415,7 @@ between host and exit server after NUM seconds. The default
is 1800 seconds (30 minutes).
.LP
.TP
-\fBUseEntryGuards \fR\fB0\fR|\fB1\fR\fP
+\fBUseEntryGuards \fR\fI0|1\fP
If this option is set to 1, we pick a few long-term entry servers, and
try to stick with them. This is desirable because
constantly changing servers increases the odds that an adversary who owns
@@ -443,7 +429,7 @@ as long-term entries for our circuits.
(Defaults to 3.)
.LP
.TP
-\fBSafeSocks \fR\fB0\fR|\fB1\fR\fP
+\fBSafeSocks \fR\fI0|1\fP
When this option is enabled, Tor will reject application connections that
use unsafe variants of the socks protocol -- ones that only provide an
IP address, meaning the application is doing a DNS resolve first.
@@ -484,9 +470,7 @@ list all connected servers as running.
.LP
.TP
\fBContactInfo \fR\fIemail_address\fP
-Administrative contact information for server. This line might get
-picked up by spam harvesters, so you may want to obscure the fact
-that it's an email address.
+Administrative contact information for server.
.LP
.TP
\fBExitPolicy \fR\fIpolicy\fR,\fIpolicy\fR,\fI...\fP
@@ -630,32 +614,6 @@ as day 1 and Sunday as day 7. If \fBday\fR is given, each accounting
period runs from the time \fIHH:MM\fR each day to the same time on the
next day. All times are local, and given in 24-hour time. (Defaults to
"month 1 0:00".)
-.LP
-.TP
-\fBServerDNSResolvConfFile \fR\fIfilename\fP
-Overrides the default DNS configuration with the configuration in
-\fIfilename\fP. The file format is the same as the standard Unix
-"\fBresolv.conf\fP" file (7). This option only effects name lookup for
-addresses requested by clients; and only takes effect if Tor was built with
-eventdns support. (Defaults to use the system DNS configuration.)
-.LP
-.TP
-\fBServerDNSSearchDomains \fR\fB0\fR|\fB1\fR\fP
-If set to \fB1\fP, then we will search for addresses in the local search
-domain. For example, if this system is configured to believe it is in
-"example.com", and a client tries to connect to "www", the client will be
-connected to "www.example.com".
-This option only effects name lookup for addresses requested by clients.
-(Defaults to "0".)
-.LP
-.TP
-\fBServerDNSDetectHijacking \fR\fB0\fR|\fB1\fR\fP
-When this option is set to 1, we will test periodically to determine whether
-our local nameservers have been configured to hijack failing DNS requests
-(usually to an advertising site). If they are, we will attempt to correct
-this. This option only effects name lookup for addresses requested by
-clients; and only takes effect if Tor was built with eventdns support.
-(Defaults to "1".)
.SH DIRECTORY SERVER OPTIONS
.PP
@@ -709,8 +667,7 @@ to this port rather than the one specified in DirPort. (Default: 0.0.0.0)
.LP
.TP
\fBDirPolicy \fR\fIpolicy\fR,\fIpolicy\fR,\fI...\fP
-Set an entrance policy for this server, to limit who can connect to the
-directory ports.
+Set an entrance policy for this server, to limit who can connect to the directory ports.
The policies have the same form as exit policies above.
.LP
.TP
diff --git a/src/common/compat.c b/src/common/compat.c
index c98748bcd2..3a05c32d45 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -24,9 +24,8 @@ const char compat_c_id[] =
#ifdef MS_WINDOWS
#include <process.h>
-#include <windows.h>
-#endif
+#endif
#ifdef HAVE_UNAME
#include <sys/utsname.h>
#endif
@@ -88,13 +87,6 @@ const char compat_c_id[] =
#ifdef HAVE_SYS_UTIME_H
#include <sys/utime.h>
#endif
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-
-#ifdef USE_BSOCKETS
-#include <bsocket.h>
-#endif
#include "log.h"
#include "util.h"
@@ -112,135 +104,6 @@ const char compat_c_id[] =
#define INADDR_NONE ((unsigned long) -1)
#endif
-#ifdef HAVE_SYS_MMAN_H
-tor_mmap_t *
-tor_mmap_file(const char *filename)
-{
- int fd; /* router file */
- char *string;
- int page_size;
- tor_mmap_t *res;
- size_t size;
-
- tor_assert(filename);
-
- fd = open(filename, O_RDONLY, 0);
- if (fd<0) {
- log_warn(LD_FS,"Could not open \"%s\" for mmap().",filename);
- return NULL;
- }
-
- size = lseek(fd, 0, SEEK_END);
- lseek(fd, 0, SEEK_SET);
- /* ensure page alignment */
- page_size = getpagesize();
- size += (size%page_size) ? page_size-(size%page_size) : 0;
-
- string = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (string == MAP_FAILED) {
- close(fd);
- log_warn(LD_FS,"Could not mmap file \"%s\": %s", filename,
- strerror(errno));
- return NULL;
- }
-
- close(fd);
-
- res = tor_malloc_zero(sizeof(tor_mmap_t));
- res->data = string;
- res->size = size;
-
- return res;
-}
-void
-tor_munmap_file(tor_mmap_t *handle)
-{
- munmap((char*)handle->data, handle->size);
- tor_free(handle);
-}
-#elif defined(MS_WINDOWS)
-typedef struct win_mmap_t {
- tor_mmap_t base;
- HANDLE file_handle;
- HANDLE mmap_handle;
-} tor_mmap_impl_t;
-tor_mmap_t *
-tor_mmap_file(const char *filename)
-{
- struct win_mmap_t *res = tor_malloc_zero(sizeof(struct win_mmap_t));
- res->mmap_handle = res->file_handle = INVALID_HANDLE_VALUE;
-
- res->file_handle = CreateFile(filename,
- GENERIC_READ,
- 0, NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- 0);
-
- if (res->file_handle == INVALID_HANDLE_VALUE)
- goto err;
-
- res->base.size = GetFileSize(res->file_handle, NULL);
-
- res->mmap_handle = CreateFileMapping(res->file_handle,
- NULL,
- PAGE_READONLY,
- (res->base.size >> 32),
- (res->base.size & 0xfffffffful),
- NULL);
- if (res->mmap_handle != INVALID_HANDLE_VALUE)
- goto err;
- res->base.data = (char*) MapViewOfFile(res->mmap_handle,
- FILE_MAP_READ,
- 0, 0, 0);
- if (!res->base.data)
- goto err;
-
- return &(res->base);
- err:
- tor_munmap_file(&res->base);
- return NULL;
-}
-void
-tor_munmap_file(tor_mmap_t *handle)
-{
- struct win_mmap_t *h = (struct win_mmap_t*)
- (((char*)handle) - STRUCT_OFFSET(struct win_mmap_t, base));
- if (handle->data)
-
- /*this is an ugly cast, but without it, "data" in struct tor_mmap_t would
- have to be redefined as const*/
- UnmapViewOfFile( (LPVOID) handle->data);
-
- if (h->mmap_handle != INVALID_HANDLE_VALUE)
- CloseHandle(h->mmap_handle);
- if (h->file_handle != INVALID_HANDLE_VALUE)
- CloseHandle(h->file_handle);
- tor_free(h);
-}
-#else
-tor_mmap_t *
-tor_mmap_file(const char *filename)
-{
- char *res = read_file_to_str(filename, 1);
- tor_mmap_t *handle;
- if (! res)
- return NULL;
- handle = tor_malloc_zero(sizeof(tor_mmap_t));
- handle->data = res;
- handle->size = strlen(res) + 1;
- return handle;
-}
-void
-tor_munmap_file(tor_mmap_t *handle)
-{
- char *d = (char*)handle->data;
- tor_free(d);
- memset(handle, sizeof(tor_mmap_t), 0);
- tor_free(handle);
-}
-#endif
-
/** Replacement for snprintf. Differs from platform snprintf in two
* ways: First, always NUL-terminates its output. Second, always
* returns -1 if the result is truncated. (Note that this return
@@ -343,6 +206,7 @@ tor_fix_source_file(const char *fname)
}
#endif
+#ifndef UNALIGNED_INT_ACCESS_OK
/**
* Read a 16-bit value beginning at <b>cp</b>. Equivalent to
* *(uint16_t*)(cp), but will not cause segfaults on platforms that forbid
@@ -385,6 +249,7 @@ set_uint32(char *cp, uint32_t v)
{
memcpy(cp,&v,4);
}
+#endif
/**
* Rename the file <b>from</b> to the file <b>to</b>. On unix, this is
@@ -429,8 +294,8 @@ touch_file(const char *fname)
void
set_socket_nonblocking(int socket)
{
-#if defined(MS_WINDOWS) && !defined(USE_BSOCKETS)
- unsigned long nonblocking = 1;
+#ifdef MS_WINDOWS
+ int nonblocking = 1;
ioctlsocket(socket, FIONBIO, (unsigned long*) &nonblocking);
#else
fcntl(socket, F_SETFL, O_NONBLOCK);
@@ -457,13 +322,10 @@ set_socket_nonblocking(int socket)
int
tor_socketpair(int family, int type, int protocol, int fd[2])
{
-//don't use win32 socketpairs (they are always bad)
-#if defined(HAVE_SOCKETPAIR) && !defined(MS_WINDOWS)
+#ifdef HAVE_SOCKETPAIR
int r;
r = socketpair(family, type, protocol, fd);
return r < 0 ? -errno : r;
-#elif defined(USE_BSOCKETS)
- return bsockepair(family, type, protocol, fd);
#else
/* This socketpair does not work when localhost is down. So
* it's really not the same thing at all. But it's close enough
@@ -494,8 +356,17 @@ tor_socketpair(int family, int type, int protocol, int fd[2])
}
listener = socket(AF_INET, type, 0);
- if (listener < 0)
+ if (listener == -1)
return -tor_socket_errno(-1);
+ if (!SOCKET_IS_POLLABLE(listener)) {
+ log_warn(LD_NET, "Too many connections; can't open socketpair");
+ tor_close_socket(listener);
+#ifdef MS_WINDOWS
+ return -ENFILE;
+#else
+ return -ENCONN;
+#endif
+ }
memset(&listen_addr, 0, sizeof(listen_addr));
listen_addr.sin_family = AF_INET;
listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
@@ -507,8 +378,12 @@ tor_socketpair(int family, int type, int protocol, int fd[2])
goto tidy_up_and_fail;
connector = socket(AF_INET, type, 0);
- if (connector < 0)
+ if (connector == -1)
+ goto tidy_up_and_fail;
+ if (!SOCKET_IS_POLLABLE(connector)) {
+ log_warn(LD_NET, "Too many connections; can't open socketpair");
goto tidy_up_and_fail;
+ }
/* We want to find out the port number to connect to. */
size = sizeof(connect_addr);
if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1)
@@ -521,8 +396,12 @@ tor_socketpair(int family, int type, int protocol, int fd[2])
size = sizeof(listen_addr);
acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size);
- if (acceptor < 0)
+ if (acceptor == -1)
+ goto tidy_up_and_fail;
+ if (!SOCKET_IS_POLLABLE(acceptor)) {
+ log_warn(LD_NET, "Too many connections; can't open socketpair");
goto tidy_up_and_fail;
+ }
if (size != sizeof(listen_addr))
goto abort_tidy_up_and_fail;
tor_close_socket(listener);
@@ -578,7 +457,7 @@ set_max_file_descriptors(unsigned long limit, unsigned long cap)
log_fn(LOG_INFO, LD_NET,
"This platform is missing getrlimit(). Proceeding.");
if (limit < cap) {
- log_info(LD_CONFIG, "ConnLimit must be at most %d. Using that.", (int)cap);
+ log_info(LD_CONFIG, "ConnLimit must be at most %d. Using that.", cap);
limit = cap;
}
#else
@@ -749,7 +628,7 @@ tor_lookup_hostname(const char *name, uint32_t *addr)
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_INET;
hints.ai_socktype = SOCK_STREAM;
- err = getaddrinfo(name, NULL, &hints, &res);
+ err = getaddrinfo(name, NULL, NULL, &res);
if (!err) {
for (res_p = res; res_p; res_p = res_p->ai_next) {
if (res_p->ai_family == AF_INET) {
@@ -846,7 +725,6 @@ get_uname(void)
{ 3, 51, "Windows NT 3.51" },
{ -1, -1, NULL }
};
-#ifdef VER_SUITE_BACKOFFICE
static struct {
unsigned int mask; const char *str;
} win_mask_table[] = {
@@ -864,10 +742,10 @@ get_uname(void)
{ VER_SUITE_TERMINAL, " {terminal services}" },
{ 0, NULL },
};
-#endif
memset(&info, 0, sizeof(info));
info.dwOSVersionInfoSize = sizeof(info);
if (! GetVersionEx((LPOSVERSIONINFO)&info)) {
+ int err = GetLastError();
strlcpy(uname_result, "Bizarre version of Windows where GetVersionEx"
" doesn't work.", sizeof(uname_result));
uname_result_is_set = 1;
@@ -903,7 +781,6 @@ get_uname(void)
(int)info.dwMajorVersion,(int)info.dwMinorVersion,
info.szCSDVersion);
}
-#ifdef VER_SUITE_BACKOFFICE
if (info.wProductType == VER_NT_DOMAIN_CONTROLLER) {
strlcat(uname_result, " [domain controller]", sizeof(uname_result));
} else if (info.wProductType == VER_NT_SERVER) {
@@ -923,7 +800,6 @@ get_uname(void)
tor_snprintf(uname_result+len, sizeof(uname_result)-len,
" {0x%x}", info.wSuiteMask);
}
-#endif
#else
strlcpy(uname_result, "Unknown platform", sizeof(uname_result));
#endif
@@ -942,14 +818,14 @@ get_uname(void)
* invoke them in a way pthreads would expect.
*/
typedef struct tor_pthread_data_t {
- void (*func)(void *);
+ int (*func)(void *);
void *data;
} tor_pthread_data_t;
static void *
tor_pthread_helper_fn(void *_data)
{
tor_pthread_data_t *data = _data;
- void (*func)(void*);
+ int (*func)(void*);
void *arg;
func = data->func;
arg = data->data;
@@ -969,7 +845,7 @@ tor_pthread_helper_fn(void *_data)
* running.
*/
int
-spawn_func(void (*func)(void *), void *data)
+spawn_func(int (*func)(void *), void *data)
{
#if defined(USE_WIN32_THREADS)
int rv;
@@ -1012,10 +888,6 @@ spawn_exit(void)
{
#if defined(USE_WIN32_THREADS)
_endthread();
- //we should never get here. my compiler thinks that _endthread returns, this
- //is an attempt to fool it.
- tor_assert(0);
- _exit(0);
#elif defined(USE_PTHREADS)
pthread_exit(NULL);
#else
@@ -1023,7 +895,6 @@ spawn_exit(void)
* call _exit, not exit, from child processes. */
_exit(0);
#endif
-
}
/** Set *timeval to the current time of day. On error, log and terminate.
@@ -1163,7 +1034,7 @@ tor_mutex_acquire(tor_mutex_t *m)
tor_assert(0);
break;
case WAIT_FAILED:
- log_warn(LD_GENERAL, "Failed to acquire mutex: %d",(int) GetLastError());
+ log_warn(LD_GENERAL, "Failed to acquire mutex: %d", GetLastError());
}
}
void
@@ -1172,7 +1043,7 @@ tor_mutex_release(tor_mutex_t *m)
BOOL r;
r = ReleaseMutex(m->handle);
if (!r) {
- log_warn(LD_GENERAL, "Failed to release mutex: %d", (int) GetLastError());
+ log_warn(LD_GENERAL, "Failed to release mutex: %d", GetLastError());
}
}
unsigned long
@@ -1239,7 +1110,7 @@ struct tor_mutex_t {
* should call tor_socket_errno <em>at most once</em> on the failing
* socket to get the error.
*/
-#if defined(MS_WINDOWS) && !defined(USE_BSOCKETS)
+#ifdef MS_WINDOWS
int
tor_socket_errno(int sock)
{
@@ -1255,7 +1126,7 @@ tor_socket_errno(int sock)
}
#endif
-#if defined(MS_WINDOWS) && !defined(USE_BSOCKETS)
+#ifdef MS_WINDOWS
#define E(code, s) { code, (s " [" #code " ]") }
struct { int code; const char *msg; } windows_socket_errors[] = {
E(WSAEINTR, "Interrupted function call"),
diff --git a/src/common/compat.h b/src/common/compat.h
index 5567f5e9c1..7975dbb9ba 100644
--- a/src/common/compat.h
+++ b/src/common/compat.h
@@ -76,34 +76,6 @@
#endif /* ifndef MAVE_MACRO__func__ */
#endif /* if not windows */
-#if defined(_MSC_VER) && (_MSC_VER < 1300)
-/* MSVC versions before 7 apparently don't believe that you can cast uint64_t
- * to double and really mean it. */
-extern INLINE double U64_TO_DBL(uint64_t x) {
- int64_t i = (int64_t) x;
- return (i < 0) ? ((double) INT64_MAX) : (double) i;
-}
-#define DBL_TO_U64(x) ((uint64_t)(int64_t) (x))
-#else
-#define U64_TO_DBL(x) ((double) (x))
-#define DBL_TO_U64(x) ((uint64_t) (x))
-#endif
-
-/* GCC has several useful attributes. */
-#if defined(__GNUC__) && __GNUC__ >= 3
-#define ATTR_NORETURN __attribute__((noreturn))
-#define ATTR_PURE __attribute__((pure))
-#define ATTR_MALLOC __attribute__((malloc))
-#define ATTR_NONNULL(x) __attribute__((nonnull x))
-#define PREDICT(exp, val) __builtin_expect((exp), (val))
-#else
-#define ATTR_NORETURN
-#define ATTR_PURE
-#define ATTR_MALLOC
-#define ATTR_NONNULL(x)
-#define PREDICT(exp, val) (exp)
-#endif
-
/* ===== String compatibility */
#ifdef MS_WINDOWS
/* Windows names string functions differently from most other platforms. */
@@ -111,13 +83,13 @@ extern INLINE double U64_TO_DBL(uint64_t x) {
#define strcasecmp stricmp
#endif
#ifndef HAVE_STRLCAT
-size_t strlcat(char *dst, const char *src, size_t siz) ATTR_NONNULL((1,2));
+size_t strlcat(char *dst, const char *src, size_t siz);
#endif
#ifndef HAVE_STRLCPY
-size_t strlcpy(char *dst, const char *src, size_t siz) ATTR_NONNULL((1,2));
+size_t strlcpy(char *dst, const char *src, size_t siz);
#endif
-#ifdef _MSC_VER
+#ifdef MS_WINDOWS
#define U64_PRINTF_ARG(a) (a)
#define U64_SCANF_ARG(a) (a)
#define U64_FORMAT "%I64u"
@@ -129,22 +101,12 @@ size_t strlcpy(char *dst, const char *src, size_t siz) ATTR_NONNULL((1,2));
#define U64_LITERAL(n) (n ## llu)
#endif
-/** Opaque bookkeeping type used for mmap accounting. */
-typedef struct tor_mmap_t {
- const char *data;
- size_t size;
-} tor_mmap_t;
-
-tor_mmap_t *tor_mmap_file(const char *filename) ATTR_NONNULL((1));
-void tor_munmap_file(tor_mmap_t *handle) ATTR_NONNULL((1));
-
int tor_snprintf(char *str, size_t size, const char *format, ...)
- CHECK_PRINTF(3,4) ATTR_NONNULL((1,3));
-int tor_vsnprintf(char *str, size_t size, const char *format, va_list args)
- ATTR_NONNULL((1,3));
+ CHECK_PRINTF(3,4);
+int tor_vsnprintf(char *str, size_t size, const char *format, va_list args);
const void *tor_memmem(const void *haystack, size_t hlen, const void *needle,
- size_t nlen) ATTR_PURE ATTR_NONNULL((1,3));
+ size_t nlen);
#define TOR_ISALPHA(c) isalpha((int)(unsigned char)(c))
#define TOR_ISALNUM(c) isalnum((int)(unsigned char)(c))
@@ -152,11 +114,9 @@ const void *tor_memmem(const void *haystack, size_t hlen, const void *needle,
#define TOR_ISXDIGIT(c) isxdigit((int)(unsigned char)(c))
#define TOR_ISDIGIT(c) isdigit((int)(unsigned char)(c))
#define TOR_ISPRINT(c) isprint((int)(unsigned char)(c))
-#define TOR_ISLOWER(c) islower((int)(unsigned char)(c))
-#define TOR_ISUPPER(c) isupper((int)(unsigned char)(c))
-#define TOR_TOLOWER(c) ((char)tolower((int)(unsigned char)(c)))
-#define TOR_TOUPPER(c) ((char)toupper((int)(unsigned char)(c)))
+#define TOR_TOLOWER(c) (char)tolower((int)(unsigned char)(c))
+#define TOR_TOUPPER(c) (char)toupper((int)(unsigned char)(c))
#ifdef MS_WINDOWS
#define _SHORT_FILE_ (tor_fix_source_file(__FILE__))
@@ -199,10 +159,8 @@ int touch_file(const char *fname);
#endif
/* ===== Net compatibility */
-#ifdef USE_BSOCKETS
-#define tor_close_socket(s) bclose(s)
-#elif defined(MS_WINDOWS)
-/** On Windows, you have to call close() on fds returned by open(),
+#ifdef MS_WINDOWS
+/** On windows, you have to call close() on fds returned by open(),
* and closesocket() on fds returned by socket(). On Unix, everything
* gets close()'d. We abstract this difference by always using
* tor_close_socket to close sockets, and always using close() on
@@ -213,21 +171,17 @@ int touch_file(const char *fname);
#define tor_close_socket(s) close(s)
#endif
-#ifdef USE_BSOCKETS
-#define tor_socket_send(s, buf, len, flags) bsend(s, buf, len, flags)
-#define tor_socket_recv(s, buf, len, flags) brecv(s, buf, len, flags)
-#else
-#define tor_socket_send(s, buf, len, flags) send(s, buf, len, flags)
-#define tor_socket_recv(s, buf, len, flags) recv(s, buf, len, flags)
-#endif
-
#if (SIZEOF_SOCKLEN_T == 0)
typedef int socklen_t;
#endif
+/* Now that we use libevent, all real sockets are safe for polling ... or
+ * if they aren't, libevent will help us. */
+#define SOCKET_IS_POLLABLE(fd) ((fd)>=0)
+
struct in_addr;
-int tor_inet_aton(const char *cp, struct in_addr *addr) ATTR_NONNULL((1,2));
-int tor_lookup_hostname(const char *name, uint32_t *addr) ATTR_NONNULL((1,2));
+int tor_inet_aton(const char *cp, struct in_addr *addr);
+int tor_lookup_hostname(const char *name, uint32_t *addr);
void set_socket_nonblocking(int socket);
int tor_socketpair(int family, int type, int protocol, int fd[2]);
int network_init(void);
@@ -237,7 +191,7 @@ int network_init(void);
* errnos against expected values, and use tor_socket_errno to find
* the actual errno after a socket operation fails.
*/
-#if defined(MS_WINDOWS) && !defined(USE_BSOCKETS)
+#ifdef MS_WINDOWS
/** Return true if e is EAGAIN or the local equivalent. */
#define ERRNO_IS_EAGAIN(e) ((e) == EAGAIN || (e) == WSAEWOULDBLOCK)
/** Return true if e is EINPROGRESS or the local equivalent. */
@@ -272,10 +226,21 @@ const char *tor_socket_strerror(int e);
/* ===== OS compatibility */
const char *get_uname(void);
-uint16_t get_uint16(const char *cp) ATTR_PURE ATTR_NONNULL((1));
-uint32_t get_uint32(const char *cp) ATTR_PURE ATTR_NONNULL((1));
-void set_uint16(char *cp, uint16_t v) ATTR_NONNULL((1));
-void set_uint32(char *cp, uint32_t v) ATTR_NONNULL((1));
+/* Some platforms segfault when you try to access a multi-byte type
+ * that isn't aligned to a word boundary. The macros and/or functions
+ * below can be used to access unaligned data on any platform.
+ */
+#ifdef UNALIGNED_INT_ACCESS_OK
+#define get_uint16(cp) (*(uint16_t*)(cp))
+#define get_uint32(cp) (*(uint32_t*)(cp))
+#define set_uint16(cp,v) do { *(uint16_t*)(cp) = (v); } while (0)
+#define set_uint32(cp,v) do { *(uint32_t*)(cp) = (v); } while (0)
+#else
+uint16_t get_uint16(const char *cp);
+uint32_t get_uint32(const char *cp);
+void set_uint16(char *cp, uint16_t v);
+void set_uint32(char *cp, uint32_t v);
+#endif
int set_max_file_descriptors(unsigned long limit, unsigned long cap);
int switch_id(char *user, char *group);
@@ -283,8 +248,8 @@ int switch_id(char *user, char *group);
char *get_user_homedir(const char *username);
#endif
-int spawn_func(void (*func)(void *), void *data);
-void spawn_exit(void) ATTR_NORETURN;
+int spawn_func(int (*func)(void *), void *data);
+void spawn_exit(void);
#if defined(ENABLE_THREADS) && defined(MS_WINDOWS)
#define USE_WIN32_THREADS
@@ -297,9 +262,8 @@ void spawn_exit(void) ATTR_NORETURN;
#undef TOR_IS_MULTITHREADED
#endif
-/* Because we use threads instead of processes on most platforms (Windows,
- * Linux, etc), we need locking for them. On platforms with poor thread
- * support or broken gethostbyname_r, these functions are no-ops. */
+/* Because we use threads instead of processes on Windows, we need locking on
+ * Windows. On Unixy platforms, these functions are no-ops. */
typedef struct tor_mutex_t tor_mutex_t;
#ifdef TOR_IS_MULTITHREADED
@@ -316,20 +280,5 @@ unsigned long tor_get_thread_id(void);
#define tor_get_thread_id() (1UL)
#endif
-/*for some reason my compiler doesn't have these version flags defined
- a nice homework assignment for someone one day is to define the rest*/
-//these are the values as given on MSDN
-#ifdef MS_WINDOWS
-
-#ifndef VER_SUITE_EMBEDDEDNT
-#define VER_SUITE_EMBEDDEDNT 0x00000040
-#endif
-
-#ifndef VER_SUITE_SINGLEUSERTS
-#define VER_SUITE_SINGLEUSERTS 0x00000100
-#endif
-
-#endif
-
#endif
diff --git a/src/common/container.c b/src/common/container.c
index 64ad420633..33a77cd42c 100644
--- a/src/common/container.c
+++ b/src/common/container.c
@@ -50,7 +50,6 @@ smartlist_create(void)
void
smartlist_free(smartlist_t *sl)
{
- tor_assert(sl != NULL);
tor_free(sl->list);
tor_free(sl);
}
@@ -128,32 +127,6 @@ smartlist_remove(smartlist_t *sl, const void *element)
}
}
-/** If <b>sl</b> is nonempty, remove and return the final element. Otherwise,
- * return NULL. */
-void *
-smartlist_pop_last(smartlist_t *sl)
-{
- tor_assert(sl);
- if (sl->num_used)
- return sl->list[--sl->num_used];
- else
- return NULL;
-}
-
-/** Reverse the order of the items in <b>sl</b>. */
-void
-smartlist_reverse(smartlist_t *sl)
-{
- int i, j;
- void *tmp;
- tor_assert(sl);
- for (i = 0, j = sl->num_used-1; i < j; ++i, --j) {
- tmp = sl->list[i];
- sl->list[i] = sl->list[j];
- sl->list[j] = tmp;
- }
-}
-
/** If there are any strings in sl equal to element, remove and free them.
* Does not preserve order. */
void
@@ -429,29 +402,6 @@ smartlist_sort(smartlist_t *sl, int (*compare)(const void **a, const void **b))
(int (*)(const void *,const void*))compare);
}
-/** Given a sorted smartlist <b>sl</b> and the comparison function used to
- * sort it, remove all duplicate members. If free_fn is provided, calls
- * free_fn on each duplicate. Otherwise, frees them with tor_free(), which
- * may not be what you want.. Preserves order.
- */
-void
-smartlist_uniq(smartlist_t *sl,
- int (*compare)(const void **a, const void **b),
- void (*free_fn)(void *a))
-{
- int i;
- for (i=1; i < sl->num_used; ++i) {
- if (compare((const void **)&(sl->list[i-1]),
- (const void **)&(sl->list[i])) == 0) {
- if (free_fn)
- free_fn(sl->list[i]);
- else
- tor_free(sl->list[i]);
- smartlist_del_keeporder(sl, i--);
- }
- }
-}
-
/** Assuming the members of <b>sl</b> are in order, return a pointer to the
* member which matches <b>key</b>. Ordering and matching are defined by a
* <b>compare</b> function, which returns 0 on a match; less than 0 if key is
@@ -485,117 +435,6 @@ smartlist_sort_strings(smartlist_t *sl)
smartlist_sort(sl, _compare_string_ptrs);
}
-/** Remove duplicate strings from a sorted list, and free them with tor_free().
- */
-void
-smartlist_uniq_strings(smartlist_t *sl)
-{
- smartlist_uniq(sl, _compare_string_ptrs, NULL);
-}
-
-#define LEFT_CHILD(i) ( ((i)+1)*2 - 1)
-#define RIGHT_CHILD(i) ( ((i)+1)*2 )
-#define PARENT(i) ( ((i)+1)/2 - 1)
-
-static INLINE void
-smartlist_heapify(smartlist_t *sl,
- int (*compare)(const void *a, const void *b),
- int idx)
-{
- while (1) {
- int left_idx = LEFT_CHILD(idx);
- int best_idx;
-
- if (left_idx >= sl->num_used)
- return;
- if (compare(sl->list[idx],sl->list[left_idx]) < 0)
- best_idx = idx;
- else
- best_idx = left_idx;
- if (left_idx+1 < sl->num_used &&
- compare(sl->list[left_idx+1],sl->list[best_idx]) < 0)
- best_idx = left_idx + 1;
-
- if (best_idx == idx) {
- return;
- } else {
- void *tmp = sl->list[idx];
- sl->list[idx] = sl->list[best_idx];
- sl->list[best_idx] = tmp;
-
- idx = best_idx;
- }
- }
-}
-
-void
-smartlist_pqueue_add(smartlist_t *sl,
- int (*compare)(const void *a, const void *b),
- void *item)
-{
- int idx;
- smartlist_add(sl,item);
-
- for (idx = sl->num_used - 1; idx; ) {
- int parent = PARENT(idx);
- if (compare(sl->list[idx], sl->list[parent]) < 0) {
- void *tmp = sl->list[parent];
- sl->list[parent] = sl->list[idx];
- sl->list[idx] = tmp;
- idx = parent;
- } else {
- return;
- }
- }
-}
-
-void *
-smartlist_pqueue_pop(smartlist_t *sl,
- int (*compare)(const void *a, const void *b))
-{
- void *top;
- tor_assert(sl->num_used);
-
- top = sl->list[0];
- if (--sl->num_used) {
- sl->list[0] = sl->list[sl->num_used];
- smartlist_heapify(sl, compare, 0);
- }
- return top;
-}
-
-void
-smartlist_pqueue_assert_ok(smartlist_t *sl,
- int (*compare)(const void *a, const void *b))
-{
- int i;
- for (i = sl->num_used - 1; i > 0; --i) {
- tor_assert(compare(sl->list[PARENT(i)], sl->list[i]) <= 0);
- }
-}
-
-/** Helper: compare two DIGEST_LEN digests. */
-static int
-_compare_digests(const void **_a, const void **_b)
-{
- return memcmp((const char*)*_a, (const char*)*_b, DIGEST_LEN);
-}
-
-/** Sort the list of DIGEST_LEN-byte digests into ascending order. */
-void
-smartlist_sort_digests(smartlist_t *sl)
-{
- smartlist_sort(sl, _compare_digests);
-}
-
-/** Remove duplicate digests from a sorted list, and free them with tor_free().
- */
-void
-smartlist_uniq_digests(smartlist_t *sl)
-{
- smartlist_uniq(sl, _compare_digests, NULL);
-}
-
#define DEFINE_MAP_STRUCTS(maptype, keydecl, prefix) \
typedef struct prefix ## entry_t { \
HT_ENTRY(prefix ## entry_t) node; \
@@ -863,7 +702,7 @@ strmap_remove_lc(strmap_t *map, const char *key)
* iter = strmap_iter_next_rmv(iter);
* free(val);
* } else {
- * for (;*cp;cp++) *cp = TOR_TOUPPER(*cp);
+ * for (;*cp;cp++) *cp = toupper(*cp);
* iter = strmap_iter_next(iter);
* }
* }
@@ -1005,17 +844,6 @@ digestmap_free(digestmap_t *map, void (*free_val)(void*))
tor_free(map);
}
-void
-strmap_assert_ok(strmap_t *map)
-{
- tor_assert(!_strmap_impl_HT_REP_IS_BAD(&map->head));
-}
-void
-digestmap_assert_ok(digestmap_t *map)
-{
- tor_assert(!_digestmap_impl_HT_REP_IS_BAD(&map->head));
-}
-
/** Return true iff <b>map</b> has no entries. */
int
strmap_isempty(strmap_t *map)
diff --git a/src/common/container.h b/src/common/container.h
index 5f0417cf4d..83c0f28229 100644
--- a/src/common/container.h
+++ b/src/common/container.h
@@ -29,29 +29,24 @@ void smartlist_clear(smartlist_t *sl);
void smartlist_add(smartlist_t *sl, void *element);
void smartlist_add_all(smartlist_t *sl, const smartlist_t *s2);
void smartlist_remove(smartlist_t *sl, const void *element);
-void *smartlist_pop_last(smartlist_t *sl);
-void smartlist_reverse(smartlist_t *sl);
void smartlist_string_remove(smartlist_t *sl, const char *element);
-int smartlist_isin(const smartlist_t *sl, const void *element) ATTR_PURE;
-int smartlist_string_isin(const smartlist_t *sl, const char *element)
- ATTR_PURE;
-int smartlist_string_num_isin(const smartlist_t *sl, int num) ATTR_PURE;
-int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2)
- ATTR_PURE;
+int smartlist_isin(const smartlist_t *sl, const void *element);
+int smartlist_string_isin(const smartlist_t *sl, const char *element);
+int smartlist_string_num_isin(const smartlist_t *sl, int num);
+int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2);
void smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2);
void smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2);
-
/* smartlist_choose() is defined in crypto.[ch] */
#ifdef DEBUG_SMARTLIST
/** Return the number of items in sl.
*/
-extern INLINE int smartlist_len(const smartlist_t *sl) ATTR_PURE {
+extern INLINE int smartlist_len(const smartlist_t *sl) {
tor_assert(sl);
return (sl)->num_used;
}
/** Return the <b>idx</b>th element of sl.
*/
-extern INLINE void *smartlist_get(const smartlist_t *sl, int idx) ATTR_PURE {
+extern INLINE void *smartlist_get(const smartlist_t *sl, int idx) {
tor_assert(sl);
tor_assert(idx>=0);
tor_assert(sl->num_used < idx);
@@ -74,34 +69,18 @@ void smartlist_del_keeporder(smartlist_t *sl, int idx);
void smartlist_insert(smartlist_t *sl, int idx, void *val);
void smartlist_sort(smartlist_t *sl,
int (*compare)(const void **a, const void **b));
-void smartlist_uniq(smartlist_t *sl,
- int (*compare)(const void **a, const void **b),
- void (*free_fn)(void *elt));
void smartlist_sort_strings(smartlist_t *sl);
-void smartlist_sort_digests(smartlist_t *sl);
-void smartlist_uniq_strings(smartlist_t *sl);
-void smartlist_uniq_digests(smartlist_t *sl);
void *smartlist_bsearch(smartlist_t *sl, const void *key,
- int (*compare)(const void *key, const void **member))
- ATTR_PURE;
-
-void smartlist_pqueue_add(smartlist_t *sl,
- int (*compare)(const void *a, const void *b),
- void *item);
-void *smartlist_pqueue_pop(smartlist_t *sl,
- int (*compare)(const void *a, const void *b));
-void smartlist_pqueue_assert_ok(smartlist_t *sl,
- int (*compare)(const void *a, const void *b));
+ int (*compare)(const void *key, const void **member));
#define SPLIT_SKIP_SPACE 0x01
#define SPLIT_IGNORE_BLANK 0x02
int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep,
int flags, int max);
char *smartlist_join_strings(smartlist_t *sl, const char *join, int terminate,
- size_t *len_out) ATTR_MALLOC;
+ size_t *len_out);
char *smartlist_join_strings2(smartlist_t *sl, const char *join,
- size_t join_len, int terminate, size_t *len_out)
- ATTR_MALLOC;
+ size_t join_len, int terminate, size_t *len_out);
/** Iterate over the items in a smartlist <b>sl</b>, in order. For each item,
* assign it to a new local variable of type <b>type</b> named <b>var</b>, and
@@ -143,8 +122,7 @@ char *smartlist_join_strings2(smartlist_t *sl, const char *join,
prefix##iter_t *prefix##iter_next(maptype *map, prefix##iter_t *iter); \
prefix##iter_t *prefix##iter_next_rmv(maptype *map, prefix##iter_t *iter); \
void prefix##iter_get(prefix##iter_t *iter, keytype *keyp, void **valp); \
- int prefix##iter_done(prefix##iter_t *iter); \
- void prefix##assert_ok(maptype *map);
+ int prefix##iter_done(prefix##iter_t *iter);
/* Map from const char * to void *. Implemented with a hash table. */
DECLARE_MAP_FNS(strmap_t, const char *, strmap_);
diff --git a/src/common/crypto.c b/src/common/crypto.c
index 57b504f5ba..62e7c3c245 100644
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@ -189,10 +189,6 @@ crypto_global_init(int useAccel)
OpenSSL_add_all_algorithms();
_crypto_global_initialized = 1;
setup_openssl_threading();
- /* XXX the below is a bug, since we can't know if we're supposed
- * to be using hardware acceleration or not. we should arrange
- * for this function to be called before init_keys. But make it
- * not complain loudly, at least until we make acceleration work. */
if (useAccel < 0) {
log_info(LD_CRYPTO, "Initializing OpenSSL via tor_tls_init().");
}
@@ -503,13 +499,13 @@ crypto_pk_write_public_key_to_string(crypto_pk_env_t *env, char **dest,
}
BIO_get_mem_ptr(b, &buf);
- (void)BIO_set_close(b, BIO_NOCLOSE); /* so BIO_free doesn't free buf */
+ BIO_set_close(b, BIO_NOCLOSE); /* so BIO_free doesn't free buf */
BIO_free(b);
tor_assert(buf->length >= 0);
*dest = tor_malloc(buf->length+1);
memcpy(*dest, buf->data, buf->length);
- (*dest)[buf->length] = 0; /* nul terminate it */
+ (*dest)[buf->length] = 0; /* null terminate it */
*len = buf->length;
BUF_MEM_free(buf);
@@ -579,6 +575,70 @@ crypto_pk_write_private_key_to_filename(crypto_pk_env_t *env,
return r;
}
+/** Allocate a new string in *<b>out</b>, containing the public portion of the
+ * RSA key in <b>env</b>, encoded first with DER, then in base-64. Return the
+ * length of the encoded representation on success, and -1 on failure.
+ *
+ * <i>This function is for temporary use only. We need a simple
+ * one-line representation for keys to work around a bug in parsing
+ * directories containing "opt keyword\n-----BEGIN OBJECT----" entries
+ * in versions of Tor up to 0.0.9pre2.</i>
+ */
+int
+crypto_pk_DER64_encode_public_key(crypto_pk_env_t *env, char **out)
+{
+ int len;
+ char buf[PK_BYTES*2]; /* Too long, but hey, stacks are big. */
+ tor_assert(env);
+ tor_assert(out);
+ len = crypto_pk_asn1_encode(env, buf, sizeof(buf));
+ if (len < 0) {
+ return -1;
+ }
+ *out = tor_malloc(len * 2); /* too long, but safe. */
+ if (base64_encode(*out, len*2, buf, len) < 0) {
+ log_warn(LD_CRYPTO, "Error base64-encoding DER-encoded key");
+ tor_free(*out);
+ return -1;
+ }
+ /* Remove spaces */
+ tor_strstrip(*out, " \r\n\t");
+ return strlen(*out);
+}
+
+/** Decode a base-64 encoded DER representation of an RSA key from <b>in</b>,
+ * and store the result in <b>env</b>. Return 0 on success, -1 on failure.
+ *
+ * <i>This function is for temporary use only. We need a simple
+ * one-line representation for keys to work around a bug in parsing
+ * directories containing "opt keyword\n-----BEGIN OBJECT----" entries
+ * in versions of Tor up to 0.0.9pre2.</i>
+ */
+crypto_pk_env_t *
+crypto_pk_DER64_decode_public_key(const char *in)
+{
+ char partitioned[PK_BYTES*2 + 16];
+ char buf[PK_BYTES*2];
+ int len;
+ tor_assert(in);
+ len = strlen(in);
+
+ if (strlen(in) > PK_BYTES*2) {
+ return NULL;
+ }
+ /* base64_decode doesn't work unless we insert linebreaks every 64
+ * characters. how dumb. */
+ if (tor_strpartition(partitioned, sizeof(partitioned), in, "\n", 64,
+ ALWAYS_TERMINATE))
+ return NULL;
+ len = base64_decode(buf, sizeof(buf), partitioned, strlen(partitioned));
+ if (len<0) {
+ log_warn(LD_CRYPTO,"Error base-64 decoding key");
+ return NULL;
+ }
+ return crypto_pk_asn1_decode(buf, len);
+}
+
/** Return true iff <b>env</b> has a valid key.
*/
int
@@ -1806,8 +1866,6 @@ secret_to_key(char *key_out, size_t key_out_len, const char *secret,
static void
_openssl_locking_cb(int mode, int n, const char *file, int line)
{
- (void)file;
- (void)line;
if (!_openssl_mutexes)
/* This is not a really good fix for the
* "release-freed-lock-from-separate-thread-on-shutdown" problem, but
diff --git a/src/common/crypto.h b/src/common/crypto.h
index 050849cfe5..df112a1d8e 100644
--- a/src/common/crypto.h
+++ b/src/common/crypto.h
@@ -79,6 +79,8 @@ int crypto_pk_read_public_key_from_string(crypto_pk_env_t *env,
const char *src, size_t len);
int crypto_pk_write_private_key_to_filename(crypto_pk_env_t *env,
const char *fname);
+int crypto_pk_DER64_encode_public_key(crypto_pk_env_t *env, char **dest);
+crypto_pk_env_t *crypto_pk_DER64_decode_public_key(const char *in);
int crypto_pk_check_key(crypto_pk_env_t *env);
int crypto_pk_cmp_keys(crypto_pk_env_t *a, crypto_pk_env_t *b);
diff --git a/src/common/ht.h b/src/common/ht.h
index a83e093264..dd90f2e4fd 100644
--- a/src/common/ht.h
+++ b/src/common/ht.h
@@ -99,7 +99,7 @@ ht_string_hash(const char *s)
#define HT_PROTOTYPE(name, type, field, hashfn, eqfn) \
int name##_HT_GROW(struct name *ht, unsigned min_capacity); \
void name##_HT_CLEAR(struct name *ht); \
- int _##name##_HT_REP_IS_BAD(struct name *ht); \
+ int _##name##_HT_REP_OK(struct name *ht); \
/* Helper: returns a pointer to the right location in the table \
* 'head' to find or insert the element 'elm'. */ \
static INLINE struct type ** \
@@ -187,6 +187,7 @@ ht_string_hash(const char *s)
int (*fn)(struct type *, void *), \
void *data) \
{ \
+ /* XXXX use tricks to prevent concurrent mod? */ \
unsigned idx; \
int remove; \
struct type **p, **nextp, *next; \
@@ -260,6 +261,77 @@ ht_string_hash(const char *s)
} \
}
+#if 0
+/* Helpers for an iterator type that saves some mod operations at the expense
+ * of many branches. Not worth it, it seems. */
+
+#define HT_ITER(type) \
+ struct type##_ITER { \
+ struct type **hti_nextp; \
+ unsigned hti_bucket; \
+ }
+
+ static INLINE void \
+ name##_HT_ITER_START(struct name *head, struct type##_ITER *iter) \
+ { \
+ /* XXXX Magic to stop modifications? */ \
+ iter->hti_bucket = 0; \
+ while (iter->hti_bucket < head->hth_table_length) { \
+ iter->hti_nextp = &head->hth_table[iter->hti_bucket]; \
+ if (*iter->hti_nextp) \
+ return; \
+ ++iter->hti_bucket; \
+ } \
+ iter->hti_nextp = NULL; \
+ } \
+ static INLINE int \
+ name##_HT_ITER_DONE(struct name *head, struct type##_ITER *iter) \
+ { \
+ return iter->hti_nextp == NULL; \
+ } \
+ static INLINE struct type * \
+ name##_HT_ITER_GET(struct name *head, struct type##_ITER *iter) \
+ { \
+ return *iter->hti_nextp; \
+ } \
+ static INLINE void \
+ name##_HT_ITER_NEXT(struct name *head, struct type##_ITER *iter) \
+ { \
+ if (!iter->hti_nextp) \
+ return; \
+ if ((*iter->hti_nextp)->field.hte_next) { \
+ iter->hti_nextp = &(*iter->hti_nextp)->field.hte_next; \
+ return; \
+ } \
+ while (++iter->hti_bucket < head->hth_table_length) { \
+ iter->hti_nextp = &head->hth_table[iter->hti_bucket]; \
+ if (*iter->hti_nextp) \
+ return; \
+ ++iter->hti_bucket; \
+ } \
+ iter->hti_nextp = NULL; \
+ } \
+ static INLINE void \
+ name##_HT_ITER_NEXT_RMV(struct name *head, struct type##_ITER *iter) \
+ { \
+ if (!iter->hti_nextp) \
+ return; \
+ --head->hth_n_entries; \
+ if ((*iter->hti_nextp)->field.hte_next) { \
+ *iter->hti_nextp = (*iter->hti_nextp)->field.hte_next; \
+ if (*iter->hti_nextp) \
+ return; \
+ } \
+ while (++iter->hti_bucket < head->hth_table_length) { \
+ iter->hti_nextp = &head->hth_table[iter->hti_bucket]; \
+ if (*iter->hti_nextp) \
+ return; \
+ ++iter->hti_bucket; \
+ } \
+ iter->hti_nextp = NULL; \
+ }
+#endif
+
#define HT_GENERATE(name, type, field, hashfn, eqfn, load, mallocfn, \
reallocfn, freefn) \
static unsigned name##_PRIMES[] = { \
@@ -345,41 +417,38 @@ ht_string_hash(const char *s)
head->hth_table_length = 0; \
HT_INIT(head); \
} \
- /* Debugging helper: return false iff the representation of 'head' is \
+ /* Debugging helper: return true iff the representation of 'head' is \
* internally consistent. */ \
int \
- _##name##_HT_REP_IS_BAD(struct name *head) \
+ _##name##_HT_REP_OK(struct name *head) \
{ \
unsigned n, i; \
struct type *elm; \
if (!head->hth_table_length) { \
- if (!head->hth_table && !head->hth_n_entries && \
- !head->hth_load_limit && head->hth_prime_idx == -1) \
- return 0; \
- else \
- return 1; \
+ return !head->hth_table && !head->hth_n_entries && \
+ !head->hth_load_limit && head->hth_prime_idx == -1; \
} \
if (!head->hth_table || head->hth_prime_idx < 0 || \
!head->hth_load_limit) \
- return 2; \
+ return 0; \
if (head->hth_n_entries > head->hth_load_limit) \
- return 3; \
+ return 0; \
if (head->hth_table_length != name##_PRIMES[head->hth_prime_idx]) \
- return 4; \
+ return 0; \
if (head->hth_load_limit != (unsigned)(load*head->hth_table_length)) \
- return 5; \
+ return 0; \
for (n = i = 0; i < head->hth_table_length; ++i) { \
for (elm = head->hth_table[i]; elm; elm = elm->field.hte_next) { \
if (elm->field.hte_hash != hashfn(elm)) \
- return 1000 + i; \
+ return 0; \
if ((elm->field.hte_hash % head->hth_table_length) != i) \
- return 10000 + i; \
+ return 0; \
++n; \
} \
} \
if (n != head->hth_n_entries) \
- return 6; \
- return 0; \
+ return 0; \
+ return 1; \
}
/*
diff --git a/src/common/log.c b/src/common/log.c
index 1d9c10d565..677cb5241c 100644
--- a/src/common/log.c
+++ b/src/common/log.c
@@ -327,12 +327,9 @@ close_logs(void)
}
/** Remove and free the log entry <b>victim</b> from the linked-list
- * logfiles (it is probably present, but it might not be due to thread
- * racing issues). After this function is called, the caller shouldn't
- * refer to <b>victim</b> anymore.
- *
- * Long-term, we need to do something about races in the log subsystem
- * in general. See bug 222 for more details.
+ * logfiles (it must be present in the list when this function is
+ * called). After this function is called, the caller shouldn't refer
+ * to <b>victim</b> anymore.
*/
static void
delete_log(logfile_t *victim)
diff --git a/src/common/log.h b/src/common/log.h
index 8122a94aa6..1b4c96e8fa 100644
--- a/src/common/log.h
+++ b/src/common/log.h
@@ -23,12 +23,14 @@
"We aren't prepared to deal with that."
#endif
#else
-/* Note: Syslog's logging code refers to priorities, with 0 being the most
- * important. Thus, all our comparisons needed to be reversed when we added
- * syslog support.
+/* XXXX Note: The code was originally written to refer to severities,
+ * with 0 being the least severe; while syslog's logging code refers to
+ * priorities, with 0 being the most important. Thus, all our comparisons
+ * needed to be reversed when we added syslog support.
*
- * The upshot of this is that comments about log levels may be messed up: for
- * "maximum severity" read "most severe" and "numerically *lowest* severity".
+ * The upshot of this is that comments about log levels may be messed
+ * up: for "maximum severity" read "most severe" and "numerically
+ * *lowest* severity".
*/
/** Debug-level severity: for hyper-verbose messages of no interest to
diff --git a/src/common/torgzip.c b/src/common/torgzip.c
index ec02870776..12cc7ec969 100644
--- a/src/common/torgzip.c
+++ b/src/common/torgzip.c
@@ -15,7 +15,7 @@ const char torgzip_c_id[] =
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
-#ifdef _MSC_VER
+#ifdef MS_WINDOWS
#include "..\..\contrib\zlib\zlib.h"
#else
#include <zlib.h>
@@ -282,97 +282,3 @@ detect_compression_method(const char *in, size_t in_len)
}
}
-struct tor_zlib_state_t {
- struct z_stream_s stream;
- int compress;
-};
-
-/** DOCDOC */
-tor_zlib_state_t *
-tor_zlib_new(int compress, compress_method_t method)
-{
- tor_zlib_state_t *out;
-
- if (method == GZIP_METHOD && !is_gzip_supported()) {
- /* Old zlib version don't support gzip in inflateInit2 */
- log_warn(LD_GENERAL, "Gzip not supported with zlib %s", ZLIB_VERSION);
- return NULL;
- }
-
- out = tor_malloc_zero(sizeof(tor_zlib_state_t));
- out->stream.zalloc = Z_NULL;
- out->stream.zfree = Z_NULL;
- out->stream.opaque = NULL;
- out->compress = compress;
- if (compress) {
- if (deflateInit2(&out->stream, Z_BEST_COMPRESSION, Z_DEFLATED,
- method_bits(method), 8, Z_DEFAULT_STRATEGY) != Z_OK)
- goto err;
- } else {
- if (inflateInit2(&out->stream, method_bits(method)) != Z_OK)
- goto err;
- }
- return out;
-
- err:
- tor_free(out);
- return NULL;
-}
-
-/** DOCDOC */
-tor_zlib_output_t
-tor_zlib_process(tor_zlib_state_t *state,
- char **out, size_t *out_len,
- const char **in, size_t *in_len,
- int finish)
-{
- int err;
- state->stream.next_in = (unsigned char*) *in;
- state->stream.avail_in = *in_len;
- state->stream.next_out = (unsigned char*) *out;
- state->stream.avail_out = *out_len;
-
- if (state->compress) {
- err = deflate(&state->stream, finish ? Z_FINISH : Z_SYNC_FLUSH);
- } else {
- err = inflate(&state->stream, finish ? Z_FINISH : Z_SYNC_FLUSH);
- }
-
- *out = (char*) state->stream.next_out;
- *out_len = state->stream.avail_out;
- *in = (const char *) state->stream.next_in;
- *in_len = state->stream.avail_in;
-
- switch (err)
- {
- case Z_STREAM_END:
- return TOR_ZLIB_DONE;
- case Z_BUF_ERROR:
- if (state->stream.avail_in == 0)
- return Z_OK;
- return TOR_ZLIB_BUF_FULL;
- case Z_OK:
- if (state->stream.avail_out == 0 || finish)
- return TOR_ZLIB_BUF_FULL;
- return TOR_ZLIB_OK;
- default:
- log_warn(LD_GENERAL, "Gzip returned an error: %s",
- state->stream.msg ? state->stream.msg : "<no message>");
- return TOR_ZLIB_ERR;
- }
-}
-
-/** DOCDOC */
-void
-tor_zlib_free(tor_zlib_state_t *state)
-{
- tor_assert(state);
-
- if (state->compress)
- deflateEnd(&state->stream);
- else
- inflateEnd(&state->stream);
-
- tor_free(state);
-}
-
diff --git a/src/common/torgzip.h b/src/common/torgzip.h
index 153ab4992d..134ef03268 100644
--- a/src/common/torgzip.h
+++ b/src/common/torgzip.h
@@ -31,17 +31,5 @@ int is_gzip_supported(void);
int detect_compression_method(const char *in, size_t in_len);
-typedef enum {
- TOR_ZLIB_OK, TOR_ZLIB_DONE, TOR_ZLIB_BUF_FULL, TOR_ZLIB_ERR
-} tor_zlib_output_t;
-typedef struct tor_zlib_state_t tor_zlib_state_t;
-tor_zlib_state_t *tor_zlib_new(int compress, compress_method_t method);
-
-tor_zlib_output_t tor_zlib_process(tor_zlib_state_t *state,
- char **out, size_t *out_len,
- const char **in, size_t *in_len,
- int finish);
-void tor_zlib_free(tor_zlib_state_t *state);
-
#endif
diff --git a/src/common/torint.h b/src/common/torint.h
index b69af3eeae..8202baa597 100644
--- a/src/common/torint.h
+++ b/src/common/torint.h
@@ -155,9 +155,6 @@ typedef unsigned long long uint64_t;
#ifndef UINT64_MAX
#define UINT64_MAX 0xffffffffffffffffull
#endif
-#ifndef INT64_MAX
-#define INT64_MAX 0x7fffffffffffffffll
-#endif
#endif
#if (SIZEOF___INT64 == 8)
@@ -172,9 +169,6 @@ typedef unsigned __int64 uint64_t;
#ifndef UINT64_MAX
#define UINT64_MAX 0xffffffffffffffffui64
#endif
-#ifndef INT64_MAX
-#define INT64_MAX 0x7fffffffffffffffi64
-#endif
#endif
#if (SIZEOF_VOID_P > 4 && SIZEOF_VOID_P <= 8)
diff --git a/src/common/tortls.c b/src/common/tortls.c
index d9e71a6380..4401185c59 100644
--- a/src/common/tortls.c
+++ b/src/common/tortls.c
@@ -40,6 +40,7 @@ const char tortls_c_id[] =
/* DOCDOC */
typedef struct tor_tls_context_t {
SSL_CTX *ctx;
+ SSL_CTX *client_only_ctx;
} tor_tls_context_t;
/** Holds a SSL object and its associated data. Members are only
@@ -169,6 +170,7 @@ tor_tls_free_all(void)
{
if (global_tls_context) {
SSL_CTX_free(global_tls_context->ctx);
+ SSL_CTX_free(global_tls_context->client_only_ctx);
tor_free(global_tls_context);
global_tls_context = NULL;
}
@@ -232,7 +234,7 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa,
if ((nid = OBJ_txt2nid("organizationName")) == NID_undef)
goto error;
if (!(X509_NAME_add_entry_by_NID(name, nid, MBSTRING_ASC,
- (unsigned char*)"Tor", -1, -1, 0)))
+ (unsigned char*)"TOR", -1, -1, 0)))
goto error;
if ((nid = OBJ_txt2nid("commonName")) == NID_undef) goto error;
if (!(X509_NAME_add_entry_by_NID(name, nid, MBSTRING_ASC,
@@ -246,7 +248,7 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa,
if ((nid = OBJ_txt2nid("organizationName")) == NID_undef)
goto error;
if (!(X509_NAME_add_entry_by_NID(name_issuer, nid, MBSTRING_ASC,
- (unsigned char*)"Tor", -1, -1, 0)))
+ (unsigned char*)"TOR", -1, -1, 0)))
goto error;
if ((nid = OBJ_txt2nid("commonName")) == NID_undef) goto error;
if (!(X509_NAME_add_entry_by_NID(name_issuer, nid, MBSTRING_ASC,
@@ -299,16 +301,20 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa,
#define CIPHER_LIST SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA
#endif
-/** Create a new TLS context for use with Tor TLS handshakes.
- * <b>identity</b> should be set to the identity key used to sign the
- * certificate, and <b>nickname</b> set to the nickname to use.
+/** Create a new TLS context. If we are going to be using it as a
+ * server, it must have isServer set to true, <b>identity</b> set to the
+ * identity key used to sign that certificate, and <b>nickname</b> set to
+ * the server's nickname. If we're only going to be a client,
+ * isServer should be false, identity should be NULL, and nickname
+ * should be NULL. Return -1 if failure, else 0.
*
* You can call this function multiple times. Each time you call it,
* it generates new certificates; all new connections will use
* the new SSL context.
*/
int
-tor_tls_context_new(crypto_pk_env_t *identity, const char *nickname,
+tor_tls_context_new(crypto_pk_env_t *identity,
+ int isServer, const char *nickname,
unsigned int key_lifetime)
{
crypto_pk_env_t *rsa = NULL;
@@ -317,71 +323,86 @@ tor_tls_context_new(crypto_pk_env_t *identity, const char *nickname,
tor_tls_context_t *result = NULL;
X509 *cert = NULL, *idcert = NULL;
char nn2[128];
+ int client_only;
+ SSL_CTX **ctx;
if (!nickname)
nickname = "null";
tor_snprintf(nn2, sizeof(nn2), "%s <identity>", nickname);
tor_tls_init();
- /* Generate short-term RSA key. */
- if (!(rsa = crypto_new_pk_env()))
- goto error;
- if (crypto_pk_generate_key(rsa)<0)
- goto error;
- /* Create certificate signed by identity key. */
- cert = tor_tls_create_certificate(rsa, identity, nickname, nn2,
- key_lifetime);
- /* Create self-signed certificate for identity key. */
- idcert = tor_tls_create_certificate(identity, identity, nn2, nn2,
- IDENTITY_CERT_LIFETIME);
- if (!cert || !idcert) {
- log(LOG_WARN, LD_CRYPTO, "Error creating certificate");
- goto error;
+ if (isServer) {
+ /* Generate short-term RSA key. */
+ if (!(rsa = crypto_new_pk_env()))
+ goto error;
+ if (crypto_pk_generate_key(rsa)<0)
+ goto error;
+ /* Create certificate signed by identity key. */
+ cert = tor_tls_create_certificate(rsa, identity, nickname, nn2,
+ key_lifetime);
+ /* Create self-signed certificate for identity key. */
+ idcert = tor_tls_create_certificate(identity, identity, nn2, nn2,
+ IDENTITY_CERT_LIFETIME);
+ if (!cert || !idcert) {
+ log(LOG_WARN, LD_CRYPTO, "Error creating certificate");
+ goto error;
+ }
}
result = tor_malloc(sizeof(tor_tls_context_t));
+ result->ctx = result->client_only_ctx = NULL;
+ for (client_only=0; client_only <= 1; ++client_only) {
+ ctx = client_only ? &result->client_only_ctx : &result->ctx;
#ifdef EVERYONE_HAS_AES
- /* Tell OpenSSL to only use TLS1 */
- if (!(result->ctx = SSL_CTX_new(TLSv1_method())))
- goto error;
+ /* Tell OpenSSL to only use TLS1 */
+ if (!(*ctx = SSL_CTX_new(TLSv1_method())))
+ goto error;
#else
- /* Tell OpenSSL to use SSL3 or TLS1 but not SSL2. */
- if (!(result->ctx = SSL_CTX_new(SSLv23_method())))
- goto error;
- SSL_CTX_set_options(result->ctx, SSL_OP_NO_SSLv2);
+ /* Tell OpenSSL to use SSL3 or TLS1 but not SSL2. */
+ if (!(*ctx = SSL_CTX_new(SSLv23_method())))
+ goto error;
+ SSL_CTX_set_options(*ctx, SSL_OP_NO_SSLv2);
#endif
- SSL_CTX_set_options(result->ctx, SSL_OP_SINGLE_DH_USE);
- if (!SSL_CTX_set_cipher_list(result->ctx, CIPHER_LIST))
- goto error;
- if (cert && !SSL_CTX_use_certificate(result->ctx,cert))
- goto error;
- X509_free(cert); /* We just added a reference to cert. */
- cert=NULL;
- if (idcert && !SSL_CTX_add_extra_chain_cert(result->ctx,idcert))
- goto error;
- idcert=NULL; /* The context now owns the reference to idcert */
- SSL_CTX_set_session_cache_mode(result->ctx, SSL_SESS_CACHE_OFF);
- tor_assert(rsa);
- if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa,1)))
- goto error;
- if (!SSL_CTX_use_PrivateKey(result->ctx, pkey))
- goto error;
- EVP_PKEY_free(pkey);
- pkey = NULL;
- if (!SSL_CTX_check_private_key(result->ctx))
- goto error;
- dh = crypto_dh_new();
- SSL_CTX_set_tmp_dh(result->ctx, _crypto_dh_env_get_dh(dh));
- crypto_dh_free(dh);
- SSL_CTX_set_verify(result->ctx, SSL_VERIFY_PEER,
- always_accept_verify_cb);
- /* let us realloc bufs that we're writing from */
- SSL_CTX_set_mode(result->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+#ifndef ENABLE_0119_PARANOIA_A
+ SSL_CTX_set_options(*ctx, SSL_OP_SINGLE_DH_USE);
+#endif
+ if (!SSL_CTX_set_cipher_list(*ctx, CIPHER_LIST))
+ goto error;
+ if (!client_only) {
+ if (cert && !SSL_CTX_use_certificate(*ctx,cert))
+ goto error;
+ X509_free(cert); /* We just added a reference to cert. */
+ cert=NULL;
+ if (idcert && !SSL_CTX_add_extra_chain_cert(*ctx,idcert))
+ goto error;
+ idcert=NULL; /* The context now owns the reference to idcert */
+ }
+ SSL_CTX_set_session_cache_mode(*ctx, SSL_SESS_CACHE_OFF);
+ if (isServer && !client_only) {
+ tor_assert(rsa);
+ if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa,1)))
+ goto error;
+ if (!SSL_CTX_use_PrivateKey(*ctx, pkey))
+ goto error;
+ EVP_PKEY_free(pkey);
+ pkey = NULL;
+ if (!SSL_CTX_check_private_key(*ctx))
+ goto error;
+ }
+ dh = crypto_dh_new();
+ SSL_CTX_set_tmp_dh(*ctx, _crypto_dh_env_get_dh(dh));
+ crypto_dh_free(dh);
+ SSL_CTX_set_verify(*ctx, SSL_VERIFY_PEER,
+ always_accept_verify_cb);
+ /* let us realloc bufs that we're writing from */
+ SSL_CTX_set_mode(*ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+ }
/* Free the old context if one exists. */
if (global_tls_context) {
/* This is safe even if there are open connections: OpenSSL does
* reference counting with SSL and SSL_CTX objects. */
SSL_CTX_free(global_tls_context->ctx);
+ SSL_CTX_free(global_tls_context->client_only_ctx);
tor_free(global_tls_context);
}
global_tls_context = result;
@@ -399,6 +420,8 @@ tor_tls_context_new(crypto_pk_env_t *identity, const char *nickname,
crypto_dh_free(dh);
if (result && result->ctx)
SSL_CTX_free(result->ctx);
+ if (result && result->client_only_ctx)
+ SSL_CTX_free(result->client_only_ctx);
if (result)
tor_free(result);
if (cert)
@@ -412,29 +435,20 @@ tor_tls_context_new(crypto_pk_env_t *identity, const char *nickname,
* determine whether it is functioning as a server.
*/
tor_tls_t *
-tor_tls_new(int sock, int isServer)
+tor_tls_new(int sock, int isServer, int use_no_cert)
{
- BIO *bio = NULL;
tor_tls_t *result = tor_malloc(sizeof(tor_tls_t));
-
+ SSL_CTX *ctx;
tor_assert(global_tls_context); /* make sure somebody made it first */
- if (!(result->ssl = SSL_new(global_tls_context->ctx))) {
+ ctx = use_no_cert ? global_tls_context->client_only_ctx
+ : global_tls_context->ctx;
+ if (!(result->ssl = SSL_new(ctx))) {
tls_log_errors(LOG_WARN, "generating TLS context");
tor_free(result);
return NULL;
}
result->socket = sock;
-#ifdef USE_BSOCKETS
- bio = BIO_new_bsocket(sock, BIO_NOCLOSE);
-#else
- bio = BIO_new_socket(sock, BIO_NOCLOSE);
-#endif
- if (! bio) {
- tls_log_errors(LOG_WARN, "opening BIO");
- tor_free(result);
- return NULL;
- }
- SSL_set_bio(result->ssl, bio, bio);
+ SSL_set_fd(result->ssl, sock);
result->state = TOR_TLS_ST_HANDSHAKE;
result->isServer = isServer;
result->wantwrite_n = 0;
@@ -543,8 +557,7 @@ tor_tls_handshake(tor_tls_t *tls)
}
r = tor_tls_get_error(tls,r,0, "handshaking", LOG_INFO);
if (ERR_peek_error() != 0) {
- tls_log_errors(tls->isServer ? LOG_INFO : LOG_WARN,
- "handshaking");
+ tls_log_errors(LOG_WARN, "handshaking");
return TOR_TLS_ERROR;
}
if (r == TOR_TLS_DONE) {
@@ -704,7 +717,7 @@ log_cert_lifetime(X509 *cert, const char *problem)
BIO_get_mem_ptr(bio, &buf);
s1 = tor_strndup(buf->data, buf->length);
- (void)BIO_reset(bio);
+ BIO_reset(bio);
if (!(ASN1_TIME_print(bio, X509_get_notAfter(cert)))) {
tls_log_errors(LOG_WARN, "printing certificate lifetime");
goto end;
@@ -869,7 +882,7 @@ tor_tls_get_n_bytes_written(tor_tls_t *tls)
}
/** Implement check_no_tls_errors: If there are any pending OpenSSL
- * errors, log an error message. */
+ * errors, log an error message and assert(0). */
void
_check_no_tls_errors(const char *fname, int line)
{
diff --git a/src/common/tortls.h b/src/common/tortls.h
index 2569abf79c..82a64cb97a 100644
--- a/src/common/tortls.h
+++ b/src/common/tortls.h
@@ -26,9 +26,9 @@ typedef struct tor_tls_t tor_tls_t;
#define TOR_TLS_DONE 0
void tor_tls_free_all(void);
-int tor_tls_context_new(crypto_pk_env_t *rsa,
+int tor_tls_context_new(crypto_pk_env_t *rsa, int isServer,
const char *nickname, unsigned int key_lifetime);
-tor_tls_t *tor_tls_new(int sock, int is_server);
+tor_tls_t *tor_tls_new(int sock, int is_server, int use_no_cert);
int tor_tls_is_server(tor_tls_t *tls);
void tor_tls_free(tor_tls_t *tls);
int tor_tls_peer_has_cert(tor_tls_t *tls);
diff --git a/src/common/util.c b/src/common/util.c
index 99ac776dcb..f82cfc1263 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -46,6 +46,26 @@ const char util_c_id[] = "$Id$";
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef HAVE_SYS_LIMITS_H
+#include <sys/limits.h>
+#endif
+#ifdef HAVE_MACHINE_LIMITS_H
+#if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
+ /* FreeBSD has a bug where it complains that this file is obsolete,
+ and I should migrate to using sys/limits. It complains even when
+ I include both.
+ __FreeBSD_kernel__ is defined by Debian GNU/kFreeBSD which
+ does the same thing (but doesn't defined __FreeBSD__).
+ */
+#include <machine/limits.h>
+#endif
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h> /* Must be included before sys/stat.h for Ultrix */
+#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -106,21 +126,19 @@ _tor_malloc(size_t size DMALLOC_PARAMS)
{
void *result;
-#ifndef MALLOC_ZERO_WORKS
/* Some libcs don't do the right thing on size==0. Override them. */
if (size==0) {
size=1;
}
-#endif
result = dmalloc_malloc(file, line, size, DMALLOC_FUNC_MALLOC, 0, 0);
- if (PREDICT(result == NULL, 0)) {
+ if (!result) {
log_err(LD_MM,"Out of memory. Dying.");
- /* If these functions die within a worker process, they won't call
- * spawn_exit, but that's ok, since the parent will run out of memory soon
- * anyway. */
+ /* XXX if these functions die within a worker process, they won't
+ * call spawn_exit */
exit(1);
}
+// memset(result,'X',size); /* deadbeef to encourage bugs */
return result;
}
@@ -146,7 +164,7 @@ _tor_realloc(void *ptr, size_t size DMALLOC_PARAMS)
void *result;
result = dmalloc_realloc(file, line, ptr, size, DMALLOC_FUNC_REALLOC, 0);
- if (PREDICT(result == NULL, 0)) {
+ if (!result) {
log_err(LD_MM,"Out of memory. Dying.");
exit(1);
}
@@ -164,7 +182,7 @@ _tor_strdup(const char *s DMALLOC_PARAMS)
tor_assert(s);
dup = dmalloc_strdup(file, line, s, 0);
- if (PREDICT(dup == NULL, 0)) {
+ if (!dup) {
log_err(LD_MM,"Out of memory. Dying.");
exit(1);
}
@@ -192,26 +210,6 @@ _tor_strndup(const char *s, size_t n DMALLOC_PARAMS)
return dup;
}
-/** Allocate a chunk of <b>len</b> bytes, with the same contents starting at
- * <b>mem</b>. */
-void *
-_tor_memdup(const void *mem, size_t len DMALLOC_PARAMS)
-{
- char *dup;
- tor_assert(mem);
- dup = _tor_malloc(len DMALLOC_FN_ARGS);
- memcpy(dup, mem, len);
- return dup;
-}
-
-/** Helper for places that need to take a function pointer to the right
- * spelling of "free()". */
-void
-_tor_free(void *mem)
-{
- tor_free(mem);
-}
-
/* =====
* String manipulation
* ===== */
@@ -347,19 +345,6 @@ tor_strisprint(const char *s)
return 1;
}
-/** Return 1 if no character in <b>s</b> is uppercase, else return 0.
- */
-int
-tor_strisnonupper(const char *s)
-{
- while (*s) {
- if (TOR_ISUPPER(*s))
- return 0;
- s++;
- }
- return 1;
-}
-
/* Compares the first strlen(s2) characters of s1 with s2. Returns as for
* strcmp.
*/
@@ -414,23 +399,17 @@ eat_whitespace(const char *s)
{
tor_assert(s);
- while (1) {
- switch (*s) {
- case '\0':
- default:
- return s;
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- ++s;
- break;
- case '#':
- ++s;
+ while (TOR_ISSPACE(*s) || *s == '#') {
+ while (TOR_ISSPACE(*s))
+ s++;
+ if (*s == '#') { /* read to a \n or \0 */
while (*s && *s != '\n')
- ++s;
+ s++;
+ if (!*s)
+ return s;
}
}
+ return s;
}
/** Return a pointer to the first char of s that is not a space or a tab,
@@ -450,47 +429,20 @@ const char *
find_whitespace(const char *s)
{
/* tor_assert(s); */
- while (1) {
- switch (*s)
- {
- case '\0':
- case '#':
- case ' ':
- case '\r':
- case '\n':
- case '\t':
- return s;
- default:
- ++s;
- }
- }
-}
-/** Return true iff the 'len' bytes at 'mem' are all zero. */
-int
-tor_mem_is_zero(const char *mem, size_t len)
-{
- static const char ZERO[] = {
- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
- };
- while (len >= sizeof(ZERO)) {
- if (memcmp(mem, ZERO, sizeof(ZERO)))
- return 0;
- len -= sizeof(ZERO);
- mem += sizeof(ZERO);
- }
- /* Deal with leftover bytes. */
- if (len)
- return ! memcmp(mem, ZERO, len);
+ while (*s && !TOR_ISSPACE(*s) && *s != '#')
+ s++;
- return 1;
+ return s;
}
/** Return true iff the DIGEST_LEN bytes in digest are all zero. */
int
tor_digest_is_zero(const char *digest)
{
- return tor_mem_is_zero(digest, DIGEST_LEN);
+ static char ZERO_DIGEST[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
+
+ return !memcmp(digest, ZERO_DIGEST, DIGEST_LEN);
}
#define CHECK_STRTOX_RESULT() \
@@ -961,7 +913,7 @@ write_all(int fd, const char *buf, size_t count, int isSocket)
while (written != count) {
if (isSocket)
- result = tor_socket_send(fd, buf+written, count-written, 0);
+ result = send(fd, buf+written, count-written, 0);
else
result = write(fd, buf+written, count-written);
if (result<0)
@@ -987,7 +939,7 @@ read_all(int fd, char *buf, size_t count, int isSocket)
while (numread != count) {
if (isSocket)
- result = tor_socket_recv(fd, buf+numread, count-numread, 0);
+ result = recv(fd, buf+numread, count-numread, 0);
else
result = read(fd, buf+numread, count-numread);
if (result<0)
@@ -1018,8 +970,6 @@ clean_name_for_stat(char *name)
return;
name[len-1]='\0';
}
-#else
- (void)name;
#endif
}
@@ -1542,8 +1492,8 @@ is_local_IP(uint32_t ip)
* Return 0 on success, -1 on failure.
*/
int
-parse_addr_port(int severity, const char *addrport, char **address,
- uint32_t *addr, uint16_t *port_out)
+parse_addr_port(const char *addrport, char **address, uint32_t *addr,
+ uint16_t *port_out)
{
const char *colon;
char *_address = NULL;
@@ -1557,14 +1507,14 @@ parse_addr_port(int severity, const char *addrport, char **address,
_address = tor_strndup(addrport, colon-addrport);
_port = (int) tor_parse_long(colon+1,10,1,65535,NULL,NULL);
if (!_port) {
- log_fn(severity, LD_GENERAL, "Port %s out of range", escaped(colon+1));
+ log_warn(LD_GENERAL, "Port %s out of range", escaped(colon+1));
ok = 0;
}
if (!port_out) {
char *esc_addrport = esc_for_log(addrport);
- log_fn(severity, LD_GENERAL,
- "Port %s given on %s when not required",
- escaped(colon+1), esc_addrport);
+ log_warn(LD_GENERAL,
+ "Port %s given on %s when not required",
+ escaped(colon+1), esc_addrport);
tor_free(esc_addrport);
ok = 0;
}
@@ -1576,7 +1526,7 @@ parse_addr_port(int severity, const char *addrport, char **address,
if (addr) {
/* There's an addr pointer, so we need to resolve the hostname. */
if (tor_lookup_hostname(_address,addr)) {
- log_fn(severity, LD_NET, "Couldn't look up %s", escaped(_address));
+ log_warn(LD_NET, "Couldn't look up %s", escaped(_address));
ok = 0;
*addr = 0;
}
@@ -1767,9 +1717,8 @@ tor_dup_addr(uint32_t addr)
return tor_strdup(buf);
}
-/* Return true iff <b>name</b> looks like it might be a hostname,
- * nickname, key, or IP address of some kind, suitable for the
- * controller's "mapaddress" command. */
+/* Return true iff <b>name</b> looks like it might be a hostname or IP
+ * address of some kind. */
int
is_plausible_address(const char *name)
{
@@ -1795,7 +1744,7 @@ is_plausible_address(const char *name)
* failure.
*/
int
-get_interface_address(int severity, uint32_t *addr)
+get_interface_address(uint32_t *addr)
{
int sock=-1, r=-1;
struct sockaddr_in target_addr, my_addr;
@@ -1807,8 +1756,7 @@ get_interface_address(int severity, uint32_t *addr)
sock = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
if (sock < 0) {
int e = tor_socket_errno(-1);
- log_fn(severity, LD_NET, "unable to create socket: %s",
- tor_socket_strerror(e));
+ log_warn(LD_NET, "unable to create socket: %s", tor_socket_strerror(e));
goto err;
}
@@ -1822,15 +1770,14 @@ get_interface_address(int severity, uint32_t *addr)
if (connect(sock,(struct sockaddr *)&target_addr,sizeof(target_addr))<0) {
int e = tor_socket_errno(sock);
- log_fn(severity, LD_NET, "connect() failed: %s", tor_socket_strerror(e));
+ log_warn(LD_NET, "connnect() failed: %s", tor_socket_strerror(e));
goto err;
}
/* XXXX Can this be right on IPv6 clients? */
if (getsockname(sock, (struct sockaddr*)&my_addr, &my_addr_len)) {
int e = tor_socket_errno(sock);
- log_fn(severity, LD_NET, "getsockname() failed: %s",
- tor_socket_strerror(e));
+ log_warn(LD_NET, "getsockname() failed: %s", tor_socket_strerror(e));
goto err;
}
diff --git a/src/common/util.h b/src/common/util.h
index 22f4ea3b99..cdcd64f6b4 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -28,7 +28,7 @@
* calling assert() normally.
*/
#ifdef NDEBUG
-/* Nobody should ever want to build with NDEBUG set. 99% of our asserts will
+/* Nobody should ever want to build with NDEBUG set. 99% of your asserts will
* be outside the critical path anyway, so it's silly to disable bugchecking
* throughout the entire program just because a few asserts are slowing you
* down. Profile, optimize the critical path, and keep debugging on.
@@ -38,17 +38,12 @@
*/
#error "Sorry; we don't support building with NDEBUG."
#else
-#ifdef __GNUC__
-#define PREDICT_FALSE(x) PREDICT((x) == ((typeof(x)) 0), 0)
-#else
-#define PREDICT_FALSE(x) !(x)
-#endif
#define tor_assert(expr) do { \
- if (PREDICT_FALSE(expr)) { \
+ if (!(expr)) { \
log(LOG_ERR, LD_BUG, "%s:%d: %s: Assertion %s failed; aborting.", \
- _SHORT_FILE_, __LINE__, __func__, #expr); \
+ _SHORT_FILE_, __LINE__, __func__, #expr); \
fprintf(stderr,"%s:%d %s: Assertion %s failed; aborting.\n", \
- _SHORT_FILE_, __LINE__, __func__, #expr); \
+ _SHORT_FILE_, __LINE__, __func__, #expr); \
abort(); \
} } while (0)
#endif
@@ -67,27 +62,22 @@
#define tor_fragile_assert()
/* Memory management */
-void *_tor_malloc(size_t size DMALLOC_PARAMS) ATTR_MALLOC;
-void *_tor_malloc_zero(size_t size DMALLOC_PARAMS) ATTR_MALLOC;
+void *_tor_malloc(size_t size DMALLOC_PARAMS);
+void *_tor_malloc_zero(size_t size DMALLOC_PARAMS);
void *_tor_realloc(void *ptr, size_t size DMALLOC_PARAMS);
-char *_tor_strdup(const char *s DMALLOC_PARAMS) ATTR_MALLOC ATTR_NONNULL((1));
-char *_tor_strndup(const char *s, size_t n DMALLOC_PARAMS)
- ATTR_MALLOC ATTR_NONNULL((1));
-void *_tor_memdup(const void *mem, size_t len DMALLOC_PARAMS)
- ATTR_MALLOC ATTR_NONNULL((1));
-void _tor_free(void *mem);
+char *_tor_strdup(const char *s DMALLOC_PARAMS);
+char *_tor_strndup(const char *s, size_t n DMALLOC_PARAMS);
#ifdef USE_DMALLOC
extern int dmalloc_free(const char *file, const int line, void *pnt,
const int func_id);
#define tor_free(p) do { \
- if (PREDICT((p)!=NULL, 1) { \
+ if (p) { \
dmalloc_free(_SHORT_FILE_, __LINE__, (p), 0); \
(p)=NULL; \
} \
} while (0)
#else
-#define tor_free(p) do { if (PREDICT((p)!=NULL,1)) { free(p); (p)=NULL;} } \
- while (0)
+#define tor_free(p) do { if (p) {free(p); (p)=NULL;} } while (0)
#endif
#define tor_malloc(size) _tor_malloc(size DMALLOC_ARGS)
@@ -95,29 +85,17 @@ extern int dmalloc_free(const char *file, const int line, void *pnt,
#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)
-#define tor_memdup(s, n) _tor_memdup(s, n DMALLOC_ARGS)
-
-/** Return the offset of <b>member</b> within the type <b>tp</b>, in bytes */
-#if defined(__GNUC__) && __GNUC__ > 3
-#define STRUCT_OFFSET(tp, member) __builtin_offsetof(tp, member)
-#else
- #define STRUCT_OFFSET(tp, member) \
- ((off_t) (((char*)&((tp*)0)->member)-(char*)0))
-#endif
/* String manipulation */
#define HEX_CHARACTERS "0123456789ABCDEFabcdef"
-void tor_strlower(char *s) ATTR_NONNULL((1));
-void tor_strupper(char *s) ATTR_NONNULL((1));
-int tor_strisprint(const char *s) ATTR_PURE ATTR_NONNULL((1));
-int tor_strisnonupper(const char *s) ATTR_PURE ATTR_NONNULL((1));
-int strcmpstart(const char *s1, const char *s2) ATTR_PURE ATTR_NONNULL((1,2));
-int strcasecmpstart(const char *s1, const char *s2)
- ATTR_PURE ATTR_NONNULL((1,2));
-int strcmpend(const char *s1, const char *s2) ATTR_PURE ATTR_NONNULL((1,2));
-int strcasecmpend(const char *s1, const char *s2)
- ATTR_PURE ATTR_NONNULL((1,2));
-int tor_strstrip(char *s, const char *strip) ATTR_NONNULL((1,2));
+void tor_strlower(char *s);
+void tor_strupper(char *s);
+int tor_strisprint(const char *s);
+int strcmpstart(const char *s1, const char *s2);
+int strcasecmpstart(const char *s1, const char *s2);
+int strcmpend(const char *s1, const char *s2);
+int strcasecmpend(const char *s1, const char *s2);
+int tor_strstrip(char *s, const char *strip);
typedef enum {
ALWAYS_TERMINATE, NEVER_TERMINATE, TERMINATE_IF_EVEN
} part_finish_rule_t;
@@ -130,13 +108,12 @@ unsigned long tor_parse_ulong(const char *s, int base, unsigned long min,
unsigned long max, int *ok, char **next);
uint64_t tor_parse_uint64(const char *s, int base, uint64_t min,
uint64_t max, int *ok, char **next);
-const char *hex_str(const char *from, size_t fromlen) ATTR_NONNULL((1));
-const char *eat_whitespace(const char *s) ATTR_PURE;
-const char *eat_whitespace_no_nl(const char *s) ATTR_PURE;
-const char *find_whitespace(const char *s) ATTR_PURE;
-int tor_mem_is_zero(const char *mem, size_t len) ATTR_PURE;
-int tor_digest_is_zero(const char *digest) ATTR_PURE;
-char *esc_for_log(const char *string) ATTR_MALLOC;
+const char *hex_str(const char *from, size_t fromlen);
+const char *eat_whitespace(const char *s);
+const char *eat_whitespace_no_nl(const char *s);
+const char *find_whitespace(const char *s);
+int tor_digest_is_zero(const char *digest);
+char *esc_for_log(const char *string);
const char *escaped(const char *string);
void base16_encode(char *dest, size_t destlen, const char *src, size_t srclen);
@@ -180,17 +157,17 @@ int write_chunks_to_file(const char *fname, const struct smartlist_t *chunks,
int append_bytes_to_file(const char *fname, const char *str, size_t len,
int bin);
-char *read_file_to_str(const char *filename, int bin) ATTR_MALLOC;
+char *read_file_to_str(const char *filename, int bin);
char *parse_line_from_str(char *line, char **key_out, char **value_out);
char *expand_filename(const char *filename);
struct smartlist_t *tor_listdir(const char *dirname);
-int path_is_relative(const char *filename) ATTR_PURE;
+int path_is_relative(const char *filename);
/* Net helpers */
-int is_internal_IP(uint32_t ip, int for_listening) ATTR_PURE;
-int is_local_IP(uint32_t ip) ATTR_PURE;
-int parse_addr_port(int severity, const char *addrport, char **address,
- uint32_t *addr, uint16_t *port_out);
+int is_internal_IP(uint32_t ip, int for_listening);
+int is_local_IP(uint32_t ip);
+int parse_addr_port(const char *addrport, char **address, uint32_t *addr,
+ uint16_t *port);
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,
@@ -199,9 +176,9 @@ int parse_addr_and_port_range(const char *s, uint32_t *addr_out,
int addr_mask_get_bits(uint32_t mask);
#define INET_NTOA_BUF_LEN 16
int tor_inet_ntoa(struct in_addr *in, char *buf, size_t buf_len);
-char *tor_dup_addr(uint32_t addr) ATTR_MALLOC;
+char *tor_dup_addr(uint32_t addr);
int is_plausible_address(const char *name);
-int get_interface_address(int severity, uint32_t *addr);
+int get_interface_address(uint32_t *addr);
/* Process helpers */
void start_daemon(void);
diff --git a/src/config/torrc.sample.in b/src/config/torrc.sample.in
index 7def88ed8a..c632d02fe5 100644
--- a/src/config/torrc.sample.in
+++ b/src/config/torrc.sample.in
@@ -1,5 +1,5 @@
## Configuration file for a typical Tor user
-## Last updated 31 July 2006 for Tor 0.1.2.1-alpha.
+## Last updated 9 February 2006 for Tor 0.1.1.13-alpha.
## (May or may not work for older or newer versions of Tor.)
##
## Lines that begin with "## " try to explain what's going on. Lines
@@ -23,7 +23,7 @@
## server, and not make any local application connections yourself.
SocksPort 9050 # what port to open for local application connections
SocksListenAddress 127.0.0.1 # accept connections only from localhost
-#SocksListenAddress 192.168.0.1:9100 # listen on this IP:port also
+#SocksListenAddress 192.168.0.1:9100 # listen on a chosen IP/port too
## Entry policies to allow/deny SOCKS requests based on IP address.
## First entry that matches wins. If no SocksPolicy is set, we accept
@@ -62,12 +62,9 @@ SocksListenAddress 127.0.0.1 # accept connections only from localhost
############### This section is just for location-hidden services ###
-## Once you have configured a hidden service, you can look at the
-## contents of the file ".../hidden_service/hostname" for the address
-## to tell people.
-##
-## HiddenServicePort x y:z says to redirect requests on port x to the
-## address y:z.
+## Look in .../hidden_service/hostname for the address to tell people.
+## HiddenServicePort x y:z says to redirect a port x request from the
+## client to y:z.
#HiddenServiceDir @LOCALSTATEDIR@/lib/tor/hidden_service/
#HiddenServicePort 80 127.0.0.1:80
@@ -80,33 +77,29 @@ SocksListenAddress 127.0.0.1 # accept connections only from localhost
################ This section is just for servers #####################
-## NOTE: If you enable these, you should consider mailing the contents
-## of the "fingerprint" file to the tor-ops, so nobody else can pick
-## your nickname and use a different key. See
-## http://tor.eff.org/docs/tor-doc-server.html for details.
+## NOTE: If you enable these, you should consider mailing your identity
+## key fingerprint to the tor-ops, so we can add you to the list of
+## servers that clients will trust. See
+## http://tor.eff.org/cvs/tor/doc/tor-doc-server.html for details.
-## Required: A unique handle for your server.
+## Required: A unique handle for this server
#Nickname ididnteditheconfig
-## The IP or FQDN for your server. Leave commented out and Tor will guess.
+## The IP or fqdn for this server. Leave commented out and Tor will guess.
#Address noname.example.com
-## Define these to limit your bandwidth usage. Note that BandwidthRate
-## must be at least 20 KB.
-#BandwidthRate 100 KB # Throttle traffic to 100KB/s (800Kbps)
-#BandwidthBurst 200 KB # But allow bursts up to 200KB/s (1600Kbps)
-
-## Contact info to be published in the directory, so we can contact you
-## if your server is misconfigured or something else goes wrong.
+## Contact info that will be published in the directory, so we can
+## contact you if you need to upgrade or if something goes wrong.
+## This is optional but recommended.
#ContactInfo Random Person <nobody AT example dot com>
## You might also include your PGP or GPG fingerprint if you have one:
#ContactInfo 1234D/FFFFFFFF Random Person <nobody AT example dot com>
-## Required: what port to advertise for Tor connections.
+## Required: what port to advertise for tor connections
#ORPort 9001
## If you want to listen on a port other than the one advertised
-## in ORPort (e.g. to advertise 443 but bind to 9090), uncomment the
-## line below too. You'll need to do ipchains or other port forwarding
+## in ORPort (e.g. to advertise 443 but bind to 9090), uncomment
+## the line below. You'll need to do ipchains or other port forwarding
## yourself to make this work.
#ORListenAddress 0.0.0.0:9090
@@ -115,15 +108,15 @@ SocksListenAddress 127.0.0.1 # accept connections only from localhost
## http://wiki.noreply.org/noreply/TheOnionRouter/TorFAQ#LimitBandwidth
#DirPort 9030 # what port to advertise for directory connections
## If you want to listen on a port other than the one advertised
-## in DirPort (e.g. to advertise 80 but bind to 9091), uncomment the line
-## below too. You'll need to do ipchains or other port forwarding yourself
+## in DirPort (e.g. to advertise 80 but bind 9091), uncomment the line
+## below. You'll need to do ipchains or other port forwarding yourself
## to make this work.
#DirListenAddress 0.0.0.0:9091
## Uncomment this if you run more than one Tor server, and add the
## nickname of each Tor server you control, even if they're on different
-## networks. You declare it here so Tor clients can avoid using more than
-## one of your servers in a single circuit.
+## networks. We declare it here so clients can avoid using more than
+## one of your servers in a given circuit.
#MyFamily nickname1,nickname2,...
## A comma-separated list of exit policies. They're considered first
@@ -142,5 +135,5 @@ SocksListenAddress 127.0.0.1 # accept connections only from localhost
##
#ExitPolicy accept *:6660-6667,reject *:* # allow irc ports but no more
#ExitPolicy accept *:119 # accept nntp as well as default exit policy
-#ExitPolicy reject *:* # no exits allowed
+#ExitPolicy reject *:* # middleman only -- no exits allowed
diff --git a/src/or/Makefile.am b/src/or/Makefile.am
index 91ec1c057c..6a77adffaa 100644
--- a/src/or/Makefile.am
+++ b/src/or/Makefile.am
@@ -4,19 +4,12 @@ noinst_PROGRAMS = test
bin_PROGRAMS = tor
-if EVENTDNS
-EVDNSSRC = eventdns.c
-else
-EVDNSSRC =
-endif
-
tor_SOURCES = buffers.c circuitbuild.c circuitlist.c \
circuituse.c command.c config.c \
connection.c connection_edge.c connection_or.c control.c \
cpuworker.c directory.c dirserv.c dns.c hibernate.c main.c \
onion.c policies.c relay.c rendcommon.c rendclient.c rendmid.c \
rendservice.c rephist.c router.c routerlist.c routerparse.c \
- $(EVDNSSRC) \
tor_main.c
tor_LDADD = ../common/libor.a ../common/libor-crypto.a -lz -lssl -lcrypto
@@ -27,10 +20,9 @@ test_SOURCES = buffers.c circuitbuild.c circuitlist.c \
cpuworker.c directory.c dirserv.c dns.c hibernate.c main.c \
onion.c policies.c relay.c rendcommon.c rendclient.c rendmid.c \
rendservice.c rephist.c router.c routerlist.c routerparse.c \
- $(EVDNSSRC) \
test.c
test_LDADD = ../common/libor.a ../common/libor-crypto.a -lz -lssl -lcrypto
-noinst_HEADERS = or.h eventdns.h eventdns_tor.h eventdns.c
+noinst_HEADERS = or.h
diff --git a/src/or/buffers.c b/src/or/buffers.c
index 290a81c8b2..f5dd19135b 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -58,15 +58,10 @@ struct buf_t {
char *cur; /**< The first byte used for storing data in the buffer. */
size_t highwater; /**< Largest observed datalen since last buf_shrink */
size_t len; /**< Maximum amount of data that <b>mem</b> can hold. */
- size_t memsize; /**< How many bytes did we actually allocate? Can be less
- * than 'len' if we shortened 'len' by a few bytes to make
- * zlib wrap around more easily. */
size_t datalen; /**< Number of bytes currently in <b>mem</b>. */
};
-/** How many bytes, total, are used in all buffers? */
uint64_t buf_total_used = 0;
-/** How many bytes, total, are allocated in all buffers? */
uint64_t buf_total_alloc = 0;
/** Size, in bytes, for newly allocated buffers. Should be a power of 2. */
@@ -93,14 +88,13 @@ buf_normalize(buf_t *buf)
char *newmem, *oldmem;
size_t sz = (buf->mem+buf->len)-buf->cur;
log_warn(LD_BUG, "Unexpected non-normalized buffer.");
- newmem = GUARDED_MEM(tor_malloc(ALLOC_LEN(buf->memsize)));
- SET_GUARDS(newmem, buf->memsize);
+ newmem = GUARDED_MEM(tor_malloc(ALLOC_LEN(buf->len)));
+ SET_GUARDS(newmem, buf->len);
memcpy(newmem, buf->cur, sz);
memcpy(newmem+sz, buf->mem, buf->datalen-sz);
oldmem = RAW_MEM(buf->mem);
tor_free(oldmem); /* Can't use tor_free directly. */
buf->mem = buf->cur = newmem;
- buf->len = buf->memsize;
check();
}
}
@@ -235,7 +229,7 @@ buf_resize(buf_t *buf, size_t new_capacity)
buf->len-offset);
buf->cur += new_capacity-buf->len;
}
- buf->memsize = buf->len = new_capacity;
+ buf->len = new_capacity;
#ifdef CHECK_AFTER_RESIZE
assert_buf_ok(buf);
@@ -255,18 +249,15 @@ buf_resize(buf_t *buf, size_t new_capacity)
static INLINE int
buf_ensure_capacity(buf_t *buf, size_t capacity)
{
- size_t new_len, min_len;
+ size_t new_len;
if (buf->len >= capacity) /* Don't grow if we're already big enough. */
return 0;
if (capacity > MAX_BUF_SIZE) /* Don't grow past the maximum. */
return -1;
- /* Find the smallest new_len equal to (2**X) for some X; such that
- * new_len is at least capacity, and at least 2*buf->len.
+ /* Find the smallest new_len equal to (2**X)*len for some X; such that
+ * new_len is at least capacity.
*/
- min_len = buf->len*2;
- new_len = 16;
- while (new_len < min_len)
- new_len *= 2;
+ new_len = buf->len*2;
while (new_len < capacity)
new_len *= 2;
/* Resize the buffer. */
@@ -334,7 +325,7 @@ buf_new_with_capacity(size_t size)
buf->magic = BUFFER_MAGIC;
buf->cur = buf->mem = GUARDED_MEM(tor_malloc(ALLOC_LEN(size)));
SET_GUARDS(buf->mem, size);
- buf->len = buf->memsize = size;
+ buf->len = size;
buf_total_alloc += size;
assert_buf_ok(buf);
@@ -355,7 +346,6 @@ buf_clear(buf_t *buf)
buf_total_used -= buf->datalen;
buf->datalen = 0;
buf->cur = buf->mem;
- buf->len = buf->memsize;
}
/** Return the number of bytes stored in <b>buf</b> */
@@ -408,7 +398,7 @@ read_to_buf_impl(int s, size_t at_most, buf_t *buf,
int read_result;
// log_fn(LOG_DEBUG,"reading at most %d bytes.",at_most);
- read_result = tor_socket_recv(s, pos, at_most, 0);
+ read_result = recv(s, pos, at_most, 0);
if (read_result < 0) {
int e = tor_socket_errno(s);
if (!ERRNO_IS_EAGAIN(e)) { /* it's a real error */
@@ -582,7 +572,7 @@ flush_buf_impl(int s, buf_t *buf, size_t sz, size_t *buf_flushlen)
{
int write_result;
- write_result = tor_socket_send(s, buf->cur, sz, 0);
+ write_result = send(s, buf->cur, sz, 0);
if (write_result < 0) {
int e = tor_socket_errno(s);
if (!ERRNO_IS_EAGAIN(e)) { /* it's a real error */
@@ -882,14 +872,14 @@ fetch_from_buf_http(buf_t *buf,
if (headers_out) {
*headers_out = tor_malloc(headerlen+1);
memcpy(*headers_out,buf->cur,headerlen);
- (*headers_out)[headerlen] = 0; /* nul terminate it */
+ (*headers_out)[headerlen] = 0; /* null terminate it */
}
if (body_out) {
tor_assert(body_used);
*body_used = bodylen;
*body_out = tor_malloc(bodylen+1);
memcpy(*body_out,buf->cur+headerlen,bodylen);
- (*body_out)[bodylen] = 0; /* nul terminate it */
+ (*body_out)[bodylen] = 0; /* null terminate it */
}
buf_remove_from_front(buf, headerlen+bodylen);
return 1;
@@ -957,9 +947,7 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
req->reply[1] = '\xFF'; /* reject all methods */
return -1;
}
- /* remove packet from buf. also remove any other extraneous
- * bytes, to support broken socks clients. */
- buf_clear(buf);
+ buf_remove_from_front(buf,2+nummethods); /* remove packet from buf */
req->replylen = 2; /* 2 bytes of response */
req->reply[0] = 5; /* socks5 reply */
@@ -974,9 +962,8 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
return 0; /* not yet */
req->command = (unsigned char) *(buf->cur+1);
if (req->command != SOCKS_COMMAND_CONNECT &&
- req->command != SOCKS_COMMAND_RESOLVE &&
- req->command != SOCKS_COMMAND_RESOLVE_PTR) {
- /* not a connect or resolve or a resolve_ptr? we don't support it. */
+ req->command != SOCKS_COMMAND_RESOLVE) {
+ /* not a connect or resolve? we don't support it. */
log_warn(LD_APP,"socks5: command %d not recognized. Rejecting.",
req->command);
return -1;
@@ -1000,8 +987,7 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
strlcpy(req->address,tmpbuf,sizeof(req->address));
req->port = ntohs(*(uint16_t*)(buf->cur+8));
buf_remove_from_front(buf, 10);
- if (req->command != SOCKS_COMMAND_RESOLVE_PTR &&
- !addressmap_have_mapping(req->address) &&
+ if (!address_is_in_virtual_range(req->address) &&
!have_warned_about_unsafe_socks) {
log_warn(LD_APP,
"Your application (using socks5 on port %d) is giving "
@@ -1027,11 +1013,6 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
"%d. Rejecting.", len+1,MAX_SOCKS_ADDR_LEN);
return -1;
}
- if (req->command == SOCKS_COMMAND_RESOLVE_PTR) {
- log_warn(LD_APP, "socks5 received RESOLVE_PTR command with "
- "hostname type. Rejecting.");
- return -1;
- }
memcpy(req->address,buf->cur+5,len);
req->address[len] = 0;
req->port = ntohs(get_uint16(buf->cur+5+len));
@@ -1066,8 +1047,7 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
req->command = (unsigned char) *(buf->cur+1);
if (req->command != SOCKS_COMMAND_CONNECT &&
req->command != SOCKS_COMMAND_RESOLVE) {
- /* not a connect or resolve? we don't support it. (No resolve_ptr with
- * socks4.) */
+ /* not a connect or resolve? we don't support it. */
log_warn(LD_APP,"socks4: command %d not recognized. Rejecting.",
req->command);
return -1;
@@ -1103,7 +1083,7 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
startaddr = NULL;
if (socks4_prot != socks4a &&
- !addressmap_have_mapping(tmpbuf) &&
+ !address_is_in_virtual_range(tmpbuf) &&
!have_warned_about_unsafe_socks) {
log_warn(LD_APP,
"Your application (using socks4 on port %d) is giving Tor "
@@ -1304,62 +1284,6 @@ fetch_from_buf_line(buf_t *buf, char *data_out, size_t *data_len)
return 1;
}
-/** Compress on uncompress the <b>data_len</b> bytes in <b>data</b> using the
- * zlib state <b>state</b>, appending the result to <b>buf</b>. If
- * <b>done</b> is true, flush the data in the state and finish the
- * compression/uncompression. Return -1 on failure, 0 on success. */
-int
-write_to_buf_zlib(buf_t *buf, tor_zlib_state_t *state,
- const char *data, size_t data_len,
- int done)
-{
- char *next;
- size_t old_avail, avail;
- int over = 0;
- do {
- buf_ensure_capacity(buf, buf->datalen + 1024);
- next = _buf_end(buf);
- if (next < buf->cur)
- old_avail = avail = buf->cur - next;
- else
- old_avail = avail = (buf->mem + buf->len) - next;
- switch (tor_zlib_process(state, &next, &avail, &data, &data_len, done)) {
- case TOR_ZLIB_DONE:
- over = 1;
- break;
- case TOR_ZLIB_ERR:
- return -1;
- case TOR_ZLIB_OK:
- if (data_len == 0)
- over = 1;
- break;
- case TOR_ZLIB_BUF_FULL:
- if (avail && buf->len >= 1024 + buf->datalen) {
- /* Zlib says we need more room (ZLIB_BUF_FULL), and we're not about
- * to wrap around (avail != 0), and resizing won't actually make us
- * un-full: we're at the end of the buffer, and zlib refuses to
- * append more here, but there's a pile of free space at the start
- * of the buffer (about 1K). So chop a few characters off the
- * end of the buffer. This feels silly; anybody got a better hack?
- *
- * (We don't just want to expand the buffer nevertheless. Consider a
- * 1/3 full buffer with a single byte free at the end. zlib will
- * often refuse to append to that, and so we want to use the
- * beginning, not double the buffer to be just 1/6 full.)
- */
- tor_assert(next >= buf->cur);
- buf->len -= avail;
- }
- break;
- }
- buf->datalen += old_avail - avail;
- if (buf->datalen > buf->highwater)
- buf->highwater = buf->datalen;
- buf_total_used += old_avail - avail;
- } while (!over);
- return 0;
-}
-
/** Log an error and exit if <b>buf</b> is corrupted.
*/
void
@@ -1374,7 +1298,7 @@ assert_buf_ok(buf_t *buf)
{
uint32_t u32 = get_uint32(buf->mem - 4);
tor_assert(u32 == START_MAGIC);
- u32 = get_uint32(buf->mem + buf->memsize);
+ u32 = get_uint32(buf->mem + buf->len);
tor_assert(u32 == END_MAGIC);
}
#endif
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index d23f21b704..6a9ed3b16b 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -43,7 +43,7 @@ static int entry_guards_dirty = 0;
static int circuit_deliver_create_cell(circuit_t *circ,
uint8_t cell_type, char *payload);
-static int onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit);
+static int onion_pick_cpath_exit(circuit_t *circ, extend_info_t *exit);
static crypt_path_t *onion_next_hop_in_cpath(crypt_path_t *cpath);
static int onion_extend_cpath(uint8_t purpose, crypt_path_t **head_ptr,
cpath_build_state_t *state);
@@ -54,19 +54,21 @@ static routerinfo_t *choose_random_entry(cpath_build_state_t *state);
static void entry_guards_changed(void);
/** Iterate over values of circ_id, starting from conn-\>next_circ_id,
- * and with the high bit specified by conn-\>circ_id_type, until we get
- * a circ_id that is not in use by any other circuit on that conn.
+ * and with the high bit specified by circ_id_type (see
+ * decide_circ_id_type()), until we get a circ_id that is not in use
+ * by any other circuit on that conn.
*
* Return it, or 0 if can't get a unique circ_id.
*/
static uint16_t
-get_unique_circ_id_by_conn(or_connection_t *conn)
+get_unique_circ_id_by_conn(connection_t *conn)
{
uint16_t test_circ_id;
uint16_t attempts=0;
uint16_t high_bit;
tor_assert(conn);
+ tor_assert(conn->type == CONN_TYPE_OR);
high_bit = (conn->circ_id_type == CIRC_ID_TYPE_HIGHER) ? 1<<15 : 0;
do {
/* Sequentially iterate over test_circ_id=1...1<<15-1 until we find a
@@ -94,13 +96,14 @@ get_unique_circ_id_by_conn(or_connection_t *conn)
* a more verbose format using spaces.
*/
char *
-circuit_list_path(origin_circuit_t *circ, int verbose)
+circuit_list_path(circuit_t *circ, int verbose)
{
crypt_path_t *hop;
smartlist_t *elements;
const char *states[] = {"closed", "waiting for keys", "open"};
char buf[128];
char *s;
+ tor_assert(CIRCUIT_IS_ORIGIN(circ));
elements = smartlist_create();
@@ -110,8 +113,8 @@ circuit_list_path(origin_circuit_t *circ, int verbose)
circ->build_state->is_internal ? "internal" : "exit",
circ->build_state->need_uptime ? " (high-uptime)" : "",
circ->build_state->desired_path_len,
- circ->_base.state == CIRCUIT_STATE_OPEN ? "" : ", exit ",
- circ->_base.state == CIRCUIT_STATE_OPEN ? "" :
+ circ->state == CIRCUIT_STATE_OPEN ? "" : ", exit ",
+ circ->state == CIRCUIT_STATE_OPEN ? "" :
(nickname?nickname:"*unnamed*"));
smartlist_add(elements, tor_strdup(buf));
}
@@ -150,7 +153,7 @@ circuit_list_path(origin_circuit_t *circ, int verbose)
* exit point.
*/
void
-circuit_log_path(int severity, unsigned int domain, origin_circuit_t *circ)
+circuit_log_path(int severity, unsigned int domain, circuit_t *circ)
{
char *s = circuit_list_path(circ,1);
log(severity,domain,"%s",s);
@@ -163,7 +166,7 @@ circuit_log_path(int severity, unsigned int domain, origin_circuit_t *circ)
* unable to extend.
*/
void
-circuit_rep_hist_note_result(origin_circuit_t *circ)
+circuit_rep_hist_note_result(circuit_t *circ)
{
crypt_path_t *hop;
char *prev_digest = NULL;
@@ -204,14 +207,74 @@ circuit_rep_hist_note_result(origin_circuit_t *circ)
} while (hop!=circ->cpath);
}
+/** A helper function for circuit_dump_by_conn() below. Log a bunch
+ * of information about circuit <b>circ</b>.
+ */
+static void
+circuit_dump_details(int severity, circuit_t *circ, int poll_index,
+ const char *type, int this_circid, int other_circid)
+{
+ log(severity, LD_CIRC, "Conn %d has %s circuit: circID %d (other side %d), "
+ "state %d (%s), born %d:",
+ poll_index, type, this_circid, other_circid, circ->state,
+ circuit_state_to_string(circ->state), (int)circ->timestamp_created);
+ if (CIRCUIT_IS_ORIGIN(circ)) { /* circ starts at this node */
+ circuit_log_path(severity, LD_CIRC, circ);
+ }
+}
+
+/** Log, at severity <b>severity</b>, information about each circuit
+ * that is connected to <b>conn</b>.
+ */
+void
+circuit_dump_by_conn(connection_t *conn, int severity)
+{
+ circuit_t *circ;
+ connection_t *tmpconn;
+
+ for (circ=global_circuitlist;circ;circ = circ->next) {
+ if (circ->marked_for_close)
+ continue;
+ if (circ->p_conn == conn)
+ circuit_dump_details(severity, circ, conn->poll_index, "App-ward",
+ circ->p_circ_id, circ->n_circ_id);
+ for (tmpconn=circ->p_streams; tmpconn; tmpconn=tmpconn->next_stream) {
+ if (tmpconn == conn) {
+ circuit_dump_details(severity, circ, conn->poll_index, "App-ward",
+ circ->p_circ_id, circ->n_circ_id);
+ }
+ }
+ if (circ->n_conn == conn)
+ circuit_dump_details(severity, circ, conn->poll_index, "Exit-ward",
+ circ->n_circ_id, circ->p_circ_id);
+ for (tmpconn=circ->n_streams; tmpconn; tmpconn=tmpconn->next_stream) {
+ if (tmpconn == conn) {
+ circuit_dump_details(severity, circ, conn->poll_index, "Exit-ward",
+ circ->n_circ_id, circ->p_circ_id);
+ }
+ }
+ if (!circ->n_conn && circ->n_addr && circ->n_port &&
+ circ->n_addr == conn->addr &&
+ circ->n_port == conn->port &&
+ !memcmp(conn->identity_digest, circ->n_conn_id_digest, DIGEST_LEN)) {
+ circuit_dump_details(severity, circ, conn->poll_index,
+ (circ->state == CIRCUIT_STATE_OPEN &&
+ !CIRCUIT_IS_ORIGIN(circ)) ?
+ "Endpoint" : "Pending",
+ circ->n_circ_id, circ->p_circ_id);
+ }
+ }
+}
+
/** Pick all the entries in our cpath. Stop and return 0 when we're
* happy, or return -1 if an error occurs. */
static int
-onion_populate_cpath(origin_circuit_t *circ)
+onion_populate_cpath(circuit_t *circ)
{
int r;
again:
- r = onion_extend_cpath(circ->_base.purpose, &circ->cpath, circ->build_state);
+ r = onion_extend_cpath(circ->purpose, &circ->cpath, circ->build_state);
+// || !CIRCUIT_IS_ORIGIN(circ)) { // wtf? -rd
if (r < 0) {
log_info(LD_CIRC,"Generating cpath hop failed.");
return -1;
@@ -221,20 +284,19 @@ again:
return 0; /* if r == 1 */
}
-/** Create and return a new origin circuit. Initialize its purpose and
+/** Create and return a new circuit. Initialize its purpose and
* build-state based on our arguments. */
-origin_circuit_t *
-origin_circuit_init(uint8_t purpose, int need_uptime, int need_capacity,
- int internal)
+circuit_t *
+circuit_init(uint8_t purpose, int need_uptime, int need_capacity, int internal)
{
/* sets circ->p_circ_id and circ->p_conn */
- origin_circuit_t *circ = origin_circuit_new();
- circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OR_WAIT);
+ circuit_t *circ = circuit_new(0, NULL);
+ circuit_set_state(circ, CIRCUIT_STATE_OR_WAIT);
circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
circ->build_state->need_uptime = need_uptime;
circ->build_state->need_capacity = need_capacity;
circ->build_state->is_internal = internal;
- circ->_base.purpose = purpose;
+ circ->purpose = purpose;
return circ;
}
@@ -245,24 +307,24 @@ origin_circuit_init(uint8_t purpose, int need_uptime, int need_capacity,
* Also launch a connection to the first OR in the chosen path, if
* it's not open already.
*/
-origin_circuit_t *
+circuit_t *
circuit_establish_circuit(uint8_t purpose, extend_info_t *info,
int need_uptime, int need_capacity, int internal)
{
- origin_circuit_t *circ;
+ circuit_t *circ;
- circ = origin_circuit_init(purpose, need_uptime, need_capacity, internal);
+ circ = circuit_init(purpose, need_uptime, need_capacity, internal);
if (onion_pick_cpath_exit(circ, info) < 0 ||
onion_populate_cpath(circ) < 0) {
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return NULL;
}
control_event_circuit_status(circ, CIRC_EVENT_LAUNCHED);
if (circuit_handle_first_hop(circ) < 0) {
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return NULL;
}
return circ;
@@ -273,10 +335,10 @@ circuit_establish_circuit(uint8_t purpose, extend_info_t *info,
* it. If we're already connected, then send the 'create' cell.
* Return 0 for ok, -1 if circ should be marked-for-close. */
int
-circuit_handle_first_hop(origin_circuit_t *circ)
+circuit_handle_first_hop(circuit_t *circ)
{
crypt_path_t *firsthop;
- or_connection_t *n_conn;
+ connection_t *n_conn;
char tmpbuf[INET_NTOA_BUF_LEN];
struct in_addr in;
@@ -290,22 +352,22 @@ circuit_handle_first_hop(origin_circuit_t *circ)
log_debug(LD_CIRC,"Looking for firsthop '%s:%u'",tmpbuf,
firsthop->extend_info->port);
/* imprint the circuit with its future n_conn->id */
- memcpy(circ->_base.n_conn_id_digest, firsthop->extend_info->identity_digest,
+ memcpy(circ->n_conn_id_digest, firsthop->extend_info->identity_digest,
DIGEST_LEN);
n_conn = connection_or_get_by_identity_digest(
firsthop->extend_info->identity_digest);
/* If we don't have an open conn, or the conn we have is obsolete
* (i.e. old or broken) and the other side will let us make a second
* connection without dropping it immediately... */
- if (!n_conn || n_conn->_base.state != OR_CONN_STATE_OPEN ||
- (n_conn->_base.or_is_obsolete &&
+ if (!n_conn || n_conn->state != OR_CONN_STATE_OPEN ||
+ (n_conn->is_obsolete &&
router_digest_version_as_new_as(firsthop->extend_info->identity_digest,
"0.1.1.9-alpha-cvs"))) {
/* not currently connected */
- circ->_base.n_addr = firsthop->extend_info->addr;
- circ->_base.n_port = firsthop->extend_info->port;
+ circ->n_addr = firsthop->extend_info->addr;
+ circ->n_port = firsthop->extend_info->port;
- if (!n_conn || n_conn->_base.or_is_obsolete) { /* launch the connection */
+ if (!n_conn || n_conn->is_obsolete) { /* launch the connection */
n_conn = connection_or_connect(firsthop->extend_info->addr,
firsthop->extend_info->port,
firsthop->extend_info->identity_digest);
@@ -322,9 +384,9 @@ circuit_handle_first_hop(origin_circuit_t *circ)
*/
return 0;
} else { /* it's already open. use it. */
- circ->_base.n_addr = n_conn->_base.addr;
- circ->_base.n_port = n_conn->_base.port;
- circ->_base.n_conn = n_conn;
+ circ->n_addr = n_conn->addr;
+ circ->n_port = n_conn->port;
+ circ->n_conn = n_conn;
log_debug(LD_CIRC,"Conn open. Delivering first onion skin.");
if (circuit_send_next_onion_skin(circ) < 0) {
log_info(LD_CIRC,"circuit_send_next_onion_skin failed.");
@@ -334,17 +396,15 @@ circuit_handle_first_hop(origin_circuit_t *circ)
return 0;
}
-extern smartlist_t *circuits_pending_or_conns;
-
/** Find any circuits that are waiting on <b>or_conn</b> to become
* open and get them to send their create cells forward.
*
* Status is 1 if connect succeeded, or 0 if connect failed.
*/
void
-circuit_n_conn_done(or_connection_t *or_conn, int status)
+circuit_n_conn_done(connection_t *or_conn, int status)
{
- smartlist_t *changed_circs;
+ extern smartlist_t *circuits_pending_or_conns;
smartlist_t *changed_circs;
log_debug(LD_CIRC,"or_conn to %s, status=%d",
@@ -368,13 +428,14 @@ circuit_n_conn_done(or_connection_t *or_conn, int status)
circuit_mark_for_close(circ, END_CIRC_REASON_OR_CONN_CLOSED);
continue;
}
- log_debug(LD_CIRC, "Found circ, sending create cell.");
+ log_debug(LD_CIRC,
+ "Found circ %d, sending create cell.", circ->n_circ_id);
/* circuit_deliver_create_cell will set n_circ_id and add us to
* orconn_circuid_circuit_map, so we don't need to call
* set_circid_orconn here. */
circ->n_conn = or_conn;
if (CIRCUIT_IS_ORIGIN(circ)) {
- if (circuit_send_next_onion_skin(TO_ORIGIN_CIRCUIT(circ)) < 0) {
+ if (circuit_send_next_onion_skin(circ) < 0) {
log_info(LD_CIRC,
"send_next_onion_skin failed; circuit marked for closing.");
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
@@ -412,14 +473,14 @@ circuit_n_conn_done(or_connection_t *or_conn, int status)
* Return -1 if we failed to find a suitable circid, else return 0.
*/
static int
-circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type,
- char *payload)
+circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type, char *payload)
{
cell_t cell;
uint16_t id;
tor_assert(circ);
tor_assert(circ->n_conn);
+ tor_assert(circ->n_conn->type == CONN_TYPE_OR);
tor_assert(payload);
tor_assert(cell_type == CELL_CREATE || cell_type == CELL_CREATE_FAST);
@@ -429,7 +490,7 @@ circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type,
return -1;
}
log_debug(LD_CIRC,"Chosen circID %u.", id);
- circuit_set_n_circid_orconn(circ, id, circ->n_conn);
+ circuit_set_circid_orconn(circ, id, circ->n_conn, N_CONN_CHANGED);
memset(&cell, 0, sizeof(cell_t));
cell.command = cell_type;
@@ -465,13 +526,13 @@ inform_testing_reachability(void)
/** Return true iff we should send a create_fast cell to build a circuit
* starting at <b>router</b>. (If <b>router</b> is NULL, we don't have
- * information on the router, so return false.) */
+ * information on the router. */
static INLINE int
should_use_create_fast_for_router(routerinfo_t *router)
{
or_options_t *options = get_options();
- if (!options->FastFirstHopPK || server_mode(options))
+ if (!options->FastFirstHopPK || options->ORPort)
return 0;
else if (!router || !router->platform ||
!tor_version_as_new_as(router->platform, "0.1.0.6-rc"))
@@ -480,6 +541,8 @@ should_use_create_fast_for_router(routerinfo_t *router)
return 1;
}
+extern int has_completed_circuit;
+
/** This is the backbone function for building circuits.
*
* If circ's first hop is closed, then we need to build a create
@@ -491,7 +554,7 @@ should_use_create_fast_for_router(routerinfo_t *router)
* Return -reason if we want to tear down circ, else return 0.
*/
int
-circuit_send_next_onion_skin(origin_circuit_t *circ)
+circuit_send_next_onion_skin(circuit_t *circ)
{
crypt_path_t *hop;
routerinfo_t *router;
@@ -500,13 +563,14 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
size_t payload_len;
tor_assert(circ);
+ tor_assert(CIRCUIT_IS_ORIGIN(circ));
if (circ->cpath->state == CPATH_STATE_CLOSED) {
int fast;
uint8_t cell_type;
log_debug(LD_CIRC,"First skin; sending create cell.");
- router = router_get_by_digest(circ->_base.n_conn->identity_digest);
+ router = router_get_by_digest(circ->n_conn->identity_digest);
fast = should_use_create_fast_for_router(router);
if (! fast) {
/* We are an OR, or we are connecting to an old Tor: we should
@@ -531,22 +595,22 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
sizeof(circ->cpath->fast_handshake_state));
}
- if (circuit_deliver_create_cell(TO_CIRCUIT(circ), cell_type, payload) < 0)
+ if (circuit_deliver_create_cell(circ, cell_type, payload) < 0)
return - END_CIRC_REASON_RESOURCELIMIT;
circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
- circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING);
+ circuit_set_state(circ, CIRCUIT_STATE_BUILDING);
log_info(LD_CIRC,"First hop: finished sending %s cell to '%s'",
fast ? "CREATE_FAST" : "CREATE",
- router ? router->nickname : "<unnamed>");
+ router ? router->nickname : "<unnamed>");
} else {
tor_assert(circ->cpath->state == CPATH_STATE_OPEN);
- tor_assert(circ->_base.state == CIRCUIT_STATE_BUILDING);
+ tor_assert(circ->state == CIRCUIT_STATE_BUILDING);
log_debug(LD_CIRC,"starting to send subsequent skin.");
hop = onion_next_hop_in_cpath(circ->cpath);
if (!hop) {
/* done building the circuit. whew. */
- circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN);
+ circuit_set_state(circ, CIRCUIT_STATE_OPEN);
log_info(LD_CIRC,"circuit built!");
circuit_reset_failure_count(0);
if (!has_completed_circuit) {
@@ -558,7 +622,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
"Looks like client functionality is working.");
if (server_mode(options) && !check_whether_orport_reachable()) {
inform_testing_reachability();
- consider_testing_reachability(1, 1);
+ consider_testing_reachability();
}
}
circuit_rep_hist_note_result(circ);
@@ -583,8 +647,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
log_debug(LD_CIRC,"Sending extend relay cell.");
/* send it to hop->prev, because it will transfer
* it to a create cell and then send to hop */
- if (connection_edge_send_command(NULL, TO_CIRCUIT(circ),
- RELAY_COMMAND_EXTEND,
+ if (connection_edge_send_command(NULL, circ, RELAY_COMMAND_EXTEND,
payload, payload_len, hop->prev) < 0)
return 0; /* circuit is closed */
@@ -599,13 +662,8 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
void
circuit_note_clock_jumped(int seconds_elapsed)
{
- if (server_mode(get_options()))
- log(LOG_WARN, LD_GENERAL,
- "Please report: your clock just jumped %d seconds forward; "
- "assuming established circuits no longer work.", seconds_elapsed);
- else
- log(LOG_NOTICE, LD_GENERAL, "Your clock just jumped %d seconds forward; "
- "assuming established circuits no longer work.", seconds_elapsed);
+ log(LOG_NOTICE, LD_GENERAL,"Your clock just jumped %d seconds forward; "
+ "assuming established circuits no longer work.", seconds_elapsed);
has_completed_circuit=0; /* so it'll log when it works again */
circuit_mark_all_unused_circs();
circuit_expire_all_dirty_circs();
@@ -619,7 +677,7 @@ circuit_note_clock_jumped(int seconds_elapsed)
int
circuit_extend(cell_t *cell, circuit_t *circ)
{
- or_connection_t *n_conn;
+ connection_t *n_conn;
relay_header_t rh;
char *onionskin;
char *id_digest=NULL;
@@ -635,12 +693,6 @@ circuit_extend(cell_t *cell, circuit_t *circ)
return -1;
}
- if (!server_mode(get_options())) {
- log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
- "Got an extend cell, but running as a client. Closing.");
- return -1;
- }
-
relay_header_unpack(&rh, cell->payload);
if (rh.length < 4+2+ONIONSKIN_CHALLENGE_LEN+DIGEST_LEN) {
@@ -660,9 +712,12 @@ circuit_extend(cell_t *cell, circuit_t *circ)
/* If we don't have an open conn, or the conn we have is obsolete
* (i.e. old or broken) and the other side will let us make a second
* connection without dropping it immediately... */
- if (!n_conn || n_conn->_base.state != OR_CONN_STATE_OPEN ||
- (n_conn->_base.or_is_obsolete &&
+ if (!n_conn || n_conn->state != OR_CONN_STATE_OPEN ||
+ (n_conn->is_obsolete &&
router_digest_version_as_new_as(id_digest,"0.1.1.9-alpha-cvs"))) {
+ /* Note that this will close circuits where the onion has the same
+ * router twice in a row in the path. I think that's ok.
+ */
struct in_addr in;
char tmpbuf[INET_NTOA_BUF_LEN];
in.s_addr = htonl(circ->n_addr);
@@ -677,9 +732,9 @@ circuit_extend(cell_t *cell, circuit_t *circ)
/* imprint the circuit with its future n_conn->id */
memcpy(circ->n_conn_id_digest, id_digest, DIGEST_LEN);
- if (n_conn && !n_conn->_base.or_is_obsolete) {
- circ->n_addr = n_conn->_base.addr;
- circ->n_port = n_conn->_base.port;
+ if (n_conn && !n_conn->is_obsolete) {
+ circ->n_addr = n_conn->addr;
+ circ->n_port = n_conn->port;
} else {
/* we should try to open a connection */
n_conn = connection_or_connect(circ->n_addr, circ->n_port, id_digest);
@@ -698,13 +753,12 @@ circuit_extend(cell_t *cell, circuit_t *circ)
}
/* these may be different if the router connected to us from elsewhere */
- circ->n_addr = n_conn->_base.addr;
- circ->n_port = n_conn->_base.port;
+ circ->n_addr = n_conn->addr;
+ circ->n_port = n_conn->port;
circ->n_conn = n_conn;
memcpy(circ->n_conn_id_digest, n_conn->identity_digest, DIGEST_LEN);
- log_debug(LD_CIRC,"n_conn is %s:%u",
- n_conn->_base.address,n_conn->_base.port);
+ log_debug(LD_CIRC,"n_conn is %s:%u",n_conn->address,n_conn->port);
if (circuit_deliver_create_cell(circ, CELL_CREATE, onionskin) < 0)
return -1;
@@ -771,12 +825,12 @@ circuit_init_cpath_crypto(crypt_path_t *cpath, char *key_data, int reverse)
* Return - reason if we want to mark circ for close, else return 0.
*/
int
-circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type,
- char *reply)
+circuit_finish_handshake(circuit_t *circ, uint8_t reply_type, char *reply)
{
char keys[CPATH_KEY_MATERIAL_LEN];
crypt_path_t *hop;
+ tor_assert(CIRCUIT_IS_ORIGIN(circ));
if (circ->cpath->state == CPATH_STATE_AWAITING_KEYS)
hop = circ->cpath;
else {
@@ -834,19 +888,20 @@ circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type,
* just give up: for circ to close, and return 0.
*/
int
-circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer)
+circuit_truncated(circuit_t *circ, crypt_path_t *layer)
{
// crypt_path_t *victim;
// connection_t *stream;
tor_assert(circ);
+ tor_assert(CIRCUIT_IS_ORIGIN(circ));
tor_assert(layer);
/* XXX Since we don't ask for truncates currently, getting a truncated
* means that a connection broke or an extend failed. For now,
* just give up.
*/
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return 0;
#if 0
@@ -879,8 +934,7 @@ circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer)
* cell back.
*/
int
-onionskin_answer(or_circuit_t *circ, uint8_t cell_type, char *payload,
- char *keys)
+onionskin_answer(circuit_t *circ, uint8_t cell_type, char *payload, char *keys)
{
cell_t cell;
crypt_path_t *tmp_cpath;
@@ -892,7 +946,7 @@ onionskin_answer(or_circuit_t *circ, uint8_t cell_type, char *payload,
cell.command = cell_type;
cell.circ_id = circ->p_circ_id;
- circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN);
+ circuit_set_state(circ, CIRCUIT_STATE_OPEN);
memcpy(cell.payload, payload,
cell_type == CELL_CREATED ? ONIONSKIN_REPLY_LEN : DIGEST_LEN*2);
@@ -920,8 +974,8 @@ onionskin_answer(or_circuit_t *circ, uint8_t cell_type, char *payload,
connection_or_write_cell_to_buf(&cell, circ->p_conn);
log_debug(LD_CIRC,"Finished sending 'created' cell.");
- if (!is_local_IP(circ->p_conn->_base.addr) &&
- !connection_or_nonopen_was_started_here(circ->p_conn)) {
+ if (!is_local_IP(circ->p_conn->addr) &&
+ tor_tls_is_server(circ->p_conn->tls)) {
/* record that we could process create cells from a non-local conn
* that we didn't initiate; presumably this means that create cells
* can reach us too. */
@@ -1058,9 +1112,8 @@ ap_stream_wants_exit_attention(connection_t *conn)
if (conn->type == CONN_TYPE_AP &&
conn->state == AP_CONN_STATE_CIRCUIT_WAIT &&
!conn->marked_for_close &&
- !connection_edge_is_rendezvous_stream(TO_EDGE_CONN(conn)) &&
- !circuit_stream_is_being_handled(TO_EDGE_CONN(conn), 0,
- MIN_CIRCUITS_HANDLING_STREAM))
+ !connection_edge_is_rendezvous_stream(conn) &&
+ !circuit_stream_is_being_handled(conn, 0, MIN_CIRCUITS_HANDLING_STREAM))
return 1;
return 0;
}
@@ -1145,7 +1198,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
for (j = 0; j < n_connections; ++j) { /* iterate over connections */
if (!ap_stream_wants_exit_attention(carray[j]))
continue; /* Skip everything but APs in CIRCUIT_WAIT */
- if (connection_ap_can_use_exit(TO_EDGE_CONN(carray[j]), router)) {
+ if (connection_ap_can_use_exit(carray[j], router)) {
++n_supported[i];
// log_fn(LOG_DEBUG,"%s is supported. n_supported[%d] now %d.",
// router->nickname, i, n_supported[i]);
@@ -1207,7 +1260,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
need_uptime?", stable":"");
return choose_good_exit_server_general(dir, 0, 0);
}
- log_notice(LD_CIRC, "All routers are down or won't exit -- choosing a "
+ log_notice(LD_CIRC, "All routers are down or middleman -- choosing a "
"doomed exit at random.");
}
for (try = 0; try < 2; try++) {
@@ -1290,13 +1343,13 @@ choose_good_exit_server(uint8_t purpose, routerlist_t *dir,
* router (or use <b>exit</b> if provided). Store these in the
* cpath. Return 0 if ok, -1 if circuit should be closed. */
static int
-onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit)
+onion_pick_cpath_exit(circuit_t *circ, extend_info_t *exit)
{
cpath_build_state_t *state = circ->build_state;
routerlist_t *rl = router_get_routerlist();
int r;
- r = new_route_len(get_options()->PathlenCoinWeight, circ->_base.purpose,
+ r = new_route_len(get_options()->PathlenCoinWeight, circ->purpose,
exit, rl->routers);
if (r < 1) /* must be at least 1 */
return -1;
@@ -1307,8 +1360,8 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit)
exit = extend_info_dup(exit);
} else { /* we have to decide one */
routerinfo_t *router =
- choose_good_exit_server(circ->_base.purpose, rl, state->need_uptime,
- state->need_capacity, state->is_internal);
+ choose_good_exit_server(circ->purpose, rl, state->need_uptime,
+ state->need_capacity, state->is_internal);
if (!router) {
log_warn(LD_CIRC,"failed to choose an exit server");
return -1;
@@ -1324,11 +1377,11 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit)
* the caller will do this if it wants to.
*/
int
-circuit_append_new_exit(origin_circuit_t *circ, extend_info_t *info)
+circuit_append_new_exit(circuit_t *circ, extend_info_t *info)
{
cpath_build_state_t *state;
tor_assert(info);
- tor_assert(circ);
+ tor_assert(circ && CIRCUIT_IS_ORIGIN(circ));
state = circ->build_state;
tor_assert(state);
@@ -1346,14 +1399,15 @@ circuit_append_new_exit(origin_circuit_t *circ, extend_info_t *info)
* send the next extend cell to begin connecting to that hop.
*/
int
-circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *info)
+circuit_extend_to_new_exit(circuit_t *circ, extend_info_t *info)
{
+ tor_assert(CIRCUIT_IS_ORIGIN(circ));
circuit_append_new_exit(circ, info);
- circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING);
+ circuit_set_state(circ, CIRCUIT_STATE_BUILDING);
if (circuit_send_next_onion_skin(circ)<0) {
log_warn(LD_CIRC, "Couldn't extend circuit to new point '%s'.",
info->nickname);
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return -1;
}
return 0;
@@ -1382,10 +1436,6 @@ count_acceptable_routers(smartlist_t *routers)
if (r->is_valid == 0) {
// log_debug(LD_CIRC,"Nope, the directory says %d is not valid.",i);
goto next_i_loop;
- /* XXX This clause makes us count incorrectly: if AllowInvalidRouters
- * allows this node in some places, then we're getting an inaccurate
- * count. For now, be conservative and don't count it. But later we
- * should try to be smarter. */
}
num++;
// log_debug(LD_CIRC,"I like %d. num_acceptable_routers now %d.",i, num);
@@ -1422,7 +1472,7 @@ onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop)
* whole network has upgraded. */
static char *
compute_preferred_testing_list(const char *answer)
-{
+{
smartlist_t *choices;
routerlist_t *rl = router_get_routerlist();
routerinfo_t *router;
@@ -1519,7 +1569,6 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state)
routerinfo_t *r, *choice;
smartlist_t *excluded;
or_options_t *options = get_options();
- (void)purpose; /* not used yet. */
if (state && options->UseEntryGuards) {
return choose_random_entry(state);
@@ -1786,7 +1835,7 @@ log_entry_guards(int severity)
{
tor_snprintf(buf, sizeof(buf), "%s (%s%s%s)",
e->nickname,
- (e->down_since || e->unlisted_since) ? "down " : "up ",
+ e->down_since ? "down " : "up ",
e->unlisted_since ? "unlisted " : "listed ",
e->made_contact ? "made-contact" : "never-contacted");
smartlist_add(elements, tor_strdup(buf));
@@ -1801,7 +1850,7 @@ log_entry_guards(int severity)
#define NUM_ENTRY_PICK_TRIES 100
-/** Add a new (preferably stable and fast) router to our
+/** Add a new (preferably stable and fast) entry to our
* entry_guards list. Return a pointer to the router if we succeed,
* or NULL if we can't find any more suitable entries.
*
@@ -1813,23 +1862,33 @@ add_an_entry_guard(routerinfo_t *chosen)
{
routerinfo_t *router;
entry_guard_t *entry;
+ int tries_left = NUM_ENTRY_PICK_TRIES;
- if (chosen) {
+again:
+ if (--tries_left <= 0) {
+ log_warn(LD_CIRC, "Tried finding a new entry guard, but failed. "
+ "Can you reach the Tor network?");
+ return NULL;
+ }
+ if (chosen)
router = chosen;
- if (is_an_entry_guard(router->cache_info.identity_digest))
- return NULL;
- } else {
+ else
router = choose_good_entry_server(CIRCUIT_PURPOSE_C_GENERAL, NULL);
- if (!router)
+ if (!router)
+ return NULL;
+ /* make sure it's not already an entry */
+ if (is_an_entry_guard(router->cache_info.identity_digest)) {
+ if (chosen)
return NULL;
+ goto again;
}
entry = tor_malloc_zero(sizeof(entry_guard_t));
log_info(LD_CIRC, "Chose '%s' as new entry guard.", router->nickname);
strlcpy(entry->nickname, router->nickname, sizeof(entry->nickname));
memcpy(entry->identity, router->cache_info.identity_digest, DIGEST_LEN);
- if (chosen) /* prepend */
+ if (chosen)
smartlist_insert(entry_guards, 0, entry);
- else /* append */
+ else
smartlist_add(entry_guards, entry);
log_entry_guards(LOG_INFO);
return router;
@@ -1973,7 +2032,7 @@ entry_guards_set_status_from_directory(void)
}
log_info(LD_CIRC, "Summary: Entry '%s' is %s, %s, and %s.",
entry->nickname,
- (entry->down_since || entry->unlisted_since) ? "down" : "up",
+ entry->down_since ? "down" : "up",
entry->unlisted_since ? "unlisted" : "listed",
entry_is_live(entry, 0, 1) ? "live" : "not live");
});
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index dba7864861..73513c4030 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -33,7 +33,7 @@ static void circuit_free_cpath_node(crypt_path_t *victim);
* very important here, since we need to do it every time a cell arrives.) */
typedef struct orconn_circid_circuit_map_t {
HT_ENTRY(orconn_circid_circuit_map_t) node;
- or_connection_t *or_conn;
+ connection_t *or_conn;
uint16_t circ_id;
circuit_t *circuit;
} orconn_circid_circuit_map_t;
@@ -68,14 +68,35 @@ HT_GENERATE(orconn_circid_map, orconn_circid_circuit_map_t, node,
*/
orconn_circid_circuit_map_t *_last_circid_orconn_ent = NULL;
-static void
-circuit_set_circid_orconn_helper(circuit_t *circ, uint16_t id,
- or_connection_t *conn,
- uint16_t old_id, or_connection_t *old_conn)
+/** Set the p_conn or n_conn field of a circuit <b>circ</b>, along
+ * with the corresponding circuit ID, and add the circuit as appropriate
+ * to the (orconn,id)-\>circuit map. */
+void
+circuit_set_circid_orconn(circuit_t *circ, uint16_t id,
+ connection_t *conn,
+ enum which_conn_changed_t which)
{
+ uint16_t old_id;
+ connection_t *old_conn;
orconn_circid_circuit_map_t search;
orconn_circid_circuit_map_t *found;
+ tor_assert(!conn || conn->type == CONN_TYPE_OR);
+
+ if (which == P_CONN_CHANGED) {
+ old_id = circ->p_circ_id;
+ old_conn = circ->p_conn;
+ circ->p_circ_id = id;
+ circ->p_conn = conn;
+ } else {
+ old_id = circ->n_circ_id;
+ old_conn = circ->n_conn;
+ circ->n_circ_id = id;
+ circ->n_conn = conn;
+ }
+ if (conn == old_conn && old_id == id)
+ return;
+
if (_last_circid_orconn_ent &&
((old_id == _last_circid_orconn_ent->circ_id &&
old_conn == _last_circid_orconn_ent->or_conn) ||
@@ -85,7 +106,7 @@ circuit_set_circid_orconn_helper(circuit_t *circ, uint16_t id,
}
if (old_conn) { /* we may need to remove it from the conn-circid map */
- tor_assert(old_conn->_base.magic == OR_CONNECTION_MAGIC);
+ tor_assert(old_conn->magic == CONNECTION_MAGIC);
search.circ_id = old_id;
search.or_conn = old_conn;
found = HT_REMOVE(orconn_circid_map, &orconn_circid_circuit_map, &search);
@@ -114,47 +135,6 @@ circuit_set_circid_orconn_helper(circuit_t *circ, uint16_t id,
++conn->n_circuits;
}
-/** Set the p_conn field of a circuit <b>circ</b>, along
- * with the corresponding circuit ID, and add the circuit as appropriate
- * to the (orconn,id)-\>circuit map. */
-void
-circuit_set_p_circid_orconn(or_circuit_t *circ, uint16_t id,
- or_connection_t *conn)
-{
- uint16_t old_id;
- or_connection_t *old_conn;
-
- old_id = circ->p_circ_id;
- old_conn = circ->p_conn;
- circ->p_circ_id = id;
- circ->p_conn = conn;
-
- if (id == old_id && conn == old_conn)
- return;
- circuit_set_circid_orconn_helper(TO_CIRCUIT(circ), id, conn,
- old_id, old_conn);
-}
-
-/** Set the n_conn field of a circuit <b>circ</b>, along
- * with the corresponding circuit ID, and add the circuit as appropriate
- * to the (orconn,id)-\>circuit map. */
-void
-circuit_set_n_circid_orconn(circuit_t *circ, uint16_t id,
- or_connection_t *conn)
-{
- uint16_t old_id;
- or_connection_t *old_conn;
-
- old_id = circ->n_circ_id;
- old_conn = circ->n_conn;
- circ->n_circ_id = id;
- circ->n_conn = conn;
-
- if (id == old_id && conn == old_conn)
- return;
- circuit_set_circid_orconn_helper(circ, id, conn, old_id, old_conn);
-}
-
/** Change the state of <b>circ</b> to <b>state</b>, adding it to or removing
* it from lists as appropriate. */
void
@@ -220,7 +200,7 @@ circuit_close_all_marked(void)
}
}
-/** Return the head of the global linked list of circuits. */
+/** Return the head of the global linked list of circuits. **/
circuit_t *
_circuit_get_global_list(void)
{
@@ -244,53 +224,36 @@ circuit_state_to_string(int state)
}
}
-/* DOCDOC */
-static void
-init_circuit_base(circuit_t *circ)
-{
- circ->timestamp_created = time(NULL);
-
- circ->package_window = CIRCWINDOW_START;
- circ->deliver_window = CIRCWINDOW_START;
-
- circuit_add(circ);
-}
-
/** Allocate space for a new circuit, initializing with <b>p_circ_id</b>
* and <b>p_conn</b>. Add it to the global circuit list.
*/
-origin_circuit_t *
-origin_circuit_new(void)
+circuit_t *
+circuit_new(uint16_t p_circ_id, connection_t *p_conn)
{
- origin_circuit_t *circ;
+ circuit_t *circ;
+ static uint32_t n_circuits_allocated = 1;
/* never zero, since a global ID of 0 is treated specially by the
* controller */
- static uint32_t n_circuits_allocated = 1;
- circ = tor_malloc_zero(sizeof(origin_circuit_t));
- circ->_base.magic = ORIGIN_CIRCUIT_MAGIC;
+ circ = tor_malloc_zero(sizeof(circuit_t));
+ circ->magic = CIRCUIT_MAGIC;
- circ->next_stream_id = crypto_rand_int(1<<16);
- circ->global_identifier = n_circuits_allocated++;
-
- init_circuit_base(TO_CIRCUIT(circ));
-
- return circ;
-}
+ circ->timestamp_created = time(NULL);
-or_circuit_t *
-or_circuit_new(uint16_t p_circ_id, or_connection_t *p_conn)
-{
/* CircIDs */
- or_circuit_t *circ;
+ if (p_conn) {
+ circuit_set_circid_orconn(circ, p_circ_id, p_conn, P_CONN_CHANGED);
+ }
+ /* circ->n_circ_id remains 0 because we haven't identified the next hop
+ * yet */
- circ = tor_malloc_zero(sizeof(or_circuit_t));
- circ->_base.magic = OR_CIRCUIT_MAGIC;
+ circ->package_window = CIRCWINDOW_START;
+ circ->deliver_window = CIRCWINDOW_START;
- if (p_conn)
- circuit_set_p_circid_orconn(circ, p_circ_id, p_conn);
+ circ->next_stream_id = crypto_rand_int(1<<16);
+ circ->global_identifier = n_circuits_allocated++;
- init_circuit_base(TO_CIRCUIT(circ));
+ circuit_add(circ);
return circ;
}
@@ -300,53 +263,35 @@ or_circuit_new(uint16_t p_circ_id, or_connection_t *p_conn)
static void
circuit_free(circuit_t *circ)
{
- void *mem;
tor_assert(circ);
- if (CIRCUIT_IS_ORIGIN(circ)) {
- origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
- mem = ocirc;
- tor_assert(circ->magic == ORIGIN_CIRCUIT_MAGIC);
- if (ocirc->build_state) {
- if (ocirc->build_state->chosen_exit)
- extend_info_free(ocirc->build_state->chosen_exit);
- if (ocirc->build_state->pending_final_cpath)
- circuit_free_cpath_node(ocirc->build_state->pending_final_cpath);
- }
- tor_free(ocirc->build_state);
-
- circuit_free_cpath(ocirc->cpath);
-
- } else {
- or_circuit_t *ocirc = TO_OR_CIRCUIT(circ);
- mem = ocirc;
- tor_assert(circ->magic == OR_CIRCUIT_MAGIC);
-
- if (ocirc->p_crypto)
- crypto_free_cipher_env(ocirc->p_crypto);
- if (ocirc->p_digest)
- crypto_free_digest_env(ocirc->p_digest);
- if (ocirc->n_crypto)
- crypto_free_cipher_env(ocirc->n_crypto);
- if (ocirc->n_digest)
- crypto_free_digest_env(ocirc->n_digest);
-
- if (ocirc->rend_splice) {
- or_circuit_t *other = ocirc->rend_splice;
- tor_assert(other->_base.magic == OR_CIRCUIT_MAGIC);
- other->rend_splice = NULL;
- }
-
- tor_free(circ->onionskin);
-
- /* remove from map. */
- circuit_set_p_circid_orconn(ocirc, 0, NULL);
+ tor_assert(circ->magic == CIRCUIT_MAGIC);
+ if (circ->n_crypto)
+ crypto_free_cipher_env(circ->n_crypto);
+ if (circ->p_crypto)
+ crypto_free_cipher_env(circ->p_crypto);
+ if (circ->n_digest)
+ crypto_free_digest_env(circ->n_digest);
+ if (circ->p_digest)
+ crypto_free_digest_env(circ->p_digest);
+ if (circ->build_state) {
+ if (circ->build_state->chosen_exit)
+ extend_info_free(circ->build_state->chosen_exit);
+ if (circ->build_state->pending_final_cpath)
+ circuit_free_cpath_node(circ->build_state->pending_final_cpath);
+ }
+ tor_free(circ->build_state);
+ tor_free(circ->onionskin);
+ circuit_free_cpath(circ->cpath);
+ if (circ->rend_splice) {
+ tor_assert(circ->rend_splice->magic == CIRCUIT_MAGIC);
+ circ->rend_splice->rend_splice = NULL;
}
-
/* Remove from map. */
- circuit_set_n_circid_orconn(circ, 0, NULL);
+ circuit_set_circid_orconn(circ, 0, NULL, P_CONN_CHANGED);
+ circuit_set_circid_orconn(circ, 0, NULL, N_CONN_CHANGED);
memset(circ, 0xAA, sizeof(circuit_t)); /* poison memory */
- tor_free(mem);
+ tor_free(circ);
}
/** Deallocate space associated with the linked list <b>cpath</b>. */
@@ -376,14 +321,11 @@ circuit_free_all(void)
circuit_t *next;
while (global_circuitlist) {
next = global_circuitlist->next;
- if (! CIRCUIT_IS_ORIGIN(global_circuitlist)) {
- or_circuit_t *or_circ = TO_OR_CIRCUIT(global_circuitlist);
- while (or_circ->resolving_streams) {
- edge_connection_t *next;
- next = or_circ->resolving_streams->next_stream;
- connection_free(TO_CONN(or_circ->resolving_streams));
- or_circ->resolving_streams = next;
- }
+ while (global_circuitlist->resolving_streams) {
+ connection_t *next;
+ next = global_circuitlist->resolving_streams->next_stream;
+ connection_free(global_circuitlist->resolving_streams);
+ global_circuitlist->resolving_streams = next;
}
circuit_free(global_circuitlist);
global_circuitlist = next;
@@ -416,92 +358,18 @@ circuit_free_cpath_node(crypt_path_t *victim)
tor_free(victim);
}
-/** A helper function for circuit_dump_by_conn() below. Log a bunch
- * of information about circuit <b>circ</b>.
- */
-static void
-circuit_dump_details(int severity, circuit_t *circ, int conn_array_index,
- const char *type, int this_circid, int other_circid)
-{
- log(severity, LD_CIRC, "Conn %d has %s circuit: circID %d (other side %d), "
- "state %d (%s), born %d:",
- conn_array_index, type, this_circid, other_circid, circ->state,
- circuit_state_to_string(circ->state), (int)circ->timestamp_created);
- if (CIRCUIT_IS_ORIGIN(circ)) { /* circ starts at this node */
- circuit_log_path(severity, LD_CIRC, TO_ORIGIN_CIRCUIT(circ));
- }
-}
-
-/** Log, at severity <b>severity</b>, information about each circuit
- * that is connected to <b>conn</b>.
- */
-void
-circuit_dump_by_conn(connection_t *conn, int severity)
-{
- circuit_t *circ;
- edge_connection_t *tmpconn;
-
- for (circ=global_circuitlist;circ;circ = circ->next) {
- circid_t n_circ_id = circ->n_circ_id, p_circ_id = 0;
- if (circ->marked_for_close)
- continue;
-
- if (! CIRCUIT_IS_ORIGIN(circ))
- p_circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
-
- if (! CIRCUIT_IS_ORIGIN(circ) && TO_OR_CIRCUIT(circ)->p_conn &&
- TO_CONN(TO_OR_CIRCUIT(circ)->p_conn) == conn)
- circuit_dump_details(severity, circ, conn->conn_array_index, "App-ward",
- p_circ_id, n_circ_id);
- if (CIRCUIT_IS_ORIGIN(circ)) {
- for (tmpconn=TO_ORIGIN_CIRCUIT(circ)->p_streams; tmpconn;
- tmpconn=tmpconn->next_stream) {
- if (TO_CONN(tmpconn) == conn) {
- circuit_dump_details(severity, circ, conn->conn_array_index,
- "App-ward", p_circ_id, n_circ_id);
- }
- }
- }
- if (circ->n_conn && TO_CONN(circ->n_conn) == conn)
- circuit_dump_details(severity, circ, conn->conn_array_index, "Exit-ward",
- n_circ_id, p_circ_id);
- if (! CIRCUIT_IS_ORIGIN(circ)) {
- for (tmpconn=TO_OR_CIRCUIT(circ)->n_streams; tmpconn;
- tmpconn=tmpconn->next_stream) {
- if (TO_CONN(tmpconn) == conn) {
- circuit_dump_details(severity, circ, conn->conn_array_index,
- "Exit-ward", n_circ_id, p_circ_id);
- }
- }
- }
- if (!circ->n_conn && circ->n_addr && circ->n_port &&
- circ->n_addr == conn->addr &&
- circ->n_port == conn->port &&
- conn->type == CONN_TYPE_OR &&
- !memcmp(TO_OR_CONN(conn)->identity_digest, circ->n_conn_id_digest,
- DIGEST_LEN)) {
- circuit_dump_details(severity, circ, conn->conn_array_index,
- (circ->state == CIRCUIT_STATE_OPEN &&
- !CIRCUIT_IS_ORIGIN(circ)) ?
- "Endpoint" : "Pending",
- n_circ_id, p_circ_id);
- }
- }
-}
-
/** Return the circuit whose global ID is <b>id</b>, or NULL if no
* such circuit exists. */
-origin_circuit_t *
+circuit_t *
circuit_get_by_global_id(uint32_t id)
{
circuit_t *circ;
for (circ=global_circuitlist;circ;circ = circ->next) {
- if (CIRCUIT_IS_ORIGIN(circ) &&
- TO_ORIGIN_CIRCUIT(circ)->global_identifier == id) {
+ if (circ->global_identifier == id) {
if (circ->marked_for_close)
return NULL;
else
- return TO_ORIGIN_CIRCUIT(circ);
+ return circ;
}
}
return NULL;
@@ -513,11 +381,13 @@ circuit_get_by_global_id(uint32_t id)
* Return NULL if no such circuit exists.
*/
static INLINE circuit_t *
-circuit_get_by_circid_orconn_impl(uint16_t circ_id, or_connection_t *conn)
+circuit_get_by_circid_orconn_impl(uint16_t circ_id, connection_t *conn)
{
orconn_circid_circuit_map_t search;
orconn_circid_circuit_map_t *found;
+ tor_assert(conn->type == CONN_TYPE_OR);
+
if (_last_circid_orconn_ent &&
circ_id == _last_circid_orconn_ent->circ_id &&
conn == _last_circid_orconn_ent->or_conn) {
@@ -537,13 +407,10 @@ circuit_get_by_circid_orconn_impl(uint16_t circ_id, or_connection_t *conn)
{
circuit_t *circ;
for (circ=global_circuitlist;circ;circ = circ->next) {
- if (! CIRCUIT_IS_ORIGIN(circ)) {
- or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
- if (or_circ->p_conn == conn && or_circ->p_circ_id == circ_id) {
- log_warn(LD_BUG,
- "circuit matches p_conn, but not in hash table (Bug!)");
- return circ;
- }
+ if (circ->p_conn == conn && circ->p_circ_id == circ_id) {
+ log_warn(LD_BUG,
+ "circuit matches p_conn, but not in hash table (Bug!)");
+ return circ;
}
if (circ->n_conn == conn && circ->n_circ_id == circ_id) {
log_warn(LD_BUG,
@@ -562,7 +429,7 @@ circuit_get_by_circid_orconn_impl(uint16_t circ_id, or_connection_t *conn)
* Return NULL if no such circuit exists.
*/
circuit_t *
-circuit_get_by_circid_orconn(uint16_t circ_id, or_connection_t *conn)
+circuit_get_by_circid_orconn(uint16_t circ_id, connection_t *conn)
{
circuit_t *circ = circuit_get_by_circid_orconn_impl(circ_id, conn);
if (!circ || circ->marked_for_close)
@@ -577,7 +444,7 @@ circuit_get_by_circid_orconn(uint16_t circ_id, or_connection_t *conn)
* Return NULL if no such circuit exists.
*/
int
-circuit_id_used_on_conn(uint16_t circ_id, or_connection_t *conn)
+circuit_id_used_on_conn(uint16_t circ_id, connection_t *conn)
{
circuit_t *circ = circuit_get_by_circid_orconn_impl(circ_id, conn);
if (circ && circ->marked_for_close)
@@ -589,14 +456,13 @@ circuit_id_used_on_conn(uint16_t circ_id, or_connection_t *conn)
/** Return the circuit that a given edge connection is using. */
circuit_t *
-circuit_get_by_edge_conn(edge_connection_t *conn)
+circuit_get_by_edge_conn(connection_t *conn)
{
circuit_t *circ;
+ tor_assert(CONN_IS_EDGE(conn));
circ = conn->on_circuit;
- tor_assert(!circ ||
- (CIRCUIT_IS_ORIGIN(circ) ? circ->magic == ORIGIN_CIRCUIT_MAGIC
- : circ->magic == OR_CIRCUIT_MAGIC));
+ tor_assert(!circ || circ->magic == CIRCUIT_MAGIC);
return circ;
}
@@ -606,24 +472,18 @@ circuit_get_by_edge_conn(edge_connection_t *conn)
* been marked already.
*/
void
-circuit_unlink_all_from_or_conn(or_connection_t *conn, int reason)
+circuit_unlink_all_from_or_conn(connection_t *conn, int reason)
{
circuit_t *circ;
for (circ = global_circuitlist; circ; circ = circ->next) {
- int mark = 0;
- if (circ->n_conn == conn) {
- circuit_set_n_circid_orconn(circ, 0, NULL);
- mark = 1;
- }
- if (! CIRCUIT_IS_ORIGIN(circ)) {
- or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
- if (or_circ->p_conn == conn) {
- circuit_set_p_circid_orconn(or_circ, 0, NULL);
- mark = 1;
- }
+ if (circ->n_conn == conn || circ->p_conn == conn) {
+ if (circ->n_conn == conn)
+ circuit_set_circid_orconn(circ, 0, NULL, N_CONN_CHANGED);
+ if (circ->p_conn == conn)
+ circuit_set_circid_orconn(circ, 0, NULL, P_CONN_CHANGED);
+ if (!circ->marked_for_close)
+ circuit_mark_for_close(circ, reason);
}
- if (mark && !circ->marked_for_close)
- circuit_mark_for_close(circ, reason);
}
}
@@ -633,91 +493,62 @@ circuit_unlink_all_from_or_conn(or_connection_t *conn, int reason)
*
* Return NULL if no such circuit exists.
*/
-origin_circuit_t *
+circuit_t *
circuit_get_by_rend_query_and_purpose(const char *rend_query, uint8_t purpose)
{
circuit_t *circ;
- tor_assert(CIRCUIT_PURPOSE_IS_ORIGIN(purpose));
-
for (circ = global_circuitlist; circ; circ = circ->next) {
if (!circ->marked_for_close &&
circ->purpose == purpose &&
- !rend_cmp_service_ids(rend_query, TO_ORIGIN_CIRCUIT(circ)->rend_query))
- return TO_ORIGIN_CIRCUIT(circ);
+ !rend_cmp_service_ids(rend_query, circ->rend_query))
+ return circ;
}
return NULL;
}
/** Return the first circuit in global_circuitlist after <b>start</b>
- * whose purpose is <b>purpose</b> is purpose, and (if set) whose
- * <b>digest</b> matches the rend_pk_digest field. Return NULL if no
- * circuit is found.
+ * whose rend_pk_digest field is <b>digest</b> and whose purpose is
+ * <b>purpose</b>. Returns NULL if no circuit is found.
* If <b>start</b> is NULL, begin at the start of the list.
- * DOCDOC origin.
*/
-origin_circuit_t *
-circuit_get_next_by_pk_and_purpose(origin_circuit_t *start,
+circuit_t *
+circuit_get_next_by_pk_and_purpose(circuit_t *start,
const char *digest, uint8_t purpose)
{
circuit_t *circ;
- tor_assert(CIRCUIT_PURPOSE_IS_ORIGIN(purpose));
if (start == NULL)
circ = global_circuitlist;
else
- circ = TO_CIRCUIT(start)->next;
+ circ = start->next;
for ( ; circ; circ = circ->next) {
if (circ->marked_for_close)
continue;
if (circ->purpose != purpose)
continue;
- if (!digest)
- return TO_ORIGIN_CIRCUIT(circ);
- else if (!memcmp(TO_ORIGIN_CIRCUIT(circ)->rend_pk_digest,
- digest, DIGEST_LEN))
- return TO_ORIGIN_CIRCUIT(circ);
+ if (!memcmp(circ->rend_pk_digest, digest, DIGEST_LEN))
+ return circ;
}
return NULL;
}
-/* DOCDOC */
-static or_circuit_t *
-circuit_get_by_rend_token_and_purpose(uint8_t purpose, const char *token,
- size_t len)
+/** Return the circuit waiting for a rendezvous with the provided cookie.
+ * Return NULL if no such circuit is found.
+ */
+circuit_t *
+circuit_get_rendezvous(const char *cookie)
{
circuit_t *circ;
for (circ = global_circuitlist; circ; circ = circ->next) {
if (! circ->marked_for_close &&
- circ->purpose == purpose &&
- ! memcmp(TO_OR_CIRCUIT(circ)->rend_token, token, len))
- return TO_OR_CIRCUIT(circ);
+ circ->purpose == CIRCUIT_PURPOSE_REND_POINT_WAITING &&
+ ! memcmp(circ->rend_cookie, cookie, REND_COOKIE_LEN) )
+ return circ;
}
return NULL;
}
-/** Return the circuit waiting for a rendezvous with the provided cookie.
- * Return NULL if no such circuit is found.
- */
-or_circuit_t *
-circuit_get_rendezvous(const char *cookie)
-{
- return circuit_get_by_rend_token_and_purpose(
- CIRCUIT_PURPOSE_REND_POINT_WAITING,
- cookie, REND_COOKIE_LEN);
-}
-
-/** Return the circuit waiting for intro cells of the given digest.
- * Return NULL if no such circuit is found.
- */
-or_circuit_t *
-circuit_get_intro_point(const char *digest)
-{
- return circuit_get_by_rend_token_and_purpose(
- CIRCUIT_PURPOSE_INTRO_POINT, digest,
- DIGEST_LEN);
-}
-
/** Return a circuit that is open, has specified <b>purpose</b>,
* has a timestamp_dirty value of 0, is uptime/capacity/internal
* if required, and if info is defined, does not already use info
@@ -728,43 +559,41 @@ circuit_get_intro_point(const char *digest)
*
* Only return internal circuits if that is requested.
*/
-origin_circuit_t *
+circuit_t *
circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
int need_uptime,
int need_capacity, int internal)
{
- circuit_t *_circ;
- origin_circuit_t *best=NULL;
+ circuit_t *circ;
+ circuit_t *best=NULL;
log_debug(LD_CIRC,
"Hunting for a circ to cannibalize: purpose %d, uptime %d, "
"capacity %d, internal %d",
purpose, need_uptime, need_capacity, internal);
- for (_circ=global_circuitlist; _circ; _circ = _circ->next) {
- if (CIRCUIT_IS_ORIGIN(_circ) &&
- _circ->state == CIRCUIT_STATE_OPEN &&
- !_circ->marked_for_close &&
- _circ->purpose == purpose &&
- !_circ->timestamp_dirty) {
- origin_circuit_t *circ = TO_ORIGIN_CIRCUIT(_circ);
- if ((!need_uptime || circ->build_state->need_uptime) &&
- (!need_capacity || circ->build_state->need_capacity) &&
- (internal == circ->build_state->is_internal)) {
- if (info) {
- /* need to make sure we don't duplicate hops */
- crypt_path_t *hop = circ->cpath;
- do {
- if (!memcmp(hop->extend_info->identity_digest,
- info->identity_digest, DIGEST_LEN))
- goto next;
- hop=hop->next;
- } while (hop!=circ->cpath);
- }
- if (!best || (best->build_state->need_uptime && !need_uptime))
- best = circ;
- next: ;
+ for (circ=global_circuitlist; circ; circ = circ->next) {
+ if (CIRCUIT_IS_ORIGIN(circ) &&
+ circ->state == CIRCUIT_STATE_OPEN &&
+ !circ->marked_for_close &&
+ circ->purpose == purpose &&
+ !circ->timestamp_dirty &&
+ (!need_uptime || circ->build_state->need_uptime) &&
+ (!need_capacity || circ->build_state->need_capacity) &&
+ (internal == circ->build_state->is_internal)) {
+ if (info) {
+ /* need to make sure we don't duplicate hops */
+ crypt_path_t *hop = circ->cpath;
+ do {
+ if (!memcmp(hop->extend_info->identity_digest,
+ info->identity_digest, DIGEST_LEN))
+ goto next;
+ hop=hop->next;
+ } while (hop!=circ->cpath);
}
+ if (!best || (best->build_state->need_uptime && !need_uptime))
+ best = circ;
+ next: ;
}
}
return best;
@@ -825,6 +654,8 @@ void
_circuit_mark_for_close(circuit_t *circ, int reason, int line,
const char *file)
{
+ connection_t *conn;
+
assert_circuit_ok(circ);
tor_assert(line);
tor_assert(file);
@@ -854,7 +685,7 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line,
}
if (circ->state == CIRCUIT_STATE_ONIONSKIN_PENDING) {
- onion_pending_remove(TO_OR_CIRCUIT(circ));
+ onion_pending_remove(circ);
}
/* If the circuit ever became OPEN, we sent it to the reputation history
* module then. If it isn't OPEN, we send it there now to remember which
@@ -862,74 +693,60 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line,
*/
if (circ->state != CIRCUIT_STATE_OPEN) {
if (CIRCUIT_IS_ORIGIN(circ)) {
- origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
- circuit_build_failed(ocirc); /* take actions if necessary */
- circuit_rep_hist_note_result(ocirc);
+ circuit_build_failed(circ); /* take actions if necessary */
}
+ circuit_rep_hist_note_result(circ);
}
if (circ->state == CIRCUIT_STATE_OR_WAIT) {
if (circuits_pending_or_conns)
smartlist_remove(circuits_pending_or_conns, circ);
}
if (CIRCUIT_IS_ORIGIN(circ)) {
- control_event_circuit_status(TO_ORIGIN_CIRCUIT(circ),
+ control_event_circuit_status(circ,
(circ->state == CIRCUIT_STATE_OPEN)?CIRC_EVENT_CLOSED:CIRC_EVENT_FAILED);
}
if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
- origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
tor_assert(circ->state == CIRCUIT_STATE_OPEN);
- tor_assert(ocirc->build_state->chosen_exit);
+ tor_assert(circ->build_state->chosen_exit);
/* treat this like getting a nack from it */
log_info(LD_REND, "Failed intro circ %s to %s (awaiting ack). "
"Removing from descriptor.",
- safe_str(ocirc->rend_query),
- safe_str(build_state_get_exit_nickname(ocirc->build_state)));
- rend_client_remove_intro_point(ocirc->build_state->chosen_exit,
- ocirc->rend_query);
+ safe_str(circ->rend_query),
+ safe_str(build_state_get_exit_nickname(circ->build_state)));
+ rend_client_remove_intro_point(circ->build_state->chosen_exit,
+ circ->rend_query);
}
+
if (circ->n_conn)
connection_or_send_destroy(circ->n_circ_id, circ->n_conn, reason);
-
- if (! CIRCUIT_IS_ORIGIN(circ)) {
- or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
- edge_connection_t *conn;
- for (conn=or_circ->n_streams; conn; conn=conn->next_stream)
- connection_edge_destroy(or_circ->p_circ_id, conn);
-
- while (or_circ->resolving_streams) {
- conn = or_circ->resolving_streams;
- or_circ->resolving_streams = conn->next_stream;
- if (!conn->_base.marked_for_close) {
- /* The other side will see a DESTROY, and infer that the connections
- * are closing because the circuit is getting torn down. No need
- * to send an end cell. */
- conn->_base.edge_has_sent_end = 1;
- connection_mark_for_close(TO_CONN(conn));
- }
- conn->on_circuit = NULL;
+ for (conn=circ->n_streams; conn; conn=conn->next_stream)
+ connection_edge_destroy(circ->n_circ_id, conn);
+ while (circ->resolving_streams) {
+ conn = circ->resolving_streams;
+ circ->resolving_streams = conn->next_stream;
+ if (!conn->marked_for_close) {
+ /* The other side will see a DESTROY, and infer that the connections
+ * are closing because the circuit is getting torn down. No need
+ * to send an end cell. */
+ conn->has_sent_end = 1;
+ connection_mark_for_close(conn);
}
-
- if (or_circ->p_conn)
- connection_or_send_destroy(or_circ->p_circ_id, or_circ->p_conn, reason);
- } else {
- origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
- edge_connection_t *conn;
- for (conn=ocirc->p_streams; conn; conn=conn->next_stream)
- connection_edge_destroy(circ->n_circ_id, conn);
+ conn->on_circuit = NULL;
}
+ if (circ->p_conn)
+ connection_or_send_destroy(circ->p_circ_id, circ->p_conn, reason);
+ for (conn=circ->p_streams; conn; conn=conn->next_stream)
+ connection_edge_destroy(circ->p_circ_id, conn);
circ->marked_for_close = line;
circ->marked_for_close_file = file;
- if (! CIRCUIT_IS_ORIGIN(circ)) {
- or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
- if (or_circ->rend_splice) {
- if (!or_circ->rend_splice->_base.marked_for_close) {
- /* do this after marking this circuit, to avoid infinite recursion. */
- circuit_mark_for_close(TO_CIRCUIT(or_circ->rend_splice), reason);
- }
- or_circ->rend_splice = NULL;
+ if (circ->rend_splice) {
+ if (!circ->rend_splice->marked_for_close) {
+ /* do this after marking this circuit, to avoid infinite recursion. */
+ circuit_mark_for_close(circ->rend_splice, reason);
}
+ circ->rend_splice = NULL;
}
}
@@ -992,49 +809,46 @@ assert_cpath_ok(const crypt_path_t *cp)
void
assert_circuit_ok(const circuit_t *c)
{
- edge_connection_t *conn;
- const or_circuit_t *or_circ = NULL;
- const origin_circuit_t *origin_circ = NULL;
+ connection_t *conn;
tor_assert(c);
- tor_assert(c->magic == ORIGIN_CIRCUIT_MAGIC || c->magic == OR_CIRCUIT_MAGIC);
+ tor_assert(c->magic == CIRCUIT_MAGIC);
tor_assert(c->purpose >= _CIRCUIT_PURPOSE_MIN &&
c->purpose <= _CIRCUIT_PURPOSE_MAX);
- if (CIRCUIT_IS_ORIGIN(c))
- origin_circ = TO_ORIGIN_CIRCUIT((circuit_t*)c);
- else
- or_circ = TO_OR_CIRCUIT((circuit_t*)c);
-
if (c->n_conn) {
+ tor_assert(c->n_conn->type == CONN_TYPE_OR);
tor_assert(!memcmp(c->n_conn->identity_digest, c->n_conn_id_digest,
DIGEST_LEN));
if (c->n_circ_id)
tor_assert(c == circuit_get_by_circid_orconn(c->n_circ_id, c->n_conn));
}
- if (or_circ && or_circ->p_conn) {
- if (or_circ->p_circ_id)
- tor_assert(c == circuit_get_by_circid_orconn(or_circ->p_circ_id,
- or_circ->p_conn));
+ if (c->p_conn) {
+ tor_assert(c->p_conn->type == CONN_TYPE_OR);
+ if (c->p_circ_id)
+ tor_assert(c == circuit_get_by_circid_orconn(c->p_circ_id, c->p_conn));
}
-#if 0 /* false now that rendezvous exits are attached to p_streams */
- if (origin_circ)
- for (conn = origin_circ->p_streams; conn; conn = conn->next_stream)
- tor_assert(conn->_base.type == CONN_TYPE_AP);
-#endif
- if (or_circ)
- for (conn = or_circ->n_streams; conn; conn = conn->next_stream)
- tor_assert(conn->_base.type == CONN_TYPE_EXIT);
+ for (conn = c->p_streams; conn; conn = conn->next_stream)
+ tor_assert(conn->type == CONN_TYPE_AP);
+ for (conn = c->n_streams; conn; conn = conn->next_stream)
+ tor_assert(conn->type == CONN_TYPE_EXIT);
tor_assert(c->deliver_window >= 0);
tor_assert(c->package_window >= 0);
if (c->state == CIRCUIT_STATE_OPEN) {
tor_assert(!c->onionskin);
- if (or_circ) {
- tor_assert(or_circ->n_crypto);
- tor_assert(or_circ->p_crypto);
- tor_assert(or_circ->n_digest);
- tor_assert(or_circ->p_digest);
+ if (c->cpath) {
+ tor_assert(CIRCUIT_IS_ORIGIN(c));
+ tor_assert(!c->n_crypto);
+ tor_assert(!c->p_crypto);
+ tor_assert(!c->n_digest);
+ tor_assert(!c->p_digest);
+ } else {
+ tor_assert(!CIRCUIT_IS_ORIGIN(c));
+ tor_assert(c->n_crypto);
+ tor_assert(c->p_crypto);
+ tor_assert(c->n_digest);
+ tor_assert(c->p_digest);
}
}
if (c->state == CIRCUIT_STATE_OR_WAIT && !c->marked_for_close) {
@@ -1044,18 +858,17 @@ assert_circuit_ok(const circuit_t *c)
tor_assert(!circuits_pending_or_conns ||
!smartlist_isin(circuits_pending_or_conns, c));
}
- if (origin_circ && origin_circ->cpath) {
- assert_cpath_ok(origin_circ->cpath);
+ if (c->cpath) {
+ assert_cpath_ok(c->cpath);
}
if (c->purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED) {
- tor_assert(or_circ);
if (!c->marked_for_close) {
- tor_assert(or_circ->rend_splice);
- tor_assert(or_circ->rend_splice->rend_splice == or_circ);
+ tor_assert(c->rend_splice);
+ tor_assert(c->rend_splice->rend_splice == c);
}
- tor_assert(or_circ->rend_splice != or_circ);
+ tor_assert(c->rend_splice != c);
} else {
- tor_assert(!or_circ || !or_circ->rend_splice);
+ tor_assert(!c->rend_splice);
}
}
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 310e8278fb..2aec912c17 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -26,13 +26,12 @@ static void circuit_increment_failure_count(void);
* Else return 0.
*/
static int
-circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
+circuit_is_acceptable(circuit_t *circ, connection_t *conn,
int must_be_open, uint8_t purpose,
int need_uptime, int need_internal,
time_t now)
{
routerinfo_t *exitrouter;
- cpath_build_state_t *build_state;
tor_assert(circ);
tor_assert(conn);
tor_assert(conn->socks_request);
@@ -72,12 +71,11 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
* circuit, it's the magical extra bob hop. so just check the nickname
* of the one we meant to finish at.
*/
- build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
- exitrouter = build_state_get_exit_router(build_state);
+ exitrouter = build_state_get_exit_router(circ->build_state);
- if (need_uptime && !build_state->need_uptime)
+ if (need_uptime && !circ->build_state->need_uptime)
return 0;
- if (need_internal != build_state->is_internal)
+ if (need_internal != circ->build_state->is_internal)
return 0;
if (purpose == CIRCUIT_PURPOSE_C_GENERAL) {
@@ -91,8 +89,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
return 0;
}
} else { /* not general */
- if (rend_cmp_service_ids(conn->rend_query,
- TO_ORIGIN_CIRCUIT(circ)->rend_query)) {
+ if (rend_cmp_service_ids(conn->rend_query, circ->rend_query)) {
/* this circ is not for this conn */
return 0;
}
@@ -117,11 +114,9 @@ circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose)
return 1;
} else {
if (a->timestamp_dirty ||
+ b->build_state->is_internal ||
a->timestamp_created > b->timestamp_created)
return 1;
- if (CIRCUIT_IS_ORIGIN(b) &&
- TO_ORIGIN_CIRCUIT(b)->build_state->is_internal)
- return 1;
}
break;
case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
@@ -154,8 +149,8 @@ circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose)
* If it's INTRODUCE_ACK_WAIT and must_be_open==0, then return the
* closest introduce-purposed circuit that you can find.
*/
-static origin_circuit_t *
-circuit_get_best(edge_connection_t *conn, int must_be_open, uint8_t purpose,
+static circuit_t *
+circuit_get_best(connection_t *conn, int must_be_open, uint8_t purpose,
int need_uptime, int need_internal)
{
circuit_t *circ, *best=NULL;
@@ -168,8 +163,6 @@ circuit_get_best(edge_connection_t *conn, int must_be_open, uint8_t purpose,
purpose == CIRCUIT_PURPOSE_C_REND_JOINED);
for (circ=global_circuitlist;circ;circ = circ->next) {
- if (!CIRCUIT_IS_ORIGIN(circ))
- continue;
if (!circuit_is_acceptable(circ,conn,must_be_open,purpose,
need_uptime,need_internal,now))
continue;
@@ -181,7 +174,7 @@ circuit_get_best(edge_connection_t *conn, int must_be_open, uint8_t purpose,
best = circ;
}
- return best ? TO_ORIGIN_CIRCUIT(best) : NULL;
+ return best;
}
/** Close all circuits that start at us, aren't open, and were born
@@ -237,8 +230,7 @@ circuit_expire_building(time_t now)
/* c_rend_ready circs measure age since timestamp_dirty,
* because that's set when they switch purposes
*/
- if (TO_ORIGIN_CIRCUIT(victim)->rend_query[0] ||
- victim->timestamp_dirty > cutoff)
+ if (!victim->rend_query[0] || victim->timestamp_dirty > cutoff)
continue;
break;
case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED:
@@ -255,8 +247,7 @@ circuit_expire_building(time_t now)
if (victim->n_conn)
log_info(LD_CIRC,"Abandoning circ %s:%d:%d (state %d:%s, purpose %d)",
- victim->n_conn->_base.address, victim->n_port,
- victim->n_circ_id,
+ victim->n_conn->address, victim->n_port, victim->n_circ_id,
victim->state, circuit_state_to_string(victim->state),
victim->purpose);
else
@@ -264,7 +255,7 @@ circuit_expire_building(time_t now)
victim->n_circ_id, victim->state,
circuit_state_to_string(victim->state), victim->purpose);
- circuit_log_path(LOG_INFO,LD_CIRC,TO_ORIGIN_CIRCUIT(victim));
+ circuit_log_path(LOG_INFO,LD_CIRC,victim);
circuit_mark_for_close(victim, END_CIRC_AT_ORIGIN);
}
}
@@ -297,8 +288,7 @@ circuit_remove_handled_ports(smartlist_t *needed_ports)
* Else return 0.
*/
int
-circuit_stream_is_being_handled(edge_connection_t *conn,
- uint16_t port, int min)
+circuit_stream_is_being_handled(connection_t *conn, uint16_t port, int min)
{
circuit_t *circ;
routerinfo_t *exitrouter;
@@ -311,14 +301,12 @@ circuit_stream_is_being_handled(edge_connection_t *conn,
if (CIRCUIT_IS_ORIGIN(circ) &&
!circ->marked_for_close &&
circ->purpose == CIRCUIT_PURPOSE_C_GENERAL &&
+ !circ->build_state->is_internal &&
(!circ->timestamp_dirty ||
circ->timestamp_dirty + get_options()->MaxCircuitDirtiness > now)) {
- cpath_build_state_t *build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
- if (build_state->is_internal)
- continue;
-
- exitrouter = build_state_get_exit_router(build_state);
- if (exitrouter && (!need_uptime || build_state->need_uptime)) {
+ exitrouter = build_state_get_exit_router(circ->build_state);
+ if (exitrouter &&
+ (!need_uptime || circ->build_state->need_uptime)) {
int ok;
if (conn) {
ok = connection_ap_can_use_exit(conn, exitrouter);
@@ -355,7 +343,6 @@ 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;
if (!CIRCUIT_IS_ORIGIN(circ))
continue;
if (circ->marked_for_close)
@@ -365,10 +352,9 @@ circuit_predict_and_launch_new(void)
if (circ->purpose != CIRCUIT_PURPOSE_C_GENERAL)
continue; /* only pay attention to general-purpose circs */
num++;
- build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
- if (build_state->is_internal)
+ if (circ->build_state->is_internal)
num_internal++;
- if (build_state->need_uptime && build_state->is_internal)
+ if (circ->build_state->need_uptime && circ->build_state->is_internal)
num_uptime_internal++;
}
@@ -459,9 +445,9 @@ circuit_build_needed_circs(time_t now)
* lists of <b>circ</b>, then remove it from the list.
*/
void
-circuit_detach_stream(circuit_t *circ, edge_connection_t *conn)
+circuit_detach_stream(circuit_t *circ, connection_t *conn)
{
- edge_connection_t *prevconn;
+ connection_t *prevconn;
tor_assert(circ);
tor_assert(conn);
@@ -469,49 +455,44 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn)
conn->cpath_layer = NULL; /* make sure we don't keep a stale pointer */
conn->on_circuit = NULL;
- if (CIRCUIT_IS_ORIGIN(circ)) {
- origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
- if (conn == origin_circ->p_streams) {
- origin_circ->p_streams = conn->next_stream;
- return;
- }
+ if (conn == circ->p_streams) {
+ circ->p_streams = conn->next_stream;
+ return;
+ }
+ if (conn == circ->n_streams) {
+ circ->n_streams = conn->next_stream;
+ return;
+ }
+ if (conn == circ->resolving_streams) {
+ circ->resolving_streams = conn->next_stream;
+ return;
+ }
- for (prevconn = origin_circ->p_streams;
- prevconn && prevconn->next_stream && prevconn->next_stream != conn;
- prevconn = prevconn->next_stream)
- ;
- if (prevconn && prevconn->next_stream) {
- prevconn->next_stream = conn->next_stream;
- return;
- }
- } else {
- or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
- if (conn == or_circ->n_streams) {
- or_circ->n_streams = conn->next_stream;
- return;
- }
- if (conn == or_circ->resolving_streams) {
- or_circ->resolving_streams = conn->next_stream;
- return;
- }
+ for (prevconn = circ->p_streams;
+ prevconn && prevconn->next_stream && prevconn->next_stream != conn;
+ prevconn = prevconn->next_stream)
+ ;
+ if (prevconn && prevconn->next_stream) {
+ prevconn->next_stream = conn->next_stream;
+ return;
+ }
- for (prevconn = or_circ->n_streams;
- prevconn && prevconn->next_stream && prevconn->next_stream != conn;
- prevconn = prevconn->next_stream)
- ;
- if (prevconn && prevconn->next_stream) {
- prevconn->next_stream = conn->next_stream;
- return;
- }
+ for (prevconn = circ->n_streams;
+ prevconn && prevconn->next_stream && prevconn->next_stream != conn;
+ prevconn = prevconn->next_stream)
+ ;
+ if (prevconn && prevconn->next_stream) {
+ prevconn->next_stream = conn->next_stream;
+ return;
+ }
- for (prevconn = or_circ->resolving_streams;
- prevconn && prevconn->next_stream && prevconn->next_stream != conn;
- prevconn = prevconn->next_stream)
- ;
- if (prevconn && prevconn->next_stream) {
- prevconn->next_stream = conn->next_stream;
- return;
- }
+ for (prevconn = circ->resolving_streams;
+ prevconn && prevconn->next_stream && prevconn->next_stream != conn;
+ prevconn = prevconn->next_stream)
+ ;
+ if (prevconn && prevconn->next_stream) {
+ prevconn->next_stream = conn->next_stream;
+ return;
}
log_err(LD_BUG,"edge conn not in circuit's list?");
@@ -538,11 +519,10 @@ circuit_about_to_close_connection(connection_t *conn)
if (!connection_state_is_open(conn)) {
/* Inform any pending (not attached) circs that they should
* give up. */
- circuit_n_conn_done(TO_OR_CONN(conn), 0);
+ circuit_n_conn_done(conn, 0);
}
/* Now close all the attached circuits on it. */
- circuit_unlink_all_from_or_conn(TO_OR_CONN(conn),
- END_CIRC_REASON_OR_CONN_CLOSED);
+ circuit_unlink_all_from_or_conn(conn, END_CIRC_REASON_OR_CONN_CLOSED);
return;
}
case CONN_TYPE_AP:
@@ -553,17 +533,17 @@ circuit_about_to_close_connection(connection_t *conn)
* been sent. But don't kill the circuit.
*/
- circ = circuit_get_by_edge_conn(TO_EDGE_CONN(conn));
+ circ = circuit_get_by_edge_conn(conn);
if (!circ)
return;
- circuit_detach_stream(circ, TO_EDGE_CONN(conn));
+ circuit_detach_stream(circ, conn);
}
} /* end switch */
}
-/** Find each circuit that has been unused for too long, or dirty
- * for too long and has no streax=ms on it: mark it for close.
+/** Find each circuit that has been dirty for too long, and has
+ * no streams on it: mark it for close.
*/
static void
circuit_expire_old_circuits(time_t now)
@@ -572,19 +552,23 @@ circuit_expire_old_circuits(time_t now)
time_t cutoff = now - get_options()->CircuitIdleTimeout;
for (circ = global_circuitlist; circ; circ = circ->next) {
- if (circ->marked_for_close || ! CIRCUIT_IS_ORIGIN(circ))
+ if (circ->marked_for_close)
continue;
/* If the circuit has been dirty for too long, and there are no streams
* on it, mark it for close.
*/
if (circ->timestamp_dirty &&
circ->timestamp_dirty + get_options()->MaxCircuitDirtiness < now &&
- !TO_ORIGIN_CIRCUIT(circ)->p_streams /* nothing attached */ ) {
+ CIRCUIT_IS_ORIGIN(circ) &&
+ !circ->p_streams /* nothing attached */ ) {
log_debug(LD_CIRC, "Closing n_circ_id %d (dirty %d secs ago, purp %d)",
circ->n_circ_id, (int)(now - circ->timestamp_dirty),
circ->purpose);
+ /* (only general and purpose_c circs can get dirty) */
+ tor_assert(!circ->n_streams);
+ tor_assert(circ->purpose <= CIRCUIT_PURPOSE_C_REND_JOINED);
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
- } else if (!circ->timestamp_dirty &&
+ } else if (!circ->timestamp_dirty && CIRCUIT_IS_ORIGIN(circ) &&
circ->state == CIRCUIT_STATE_OPEN &&
circ->purpose == CIRCUIT_PURPOSE_C_GENERAL) {
if (circ->timestamp_created < cutoff) {
@@ -597,72 +581,30 @@ circuit_expire_old_circuits(time_t now)
}
}
-#define NUM_PARALLEL_TESTING_CIRCS 4
-
-static int have_performed_bandwidth_test = 0;
-
-/** Reset have_performed_bandwidth_test, so we'll start building
- * testing circuits again so we can exercise our bandwidth. */
-void
-reset_bandwidth_test(void)
-{
- have_performed_bandwidth_test = 0;
-}
-
-/** Return 1 if we've already exercised our bandwidth, or if we
- * have fewer than NUM_PARALLEL_TESTING_CIRCS testing circuits
- * established or on the way. Else return 0.
- */
-int
-circuit_enough_testing_circs(void)
-{
- circuit_t *circ;
- int num = 0;
-
- if (have_performed_bandwidth_test)
- return 1;
-
- for (circ = global_circuitlist; circ; circ = circ->next) {
- if (!circ->marked_for_close && CIRCUIT_IS_ORIGIN(circ) &&
- circ->purpose == CIRCUIT_PURPOSE_TESTING &&
- circ->state == CIRCUIT_STATE_OPEN)
- num++;
- }
- return num >= NUM_PARALLEL_TESTING_CIRCS;
-}
-
-/** A testing circuit has completed. Take whatever stats we want.
- * Noticing reachability is taken care of in onionskin_answer(),
- * so there's no need to record anything here. But if we still want
- * to do the bandwidth test, and we now have enough testing circuits
- * open, do it.
- */
+/** A testing circuit has completed. Take whatever stats we want. */
static void
-circuit_testing_opened(origin_circuit_t *circ)
+circuit_testing_opened(circuit_t *circ)
{
- if (have_performed_bandwidth_test) {
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
- } else if (circuit_enough_testing_circs()) {
- router_perform_bandwidth_test(NUM_PARALLEL_TESTING_CIRCS, time(NULL));
- have_performed_bandwidth_test = 1;
- } else
- consider_testing_reachability(1, 0);
+ /* For now, we only use testing circuits to see if our ORPort is
+ reachable. But we remember reachability in onionskin_answer(),
+ so there's no need to record anything here. Just close the circ. */
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
}
/** A testing circuit has failed to build. Take whatever stats we want. */
static void
-circuit_testing_failed(origin_circuit_t *circ, int at_last_hop)
+circuit_testing_failed(circuit_t *circ, int at_last_hop)
{
- if (server_mode(get_options()) && check_whether_orport_reachable())
- return;
+#if 0
+ routerinfo_t *me = router_get_my_routerinfo();
+ if (!at_last_hop)
+ circuit_launch_by_router(CIRCUIT_PURPOSE_TESTING, me, 0, 1, 1);
+ else
+#endif
log_info(LD_GENERAL,
"Our testing circuit (to see if your ORPort is reachable) "
"has failed. I'll try again later.");
-
- /* These aren't used yet. */
- (void)circ;
- (void)at_last_hop;
}
/** The circuit <b>circ</b> has just become open. Take the next
@@ -672,11 +614,11 @@ circuit_testing_failed(origin_circuit_t *circ, int at_last_hop)
* that could use circ.
*/
void
-circuit_has_opened(origin_circuit_t *circ)
+circuit_has_opened(circuit_t *circ)
{
control_event_circuit_status(circ, CIRC_EVENT_BUILT);
- switch (TO_CIRCUIT(circ)->purpose) {
+ switch (circ->purpose) {
case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
rend_client_rendcirc_has_opened(circ);
connection_ap_attach_pending();
@@ -701,7 +643,7 @@ circuit_has_opened(origin_circuit_t *circ)
circuit_testing_opened(circ);
break;
default:
- log_err(LD_BUG,"unhandled purpose %d",circ->_base.purpose);
+ log_err(LD_BUG,"unhandled purpose %d",circ->purpose);
tor_assert(0);
}
}
@@ -709,7 +651,7 @@ circuit_has_opened(origin_circuit_t *circ)
/** Called whenever a circuit could not be successfully built.
*/
void
-circuit_build_failed(origin_circuit_t *circ)
+circuit_build_failed(circuit_t *circ)
{
/* we should examine circ and see if it failed because of
* the last hop or an earlier hop. then use this info below.
@@ -726,35 +668,38 @@ circuit_build_failed(origin_circuit_t *circ)
circ->cpath->state != CPATH_STATE_OPEN) {
/* We failed at the first hop. If there's an OR connection
to blame, blame it. */
- or_connection_t *n_conn = NULL;
- if (circ->_base.n_conn) {
- n_conn = circ->_base.n_conn;
- } else if (circ->_base.state == CIRCUIT_STATE_OR_WAIT) {
+ connection_t *n_conn = NULL;
+ if (circ->n_conn) {
+ n_conn = circ->n_conn;
+ } else if (circ->state == CIRCUIT_STATE_OR_WAIT) {
/* we have to hunt for it */
- n_conn = connection_or_get_by_identity_digest(
- circ->_base.n_conn_id_digest);
+ n_conn = connection_or_get_by_identity_digest(circ->n_conn_id_digest);
}
if (n_conn) {
log_info(LD_OR,
"Our circuit failed to get a response from the first hop "
"(%s:%d). I'm going to try to rotate to a better connection.",
- n_conn->_base.address, n_conn->_base.port);
- n_conn->_base.or_is_obsolete = 1;
+ n_conn->address, n_conn->port);
+ n_conn->is_obsolete = 1;
entry_guard_set_status(n_conn->identity_digest, 0);
}
}
- switch (circ->_base.purpose) {
+ switch (circ->purpose) {
case CIRCUIT_PURPOSE_C_GENERAL:
- /* If we never built the circuit, note it as a failure. */
- circuit_increment_failure_count();
+ if (circ->state != CIRCUIT_STATE_OPEN) {
+ /* If we never built the circuit, note it as a failure. */
+ /* Note that we can't just check circ->cpath here, because if
+ * circuit-building failed immediately, it won't be set yet. */
+ circuit_increment_failure_count();
+ }
break;
case CIRCUIT_PURPOSE_TESTING:
circuit_testing_failed(circ, failed_at_last_hop);
break;
case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
/* at Bob, waiting for introductions */
- if (circ->_base.state != CIRCUIT_STATE_OPEN) {
+ if (circ->state != CIRCUIT_STATE_OPEN) {
circuit_increment_failure_count();
}
/* no need to care here, because bob will rebuild intro
@@ -769,7 +714,9 @@ circuit_build_failed(origin_circuit_t *circ)
break;
case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
/* at Alice, waiting for Bob */
- circuit_increment_failure_count();
+ if (circ->state != CIRCUIT_STATE_OPEN) {
+ circuit_increment_failure_count();
+ }
/* Alice will pick a new rend point when this one dies, if
* the stream in question still cares. No need to act here. */
break;
@@ -803,11 +750,11 @@ static int did_circs_fail_last_period = 0;
/** Launch a new circuit; see circuit_launch_by_extend_info() for
* details on arguments. */
-origin_circuit_t *
+circuit_t *
circuit_launch_by_router(uint8_t purpose, routerinfo_t *exit,
int need_uptime, int need_capacity, int internal)
{
- origin_circuit_t *circ;
+ circuit_t *circ;
extend_info_t *info = NULL;
if (exit)
info = extend_info_from_router(exit);
@@ -824,11 +771,11 @@ circuit_launch_by_router(uint8_t purpose, routerinfo_t *exit,
* choose among routers with high bandwidth. If <b>internal</b> is true, the
* last hop need not be an exit node. Return the newly allocated circuit on
* success, or NULL on failure. */
-origin_circuit_t *
+circuit_t *
circuit_launch_by_extend_info(uint8_t purpose, extend_info_t *extend_info,
int need_uptime, int need_capacity, int internal)
{
- origin_circuit_t *circ;
+ circuit_t *circ;
if (!router_have_minimum_dir_info()) {
log_debug(LD_CIRC,"Haven't fetched enough directory info yet; canceling "
@@ -844,11 +791,11 @@ circuit_launch_by_extend_info(uint8_t purpose, extend_info_t *extend_info,
if (circ) {
log_info(LD_CIRC,"Cannibalizing circ '%s' for purpose %d",
build_state_get_exit_nickname(circ->build_state), purpose);
- circ->_base.purpose = purpose;
+ circ->purpose = purpose;
/* reset the birth date of this circ, else expire_building
* will see it and think it's been trying to build since it
* began. */
- circ->_base.timestamp_created = time(NULL);
+ circ->timestamp_created = time(NULL);
switch (purpose) {
case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
@@ -888,7 +835,7 @@ circuit_launch_by_extend_info(uint8_t purpose, extend_info_t *extend_info,
/** Launch a new circuit; see circuit_launch_by_extend_info() for
* details on arguments. */
-origin_circuit_t *
+circuit_t *
circuit_launch_by_nickname(uint8_t purpose, const char *exit_nickname,
int need_uptime, int need_capacity, int internal)
{
@@ -929,26 +876,25 @@ circuit_reset_failure_count(int timeout)
n_circuit_failures = 0;
}
-/** Find an open circ that we're happy to use for <b>conn</b> and return 1. If
- * there isn't one, and there isn't one on the way, launch one and return
- * 0. If it will never work, return -1.
+/** Find an open circ that we're happy with: return 1. If there isn't
+ * one, and there isn't one on the way, launch one and return 0. If it
+ * will never work, return -1.
*
* Write the found or in-progress or launched circ into *circp.
*/
static int
-circuit_get_open_circ_or_launch(edge_connection_t *conn,
+circuit_get_open_circ_or_launch(connection_t *conn,
uint8_t desired_circuit_purpose,
- origin_circuit_t **circp)
+ circuit_t **circp)
{
- origin_circuit_t *circ;
+ circuit_t *circ;
int is_resolve;
int need_uptime, need_internal;
tor_assert(conn);
tor_assert(circp);
- tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT);
- is_resolve = (conn->socks_request->command == SOCKS_COMMAND_RESOLVE ||
- conn->socks_request->command == SOCKS_COMMAND_RESOLVE_PTR);
+ tor_assert(conn->state == AP_CONN_STATE_CIRCUIT_WAIT);
+ is_resolve = conn->socks_request->command == SOCKS_COMMAND_RESOLVE;
need_uptime = smartlist_string_num_isin(get_options()->LongLivedPorts,
conn->socks_request->port);
@@ -1010,7 +956,7 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
"No intro points for '%s': refetching service descriptor.",
safe_str(conn->rend_query));
rend_client_refetch_renddesc(conn->rend_query);
- conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT;
+ conn->state = AP_CONN_STATE_RENDDESC_WAIT;
return 0;
}
log_info(LD_REND,"Chose '%s' as intro point for '%s'.",
@@ -1023,16 +969,11 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_GENERAL) {
if (conn->chosen_exit_name) {
routerinfo_t *r;
- int opt = conn->_base.chosen_exit_optional;
if (!(r = router_get_by_nickname(conn->chosen_exit_name, 1))) {
- log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP,
- "Requested exit point '%s' is not known. %s.",
- conn->chosen_exit_name, opt ? "Trying others" : "Closing");
- if (opt) {
- conn->_base.chosen_exit_optional = 0;
- tor_free(conn->chosen_exit_name);
- return 0;
- }
+ /*XXXX NM domain? */
+ log_notice(LD_CIRC,
+ "Requested exit point '%s' is not known. Closing.",
+ conn->chosen_exit_name);
return -1;
}
extend_info = extend_info_from_router(r);
@@ -1057,8 +998,8 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
if (circ) {
/* write the service_id into circ */
strlcpy(circ->rend_query, conn->rend_query, sizeof(circ->rend_query));
- if (circ->_base.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND &&
- circ->_base.state == CIRCUIT_STATE_OPEN)
+ if (circ->purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND &&
+ circ->state == CIRCUIT_STATE_OPEN)
rend_client_rendcirc_has_opened(circ);
}
}
@@ -1077,18 +1018,19 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
* circ's cpath.
*/
static void
-link_apconn_to_circ(edge_connection_t *apconn, origin_circuit_t *circ)
+link_apconn_to_circ(connection_t *apconn, circuit_t *circ)
{
/* add it into the linked list of streams on this circuit */
log_debug(LD_APP|LD_CIRC, "attaching new conn to circ. n_circ_id %d.",
- circ->_base.n_circ_id);
+ circ->n_circ_id);
/* reset it, so we can measure circ timeouts */
- apconn->_base.timestamp_lastread = time(NULL);
+ apconn->timestamp_lastread = time(NULL);
apconn->next_stream = circ->p_streams;
- apconn->on_circuit = TO_CIRCUIT(circ);
+ apconn->on_circuit = circ;
/* assert_connection_ok(conn, time(NULL)); */
circ->p_streams = apconn;
+ tor_assert(CIRCUIT_IS_ORIGIN(circ));
tor_assert(circ->cpath);
tor_assert(circ->cpath->prev);
tor_assert(circ->cpath->prev->state == CPATH_STATE_OPEN);
@@ -1098,7 +1040,7 @@ link_apconn_to_circ(edge_connection_t *apconn, origin_circuit_t *circ)
/** If an exit wasn't specifically chosen, save the history for future
* use. */
static void
-consider_recording_trackhost(edge_connection_t *conn, origin_circuit_t *circ)
+consider_recording_trackhost(connection_t *conn, circuit_t *circ)
{
int found_needle = 0;
char *str;
@@ -1110,7 +1052,7 @@ consider_recording_trackhost(edge_connection_t *conn, origin_circuit_t *circ)
/* Search the addressmap for this conn's destination. */
/* If he's not in the address map.. */
if (!options->TrackHostExits ||
- addressmap_have_mapping(conn->socks_request->address))
+ addressmap_already_mapped(conn->socks_request->address))
return; /* nothing to track, or already mapped */
SMARTLIST_FOREACH(options->TrackHostExits, const char *, cp, {
@@ -1152,20 +1094,21 @@ consider_recording_trackhost(edge_connection_t *conn, origin_circuit_t *circ)
* send a begin or resolve cell as appropriate. Return values are as
* for connection_ap_handshake_attach_circuit. */
int
-connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn,
- origin_circuit_t *circ)
+connection_ap_handshake_attach_chosen_circuit(connection_t *conn,
+ circuit_t *circ)
{
tor_assert(conn);
- tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT ||
- conn->_base.state == AP_CONN_STATE_CONTROLLER_WAIT);
+ tor_assert(conn->type == CONN_TYPE_AP);
+ tor_assert(conn->state == AP_CONN_STATE_CIRCUIT_WAIT ||
+ conn->state == AP_CONN_STATE_CONTROLLER_WAIT);
tor_assert(conn->socks_request);
tor_assert(circ);
- tor_assert(circ->_base.state == CIRCUIT_STATE_OPEN);
+ tor_assert(circ->state == CIRCUIT_STATE_OPEN);
- conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
+ conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
- if (!circ->_base.timestamp_dirty)
- circ->_base.timestamp_dirty = time(NULL);
+ if (!circ->timestamp_dirty)
+ circ->timestamp_dirty = time(NULL);
link_apconn_to_circ(conn, circ);
tor_assert(conn->socks_request);
@@ -1189,18 +1132,19 @@ connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn,
* right next step, and return 1.
*/
int
-connection_ap_handshake_attach_circuit(edge_connection_t *conn)
+connection_ap_handshake_attach_circuit(connection_t *conn)
{
int retval;
int conn_age;
int severity;
tor_assert(conn);
- tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT);
+ tor_assert(conn->type == CONN_TYPE_AP);
+ tor_assert(conn->state == AP_CONN_STATE_CIRCUIT_WAIT);
tor_assert(conn->socks_request);
- conn_age = time(NULL) - conn->_base.timestamp_created;
- severity = (!conn->_base.addr && !conn->_base.port) ? LOG_INFO : LOG_NOTICE;
+ conn_age = time(NULL) - conn->timestamp_created;
+ severity = (!conn->addr && !conn->port) ? LOG_INFO : LOG_NOTICE;
if (conn_age > get_options()->SocksTimeout) {
log_fn(severity, LD_APP,
"Tried for %d seconds to get a connection to %s:%d. Giving up.",
@@ -1210,32 +1154,20 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
}
if (!connection_edge_is_rendezvous_stream(conn)) { /* we're a general conn */
- origin_circuit_t *circ=NULL;
+ circuit_t *circ=NULL;
if (conn->chosen_exit_name) {
routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1);
- int opt = conn->_base.chosen_exit_optional;
if (!router) {
- log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP,
- "Requested exit point '%s' is not known. %s.",
- conn->chosen_exit_name, opt ? "Trying others" : "Closing");
- if (opt) {
- conn->_base.chosen_exit_optional = 0;
- tor_free(conn->chosen_exit_name);
- return 0;
- }
+ log_warn(LD_APP,
+ "Requested exit point '%s' is not known. Closing.",
+ conn->chosen_exit_name);
return -1;
}
- if (conn->_base.purpose != EXIT_PURPOSE_RESOLVE &&
- !connection_ap_can_use_exit(conn, router)) {
- log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP,
- "Requested exit point '%s' would refuse request. %s.",
- conn->chosen_exit_name, opt ? "Trying others" : "Closing");
- if (opt) {
- conn->_base.chosen_exit_optional = 0;
- tor_free(conn->chosen_exit_name);
- return 0;
- }
+ if (!connection_ap_can_use_exit(conn, router)) {
+ log_warn(LD_APP,
+ "Requested exit point '%s' would refuse request. Closing.",
+ conn->chosen_exit_name);
return -1;
}
}
@@ -1248,7 +1180,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
log_debug(LD_APP|LD_CIRC,
"Attaching apconn to circ %d (stream %d sec old).",
- circ->_base.n_circ_id, conn_age);
+ circ->n_circ_id, conn_age);
/* here, print the circ's path. so people can figure out which circs are
* sucking. */
circuit_log_path(LOG_INFO,LD_APP|LD_CIRC,circ);
@@ -1257,7 +1189,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
return connection_ap_handshake_attach_chosen_circuit(conn, circ);
} else { /* we're a rendezvous conn */
- origin_circuit_t *rendcirc=NULL, *introcirc=NULL;
+ circuit_t *rendcirc=NULL, *introcirc=NULL;
tor_assert(!conn->cpath_layer);
@@ -1273,25 +1205,25 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
log_info(LD_REND,
"rend joined circ %d already here. attaching. "
"(stream %d sec old)",
- rendcirc->_base.n_circ_id, conn_age);
+ rendcirc->n_circ_id, conn_age);
/* Mark rendezvous circuits as 'newly dirty' every time you use
* them, since the process of rebuilding a rendezvous circ is so
* expensive. There is a tradeoffs between linkability and
* feasibility, at this point.
*/
- rendcirc->_base.timestamp_dirty = time(NULL);
+ rendcirc->timestamp_dirty = time(NULL);
link_apconn_to_circ(conn, rendcirc);
if (connection_ap_handshake_send_begin(conn, rendcirc) < 0)
return 0; /* already marked, let them fade away */
return 1;
}
- if (rendcirc && (rendcirc->_base.purpose ==
+ if (rendcirc && (rendcirc->purpose ==
CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED)) {
log_info(LD_REND,
"pending-join circ %d already here, with intro ack. "
"Stalling. (stream %d sec old)",
- rendcirc->_base.n_circ_id, conn_age);
+ rendcirc->n_circ_id, conn_age);
return 0;
}
@@ -1305,8 +1237,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
tor_assert(introcirc);
log_info(LD_REND, "Intro circ %d present and awaiting ack (rend %d). "
"Stalling. (stream %d sec old)",
- introcirc->_base.n_circ_id,
- rendcirc ? rendcirc->_base.n_circ_id : 0,
+ introcirc->n_circ_id, rendcirc ? rendcirc->n_circ_id : 0,
conn_age);
return 0;
}
@@ -1314,34 +1245,32 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
/* now rendcirc and introcirc are each either undefined or not finished */
if (rendcirc && introcirc &&
- rendcirc->_base.purpose == CIRCUIT_PURPOSE_C_REND_READY) {
+ rendcirc->purpose == CIRCUIT_PURPOSE_C_REND_READY) {
log_info(LD_REND,
"ready rend circ %d already here (no intro-ack yet on "
"intro %d). (stream %d sec old)",
- rendcirc->_base.n_circ_id,
- introcirc->_base.n_circ_id, conn_age);
+ rendcirc->n_circ_id, introcirc->n_circ_id, conn_age);
- tor_assert(introcirc->_base.purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
- if (introcirc->_base.state == CIRCUIT_STATE_OPEN) {
+ tor_assert(introcirc->purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
+ if (introcirc->state == CIRCUIT_STATE_OPEN) {
log_info(LD_REND,"found open intro circ %d (rend %d); sending "
"introduction. (stream %d sec old)",
- introcirc->_base.n_circ_id, rendcirc->_base.n_circ_id,
- conn_age);
+ introcirc->n_circ_id, rendcirc->n_circ_id, conn_age);
if (rend_client_send_introduction(introcirc, rendcirc) < 0) {
return -1;
}
- rendcirc->_base.timestamp_dirty = time(NULL);
- introcirc->_base.timestamp_dirty = time(NULL);
- assert_circuit_ok(TO_CIRCUIT(rendcirc));
- assert_circuit_ok(TO_CIRCUIT(introcirc));
+ rendcirc->timestamp_dirty = time(NULL);
+ introcirc->timestamp_dirty = time(NULL);
+ assert_circuit_ok(rendcirc);
+ assert_circuit_ok(introcirc);
return 0;
}
}
log_info(LD_REND, "Intro (%d) and rend (%d) circs are not both ready. "
"Stalling conn. (%d sec old)",
- introcirc ? introcirc->_base.n_circ_id : 0,
- rendcirc ? rendcirc->_base.n_circ_id : 0, conn_age);
+ introcirc ? introcirc->n_circ_id : 0,
+ rendcirc ? rendcirc->n_circ_id : 0, conn_age);
return 0;
}
}
diff --git a/src/or/command.c b/src/or/command.c
index f87b2b0554..6c55174772 100644
--- a/src/or/command.c
+++ b/src/or/command.c
@@ -27,10 +27,10 @@ uint64_t stats_n_relay_cells_processed = 0;
uint64_t stats_n_destroy_cells_processed = 0;
/* These are the main four functions for processing cells */
-static void command_process_create_cell(cell_t *cell, or_connection_t *conn);
-static void command_process_created_cell(cell_t *cell, or_connection_t *conn);
-static void command_process_relay_cell(cell_t *cell, or_connection_t *conn);
-static void command_process_destroy_cell(cell_t *cell, or_connection_t *conn);
+static void command_process_create_cell(cell_t *cell, connection_t *conn);
+static void command_process_created_cell(cell_t *cell, connection_t *conn);
+static void command_process_relay_cell(cell_t *cell, connection_t *conn);
+static void command_process_destroy_cell(cell_t *cell, connection_t *conn);
#ifdef KEEP_TIMING_STATS
/** This is a wrapper function around the actual function that processes the
@@ -38,8 +38,8 @@ static void command_process_destroy_cell(cell_t *cell, or_connection_t *conn);
* by the number of microseconds used by the call to <b>*func(cell, conn)</b>.
*/
static void
-command_time_process_cell(cell_t *cell, or_connection_t *conn, int *time,
- void (*func)(cell_t *, or_connection_t *))
+command_time_process_cell(cell_t *cell, connection_t *conn, int *time,
+ void (*func)(cell_t *, connection_t *))
{
struct timeval start, end;
long time_passed;
@@ -68,7 +68,7 @@ command_time_process_cell(cell_t *cell, or_connection_t *conn, int *time,
* process each type of cell.
*/
void
-command_process_cell(cell_t *cell, or_connection_t *conn)
+command_process_cell(cell_t *cell, connection_t *conn)
{
#ifdef KEEP_TIMING_STATS
/* how many of each cell have we seen so far this second? needs better
@@ -159,9 +159,9 @@ command_process_cell(cell_t *cell, or_connection_t *conn)
* picked up again when the cpuworker finishes decrypting it.
*/
static void
-command_process_create_cell(cell_t *cell, or_connection_t *conn)
+command_process_create_cell(cell_t *cell, connection_t *conn)
{
- or_circuit_t *circ;
+ circuit_t *circ;
int id_is_high;
if (we_are_hibernating()) {
@@ -182,35 +182,33 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn)
return;
}
- if (!server_mode(get_options())) {
- log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
- "Received create cell (type %d) from %s:%d, but we're a client. "
- "Sending back a destroy.",
- (int)cell->command, conn->_base.address, conn->_base.port);
- connection_or_send_destroy(cell->circ_id, conn,
- END_CIRC_REASON_TORPROTOCOL);
- return;
- }
-
- /* If the high bit of the circuit ID is not as expected, close the
- * circ. */
+ /* If the high bit of the circuit ID is not as expected, then switch
+ * which half of the space we'll use for our own CREATE cells.
+ *
+ * This can happen because Tor 0.0.9pre5 and earlier decide which
+ * half to use based on nickname, and we now use identity keys.
+ */
id_is_high = cell->circ_id & (1<<15);
- if ((id_is_high && conn->circ_id_type == CIRC_ID_TYPE_HIGHER) ||
- (!id_is_high && conn->circ_id_type == CIRC_ID_TYPE_LOWER)) {
- log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
- "Received create cell with unexpected circ_id %d. Closing.",
- cell->circ_id);
- connection_or_send_destroy(cell->circ_id, conn,
- END_CIRC_REASON_TORPROTOCOL);
- return;
+ if (id_is_high && conn->circ_id_type == CIRC_ID_TYPE_HIGHER) {
+ log_info(LD_OR, "Got a high circuit ID from %s (%d); switching to "
+ "low circuit IDs.",
+ conn->nickname ? conn->nickname : "client", conn->s);
+ conn->circ_id_type = CIRC_ID_TYPE_LOWER;
+ } else if (!id_is_high && conn->circ_id_type == CIRC_ID_TYPE_LOWER) {
+ log_info(LD_OR, "Got a low circuit ID from %s (%d); switching to "
+ "high circuit IDs.",
+ conn->nickname ? conn->nickname : "client", conn->s);
+ conn->circ_id_type = CIRC_ID_TYPE_HIGHER;
}
- if (circuit_get_by_circid_orconn(cell->circ_id, conn)) {
+ circ = circuit_get_by_circid_orconn(cell->circ_id, conn);
+
+ if (circ) {
routerinfo_t *router = router_get_by_digest(conn->identity_digest);
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
- "Received CREATE cell (circID %d) for known circ. "
+ "received CREATE cell (circID %d) for known circ. "
"Dropping (age %d).",
- cell->circ_id, (int)(time(NULL) - conn->_base.timestamp_created));
+ cell->circ_id, (int)(time(NULL) - conn->timestamp_created));
if (router)
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Details: nickname \"%s\", platform %s.",
@@ -218,34 +216,34 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn)
return;
}
- circ = or_circuit_new(cell->circ_id, conn);
- circ->_base.purpose = CIRCUIT_PURPOSE_OR;
- circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_ONIONSKIN_PENDING);
+ circ = circuit_new(cell->circ_id, conn);
+ circ->purpose = CIRCUIT_PURPOSE_OR;
+ circuit_set_state(circ, CIRCUIT_STATE_ONIONSKIN_PENDING);
if (cell->command == CELL_CREATE) {
- circ->_base.onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN);
- memcpy(circ->_base.onionskin, cell->payload, ONIONSKIN_CHALLENGE_LEN);
+ circ->onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN);
+ memcpy(circ->onionskin, cell->payload, ONIONSKIN_CHALLENGE_LEN);
- /* hand it off to the cpuworkers, and then return. */
+ /* hand it off to the cpuworkers, and then return */
if (assign_to_cpuworker(NULL, CPUWORKER_TASK_ONION, circ) < 0) {
log_warn(LD_GENERAL,"Failed to hand off onionskin. Closing.");
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
+ circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
return;
}
log_debug(LD_OR,"success: handed off onionskin.");
} else {
/* This is a CREATE_FAST cell; we can handle it immediately without using
- * a CPU worker. */
+ * a CPU worker.*/
char keys[CPATH_KEY_MATERIAL_LEN];
char reply[DIGEST_LEN*2];
tor_assert(cell->command == CELL_CREATE_FAST);
if (fast_server_handshake(cell->payload, reply, keys, sizeof(keys))<0) {
log_warn(LD_OR,"Failed to generate key material. Closing.");
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
+ circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
return;
}
if (onionskin_answer(circ, CELL_CREATED_FAST, reply, keys)<0) {
log_warn(LD_OR,"Failed to reply to CREATE_FAST cell. Closing.");
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
+ circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
return;
}
}
@@ -260,7 +258,7 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn)
* extend to the next hop in the circuit if necessary.
*/
static void
-command_process_created_cell(cell_t *cell, or_connection_t *conn)
+command_process_created_cell(cell_t *cell, connection_t *conn)
{
circuit_t *circ;
@@ -275,22 +273,20 @@ command_process_created_cell(cell_t *cell, or_connection_t *conn)
if (circ->n_circ_id != cell->circ_id) {
log_fn(LOG_PROTOCOL_WARN,LD_PROTOCOL,
- "got created cell from Tor client? Closing.");
+ "got created cell from OPward? Closing.");
circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL);
return;
}
if (CIRCUIT_IS_ORIGIN(circ)) { /* we're the OP. Handshake this. */
- origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
log_debug(LD_OR,"at OP. Finishing handshake.");
- if (circuit_finish_handshake(origin_circ, cell->command,
- cell->payload) < 0) {
+ if (circuit_finish_handshake(circ, cell->command, cell->payload) < 0) {
log_warn(LD_OR,"circuit_finish_handshake failed.");
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return;
}
log_debug(LD_OR,"Moving to next skin.");
- if (circuit_send_next_onion_skin(origin_circ) < 0) {
+ if (circuit_send_next_onion_skin(circ) < 0) {
log_info(LD_OR,"circuit_send_next_onion_skin failed.");
/* XXX push this circuit_close lower */
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
@@ -309,7 +305,7 @@ command_process_created_cell(cell_t *cell, or_connection_t *conn)
* circuit_receive_relay_cell() for actual processing.
*/
static void
-command_process_relay_cell(cell_t *cell, or_connection_t *conn)
+command_process_relay_cell(cell_t *cell, connection_t *conn)
{
circuit_t *circ;
int reason;
@@ -319,7 +315,7 @@ command_process_relay_cell(cell_t *cell, or_connection_t *conn)
if (!circ) {
log_debug(LD_OR,
"unknown circuit %d on connection from %s:%d. Dropping.",
- cell->circ_id, conn->_base.address, conn->_base.port);
+ cell->circ_id, conn->address, conn->port);
return;
}
@@ -329,9 +325,7 @@ command_process_relay_cell(cell_t *cell, or_connection_t *conn)
return;
}
- if (!CIRCUIT_IS_ORIGIN(circ) &&
- cell->circ_id == TO_OR_CIRCUIT(circ)->p_circ_id) {
- /* it's an outgoing cell */
+ if (cell->circ_id == circ->p_circ_id) { /* it's an outgoing cell */
if ((reason = circuit_receive_relay_cell(cell, circ,
CELL_DIRECTION_OUT)) < 0) {
log_fn(LOG_PROTOCOL_WARN,LD_PROTOCOL,"circuit_receive_relay_cell "
@@ -364,7 +358,7 @@ command_process_relay_cell(cell_t *cell, or_connection_t *conn)
* and passes the destroy cell onward if necessary).
*/
static void
-command_process_destroy_cell(cell_t *cell, or_connection_t *conn)
+command_process_destroy_cell(cell_t *cell, connection_t *conn)
{
circuit_t *circ;
uint8_t reason;
@@ -373,18 +367,17 @@ command_process_destroy_cell(cell_t *cell, or_connection_t *conn)
reason = (uint8_t)cell->payload[0];
if (!circ) {
log_info(LD_OR,"unknown circuit %d on connection from %s:%d. Dropping.",
- cell->circ_id, conn->_base.address, conn->_base.port);
+ cell->circ_id, conn->address, conn->port);
return;
}
log_debug(LD_OR,"Received for circID %d.",cell->circ_id);
- if (!CIRCUIT_IS_ORIGIN(circ) &&
- cell->circ_id == TO_OR_CIRCUIT(circ)->p_circ_id) {
+ if (cell->circ_id == circ->p_circ_id) {
/* the destroy came from behind */
- circuit_set_p_circid_orconn(TO_OR_CIRCUIT(circ), 0, NULL);
+ circuit_set_circid_orconn(circ, 0, NULL, P_CONN_CHANGED);
circuit_mark_for_close(circ, reason);
} else { /* the destroy came from ahead */
- circuit_set_n_circid_orconn(circ, 0, NULL);
+ circuit_set_circid_orconn(circ, 0, NULL, N_CONN_CHANGED);
if (CIRCUIT_IS_ORIGIN(circ)) {
circuit_mark_for_close(circ, reason);
} else {
diff --git a/src/or/config.c b/src/or/config.c
index 523ec22bfe..d8ae9a47c2 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -76,8 +76,6 @@ static config_abbrev_t _option_abbrevs[] = {
{ "NumHelperNodes", "NumEntryGuards", 0, 0},
{ "UseEntryNodes", "UseEntryGuards", 0, 0},
{ "NumEntryNodes", "NumEntryGuards", 0, 0},
- { "ResolvConf", "ServerDNSResolvConfFile", 0, 1},
- { "SearchDomains", "ServerDNSSearchDomains", 0, 1},
{ NULL, NULL, 0, 0},
};
/* A list of state-file abbreviations, for compatibility. */
@@ -102,6 +100,10 @@ typedef struct config_var_t {
const char *initvalue; /**< String (or null) describing initial value. */
} config_var_t;
+/** Return the offset of <b>member</b> within the type <b>tp</b>, in bytes */
+#define STRUCT_OFFSET(tp, member) \
+ ((off_t) (((char*)&((tp*)0)->member)-(char*)0))
+
#define STRUCT_VAR_P(st, off) \
((void*) ( ((char*)st) + off ) )
@@ -132,7 +134,6 @@ static config_var_t _option_vars[] = {
VAR("AuthDirReject", LINELIST, AuthDirReject, NULL),
VAR("AuthDirRejectUnlisted",BOOL, AuthDirRejectUnlisted,"0"),
VAR("AuthoritativeDirectory",BOOL, AuthoritativeDir, "0"),
- VAR("AvoidDiskWrites", BOOL, AvoidDiskWrites, "0"),
VAR("BandwidthBurst", MEMUNIT, BandwidthBurst, "6 MB"),
VAR("BandwidthRate", MEMUNIT, BandwidthRate, "3 MB"),
VAR("CircuitBuildTimeout", INTERVAL, CircuitBuildTimeout, "1 minute"),
@@ -147,7 +148,8 @@ static config_var_t _option_vars[] = {
VAR("DebugLogFile", STRING, DebugLogFile, NULL),
VAR("DirAllowPrivateAddresses",BOOL, DirAllowPrivateAddresses, NULL),
VAR("DirListenAddress", LINELIST, DirListenAddress, NULL),
- OBSOLETE("DirFetchPeriod"),
+ /* if DirFetchPeriod is 0, see get_dir_fetch_period() in main.c */
+ VAR("DirFetchPeriod", INTERVAL, DirFetchPeriod, "0 seconds"),
VAR("DirPolicy", LINELIST, DirPolicy, NULL),
VAR("DirPort", UINT, DirPort, "0"),
OBSOLETE("DirPostPeriod"),
@@ -182,7 +184,7 @@ static config_var_t _option_vars[] = {
VAR("LogFile", LINELIST_S, OldLogOptions, NULL),
VAR("LogLevel", LINELIST_S, OldLogOptions, NULL),
VAR("LongLivedPorts", CSV, LongLivedPorts,
- "21,22,706,1863,5050,5190,5222,5223,6667,8300"),
+ "21,22,706,1863,5050,5190,5222,5223,6667,8300,8888"),
VAR("MapAddress", LINELIST, AddressMap, NULL),
VAR("MaxAdvertisedBandwidth",MEMUNIT,MaxAdvertisedBandwidth,"128 TB"),
VAR("MaxCircuitDirtiness", INTERVAL, MaxCircuitDirtiness, "10 minutes"),
@@ -211,8 +213,6 @@ static config_var_t _option_vars[] = {
VAR("RecommendedClientVersions", LINELIST, RecommendedClientVersions, NULL),
VAR("RecommendedServerVersions", LINELIST, RecommendedServerVersions, NULL),
VAR("RedirectExit", LINELIST, RedirectExit, NULL),
- VAR("RelayBandwidthBurst", MEMUNIT, RelayBandwidthBurst, "0"),
- VAR("RelayBandwidthRate", MEMUNIT, RelayBandwidthRate, "0"),
VAR("RendExcludeNodes", STRING, RendExcludeNodes, NULL),
VAR("RendNodes", STRING, RendNodes, NULL),
VAR("RendPostPeriod", INTERVAL, RendPostPeriod, "1 hour"),
@@ -222,15 +222,13 @@ static config_var_t _option_vars[] = {
VAR("RunTesting", BOOL, RunTesting, "0"),
VAR("SafeLogging", BOOL, SafeLogging, "1"),
VAR("SafeSocks", BOOL, SafeSocks, "0"),
- VAR("ServerDNSDetectHijacking",BOOL, ServerDNSDetectHijacking,"1"),
- VAR("ServerDNSResolvConfFile", STRING, ServerDNSResolvConfFile, NULL),
- VAR("ServerDNSSearchDomains", BOOL, ServerDNSSearchDomains, "0"),
VAR("ShutdownWaitLength", INTERVAL, ShutdownWaitLength, "30 seconds"),
VAR("SocksListenAddress", LINELIST, SocksListenAddress, NULL),
VAR("SocksPolicy", LINELIST, SocksPolicy, NULL),
VAR("SocksPort", UINT, SocksPort, "9050"),
VAR("SocksTimeout", INTERVAL, SocksTimeout, "2 minutes"),
- OBSOLETE("StatusFetchPeriod"),
+ /* if StatusFetchPeriod is 0, see get_status_fetch_period() in main.c */
+ VAR("StatusFetchPeriod", INTERVAL, StatusFetchPeriod, "0 seconds"),
VAR("StrictEntryNodes", BOOL, StrictEntryNodes, "0"),
VAR("StrictExitNodes", BOOL, StrictExitNodes, "0"),
VAR("SysLog", LINELIST_S, OldLogOptions, NULL),
@@ -239,8 +237,6 @@ static config_var_t _option_vars[] = {
VAR("TrackHostExits", CSV, TrackHostExits, NULL),
VAR("TrackHostExitsExpire",INTERVAL, TrackHostExitsExpire, "30 minutes"),
OBSOLETE("TrafficShaping"),
- VAR("TransListenAddress", LINELIST, TransListenAddress, NULL),
- VAR("TransPort", UINT, TransPort, "0"),
VAR("UseEntryGuards", BOOL, UseEntryGuards, "1"),
VAR("User", STRING, User, NULL),
VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir, "0"),
@@ -395,15 +391,11 @@ static int or_state_validate(or_state_t *old_options, or_state_t *options,
static uint64_t config_parse_memunit(const char *s, int *ok);
static int config_parse_interval(const char *s, int *ok);
-static void print_svn_version(void);
+static void print_cvs_version(void);
static void init_libevent(void);
static int opt_streq(const char *s1, const char *s2);
-typedef enum {
- LE_OLD=0, LE_10C, LE_10D, LE_10E, LE_11, LE_11A, LE_11B, LE_OTHER
-} le_version_t;
-static le_version_t decode_libevent_version(void);
#if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
-static void check_libevent_version(const char *m, int server);
+static void check_libevent_version(const char *m, const char *v, int server);
#endif
/*static*/ or_options_t *options_new(void);
@@ -453,7 +445,7 @@ static or_state_t *global_state = NULL;
static void *
config_alloc(config_format_t *fmt)
{
- void *opts = tor_malloc_zero(fmt->size);
+ void *opts = opts = tor_malloc_zero(fmt->size);
*(uint32_t*)STRUCT_VAR_P(opts, fmt->magic_offset) = fmt->magic;
CHECK(fmt, opts);
return opts;
@@ -522,9 +514,7 @@ safe_str(const char *address)
return address;
}
-/** Equivalent to escaped(safe_str(address)). See reentrancy node on
- * escaped(): don't use this outside the main thread, or twice in the same
- * log statement. */
+/** Equivalent to escaped(safe_str(address)) */
const char *
escaped_safe_str(const char *address)
{
@@ -540,7 +530,6 @@ add_default_trusted_dirservers(void)
{
int i;
const char *dirservers[] = {
- /* eventually we should mark moria1 as "v1only" */
"moria1 v1 18.244.0.188:9031 "
"FFCB 46DB 1339 DA84 674C 70D7 CB58 6434 C437 0441",
"moria2 v1 18.244.0.114:80 "
@@ -798,22 +787,18 @@ options_act(or_options_t *old_options)
log_info(LD_GENERAL,
"Worker-related options changed. Rotating workers.");
if (server_mode(options) && !server_mode(old_options)) {
+ extern int has_completed_circuit;
if (init_keys() < 0) {
log_err(LD_GENERAL,"Error initializing keys; exiting");
return -1;
}
server_has_changed_ip();
- if (has_completed_circuit || !any_predicted_circuits(time(NULL)))
+ if (has_completed_circuit)
inform_testing_reachability();
}
cpuworkers_rotate();
- dns_reset();
- }
-#ifdef USE_EVENTDNS
- else {
- dns_reset();
+ dnsworkers_rotate();
}
-#endif
}
/* Check if we need to parse and add the EntryNodes config option. */
@@ -822,12 +807,6 @@ options_act(or_options_t *old_options)
!opt_streq(old_options->EntryNodes, options->EntryNodes)))
entry_nodes_should_be_added();
- /* If the user wants to avoid certain nodes, make sure none of them
- * are already entryguards */
- if (options->ExcludeNodes) {
- // XXX TODO
- }
-
/* Since our options changed, we might need to regenerate and upload our
* server descriptor.
*/
@@ -1295,9 +1274,19 @@ get_assigned_option(config_format_t *fmt, or_options_t *options,
if (!var) {
log_warn(LD_CONFIG, "Unknown option '%s'. Failing.", key);
return NULL;
+ } else if (var->type == CONFIG_TYPE_LINELIST_S) {
+ log_warn(LD_CONFIG,
+ "Can't return context-sensitive '%s' on its own", key);
+ return NULL;
}
value = STRUCT_VAR_P(options, var->var_offset);
+ if (var->type == CONFIG_TYPE_LINELIST ||
+ var->type == CONFIG_TYPE_LINELIST_V) {
+ /* Linelist requires special handling: we just copy and return it. */
+ return config_lines_dup(*(const config_line_t**)value);
+ }
+
result = tor_malloc_zero(sizeof(config_line_t));
result->key = tor_strdup(var->name);
switch (var->type)
@@ -1353,17 +1342,6 @@ get_assigned_option(config_format_t *fmt, or_options_t *options,
tor_free(result->key);
tor_free(result);
return NULL;
- case CONFIG_TYPE_LINELIST_S:
- log_warn(LD_CONFIG,
- "Can't return context-sensitive '%s' on its own", key);
- tor_free(result->key);
- tor_free(result);
- return NULL;
- case CONFIG_TYPE_LINELIST:
- case CONFIG_TYPE_LINELIST_V:
- tor_free(result->key);
- tor_free(result);
- return config_lines_dup(*(const config_line_t**)value);
default:
tor_free(result->key);
tor_free(result);
@@ -1513,7 +1491,6 @@ static void
option_clear(config_format_t *fmt, or_options_t *options, config_var_t *var)
{
void *lvalue = STRUCT_VAR_P(options, var->var_offset);
- (void)fmt; /* unused */
switch (var->type) {
case CONFIG_TYPE_STRING:
tor_free(*(char**)lvalue);
@@ -1596,8 +1573,8 @@ print_usage(void)
* public IP address.
*/
int
-resolve_my_address(int warn_severity, or_options_t *options,
- uint32_t *addr_out, char **hostname_out)
+resolve_my_address(or_options_t *options, uint32_t *addr_out,
+ char **hostname_out)
{
struct in_addr in;
struct hostent *rent;
@@ -1607,8 +1584,6 @@ resolve_my_address(int warn_severity, or_options_t *options,
char tmpbuf[INET_NTOA_BUF_LEN];
static uint32_t old_addr=0;
const char *address = options->Address;
- int notice_severity = warn_severity <= LOG_NOTICE ?
- LOG_NOTICE : warn_severity;
tor_assert(addr_out);
@@ -1619,13 +1594,13 @@ resolve_my_address(int warn_severity, or_options_t *options,
explicit_hostname = 0; /* it's implicit */
if (gethostname(hostname, sizeof(hostname)) < 0) {
- log_fn(warn_severity, LD_NET,"Error obtaining local hostname");
+ log_warn(LD_NET,"Error obtaining local hostname");
return -1;
}
log_debug(LD_CONFIG,"Guessed local host name as '%s'",hostname);
}
- /* now we know hostname. resolve it and keep only the IP address */
+ /* now we know hostname. resolve it and keep only the IP */
if (tor_inet_aton(hostname, &in) == 0) {
/* then we have to resolve it */
@@ -1635,22 +1610,21 @@ resolve_my_address(int warn_severity, or_options_t *options,
uint32_t interface_ip;
if (explicit_hostname) {
- log_fn(warn_severity, LD_CONFIG,
- "Could not resolve local Address '%s'. Failing.", hostname);
+ log_warn(LD_CONFIG,"Could not resolve local Address '%s'. Failing.",
+ hostname);
return -1;
}
- log_fn(notice_severity, LD_CONFIG,
- "Could not resolve guessed local hostname '%s'. "
- "Trying something else.", hostname);
- if (get_interface_address(warn_severity, &interface_ip)) {
- log_fn(warn_severity, LD_CONFIG,
- "Could not get local interface IP address. Failing.");
+ log_notice(LD_CONFIG, "Could not resolve guessed local hostname '%s'. "
+ "Trying something else.", hostname);
+ if (get_interface_address(&interface_ip)) {
+ log_warn(LD_CONFIG, "Could not get local interface IP address. "
+ "Failing.");
return -1;
}
in.s_addr = htonl(interface_ip);
tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
- log_fn(notice_severity, LD_CONFIG, "Learned IP address '%s' for "
- "local interface. Using that.", tmpbuf);
+ log_notice(LD_CONFIG, "Learned IP address '%s' for local interface."
+ " Using that.", tmpbuf);
strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname));
} else {
tor_assert(rent->h_length == 4);
@@ -1661,26 +1635,24 @@ resolve_my_address(int warn_severity, or_options_t *options,
uint32_t interface_ip;
tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
- log_fn(notice_severity, LD_CONFIG, "Guessed local hostname '%s' "
- "resolves to a private IP address (%s). Trying something "
- "else.", hostname, tmpbuf);
+ log_notice(LD_CONFIG, "Guessed local hostname '%s' resolves to a "
+ "private IP address (%s). Trying something else.", hostname,
+ tmpbuf);
- if (get_interface_address(warn_severity, &interface_ip)) {
- log_fn(warn_severity, LD_CONFIG,
- "Could not get local interface IP address. Too bad.");
+ if (get_interface_address(&interface_ip)) {
+ log_warn(LD_CONFIG, "Could not get local interface IP address. "
+ "Too bad.");
} else if (is_internal_IP(interface_ip, 0)) {
struct in_addr in2;
in2.s_addr = htonl(interface_ip);
tor_inet_ntoa(&in2,tmpbuf,sizeof(tmpbuf));
- log_fn(notice_severity, LD_CONFIG,
- "Interface IP address '%s' is a private address too. "
- "Ignoring.", tmpbuf);
+ log_notice(LD_CONFIG, "Interface IP '%s' is a private address "
+ "too. Ignoring.", tmpbuf);
} else {
in.s_addr = htonl(interface_ip);
tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
- log_fn(notice_severity, LD_CONFIG,
- "Learned IP address '%s' for local interface."
- " Using that.", tmpbuf);
+ log_notice(LD_CONFIG, "Learned IP address '%s' for local interface."
+ " Using that.", tmpbuf);
strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname));
}
}
@@ -1694,18 +1666,18 @@ resolve_my_address(int warn_severity, or_options_t *options,
if (!options->DirServers) {
/* if they are using the default dirservers, disallow internal IPs
* always. */
- log_fn(warn_severity, LD_CONFIG,
- "Address '%s' resolves to private IP address '%s'. "
- "Tor servers that use the default DirServers must have public "
- "IP addresses.", hostname, tmpbuf);
+ log_warn(LD_CONFIG,"Address '%s' resolves to private IP '%s'. "
+ "Tor servers that use the default DirServers must have public "
+ "IP addresses.",
+ hostname, tmpbuf);
return -1;
}
if (!explicit_ip) {
/* even if they've set their own dirservers, require an explicit IP if
* they're using an internal address. */
- log_fn(warn_severity, LD_CONFIG, "Address '%s' resolves to private "
- "IP address '%s'. Please set the Address config option to be "
- "the IP address you want to use.", hostname, tmpbuf);
+ log_warn(LD_CONFIG,"Address '%s' resolves to private IP '%s'. Please "
+ "set the Address config option to be the IP you want to use.",
+ hostname, tmpbuf);
return -1;
}
}
@@ -1713,9 +1685,7 @@ resolve_my_address(int warn_severity, or_options_t *options,
log_debug(LD_CONFIG, "Resolved Address to '%s'.", tmpbuf);
*addr_out = ntohl(in.s_addr);
if (old_addr && old_addr != *addr_out) {
- /* Leave this as a notice, regardless of the requested severity,
- * at least until dynamic IP address support becomes bulletproof. */
- log_notice(LD_NET, "Your IP address seems to have changed. Updating.");
+ log_notice(LD_NET, "Your IP seems to have changed. Updating.");
server_has_changed_ip();
}
old_addr = *addr_out;
@@ -1993,40 +1963,23 @@ validate_ports_csv(smartlist_t *sl, const char *name, char **msg)
return 0;
}
-#if 0
-/* XXXX Unused. */
-/** Return 0 if every element of sl is a string holding an IP address, or if sl
- * is NULL. Otherwise set *msg and return -1. */
-static int
-validate_ips_csv(smartlist_t *sl, const char *name, char **msg)
-{
- char buf[1024];
- tor_assert(name);
-
- if (!sl)
- return 0;
-
- SMARTLIST_FOREACH(sl, const char *, cp,
- {
- struct in_addr in;
- if (0 == tor_inet_aton(cp, &in)) {
- int r = tor_snprintf(buf, sizeof(buf),
- "Malformed address '%s' out of range in %s", cp, name);
- *msg = tor_strdup(r >= 0 ? buf : "internal error");
- return -1;
- }
- });
- return 0;
-}
-#endif
-
+/** Lowest allowable value for DirFetchPeriod; if this is too low, clients can
+ * overload the directory system. */
+#define MIN_DIR_FETCH_PERIOD (10*60)
/** Lowest allowable value for RendPostPeriod; if this is too low, hidden
* services can overload the directory system. */
#define MIN_REND_POST_PERIOD (5*60)
+/** Lowest allowable value for StatusFetchPeriod; if this is too low, clients
+ * can overload the directory system. */
+#define MIN_STATUS_FETCH_PERIOD (5*60)
/** Highest allowable value for DirFetchPeriod, StatusFetchPeriod, and
* RendPostPeriod. */
#define MAX_DIR_PERIOD (MIN_ONION_KEY_LIFETIME/2)
+/** Highest allowable value for DirFetchPeriod for directory caches. */
+#define MAX_CACHE_DIR_FETCH_PERIOD (60*60)
+/** Highest allowable value for StatusFetchPeriod for directory caches. */
+#define MAX_CACHE_STATUS_FETCH_PERIOD (15*60)
/** Return 0 if every setting in <b>options</b> is reasonable, and a
* permissible transition from <b>old_options</b>. Else return -1.
@@ -2078,39 +2031,27 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (options->ControlPort == 0 && options->ControlListenAddress != NULL)
REJECT("ControlPort must be defined if ControlListenAddress is defined.");
- if (options->TransPort == 0 && options->TransListenAddress != NULL)
- REJECT("TransPort must be defined if TransListenAddress is defined.");
-
#if 0 /* don't complain, since a standard configuration does this! */
if (options->SocksPort == 0 && options->SocksListenAddress != NULL)
REJECT("SocksPort must be defined if SocksListenAddress is defined.");
#endif
- for (i = 0; i < 2; ++i) {
- int is_socks = i==0;
- config_line_t *line, *opt, *old;
- const char *tp = is_socks ? "SOCKS proxy" : "transparent proxy";
- if (is_socks) {
- opt = options->SocksListenAddress;
- old = old_options ? old_options->SocksListenAddress : NULL;
- } else {
- opt = options->TransListenAddress;
- old = old_options ? old_options->TransListenAddress : NULL;
- }
-
- for (line = opt; line; line = line->next) {
- char *address = NULL;
+ if (options->SocksListenAddress) {
+ config_line_t *line = NULL;
+ char *address = NULL;
+ for (line = options->SocksListenAddress; line; line = line->next) {
uint16_t port;
uint32_t addr;
- if (parse_addr_port(LOG_WARN, line->value, &address, &addr, &port)<0)
+ if (parse_addr_port(line->value, &address, &addr, &port)<0)
continue; /* We'll warn about this later. */
if (!is_internal_IP(addr, 1) &&
- (!old_options || !config_lines_eq(old, opt))) {
+ (!old_options || !config_lines_eq(old_options->SocksListenAddress,
+ options->SocksListenAddress))) {
log_warn(LD_CONFIG,
- "You specified a public address '%s' for a %s. Other "
+ "You specified a public address '%s' for a SOCKS listener. Other "
"people on the Internet might find your computer and use it as "
- "an open %s. Please don't allow this unless you have "
- "a good reason.", address, tp, tp);
+ "an open SOCKS proxy. Please don't allow this unless you have "
+ "a good reason.", address);
}
tor_free(address);
}
@@ -2157,10 +2098,10 @@ options_validate(or_options_t *old_options, or_options_t *options,
options->PublishServerDescriptor = 0;
}
- if (authdir_mode(options)) {
+ if (server_mode(options)) {
/* confirm that our address isn't broken, so we can complain now */
uint32_t tmp;
- if (resolve_my_address(LOG_WARN, options, &tmp, NULL) < 0)
+ if (resolve_my_address(options, &tmp, NULL) < 0)
REJECT("Failed to resolve/guess local address. See logs for details.");
}
@@ -2172,12 +2113,8 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (options->SocksPort < 0 || options->SocksPort > 65535)
REJECT("SocksPort option out of bounds.");
- if (options->TransPort < 0 || options->TransPort > 65535)
- REJECT("TransPort option out of bounds.");
-
- if (options->SocksPort == 0 && options->TransPort == 0 &&
- options->ORPort == 0)
- REJECT("SocksPort, TransPort, and ORPort are all undefined? Quitting.");
+ if (options->SocksPort == 0 && options->ORPort == 0)
+ REJECT("SocksPort and ORPort are both undefined? Quitting.");
if (options->ControlPort < 0 || options->ControlPort > 65535)
REJECT("ControlPort option out of bounds.");
@@ -2185,11 +2122,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (options->DirPort < 0 || options->DirPort > 65535)
REJECT("DirPort option out of bounds.");
-#ifndef USE_TRANSPARENT
- if (options->TransPort || options->TransListenAddress)
- REJECT("TransPort and TransListenAddress are disabled in this build.");
-#endif
-
if (options->StrictExitNodes &&
(!options->ExitNodes || !strlen(options->ExitNodes)) &&
(!old_options ||
@@ -2364,12 +2296,51 @@ options_validate(or_options_t *old_options, or_options_t *options,
(options->PathlenCoinWeight < 0.0 || options->PathlenCoinWeight >= 1.0))
REJECT("PathlenCoinWeight option must be >=0.0 and <1.0.");
+ if (options->DirFetchPeriod &&
+ options->DirFetchPeriod < MIN_DIR_FETCH_PERIOD) {
+ log(LOG_WARN, LD_CONFIG,
+ "DirFetchPeriod option must be at least %d seconds. Clipping.",
+ MIN_DIR_FETCH_PERIOD);
+ options->DirFetchPeriod = MIN_DIR_FETCH_PERIOD;
+ }
+ if (options->StatusFetchPeriod &&
+ options->StatusFetchPeriod < MIN_STATUS_FETCH_PERIOD) {
+ log(LOG_WARN, LD_CONFIG,
+ "StatusFetchPeriod option must be at least %d seconds. Clipping.",
+ MIN_STATUS_FETCH_PERIOD);
+ options->StatusFetchPeriod = MIN_STATUS_FETCH_PERIOD;
+ }
if (options->RendPostPeriod < MIN_REND_POST_PERIOD) {
log(LOG_WARN,LD_CONFIG,"RendPostPeriod option must be at least %d seconds."
" Clipping.", MIN_REND_POST_PERIOD);
options->RendPostPeriod = MIN_REND_POST_PERIOD;
}
+ if (options->DirPort && ! options->AuthoritativeDir) {
+ if (options->DirFetchPeriod > MAX_CACHE_DIR_FETCH_PERIOD) {
+ log(LOG_WARN, LD_CONFIG, "Caching directory servers must have "
+ "DirFetchPeriod less than %d seconds. Clipping.",
+ MAX_CACHE_DIR_FETCH_PERIOD);
+ options->DirFetchPeriod = MAX_CACHE_DIR_FETCH_PERIOD;
+ }
+ if (options->StatusFetchPeriod > MAX_CACHE_STATUS_FETCH_PERIOD) {
+ log(LOG_WARN, LD_CONFIG, "Caching directory servers must have "
+ "StatusFetchPeriod less than %d seconds. Clipping.",
+ MAX_CACHE_STATUS_FETCH_PERIOD);
+ options->StatusFetchPeriod = MAX_CACHE_STATUS_FETCH_PERIOD;
+ }
+ }
+
+ if (options->DirFetchPeriod > MAX_DIR_PERIOD) {
+ log(LOG_WARN, LD_CONFIG, "DirFetchPeriod is too large; clipping to %ds.",
+ MAX_DIR_PERIOD);
+ options->DirFetchPeriod = MAX_DIR_PERIOD;
+ }
+ if (options->StatusFetchPeriod > MAX_DIR_PERIOD) {
+ log(LOG_WARN, LD_CONFIG,"StatusFetchPeriod is too large; clipping to %ds.",
+ MAX_DIR_PERIOD);
+ options->StatusFetchPeriod = MAX_DIR_PERIOD;
+ }
if (options->RendPostPeriod > MAX_DIR_PERIOD) {
log(LOG_WARN, LD_CONFIG, "RendPostPeriod is too large; clipping to %ds.",
MAX_DIR_PERIOD);
@@ -2408,7 +2379,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
REJECT("Failed to parse accounting options. See logs for details.");
if (options->HttpProxy) { /* parse it now */
- if (parse_addr_port(LOG_WARN, options->HttpProxy, NULL,
+ if (parse_addr_port(options->HttpProxy, NULL,
&options->HttpProxyAddr, &options->HttpProxyPort) < 0)
REJECT("HttpProxy failed to parse or resolve. Please fix.");
if (options->HttpProxyPort == 0) { /* give it a default */
@@ -2422,7 +2393,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
if (options->HttpsProxy) { /* parse it now */
- if (parse_addr_port(LOG_WARN, options->HttpsProxy, NULL,
+ if (parse_addr_port(options->HttpsProxy, NULL,
&options->HttpsProxyAddr, &options->HttpsProxyPort) <0)
REJECT("HttpsProxy failed to parse or resolve. Please fix.");
if (options->HttpsProxyPort == 0) { /* give it a default */
@@ -2445,12 +2416,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (options->UseEntryGuards && ! options->NumEntryGuards)
REJECT("Cannot enable UseEntryGuards with NumEntryGuards set to 0");
-#ifndef USE_EVENTDNS
- if (options->ServerDNSResolvConfFile)
- log(LOG_WARN, LD_CONFIG,
- "ServerDNSResolvConfFile only works when eventdns support is enabled.");
-#endif
-
if (check_nickname_list(options->ExitNodes, "ExitNodes", msg))
return -1;
if (check_nickname_list(options->EntryNodes, "EntryNodes", msg))
@@ -2574,8 +2539,6 @@ options_transition_affects_workers(or_options_t *old_options,
if (!opt_streq(old_options->DataDirectory, new_options->DataDirectory) ||
old_options->NumCpus != new_options->NumCpus ||
old_options->ORPort != new_options->ORPort ||
- old_options->ServerDNSSearchDomains !=
- new_options->ServerDNSSearchDomains ||
old_options->SafeLogging != new_options->SafeLogging ||
!config_lines_eq(old_options->Logs, new_options->Logs))
return 1;
@@ -2734,7 +2697,7 @@ options_init_from_torrc(int argc, char **argv)
if (argc > 1 && (!strcmp(argv[1],"--version"))) {
printf("Tor version %s.\n",VERSION);
if (argc > 2 && (!strcmp(argv[2],"--version"))) {
- print_svn_version();
+ print_cvs_version();
}
exit(0);
}
@@ -2769,11 +2732,11 @@ options_init_from_torrc(int argc, char **argv)
if (using_default_torrc) {
/* didn't find one, try CONFDIR */
const char *dflt = get_default_conf_file();
+ char *fn = NULL;
if (dflt && file_status(dflt) == FN_FILE) {
fname = tor_strdup(dflt);
} else {
#ifndef MS_WINDOWS
- char *fn;
fn = expand_filename("~/.torrc");
if (fn && file_status(fn) == FN_FILE) {
fname = fn;
@@ -3205,8 +3168,8 @@ parse_redirect_line(smartlist_t *result, config_line_t *line, char **msg)
if (0==strcasecmp(smartlist_get(elements,1), "pass")) {
r->is_redirect = 0;
} else {
- if (parse_addr_port(LOG_WARN, smartlist_get(elements,1),NULL,
- &r->addr_dest, &r->port_dest)) {
+ if (parse_addr_port(smartlist_get(elements,1),NULL,&r->addr_dest,
+ &r->port_dest)) {
*msg = tor_strdup("Error parsing dest address in RedirectExit line");
goto err;
}
@@ -3271,7 +3234,7 @@ parse_dir_server_line(const char *line, int validate_only)
goto err;
}
addrport = smartlist_get(items, 0);
- if (parse_addr_port(LOG_WARN, addrport, &address, NULL, &port)<0) {
+ if (parse_addr_port(addrport, &address, NULL, &port)<0) {
log_warn(LD_CONFIG, "Error parsing DirServer address '%s'", addrport);
goto err;
}
@@ -3401,8 +3364,6 @@ write_configuration_file(const char *fname, or_options_t *options)
break;
case FN_NOENT:
break;
- case FN_ERROR:
- case FN_DIR:
default:
log_warn(LD_CONFIG,
"Config file \"%s\" is not a file? Failing.", fname);
@@ -3594,20 +3555,7 @@ init_libevent(void)
*/
suppress_libevent_log_msg("Function not implemented");
#ifdef __APPLE__
- if (decode_libevent_version() < LE_11B) {
- setenv("EVENT_NOKQUEUE","1",1);
- } else if (!getenv("EVENT_NOKQUEUE")) {
- const char *ver = NULL;
-#ifdef HAVE_EVENT_GET_VERSION
- ver = event_get_version();
-#endif
- /* If we're 1.1b or later, we'd better have get_version() */
- tor_assert(ver);
- log(LOG_NOTICE, LD_GENERAL, "Enabling experimental OS X kqueue support "
- "with libevent %s. If this turns out to not work, "
- "set the environment variable EVENT_NOKQUEUE, and tell the Tor "
- "developers.", ver);
- }
+ setenv("EVENT_NOKQUEUE","1",1);
#endif
event_init();
suppress_libevent_log_msg(NULL);
@@ -3617,78 +3565,46 @@ init_libevent(void)
log(LOG_NOTICE, LD_GENERAL,
"Initialized libevent version %s using method %s. Good.",
event_get_version(), event_get_method());
- check_libevent_version(event_get_method(), get_options()->ORPort != 0);
+ check_libevent_version(event_get_method(), event_get_version(),
+ get_options()->ORPort != 0);
#else
log(LOG_NOTICE, LD_GENERAL,
"Initialized old libevent (version 1.0b or earlier).");
log(LOG_WARN, LD_GENERAL,
- "You have a *VERY* old version of libevent. It is likely to be buggy; "
- "please build Tor with a more recent version.");
+ "You have a very old version of libevent. It is likely to be buggy; "
+ "please consider building Tor with a more recent version.");
#endif
}
#if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
-static const struct {
- const char *name; le_version_t version;
-} le_version_table[] = {
- /* earlier versions don't have get_version. */
- { "1.0c", LE_10C },
- { "1.0d", LE_10D },
- { "1.0e", LE_10E },
- { "1.1", LE_11 },
- { "1.1a", LE_11A },
- { "1.1b", LE_11B },
- { NULL, 0 }
-};
-
-static le_version_t
-decode_libevent_version(void)
-{
- const char *v = event_get_version();
- int i;
- for (i=0; le_version_table[i].name; ++i) {
- if (!strcmp(le_version_table[i].name, v)) {
- return le_version_table[i].version;
- }
- }
- return LE_OTHER;
-}
-
/**
* Compare the given libevent method and version to a list of versions
* which are known not to work. Warn the user as appropriate.
*
*/
static void
-check_libevent_version(const char *m, int server)
+check_libevent_version(const char *m, const char *v, int server)
{
int buggy = 0, iffy = 0, slow = 0;
- le_version_t version;
- const char *v = event_get_version();
- version = decode_libevent_version();
+ tor_assert(m && v);
- /* XXX Would it be worthwhile disabling the methods that we know
- * are buggy, rather than just warning about them and then proceeding
- * to use them? If so, we should probably not wrap this whole thing
- * in HAVE_EVENT_GET_VERSION and HAVE_EVENT_GET_METHOD. -RD */
if (!strcmp(m, "kqueue")) {
- if (version < LE_11B)
+ if (!strcmp(v, "1.0c") || !strcmp(v, "1.0d") || !strcmp(v, "1.0e") ||
+ !strcmp(v, "1.1")) {
buggy = 1;
+ }
} else if (!strcmp(m, "epoll")) {
- if (version < LE_11)
+ if (!strcmp(v, "1.0c") || !strcmp(v, "1.0d") || !strcmp(v, "1.0e"))
iffy = 1;
} else if (!strcmp(m, "poll")) {
- if (version < LE_10E)
+ if (!strcmp(v, "1.0c") || !strcmp(v, "1.0d"))
buggy = 1;
- else if (version < LE_11)
+ else if (!strcmp(v, "1.0e"))
slow = 1;
} else if (!strcmp(m, "poll")) {
- if (version < LE_11)
+ if (!strcmp(v, "1.0c") || !strcmp(v, "1.0d") || !strcmp(v, "1.0e"))
slow = 1;
- } else if (!strcmp(m, "win32")) {
- if (version < LE_11B)
- buggy = 1;
}
if (buggy) {
@@ -3707,12 +3623,6 @@ check_libevent_version(const char *m, int server)
}
}
-#else
-static le_version_t
-decode_libevent_version(void)
-{
- return LE_OLD;
-}
#endif
/** Return the persistent state struct for this Tor. */
@@ -3744,10 +3654,6 @@ static int
or_state_validate(or_state_t *old_state, or_state_t *state,
int from_setconf, char **msg)
{
- /* We don't use these; only options do. Still, we need to match that
- * signature. */
- (void) from_setconf;
- (void) old_state;
if (entry_guards_parse_state(state, 0, msg)<0) {
return -1;
}
@@ -3798,7 +3704,7 @@ or_state_load(void)
or_state_t *new_state = NULL;
char *contents = NULL, *fname;
char *errmsg = NULL;
- int r = -1, badstate = 0;
+ int r = -1;
fname = get_or_state_fname();
switch (file_status(fname)) {
@@ -3810,8 +3716,6 @@ or_state_load(void)
break;
case FN_NOENT:
break;
- case FN_ERROR:
- case FN_DIR:
default:
log_warn(LD_GENERAL,"State file \"%s\" is not a file? Failing.", fname);
goto done;
@@ -3828,68 +3732,30 @@ or_state_load(void)
lines, 0, 0, &errmsg);
config_free_lines(lines);
if (assign_retval<0)
- badstate = 1;
- if (errmsg) {
- log_warn(LD_GENERAL, "%s", errmsg);
- tor_free(errmsg);
- }
- }
-
- if (!badstate && or_state_validate(NULL, new_state, 1, &errmsg) < 0)
- badstate = 1;
-
- if (errmsg) {
- log_warn(LD_GENERAL, "%s", errmsg);
- tor_free(errmsg);
+ goto done;
}
- if (badstate && !contents) {
- log_warn(LD_BUG, "Uh oh. We couldn't even validate our own default state."
- " This is a bug in Tor.");
+ if (or_state_validate(NULL, new_state, 1, &errmsg) < 0) {
goto done;
- } else if (badstate && contents) {
- int i;
- file_status_t status;
- size_t len = strlen(fname)+16;
- char *fname2 = tor_malloc(len);
- for (i = 0; i < 100; ++i) {
- tor_snprintf(fname2, len, "%s.%d", fname, i);
- status = file_status(fname2);
- if (status == FN_NOENT)
- break;
- }
- if (i == 100) {
- log_warn(LD_BUG, "Unable to parse state in \"%s\"; too many saved bad "
- "state files to move aside. Discarding the old state file.",
- fname);
- unlink(fname);
- } else {
- log_warn(LD_BUG, "Unable to parse state in \"%s\". Moving it aside "
- "to \"%s\". This could be a bug in Tor; please tell "
- "the developers.", fname, fname2);
- rename(fname, fname2);
- }
- tor_free(fname2);
- tor_free(contents);
- config_free(&state_format, new_state);
+ }
- new_state = tor_malloc_zero(sizeof(or_state_t));
- new_state->_magic = OR_STATE_MAGIC;
- config_init(&state_format, new_state);
- } else if (contents) {
+ if (contents)
log_info(LD_GENERAL, "Loaded state from \"%s\"", fname);
- } else {
+ else
log_info(LD_GENERAL, "Initialized state");
- }
or_state_set(new_state);
new_state = NULL;
if (!contents) {
global_state->dirty = 1;
or_state_save();
}
- r = 0;
+ r = 0;
done:
+ if (errmsg) {
+ log_warn(LD_GENERAL, "%s", errmsg);
+ tor_free(errmsg);
+ }
tor_free(fname);
tor_free(contents);
if (new_state)
@@ -3996,47 +3862,47 @@ config_getinfo_helper(const char *question, char **answer)
#include "../common/ht.h"
#include "../common/test.h"
-extern const char aes_c_id[];
-extern const char compat_c_id[];
-extern const char container_c_id[];
-extern const char crypto_c_id[];
-extern const char log_c_id[];
-extern const char torgzip_c_id[];
-extern const char tortls_c_id[];
-extern const char util_c_id[];
-
-extern const char buffers_c_id[];
-extern const char circuitbuild_c_id[];
-extern const char circuitlist_c_id[];
-extern const char circuituse_c_id[];
-extern const char command_c_id[];
-// extern const char config_c_id[];
-extern const char connection_c_id[];
-extern const char connection_edge_c_id[];
-extern const char connection_or_c_id[];
-extern const char control_c_id[];
-extern const char cpuworker_c_id[];
-extern const char directory_c_id[];
-extern const char dirserv_c_id[];
-extern const char dns_c_id[];
-extern const char hibernate_c_id[];
-extern const char main_c_id[];
-extern const char onion_c_id[];
-extern const char policies_c_id[];
-extern const char relay_c_id[];
-extern const char rendclient_c_id[];
-extern const char rendcommon_c_id[];
-extern const char rendmid_c_id[];
-extern const char rendservice_c_id[];
-extern const char rephist_c_id[];
-extern const char router_c_id[];
-extern const char routerlist_c_id[];
-extern const char routerparse_c_id[];
-
/** Dump the version of every file to the log. */
static void
-print_svn_version(void)
-{
+print_cvs_version(void)
+{
+ extern const char aes_c_id[];
+ extern const char compat_c_id[];
+ extern const char container_c_id[];
+ extern const char crypto_c_id[];
+ extern const char log_c_id[];
+ extern const char torgzip_c_id[];
+ extern const char tortls_c_id[];
+ extern const char util_c_id[];
+
+ extern const char buffers_c_id[];
+ extern const char circuitbuild_c_id[];
+ extern const char circuitlist_c_id[];
+ extern const char circuituse_c_id[];
+ extern const char command_c_id[];
+// extern const char config_c_id[];
+ extern const char connection_c_id[];
+ extern const char connection_edge_c_id[];
+ extern const char connection_or_c_id[];
+ extern const char control_c_id[];
+ extern const char cpuworker_c_id[];
+ extern const char directory_c_id[];
+ extern const char dirserv_c_id[];
+ extern const char dns_c_id[];
+ extern const char hibernate_c_id[];
+ extern const char main_c_id[];
+ extern const char onion_c_id[];
+ extern const char policies_c_id[];
+ extern const char relay_c_id[];
+ extern const char rendclient_c_id[];
+ extern const char rendcommon_c_id[];
+ extern const char rendmid_c_id[];
+ extern const char rendservice_c_id[];
+ extern const char rephist_c_id[];
+ extern const char router_c_id[];
+ extern const char routerlist_c_id[];
+ extern const char routerparse_c_id[];
+
puts(AES_H_ID);
puts(COMPAT_H_ID);
puts(CONTAINER_H_ID);
diff --git a/src/or/connection.c b/src/or/connection.c
index 88346f8aad..3135c61584 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -16,12 +16,10 @@ const char connection_c_id[] =
static connection_t *connection_create_listener(const char *listenaddress,
uint16_t listenport, int type);
-static int connection_init_accepted_conn(connection_t *conn,
- uint8_t listener_type);
+static int connection_init_accepted_conn(connection_t *conn);
static int connection_handle_listener_read(connection_t *conn, int new_type);
-static int connection_receiver_bucket_should_increase(or_connection_t *conn);
+static int connection_receiver_bucket_should_increase(connection_t *conn);
static int connection_finished_flushing(connection_t *conn);
-static int connection_flushed_some(connection_t *conn);
static int connection_finished_connecting(connection_t *conn);
static int connection_reached_eof(connection_t *conn);
static int connection_read_to_buf(connection_t *conn, int *max_to_read);
@@ -45,7 +43,6 @@ conn_type_to_string(int type)
case CONN_TYPE_OR: return "OR";
case CONN_TYPE_EXIT: return "Exit";
case CONN_TYPE_AP_LISTENER: return "Socks listener";
- case CONN_TYPE_AP_TRANS_LISTENER: return "Transparent listener";
case CONN_TYPE_AP: return "Socks";
case CONN_TYPE_DIR_LISTENER: return "Directory listener";
case CONN_TYPE_DIR: return "Directory";
@@ -71,7 +68,6 @@ conn_state_to_string(int type, int state)
switch (type) {
case CONN_TYPE_OR_LISTENER:
case CONN_TYPE_AP_LISTENER:
- case CONN_TYPE_AP_TRANS_LISTENER:
case CONN_TYPE_DIR_LISTENER:
case CONN_TYPE_CONTROL_LISTENER:
if (state == LISTENER_STATE_READY)
@@ -96,7 +92,6 @@ conn_state_to_string(int type, int state)
break;
case CONN_TYPE_AP:
switch (state) {
- case AP_CONN_STATE_ORIGDST_WAIT:
case AP_CONN_STATE_SOCKS_WAIT: return "waiting for dest info";
case AP_CONN_STATE_RENDDESC_WAIT: return "waiting for rendezvous desc";
case AP_CONN_STATE_CONTROLLER_WAIT: return "waiting for controller";
@@ -149,7 +144,7 @@ conn_state_to_string(int type, int state)
/** Allocate space for a new connection_t. This function just initializes
* conn; you must call connection_add() to link it into the main array.
*
- * Set conn-\>type to <b>type</b>. Set conn-\>s and conn-\>conn_array_index to
+ * Set conn-\>type to <b>type</b>. Set conn-\>s and conn-\>poll_index to
* -1 to signify they are not yet assigned.
*
* If conn is not a listener type, allocate buffers for it. If it's
@@ -162,40 +157,15 @@ conn_state_to_string(int type, int state)
connection_t *
connection_new(int type)
{
- static uint32_t n_connections_allocated = 1;
+ static uint32_t n_connections_allocated = 0;
connection_t *conn;
time_t now = time(NULL);
- size_t length;
- uint32_t magic;
- switch (type) {
- case CONN_TYPE_OR:
- length = sizeof(or_connection_t);
- magic = OR_CONNECTION_MAGIC;
- break;
- case CONN_TYPE_EXIT:
- case CONN_TYPE_AP:
- length = sizeof(edge_connection_t);
- magic = EDGE_CONNECTION_MAGIC;
- break;
- case CONN_TYPE_DIR:
- length = sizeof(dir_connection_t);
- magic = DIR_CONNECTION_MAGIC;
- break;
- case CONN_TYPE_CONTROL:
- length = sizeof(control_connection_t);
- magic = CONTROL_CONNECTION_MAGIC;
- break;
- default:
- length = sizeof(connection_t);
- magic = BASE_CONNECTION_MAGIC;
- break;
- }
-
- conn = tor_malloc_zero(length);
- conn->magic = magic;
+ conn = tor_malloc_zero(sizeof(connection_t));
+ conn->magic = CONNECTION_MAGIC;
conn->s = -1; /* give it a default of 'not used' */
- conn->conn_array_index = -1; /* also default to 'not used' */
+ conn->poll_index = -1; /* also default to 'not used' */
+ conn->global_identifier = n_connections_allocated++;
conn->type = type;
if (!connection_is_listener(conn)) { /* listeners never use their buf */
@@ -203,14 +173,10 @@ connection_new(int type)
conn->outbuf = buf_new();
}
if (type == CONN_TYPE_AP) {
- TO_EDGE_CONN(conn)->socks_request =
- tor_malloc_zero(sizeof(socks_request_t));
- }
- if (CONN_IS_EDGE(conn)) {
- TO_EDGE_CONN(conn)->global_identifier = n_connections_allocated++;
+ conn->socks_request = tor_malloc_zero(sizeof(socks_request_t));
}
- if (type == CONN_TYPE_OR)
- TO_OR_CONN(conn)->next_circ_id = crypto_rand_int(1<<15);
+
+ conn->next_circ_id = crypto_rand_int(1<<15);
conn->timestamp_created = now;
conn->timestamp_lastread = now;
@@ -242,72 +208,30 @@ connection_unregister(connection_t *conn)
static void
_connection_free(connection_t *conn)
{
- void *mem;
- switch (conn->type) {
- case CONN_TYPE_OR:
- tor_assert(conn->magic == OR_CONNECTION_MAGIC);
- mem = TO_OR_CONN(conn);
- break;
- case CONN_TYPE_AP:
- case CONN_TYPE_EXIT:
- tor_assert(conn->magic == EDGE_CONNECTION_MAGIC);
- mem = TO_EDGE_CONN(conn);
- break;
- case CONN_TYPE_DIR:
- tor_assert(conn->magic == DIR_CONNECTION_MAGIC);
- mem = TO_DIR_CONN(conn);
- break;
- case CONN_TYPE_CONTROL:
- tor_assert(conn->magic == CONTROL_CONNECTION_MAGIC);
- mem = TO_CONTROL_CONN(conn);
- break;
- default:
- tor_assert(conn->magic == BASE_CONNECTION_MAGIC);
- mem = conn;
- break;
- }
+ tor_assert(conn->magic == CONNECTION_MAGIC);
if (!connection_is_listener(conn)) {
buf_free(conn->inbuf);
buf_free(conn->outbuf);
}
-
tor_free(conn->address);
+ tor_free(conn->chosen_exit_name);
if (connection_speaks_cells(conn)) {
- or_connection_t *or_conn = TO_OR_CONN(conn);
- if (or_conn->tls) {
- tor_tls_free(or_conn->tls);
- or_conn->tls = NULL;
+ if (conn->tls) {
+ tor_tls_free(conn->tls);
+ conn->tls = NULL;
}
-
- tor_free(or_conn->nickname);
- }
- if (CONN_IS_EDGE(conn)) {
- edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
- tor_free(edge_conn->chosen_exit_name);
- tor_free(edge_conn->socks_request);
- }
- if (conn->type == CONN_TYPE_CONTROL) {
- control_connection_t *control_conn = TO_CONTROL_CONN(conn);
- tor_free(control_conn->incoming_cmd);
}
+ if (conn->identity_pkey)
+ crypto_free_pk_env(conn->identity_pkey);
+ tor_free(conn->nickname);
+ tor_free(conn->socks_request);
+ tor_free(conn->incoming_cmd);
tor_free(conn->read_event); /* Probably already freed by connection_free. */
tor_free(conn->write_event); /* Probably already freed by connection_free. */
-
- if (conn->type == CONN_TYPE_DIR) {
- dir_connection_t *dir_conn = TO_DIR_CONN(conn);
- tor_free(dir_conn->requested_resource);
- if (dir_conn->zlib_state)
- tor_zlib_free(dir_conn->zlib_state);
- if (dir_conn->fingerprint_stack) {
- SMARTLIST_FOREACH(dir_conn->fingerprint_stack, char *, cp, tor_free(cp));
- smartlist_free(dir_conn->fingerprint_stack);
- }
- if (dir_conn->cached_dir)
- cached_dir_decref(dir_conn->cached_dir);
- }
+ tor_free(conn->requested_resource);
if (conn->s >= 0) {
log_debug(LD_NET,"closing fd %d.",conn->s);
@@ -315,13 +239,13 @@ _connection_free(connection_t *conn)
}
if (conn->type == CONN_TYPE_OR &&
- !tor_digest_is_zero(TO_OR_CONN(conn)->identity_digest)) {
+ !tor_digest_is_zero(conn->identity_digest)) {
log_warn(LD_BUG, "called on OR conn with non-zeroed identity_digest");
- connection_or_remove_from_identity_map(TO_OR_CONN(conn));
+ connection_or_remove_from_identity_map(conn);
}
memset(conn, 0xAA, sizeof(connection_t)); /* poison memory */
- tor_free(mem);
+ tor_free(conn);
}
/** Make sure <b>conn</b> isn't in any of the global conn lists; then free it.
@@ -335,12 +259,12 @@ connection_free(connection_t *conn)
if (connection_speaks_cells(conn)) {
if (conn->state == OR_CONN_STATE_OPEN)
directory_set_dirty();
- if (!tor_digest_is_zero(TO_OR_CONN(conn)->identity_digest)) {
- connection_or_remove_from_identity_map(TO_OR_CONN(conn));
+ if (!tor_digest_is_zero(conn->identity_digest)) {
+ connection_or_remove_from_identity_map(conn);
}
}
if (conn->type == CONN_TYPE_CONTROL) {
- TO_CONTROL_CONN(conn)->event_mask = 0;
+ conn->event_mask = 0;
control_update_global_event_mask();
}
connection_unregister(conn);
@@ -366,7 +290,7 @@ connection_free_all(void)
/* We don't want to log any messages to controllers. */
for (i=0;i<n;i++)
if (carray[i]->type == CONN_TYPE_CONTROL)
- TO_CONTROL_CONN(carray[i])->event_mask = 0;
+ carray[i]->event_mask = 0;
control_update_global_event_mask();
/* Unlink everything from the identity map. */
@@ -395,14 +319,11 @@ void
connection_about_to_close_connection(connection_t *conn)
{
circuit_t *circ;
- dir_connection_t *dir_conn;
- or_connection_t *or_conn;
- edge_connection_t *edge_conn;
assert(conn->marked_for_close);
if (CONN_IS_EDGE(conn)) {
- if (!conn->edge_has_sent_end) {
+ if (!conn->has_sent_end) {
log_warn(LD_BUG, "Harmless bug: Edge connection (marked at %s:%d) "
"hasn't sent end yet?",
conn->marked_for_close_file, conn->marked_for_close);
@@ -412,25 +333,23 @@ connection_about_to_close_connection(connection_t *conn)
switch (conn->type) {
case CONN_TYPE_DIR:
- dir_conn = TO_DIR_CONN(conn);
if (conn->state < DIR_CONN_STATE_CLIENT_FINISHED) {
/* It's a directory connection and connecting or fetching
* failed: forget about this router, and maybe try again. */
- connection_dir_request_failed(dir_conn);
+ connection_dir_request_failed(conn);
// XXX if it's rend desc we may want to retry -RD
}
if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC)
- rend_client_desc_here(dir_conn->rend_query); /* give it a try */
+ rend_client_desc_here(conn->rend_query); /* give it a try */
break;
case CONN_TYPE_OR:
- or_conn = TO_OR_CONN(conn);
/* Remember why we're closing this connection. */
if (conn->state != OR_CONN_STATE_OPEN) {
- if (connection_or_nonopen_was_started_here(or_conn)) {
- rep_hist_note_connect_failed(or_conn->identity_digest, time(NULL));
- entry_guard_set_status(or_conn->identity_digest, 0);
- router_set_status(or_conn->identity_digest, 0);
- control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED);
+ if (connection_or_nonopen_was_started_here(conn)) {
+ rep_hist_note_connect_failed(conn->identity_digest, time(NULL));
+ entry_guard_set_status(conn->identity_digest, 0);
+ router_set_status(conn->identity_digest, 0);
+ control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED);
}
} else if (conn->hold_open_until_flushed) {
/* XXXX009 We used to have an arg that told us whether we closed the
@@ -442,32 +361,30 @@ connection_about_to_close_connection(connection_t *conn)
* flushing still get noted as dead, not disconnected. But this is an
* improvement. -NM
*/
- rep_hist_note_disconnect(or_conn->identity_digest, time(NULL));
- control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED);
- } else if (or_conn->identity_digest) {
- rep_hist_note_connection_died(or_conn->identity_digest, time(NULL));
- control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED);
+ rep_hist_note_disconnect(conn->identity_digest, time(NULL));
+ control_event_or_conn_status(conn, OR_CONN_EVENT_CLOSED);
+ } else if (conn->identity_digest) {
+ rep_hist_note_connection_died(conn->identity_digest, time(NULL));
+ control_event_or_conn_status(conn, OR_CONN_EVENT_CLOSED);
}
break;
case CONN_TYPE_AP:
- edge_conn = TO_EDGE_CONN(conn);
- if (edge_conn->socks_request->has_finished == 0) {
+ if (conn->socks_request->has_finished == 0) {
/* since conn gets removed right after this function finishes,
* there's no point trying to send back a reply at this point. */
log_warn(LD_BUG,"Bug: Closing stream (marked at %s:%d) without sending"
" back a socks reply.",
conn->marked_for_close_file, conn->marked_for_close);
} else {
- control_event_stream_status(edge_conn, STREAM_EVENT_CLOSED);
+ control_event_stream_status(conn, STREAM_EVENT_CLOSED);
}
break;
case CONN_TYPE_EXIT:
- edge_conn = TO_EDGE_CONN(conn);
if (conn->state == EXIT_CONN_STATE_RESOLVING) {
- circ = circuit_get_by_edge_conn(edge_conn);
+ circ = circuit_get_by_edge_conn(conn);
if (circ)
- circuit_detach_stream(circ, edge_conn);
- connection_dns_remove(edge_conn);
+ circuit_detach_stream(circ, conn);
+ connection_dns_remove(conn);
}
break;
case CONN_TYPE_DNSWORKER:
@@ -598,7 +515,7 @@ connection_create_listener(const char *listenaddress, uint16_t listenport,
#endif
memset(&listenaddr,0,sizeof(struct sockaddr_in));
- if (parse_addr_port(LOG_WARN, listenaddress, &address, &addr, &usePort)<0) {
+ if (parse_addr_port(listenaddress, &address, &addr, &usePort)<0) {
log_warn(LD_CONFIG,
"Error parsing/resolving ListenAddress %s", listenaddress);
return NULL;
@@ -617,6 +534,10 @@ connection_create_listener(const char *listenaddress, uint16_t listenport,
if (s < 0) {
log_warn(LD_NET,"Socket creation failed.");
goto err;
+ } else if (!SOCKET_IS_POLLABLE(s)) {
+ log_warn(LD_NET,"Too many connections; can't create pollable listener.");
+ tor_close_socket(s);
+ goto err;
}
#ifndef MS_WINDOWS
@@ -716,8 +637,16 @@ connection_handle_listener_read(connection_t *conn, int new_type)
memset(addrbuf, 0, sizeof(addrbuf));
news = accept(conn->s,(struct sockaddr *)&addrbuf,&remotelen);
- if (news < 0) { /* accept() error */
- int e = tor_socket_errno(conn->s);
+ if (!SOCKET_IS_POLLABLE(news)) {
+ /* accept() error, or too many conns to poll */
+ int e;
+ if (news>=0) {
+ /* Too many conns to poll. */
+ log_warn(LD_NET,"Too many connections; couldn't accept connection.");
+ tor_close_socket(news);
+ return 0;
+ }
+ e = tor_socket_errno(conn->s);
if (ERRNO_IS_ACCEPT_EAGAIN(e)) {
return 0; /* he hung up before we could accept(). that's fine. */
} else if (ERRNO_IS_ACCEPT_RESOURCE_LIMIT(e)) {
@@ -790,7 +719,7 @@ connection_handle_listener_read(connection_t *conn, int new_type)
return 0; /* no need to tear down the parent */
}
- if (connection_init_accepted_conn(newconn, conn->type) < 0) {
+ if (connection_init_accepted_conn(newconn) < 0) {
connection_mark_for_close(newconn);
return 0;
}
@@ -801,23 +730,16 @@ connection_handle_listener_read(connection_t *conn, int new_type)
* If conn is an OR, start the tls handshake.
*/
static int
-connection_init_accepted_conn(connection_t *conn, uint8_t listener_type)
+connection_init_accepted_conn(connection_t *conn)
{
connection_start_reading(conn);
switch (conn->type) {
case CONN_TYPE_OR:
- control_event_or_conn_status(TO_OR_CONN(conn), OR_CONN_EVENT_NEW);
- return connection_tls_start_handshake(TO_OR_CONN(conn), 1);
+ control_event_or_conn_status(conn, OR_CONN_EVENT_NEW);
+ return connection_tls_start_handshake(conn, 1);
case CONN_TYPE_AP:
- switch (listener_type) {
- case CONN_TYPE_AP_LISTENER:
- conn->state = AP_CONN_STATE_SOCKS_WAIT;
- break;
- case CONN_TYPE_AP_TRANS_LISTENER:
- conn->state = AP_CONN_STATE_ORIGDST_WAIT;
- break;
- }
+ conn->state = AP_CONN_STATE_SOCKS_WAIT;
break;
case CONN_TYPE_DIR:
conn->purpose = DIR_PURPOSE_SERVER;
@@ -851,6 +773,12 @@ connection_connect(connection_t *conn, char *address,
log_warn(LD_NET,"Error creating network socket: %s",
tor_socket_strerror(tor_socket_errno(-1)));
return -1;
+ } else if (!SOCKET_IS_POLLABLE(s)) {
+ log_warn(LD_NET,
+ "Too many connections; can't create pollable connection to %s",
+ escaped_safe_str(address));
+ tor_close_socket(s);
+ return -1;
}
if (options->OutboundBindAddress) {
@@ -975,7 +903,7 @@ retry_listeners(int type, config_line_t *cfg,
{
char *address=NULL;
uint16_t port;
- if (!parse_addr_port(LOG_WARN, wanted->value, &address, NULL, &port)) {
+ if (! parse_addr_port(wanted->value, &address, NULL, &port)) {
int addr_matches = !strcasecmp(address, conn->address);
tor_free(address);
if (! port)
@@ -1057,10 +985,6 @@ retry_all_listeners(int force, smartlist_t *replaced_conns,
options->SocksPort, "127.0.0.1", force,
replaced_conns, new_conns, 0)<0)
return -1;
- if (retry_listeners(CONN_TYPE_AP_TRANS_LISTENER, options->TransListenAddress,
- options->TransPort, "127.0.0.1", force,
- replaced_conns, new_conns, 0)<0)
- return -1;
if (retry_listeners(CONN_TYPE_CONTROL_LISTENER,
options->ControlListenAddress,
options->ControlPort, "127.0.0.1", force,
@@ -1093,11 +1017,9 @@ connection_bucket_read_limit(connection_t *conn)
if (at_most > global_read_bucket)
at_most = global_read_bucket;
- if (connection_speaks_cells(conn) && conn->state == OR_CONN_STATE_OPEN) {
- or_connection_t *or_conn = TO_OR_CONN(conn);
- if (at_most > or_conn->receiver_bucket)
- at_most = or_conn->receiver_bucket;
- }
+ if (connection_speaks_cells(conn) && conn->state == OR_CONN_STATE_OPEN)
+ if (at_most > conn->receiver_bucket)
+ at_most = conn->receiver_bucket;
if (at_most < 0)
return 0;
@@ -1140,8 +1062,10 @@ static void
connection_read_bucket_decrement(connection_t *conn, int num_read)
{
global_read_bucket -= num_read;
+ //tor_assert(global_read_bucket >= 0);
if (connection_speaks_cells(conn) && conn->state == OR_CONN_STATE_OPEN) {
- TO_OR_CONN(conn)->receiver_bucket -= num_read;
+ conn->receiver_bucket -= num_read;
+ //tor_assert(conn->receiver_bucket >= 0);
}
}
@@ -1158,7 +1082,7 @@ connection_consider_empty_buckets(connection_t *conn)
}
if (connection_speaks_cells(conn) &&
conn->state == OR_CONN_STATE_OPEN &&
- TO_OR_CONN(conn)->receiver_bucket <= 0) {
+ conn->receiver_bucket <= 0) {
LOG_FN_CONN(conn,
(LOG_DEBUG,LD_NET,"receiver bucket exhausted. Pausing."));
conn->wants_to_read = 1;
@@ -1166,7 +1090,8 @@ connection_consider_empty_buckets(connection_t *conn)
}
}
-/** Initialize the global read bucket to options->BandwidthBurst. */
+/** Initialize the global read bucket to options->BandwidthBurst,
+ * and current_time to the current time. */
void
connection_bucket_init(void)
{
@@ -1184,9 +1109,6 @@ connection_bucket_refill(struct timeval *now)
connection_t *conn;
connection_t **carray;
or_options_t *options = get_options();
- /* Not used, but it should be! We might have rolled over more than one
- * second! XXXX */
- (void) now;
/* refill the global buckets */
if (global_read_bucket < (int)options->BandwidthBurst) {
@@ -1203,15 +1125,10 @@ connection_bucket_refill(struct timeval *now)
for (i=0;i<n;i++) {
conn = carray[i];
- if (connection_speaks_cells(conn)) {
- or_connection_t *or_conn = TO_OR_CONN(conn);
- if (connection_receiver_bucket_should_increase(or_conn)) {
- or_conn->receiver_bucket += or_conn->bandwidthrate;
- if (or_conn->receiver_bucket > or_conn->bandwidthburst)
- or_conn->receiver_bucket = or_conn->bandwidthburst;
- //log_fn(LOG_DEBUG,"Receiver bucket %d now %d.", i,
- // conn->receiver_bucket);
- }
+ if (connection_receiver_bucket_should_increase(conn)) {
+ conn->receiver_bucket = conn->bandwidth;
+ //log_fn(LOG_DEBUG,"Receiver bucket %d now %d.", i,
+ // conn->receiver_bucket);
}
if (conn->wants_to_read == 1 /* it's marked to turn reading back on now */
@@ -1220,7 +1137,7 @@ connection_bucket_refill(struct timeval *now)
* not the best place to check this.) */
&& (!connection_speaks_cells(conn) ||
conn->state != OR_CONN_STATE_OPEN ||
- TO_OR_CONN(conn)->receiver_bucket > 0)) {
+ conn->receiver_bucket > 0)) {
/* and either a non-cell conn or a cell conn with non-empty bucket */
LOG_FN_CONN(conn, (LOG_DEBUG,LD_NET,"waking up conn (fd %d)",conn->s));
conn->wants_to_read = 0;
@@ -1237,13 +1154,16 @@ connection_bucket_refill(struct timeval *now)
* should add another pile of tokens to it?
*/
static int
-connection_receiver_bucket_should_increase(or_connection_t *conn)
+connection_receiver_bucket_should_increase(connection_t *conn)
{
tor_assert(conn);
- if (conn->_base.state != OR_CONN_STATE_OPEN)
+ if (!connection_speaks_cells(conn))
+ return 0; /* edge connections don't use receiver_buckets */
+ if (conn->state != OR_CONN_STATE_OPEN)
return 0; /* only open connections play the rate limiting game */
- if (conn->receiver_bucket >= conn->bandwidthburst)
+
+ if (conn->receiver_bucket >= conn->bandwidth)
return 0;
return 1;
@@ -1275,7 +1195,6 @@ connection_handle_read(connection_t *conn)
case CONN_TYPE_OR_LISTENER:
return connection_handle_listener_read(conn, CONN_TYPE_OR);
case CONN_TYPE_AP_LISTENER:
- case CONN_TYPE_AP_TRANS_LISTENER:
return connection_handle_listener_read(conn, CONN_TYPE_AP);
case CONN_TYPE_DIR_LISTENER:
return connection_handle_listener_read(conn, CONN_TYPE_DIR);
@@ -1290,15 +1209,15 @@ loop_again:
/* There's a read error; kill the connection.*/
connection_close_immediate(conn); /* Don't flush; connection is dead. */
if (CONN_IS_EDGE(conn)) {
- edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
- connection_edge_end_errno(edge_conn, edge_conn->cpath_layer);
- if (edge_conn->socks_request) /* broken, don't send a socks reply back */
- edge_conn->socks_request->has_finished = 1;
+ connection_edge_end_errno(conn, conn->cpath_layer);
+ if (conn->socks_request) /* broken, so don't send a socks reply back */
+ conn->socks_request->has_finished = 1;
}
connection_mark_for_close(conn);
return -1;
}
- if (CONN_IS_EDGE(conn) && try_to_read != max_to_read) {
+ if (CONN_IS_EDGE(conn) &&
+ try_to_read != max_to_read) {
/* instruct it not to try to package partial cells. */
if (connection_process_inbuf(conn, 0) < 0) {
return -1;
@@ -1355,32 +1274,29 @@ connection_read_to_buf(connection_t *conn, int *max_to_read)
if (connection_speaks_cells(conn) &&
conn->state > OR_CONN_STATE_PROXY_READING) {
int pending;
- or_connection_t *or_conn = TO_OR_CONN(conn);
if (conn->state == OR_CONN_STATE_HANDSHAKING) {
/* continue handshaking even if global token bucket is empty */
- return connection_tls_continue_handshake(or_conn);
+ return connection_tls_continue_handshake(conn);
}
log_debug(LD_NET,
"%d: starting, inbuf_datalen %d (%d pending in tls object)."
" at_most %d.",
conn->s,(int)buf_datalen(conn->inbuf),
- tor_tls_get_pending_bytes(or_conn->tls), at_most);
+ tor_tls_get_pending_bytes(conn->tls), at_most);
/* else open, or closing */
- result = read_to_buf_tls(or_conn->tls, at_most, conn->inbuf);
+ result = read_to_buf_tls(conn->tls, at_most, conn->inbuf);
switch (result) {
case TOR_TLS_CLOSE:
log_info(LD_NET,"TLS connection closed on read. Closing. "
"(Nickname %s, address %s",
- or_conn->nickname ? or_conn->nickname : "not set",
- conn->address);
+ conn->nickname ? conn->nickname : "not set", conn->address);
return -1;
case TOR_TLS_ERROR:
log_info(LD_NET,"tls error. breaking (nickname %s, address %s).",
- or_conn->nickname ? or_conn->nickname : "not set",
- conn->address);
+ conn->nickname ? conn->nickname : "not set", conn->address);
return -1;
case TOR_TLS_WANTWRITE:
connection_start_writing(conn);
@@ -1392,12 +1308,12 @@ connection_read_to_buf(connection_t *conn, int *max_to_read)
default:
break;
}
- pending = tor_tls_get_pending_bytes(or_conn->tls);
+ pending = tor_tls_get_pending_bytes(conn->tls);
if (pending) {
/* XXXX If we have any pending bytes, read them now. This *can*
* take us over our read allotment, but really we shouldn't be
* believing that SSL bytes are the same as TCP bytes anyway. */
- int r2 = read_to_buf_tls(or_conn->tls, pending, conn->inbuf);
+ int r2 = read_to_buf_tls(conn->tls, pending, conn->inbuf);
if (r2<0) {
log_warn(LD_BUG, "Bug: apparently, reading pending bytes can fail.");
return -1;
@@ -1407,11 +1323,9 @@ connection_read_to_buf(connection_t *conn, int *max_to_read)
}
} else {
- int reached_eof = 0;
CONN_LOG_PROTECT(conn,
- result = read_to_buf(conn->s, at_most, conn->inbuf, &reached_eof));
- if (reached_eof)
- conn->inbuf_reached_eof = 1;
+ result = read_to_buf(conn->s, at_most, conn->inbuf,
+ &conn->inbuf_reached_eof));
// log_fn(LOG_DEBUG,"read_to_buf returned %d.",read_result);
@@ -1504,8 +1418,7 @@ connection_handle_write(connection_t *conn)
log_warn(LD_BUG,
"getsockopt() syscall failed?! Please report to tor-ops.");
if (CONN_IS_EDGE(conn))
- connection_edge_end_errno(TO_EDGE_CONN(conn),
- TO_EDGE_CONN(conn)->cpath_layer);
+ connection_edge_end_errno(conn, conn->cpath_layer);
connection_mark_for_close(conn);
return -1;
}
@@ -1514,8 +1427,7 @@ connection_handle_write(connection_t *conn)
if (!ERRNO_IS_CONN_EINPROGRESS(e)) {
log_info(LD_NET,"in-progress connect failed. Removing.");
if (CONN_IS_EDGE(conn))
- connection_edge_end_errno(TO_EDGE_CONN(conn),
- TO_EDGE_CONN(conn)->cpath_layer);
+ connection_edge_end_errno(conn, conn->cpath_layer);
connection_close_immediate(conn);
connection_mark_for_close(conn);
@@ -1523,7 +1435,7 @@ connection_handle_write(connection_t *conn)
* ignores unrecognized routers
*/
if (conn->type == CONN_TYPE_OR && !get_options()->HttpsProxy)
- router_set_status(TO_OR_CONN(conn)->identity_digest, 0);
+ router_set_status(conn->identity_digest, 0);
return -1;
} else {
return 0; /* no change, see if next time is better */
@@ -1538,10 +1450,9 @@ connection_handle_write(connection_t *conn)
if (connection_speaks_cells(conn) &&
conn->state > OR_CONN_STATE_PROXY_READING) {
- or_connection_t *or_conn = TO_OR_CONN(conn);
if (conn->state == OR_CONN_STATE_HANDSHAKING) {
connection_stop_writing(conn);
- if (connection_tls_continue_handshake(or_conn) < 0) {
+ if (connection_tls_continue_handshake(conn) < 0) {
/* Don't flush; connection is dead. */
connection_close_immediate(conn);
connection_mark_for_close(conn);
@@ -1551,7 +1462,7 @@ connection_handle_write(connection_t *conn)
}
/* else open, or closing */
- result = flush_buf_tls(or_conn->tls, conn->outbuf,
+ result = flush_buf_tls(conn->tls, conn->outbuf,
max_to_write, &conn->outbuf_flushlen);
switch (result) {
case TOR_TLS_ERROR:
@@ -1589,8 +1500,7 @@ connection_handle_write(connection_t *conn)
max_to_write, &conn->outbuf_flushlen));
if (result < 0) {
if (CONN_IS_EDGE(conn))
- connection_edge_end_errno(TO_EDGE_CONN(conn),
- TO_EDGE_CONN(conn)->cpath_layer);
+ connection_edge_end_errno(conn, conn->cpath_layer);
connection_close_immediate(conn); /* Don't flush; connection is dead. */
connection_mark_for_close(conn);
@@ -1598,13 +1508,9 @@ connection_handle_write(connection_t *conn)
}
}
- if (result > 0) {
- if (!is_local_IP(conn->addr)) { /* remember it */
- rep_hist_note_bytes_written(result, time(NULL));
- global_write_bucket -= result;
- }
- if (connection_flushed_some(conn) < 0)
- connection_mark_for_close(conn);
+ if (result > 0 && !is_local_IP(conn->addr)) { /* remember it */
+ rep_hist_note_bytes_written(result, now);
+ global_write_bucket -= result;
}
if (!connection_wants_to_flush(conn)) { /* it's done flushing */
@@ -1620,17 +1526,16 @@ connection_handle_write(connection_t *conn)
/* A controller event has just happened with such urgency that we
* need to write it onto controller <b>conn</b> immediately. */
void
-_connection_controller_force_write(control_connection_t *control_conn)
+_connection_controller_force_write(connection_t *conn)
{
/* XXX This is hideous code duplication, but raising it seems a little
* tricky for now. Think more about this one. We only call it for
* EVENT_ERR_MSG, so messing with buckets a little isn't such a big problem.
*/
int result;
- connection_t *conn;
- tor_assert(control_conn);
- conn = TO_CONN(control_conn);
-
+ tor_assert(conn);
+ tor_assert(!conn->tls);
+ tor_assert(conn->type == CONN_TYPE_CONTROL);
if (conn->marked_for_close || conn->s < 0)
return;
@@ -1643,13 +1548,9 @@ _connection_controller_force_write(control_connection_t *control_conn)
return;
}
- if (result > 0) {
- if (!is_local_IP(conn->addr)) { /* remember it */
- rep_hist_note_bytes_written(result, time(NULL));
- global_write_bucket -= result;
- }
- if (connection_flushed_some(conn) < 0)
- connection_mark_for_close(conn);
+ if (result > 0 && !is_local_IP(conn->addr)) { /* remember it */
+ rep_hist_note_bytes_written(result, time(NULL));
+ global_write_bucket -= result;
}
if (!connection_wants_to_flush(conn)) { /* it's done flushing */
@@ -1680,7 +1581,7 @@ connection_write_to_buf(const char *string, size_t len, connection_t *conn)
wrong compared to our max outbuf size. close the whole circuit. */
log_warn(LD_NET,
"write_to_buf failed. Closing circuit (fd %d).", conn->s);
- circuit_mark_for_close(circuit_get_by_edge_conn(TO_EDGE_CONN(conn)),
+ circuit_mark_for_close(circuit_get_by_edge_conn(conn),
END_CIRC_REASON_INTERNAL);
} else {
log_warn(LD_NET,
@@ -1694,45 +1595,13 @@ connection_write_to_buf(const char *string, size_t len, connection_t *conn)
conn->outbuf_flushlen += len;
}
-void
-connection_write_to_buf_zlib(dir_connection_t *dir_conn,
- const char *data, size_t data_len,
- int done)
-{
- int r;
- size_t old_datalen;
- connection_t *conn;
- if (!data_len)
- return;
- conn = TO_CONN(dir_conn);
- /* if it's marked for close, only allow write if we mean to flush it */
- if (conn->marked_for_close && !conn->hold_open_until_flushed)
- return;
-
- old_datalen = buf_datalen(conn->outbuf);
- /* XXXX TOO much duplicate code! XXXX012NM */
- CONN_LOG_PROTECT(conn, r = write_to_buf_zlib(
- conn->outbuf, dir_conn->zlib_state,
- data, data_len, done));
- if (r < 0) {
- log_warn(LD_NET,
- "write_to_buf failed. Closing connection (fd %d).", conn->s);
- connection_mark_for_close(conn);
- return;
- }
-
- connection_start_writing(conn);
- conn->outbuf_flushlen += buf_datalen(conn->outbuf) - old_datalen;
-}
-
/** Return the conn to addr/port that has the most recent
* timestamp_created, or NULL if no such conn exists. */
-or_connection_t *
+connection_t *
connection_or_exact_get_by_addr_port(uint32_t addr, uint16_t port)
{
int i, n;
- connection_t *conn;
- or_connection_t *best=NULL;
+ connection_t *conn, *best=NULL;
connection_t **carray;
get_connection_array(&carray,&n);
@@ -1742,8 +1611,8 @@ connection_or_exact_get_by_addr_port(uint32_t addr, uint16_t port)
conn->addr == addr &&
conn->port == port &&
!conn->marked_for_close &&
- (!best || best->_base.timestamp_created < conn->timestamp_created))
- best = TO_OR_CONN(conn);
+ (!best || best->timestamp_created < conn->timestamp_created))
+ best = conn;
}
return best;
}
@@ -1775,7 +1644,7 @@ connection_get_by_type_addr_port_purpose(int type,
/** Return the connection with id <b>id</b> if it is not already marked for
* close.
*/
-edge_connection_t *
+connection_t *
connection_get_by_global_id(uint32_t id)
{
int i, n;
@@ -1785,9 +1654,9 @@ connection_get_by_global_id(uint32_t id)
get_connection_array(&carray,&n);
for (i=0;i<n;i++) {
conn = carray[i];
- if (CONN_IS_EDGE(conn) && TO_EDGE_CONN(conn)->global_identifier == id) {
+ if (conn->global_identifier == id) {
if (!conn->marked_for_close)
- return TO_EDGE_CONN(conn);
+ return conn;
else
return NULL;
}
@@ -1865,22 +1734,14 @@ connection_get_by_type_state_rendquery(int type, int state,
connection_t *conn;
connection_t **carray;
- tor_assert(type == CONN_TYPE_DIR ||
- type == CONN_TYPE_AP || type == CONN_TYPE_EXIT);
-
get_connection_array(&carray,&n);
for (i=0;i<n;i++) {
conn = carray[i];
if (conn->type == type &&
!conn->marked_for_close &&
- (!state || state == conn->state)) {
- if (type == CONN_TYPE_DIR &&
- rend_cmp_service_ids(rendquery, TO_DIR_CONN(conn)->rend_query))
- return conn;
- else if (CONN_IS_EDGE(conn) &&
- rend_cmp_service_ids(rendquery, TO_EDGE_CONN(conn)->rend_query))
- return conn;
- }
+ (!state || state == conn->state) &&
+ !rend_cmp_service_ids(rendquery, conn->rend_query))
+ return conn;
}
return NULL;
}
@@ -1911,7 +1772,6 @@ connection_is_listener(connection_t *conn)
{
if (conn->type == CONN_TYPE_OR_LISTENER ||
conn->type == CONN_TYPE_AP_LISTENER ||
- conn->type == CONN_TYPE_AP_TRANS_LISTENER ||
conn->type == CONN_TYPE_DIR_LISTENER ||
conn->type == CONN_TYPE_CONTROL_LISTENER)
return 1;
@@ -1999,7 +1859,7 @@ client_check_address_changed(int sock)
uint32_t *ip;
if (!last_interface_ip)
- get_interface_address(LOG_INFO, &last_interface_ip);
+ get_interface_address(&last_interface_ip);
if (!outgoing_addrs)
outgoing_addrs = smartlist_create();
@@ -2017,7 +1877,7 @@ client_check_address_changed(int sock)
/* Uh-oh. We haven't connected from this address before. Has the interface
* address changed? */
- if (get_interface_address(LOG_INFO, &iface_ip)<0)
+ if (get_interface_address(&iface_ip)<0)
return;
ip = tor_malloc(sizeof(uint32_t));
*ip = ip_out;
@@ -2051,19 +1911,18 @@ connection_process_inbuf(connection_t *conn, int package_partial)
switch (conn->type) {
case CONN_TYPE_OR:
- return connection_or_process_inbuf(TO_OR_CONN(conn));
+ return connection_or_process_inbuf(conn);
case CONN_TYPE_EXIT:
case CONN_TYPE_AP:
- return connection_edge_process_inbuf(TO_EDGE_CONN(conn),
- package_partial);
+ return connection_edge_process_inbuf(conn, package_partial);
case CONN_TYPE_DIR:
- return connection_dir_process_inbuf(TO_DIR_CONN(conn));
+ return connection_dir_process_inbuf(conn);
case CONN_TYPE_DNSWORKER:
return connection_dns_process_inbuf(conn);
case CONN_TYPE_CPUWORKER:
return connection_cpu_process_inbuf(conn);
case CONN_TYPE_CONTROL:
- return connection_control_process_inbuf(TO_CONTROL_CONN(conn));
+ return connection_control_process_inbuf(conn);
default:
log_err(LD_BUG,"Bug: got unexpected conn type %d.", conn->type);
tor_fragile_assert();
@@ -2071,17 +1930,6 @@ connection_process_inbuf(connection_t *conn, int package_partial)
}
}
-/** Called whenever we've written data on a connection. */
-static int
-connection_flushed_some(connection_t *conn)
-{
- if (conn->type == CONN_TYPE_DIR &&
- conn->state == DIR_CONN_STATE_SERVER_WRITING)
- return connection_dirserv_flushed_some(TO_DIR_CONN(conn));
- else
- return 0;
-}
-
/** We just finished flushing bytes from conn-\>outbuf, and there
* are no more bytes remaining.
*
@@ -2097,18 +1945,18 @@ connection_finished_flushing(connection_t *conn)
switch (conn->type) {
case CONN_TYPE_OR:
- return connection_or_finished_flushing(TO_OR_CONN(conn));
+ return connection_or_finished_flushing(conn);
case CONN_TYPE_AP:
case CONN_TYPE_EXIT:
- return connection_edge_finished_flushing(TO_EDGE_CONN(conn));
+ return connection_edge_finished_flushing(conn);
case CONN_TYPE_DIR:
- return connection_dir_finished_flushing(TO_DIR_CONN(conn));
+ return connection_dir_finished_flushing(conn);
case CONN_TYPE_DNSWORKER:
return connection_dns_finished_flushing(conn);
case CONN_TYPE_CPUWORKER:
return connection_cpu_finished_flushing(conn);
case CONN_TYPE_CONTROL:
- return connection_control_finished_flushing(TO_CONTROL_CONN(conn));
+ return connection_control_finished_flushing(conn);
default:
log_err(LD_BUG,"Bug: got unexpected conn type %d.", conn->type);
tor_fragile_assert();
@@ -2129,11 +1977,11 @@ connection_finished_connecting(connection_t *conn)
switch (conn->type)
{
case CONN_TYPE_OR:
- return connection_or_finished_connecting(TO_OR_CONN(conn));
+ return connection_or_finished_connecting(conn);
case CONN_TYPE_EXIT:
- return connection_edge_finished_connecting(TO_EDGE_CONN(conn));
+ return connection_edge_finished_connecting(conn);
case CONN_TYPE_DIR:
- return connection_dir_finished_connecting(TO_DIR_CONN(conn));
+ return connection_dir_finished_connecting(conn);
default:
log_err(LD_BUG,"Bug: got unexpected conn type %d.", conn->type);
tor_fragile_assert();
@@ -2147,18 +1995,18 @@ connection_reached_eof(connection_t *conn)
{
switch (conn->type) {
case CONN_TYPE_OR:
- return connection_or_reached_eof(TO_OR_CONN(conn));
+ return connection_or_reached_eof(conn);
case CONN_TYPE_AP:
case CONN_TYPE_EXIT:
- return connection_edge_reached_eof(TO_EDGE_CONN(conn));
+ return connection_edge_reached_eof(conn);
case CONN_TYPE_DIR:
- return connection_dir_reached_eof(TO_DIR_CONN(conn));
+ return connection_dir_reached_eof(conn);
case CONN_TYPE_DNSWORKER:
return connection_dns_reached_eof(conn);
case CONN_TYPE_CPUWORKER:
return connection_cpu_reached_eof(conn);
case CONN_TYPE_CONTROL:
- return connection_control_reached_eof(TO_CONTROL_CONN(conn));
+ return connection_control_reached_eof(conn);
default:
log_err(LD_BUG,"Bug: got unexpected conn type %d.", conn->type);
tor_fragile_assert();
@@ -2172,28 +2020,10 @@ connection_reached_eof(connection_t *conn)
void
assert_connection_ok(connection_t *conn, time_t now)
{
- (void) now; /* XXXX unused. */
tor_assert(conn);
+ tor_assert(conn->magic == CONNECTION_MAGIC);
tor_assert(conn->type >= _CONN_TYPE_MIN);
tor_assert(conn->type <= _CONN_TYPE_MAX);
- switch (conn->type) {
- case CONN_TYPE_OR:
- tor_assert(conn->magic == OR_CONNECTION_MAGIC);
- break;
- case CONN_TYPE_AP:
- case CONN_TYPE_EXIT:
- tor_assert(conn->magic == EDGE_CONNECTION_MAGIC);
- break;
- case CONN_TYPE_DIR:
- tor_assert(conn->magic == DIR_CONNECTION_MAGIC);
- break;
- case CONN_TYPE_CONTROL:
- tor_assert(conn->magic == CONTROL_CONNECTION_MAGIC);
- break;
- default:
- tor_assert(conn->magic == BASE_CONNECTION_MAGIC);
- break;
- }
if (conn->outbuf_flushlen > 0) {
tor_assert(connection_is_writing(conn) || conn->wants_to_write);
@@ -2202,7 +2032,7 @@ assert_connection_ok(connection_t *conn, time_t now)
if (conn->hold_open_until_flushed)
tor_assert(conn->marked_for_close);
- /* XXX check: wants_to_read, wants_to_write, s, conn_array_index,
+ /* XXX check: wants_to_read, wants_to_write, s, poll_index,
* marked_for_close. */
/* buffers */
@@ -2220,8 +2050,9 @@ assert_connection_ok(connection_t *conn, time_t now)
*/
#endif
- if (conn->type == CONN_TYPE_OR) {
- or_connection_t *or_conn = TO_OR_CONN(conn);
+ if (conn->type != CONN_TYPE_OR) {
+ tor_assert(!conn->tls);
+ } else {
if (conn->state == OR_CONN_STATE_OPEN) {
/* tor_assert(conn->bandwidth > 0); */
/* the above isn't necessarily true: if we just did a TLS
@@ -2234,37 +2065,48 @@ assert_connection_ok(connection_t *conn, time_t now)
// tor_assert(conn->addr && conn->port);
tor_assert(conn->address);
if (conn->state > OR_CONN_STATE_PROXY_READING)
- tor_assert(or_conn->tls);
+ tor_assert(conn->tls);
}
- if (CONN_IS_EDGE(conn)) {
- edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
+ if (! CONN_IS_EDGE(conn)) {
+ tor_assert(!conn->stream_id);
+ tor_assert(!conn->next_stream);
+ tor_assert(!conn->cpath_layer);
+ tor_assert(!conn->package_window);
+ tor_assert(!conn->deliver_window);
+#if 0
+ tor_assert(!conn->done_sending);
+ tor_assert(!conn->done_receiving);
+#endif
+ } else {
/* XXX unchecked: package window, deliver window. */
- if (conn->type == CONN_TYPE_AP) {
-
- tor_assert(edge_conn->socks_request);
- if (conn->state == AP_CONN_STATE_OPEN) {
- tor_assert(edge_conn->socks_request->has_finished);
- if (!conn->marked_for_close) {
- tor_assert(edge_conn->cpath_layer);
- assert_cpath_layer_ok(edge_conn->cpath_layer);
- }
+ }
+ if (conn->type == CONN_TYPE_AP) {
+ tor_assert(conn->socks_request);
+ if (conn->state == AP_CONN_STATE_OPEN) {
+ tor_assert(conn->socks_request->has_finished);
+ if (!conn->marked_for_close) {
+ tor_assert(conn->cpath_layer);
+ assert_cpath_layer_ok(conn->cpath_layer);
}
}
- if (conn->type == CONN_TYPE_EXIT) {
- tor_assert(conn->purpose == EXIT_PURPOSE_CONNECT ||
- conn->purpose == EXIT_PURPOSE_RESOLVE);
- }
+ } else {
+ tor_assert(!conn->socks_request);
+ }
+ if (conn->type == CONN_TYPE_EXIT) {
+ tor_assert(conn->purpose == EXIT_PURPOSE_CONNECT ||
+ conn->purpose == EXIT_PURPOSE_RESOLVE);
} else if (conn->type != CONN_TYPE_DIR) {
- /* Purpose is only used for dir and exit types currently */
- tor_assert(!conn->purpose);
+ tor_assert(!conn->purpose); /* only used for dir types currently */
+ }
+ if (conn->type != CONN_TYPE_DIR) {
+ tor_assert(!conn->requested_resource);
}
switch (conn->type)
{
case CONN_TYPE_OR_LISTENER:
case CONN_TYPE_AP_LISTENER:
- case CONN_TYPE_AP_TRANS_LISTENER:
case CONN_TYPE_DIR_LISTENER:
case CONN_TYPE_CONTROL_LISTENER:
tor_assert(conn->state == LISTENER_STATE_READY);
@@ -2272,7 +2114,7 @@ assert_connection_ok(connection_t *conn, time_t now)
case CONN_TYPE_OR:
tor_assert(conn->state >= _OR_CONN_STATE_MIN);
tor_assert(conn->state <= _OR_CONN_STATE_MAX);
- tor_assert(TO_OR_CONN(conn)->n_circuits >= 0);
+ tor_assert(conn->n_circuits >= 0);
break;
case CONN_TYPE_EXIT:
tor_assert(conn->state >= _EXIT_CONN_STATE_MIN);
@@ -2283,7 +2125,7 @@ assert_connection_ok(connection_t *conn, time_t now)
case CONN_TYPE_AP:
tor_assert(conn->state >= _AP_CONN_STATE_MIN);
tor_assert(conn->state <= _AP_CONN_STATE_MAX);
- tor_assert(TO_EDGE_CONN(conn)->socks_request);
+ tor_assert(conn->socks_request);
break;
case CONN_TYPE_DIR:
tor_assert(conn->state >= _DIR_CONN_STATE_MIN);
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 9ab672ff07..902e0c009b 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -13,37 +13,25 @@ const char connection_edge_c_id[] =
#include "or.h"
-#ifdef HAVE_LINUX_NETFILTER_IPV4_H
-#include <linux/netfilter_ipv4.h>
-#define TRANS_NETFILTER
-#endif
-
-#if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
-#include <net/if.h>
-#include <net/pfvar.h>
-#define TRANS_PF
-#endif
-
/* List of exit_redirect_t */
static smartlist_t *redirect_exit_list = NULL;
-static int connection_ap_handshake_process_socks(edge_connection_t *conn);
-static int connection_ap_process_transparent(edge_connection_t *conn);
+static int connection_ap_handshake_process_socks(connection_t *conn);
/** An AP stream has failed/finished. If it hasn't already sent back
* a socks reply, send one now (based on endreason). Also set
* has_sent_end to 1, and mark the conn.
*/
void
-_connection_mark_unattached_ap(edge_connection_t *conn, int endreason,
+_connection_mark_unattached_ap(connection_t *conn, int endreason,
int line, const char *file)
{
- tor_assert(conn->_base.type == CONN_TYPE_AP);
- conn->_base.edge_has_sent_end = 1; /* no circ yet */
+ tor_assert(conn->type == CONN_TYPE_AP);
+ conn->has_sent_end = 1; /* no circ yet */
- if (conn->_base.marked_for_close) {
+ if (conn->marked_for_close) {
/* This call will warn as appropriate. */
- _connection_mark_for_close(TO_CONN(conn), line, file);
+ _connection_mark_for_close(conn, line, file);
return;
}
@@ -63,36 +51,49 @@ _connection_mark_unattached_ap(edge_connection_t *conn, int endreason,
0, NULL, -1);
}
- _connection_mark_for_close(TO_CONN(conn), line, file);
- conn->_base.hold_open_until_flushed = 1;
+ _connection_mark_for_close(conn, line, file);
+ conn->hold_open_until_flushed = 1;
}
/** There was an EOF. Send an end and mark the connection for close.
*/
int
-connection_edge_reached_eof(edge_connection_t *conn)
+connection_edge_reached_eof(connection_t *conn)
{
- if (buf_datalen(conn->_base.inbuf) &&
- connection_state_is_open(TO_CONN(conn))) {
+#ifdef HALF_OPEN
+ /* eof reached; we're done reading, but we might want to write more. */
+ conn->done_receiving = 1;
+ shutdown(conn->s, 0); /* XXX check return, refactor NM */
+ if (conn->done_sending) {
+ connection_edge_end(conn, END_STREAM_REASON_DONE, conn->cpath_layer);
+ connection_mark_for_close(conn);
+ } else {
+ connection_edge_send_command(conn, circuit_get_by_edge_conn(conn),
+ RELAY_COMMAND_END,
+ NULL, 0, conn->cpath_layer);
+ }
+ return 0;
+#else
+ if (buf_datalen(conn->inbuf) && connection_state_is_open(conn)) {
/* it still has stuff to process. don't let it die yet. */
return 0;
}
- log_info(LD_EDGE,"conn (fd %d) reached eof. Closing.", conn->_base.s);
- if (!conn->_base.marked_for_close) {
+ log_info(LD_EDGE,"conn (fd %d) reached eof. Closing.", conn->s);
+ if (!conn->marked_for_close) {
/* only mark it if not already marked. it's possible to
* get the 'end' right around when the client hangs up on us. */
connection_edge_end(conn, END_STREAM_REASON_DONE, conn->cpath_layer);
if (conn->socks_request) /* eof, so don't send a socks reply back */
conn->socks_request->has_finished = 1;
- connection_mark_for_close(TO_CONN(conn));
+ connection_mark_for_close(conn);
}
return 0;
+#endif
}
/** Handle new bytes on conn->inbuf based on state:
* - If it's waiting for socks info, try to read another step of the
* socks handshake out of conn->inbuf.
- * - If it's waiting for the original destination, fetch it.
* - If it's open, then package more relay cells from the stream.
* - Else, leave the bytes on inbuf alone for now.
*
@@ -100,28 +101,23 @@ connection_edge_reached_eof(edge_connection_t *conn)
* else return 0.
*/
int
-connection_edge_process_inbuf(edge_connection_t *conn, int package_partial)
+connection_edge_process_inbuf(connection_t *conn, int package_partial)
{
tor_assert(conn);
+ tor_assert(CONN_IS_EDGE(conn));
- switch (conn->_base.state) {
+ switch (conn->state) {
case AP_CONN_STATE_SOCKS_WAIT:
if (connection_ap_handshake_process_socks(conn) < 0) {
/* already marked */
return -1;
}
return 0;
- case AP_CONN_STATE_ORIGDST_WAIT:
- if (connection_ap_process_transparent(conn) < 0) {
- /* already marked */
- return -1;
- }
- return 0;
case AP_CONN_STATE_OPEN:
case EXIT_CONN_STATE_OPEN:
if (connection_edge_package_raw_inbuf(conn, package_partial) < 0) {
/* (We already sent an end cell if possible) */
- connection_mark_for_close(TO_CONN(conn));
+ connection_mark_for_close(conn);
return -1;
}
return 0;
@@ -133,13 +129,13 @@ connection_edge_process_inbuf(edge_connection_t *conn, int package_partial)
case AP_CONN_STATE_CONTROLLER_WAIT:
log_info(LD_EDGE,
"data from edge while in '%s' state. Leaving it on buffer.",
- conn_state_to_string(conn->_base.type, conn->_base.state));
+ conn_state_to_string(conn->type, conn->state));
return 0;
}
- log_warn(LD_BUG,"Bug: Got unexpected state %d. Closing.",conn->_base.state);
+ log_warn(LD_BUG,"Bug: Got unexpected state %d. Closing.",conn->state);
tor_fragile_assert();
connection_edge_end(conn, END_STREAM_REASON_INTERNAL, conn->cpath_layer);
- connection_mark_for_close(TO_CONN(conn));
+ connection_mark_for_close(conn);
return -1;
}
@@ -147,18 +143,19 @@ connection_edge_process_inbuf(edge_connection_t *conn, int package_partial)
* Mark it for close and return 0.
*/
int
-connection_edge_destroy(uint16_t circ_id, edge_connection_t *conn)
+connection_edge_destroy(uint16_t circ_id, connection_t *conn)
{
- if (!conn->_base.marked_for_close) {
+ tor_assert(CONN_IS_EDGE(conn));
+
+ if (!conn->marked_for_close) {
log_info(LD_EDGE,
"CircID %d: At an edge. Marking connection for close.", circ_id);
- if (conn->_base.type == CONN_TYPE_AP) {
+ if (conn->type == CONN_TYPE_AP) {
connection_mark_unattached_ap(conn, END_STREAM_REASON_DESTROY);
} else {
- /* closing the circuit, nothing to send an END to */
- conn->_base.edge_has_sent_end = 1;
- connection_mark_for_close(TO_CONN(conn));
- conn->_base.hold_open_until_flushed = 1;
+ conn->has_sent_end = 1; /* closing the circuit, nothing to send to */
+ connection_mark_for_close(conn);
+ conn->hold_open_until_flushed = 1;
}
}
conn->cpath_layer = NULL;
@@ -175,46 +172,45 @@ connection_edge_destroy(uint16_t circ_id, edge_connection_t *conn)
* else return 0.
*/
int
-connection_edge_end(edge_connection_t *conn, char reason,
- crypt_path_t *cpath_layer)
+connection_edge_end(connection_t *conn, char reason, crypt_path_t *cpath_layer)
{
char payload[RELAY_PAYLOAD_SIZE];
size_t payload_len=1;
circuit_t *circ;
- if (conn->_base.edge_has_sent_end) {
+ if (conn->has_sent_end) {
log_warn(LD_BUG,"Harmless bug: Calling connection_edge_end (reason %d) "
"on an already ended stream?", reason);
tor_fragile_assert();
return -1;
}
- if (conn->_base.marked_for_close) {
+ if (conn->marked_for_close) {
log_warn(LD_BUG,
"Bug: called on conn that's already marked for close at %s:%d.",
- conn->_base.marked_for_close_file, conn->_base.marked_for_close);
+ conn->marked_for_close_file, conn->marked_for_close);
return 0;
}
payload[0] = reason;
if (reason == END_STREAM_REASON_EXITPOLICY &&
!connection_edge_is_rendezvous_stream(conn)) {
- set_uint32(payload+1, htonl(conn->_base.addr));
- set_uint32(payload+5, htonl(dns_clip_ttl(conn->address_ttl)));
+ set_uint32(payload+1, htonl(conn->addr));
+ /* XXXX fill with a real TTL! */
+ set_uint32(payload+5, htonl(MAX_DNS_ENTRY_AGE));
payload_len += 8;
}
circ = circuit_get_by_edge_conn(conn);
if (circ && !circ->marked_for_close) {
- log_debug(LD_EDGE,"Marking conn (fd %d) and sending end.",conn->_base.s);
+ log_debug(LD_EDGE,"Marking conn (fd %d) and sending end.",conn->s);
connection_edge_send_command(conn, circ, RELAY_COMMAND_END,
payload, payload_len, cpath_layer);
} else {
- log_debug(LD_EDGE,"Marking conn (fd %d); no circ to send end.",
- conn->_base.s);
+ log_debug(LD_EDGE,"Marking conn (fd %d); no circ to send end.",conn->s);
}
- conn->_base.edge_has_sent_end = 1;
+ conn->has_sent_end = 1;
return 0;
}
@@ -223,11 +219,11 @@ connection_edge_end(edge_connection_t *conn, char reason,
* an appropriate relay end cell to <b>cpath_layer</b>.
**/
int
-connection_edge_end_errno(edge_connection_t *conn, crypt_path_t *cpath_layer)
+connection_edge_end_errno(connection_t *conn, crypt_path_t *cpath_layer)
{
uint8_t reason;
tor_assert(conn);
- reason = (uint8_t)errno_to_end_reason(tor_socket_errno(conn->_base.s));
+ reason = (uint8_t)errno_to_end_reason(tor_socket_errno(conn->s));
return connection_edge_end(conn, reason, cpath_layer);
}
@@ -242,26 +238,26 @@ connection_edge_end_errno(edge_connection_t *conn, crypt_path_t *cpath_layer)
* return 0.
*/
int
-connection_edge_finished_flushing(edge_connection_t *conn)
+connection_edge_finished_flushing(connection_t *conn)
{
tor_assert(conn);
+ tor_assert(CONN_IS_EDGE(conn));
- switch (conn->_base.state) {
+ switch (conn->state) {
case AP_CONN_STATE_OPEN:
case EXIT_CONN_STATE_OPEN:
- connection_stop_writing(TO_CONN(conn));
+ connection_stop_writing(conn);
connection_edge_consider_sending_sendme(conn);
return 0;
case AP_CONN_STATE_SOCKS_WAIT:
- case AP_CONN_STATE_ORIGDST_WAIT:
case AP_CONN_STATE_RENDDESC_WAIT:
case AP_CONN_STATE_CIRCUIT_WAIT:
case AP_CONN_STATE_CONNECT_WAIT:
case AP_CONN_STATE_CONTROLLER_WAIT:
- connection_stop_writing(TO_CONN(conn));
+ connection_stop_writing(conn);
return 0;
default:
- log_warn(LD_BUG,"BUG: called in unexpected state %d.",conn->_base.state);
+ log_warn(LD_BUG,"BUG: called in unexpected state %d.", conn->state);
tor_fragile_assert();
return -1;
}
@@ -272,15 +268,13 @@ connection_edge_finished_flushing(edge_connection_t *conn)
* data, deliver 'CONNECTED' relay cells as appropriate, and check
* any pending data that may have been received. */
int
-connection_edge_finished_connecting(edge_connection_t *edge_conn)
+connection_edge_finished_connecting(connection_t *conn)
{
char valbuf[INET_NTOA_BUF_LEN];
- connection_t *conn;
struct in_addr in;
- tor_assert(edge_conn);
- tor_assert(edge_conn->_base.type == CONN_TYPE_EXIT);
- conn = TO_CONN(edge_conn);
+ tor_assert(conn);
+ tor_assert(conn->type == CONN_TYPE_EXIT);
tor_assert(conn->state == EXIT_CONN_STATE_CONNECTING);
in.s_addr = htonl(conn->addr);
@@ -294,42 +288,23 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn)
* cells */
connection_start_writing(conn);
/* deliver a 'connected' relay cell back through the circuit. */
- if (connection_edge_is_rendezvous_stream(edge_conn)) {
- if (connection_edge_send_command(edge_conn,
- circuit_get_by_edge_conn(edge_conn),
+ if (connection_edge_is_rendezvous_stream(conn)) {
+ if (connection_edge_send_command(conn, circuit_get_by_edge_conn(conn),
RELAY_COMMAND_CONNECTED, NULL, 0,
- edge_conn->cpath_layer) < 0)
+ conn->cpath_layer) < 0)
return 0; /* circuit is closed, don't continue */
} else {
char connected_payload[8];
set_uint32(connected_payload, htonl(conn->addr));
set_uint32(connected_payload+4,
- htonl(dns_clip_ttl(edge_conn->address_ttl)));
- if (connection_edge_send_command(edge_conn,
- circuit_get_by_edge_conn(edge_conn),
- RELAY_COMMAND_CONNECTED,
- connected_payload, 8,
- edge_conn->cpath_layer) < 0)
+ htonl(MAX_DNS_ENTRY_AGE)); /* XXXX fill with a real TTL */
+ if (connection_edge_send_command(conn, circuit_get_by_edge_conn(conn),
+ RELAY_COMMAND_CONNECTED, connected_payload, 8, conn->cpath_layer) < 0)
return 0; /* circuit is closed, don't continue */
}
- tor_assert(edge_conn->package_window > 0);
+ tor_assert(conn->package_window > 0);
/* in case the server has written anything */
- return connection_edge_process_inbuf(edge_conn, 1);
-}
-
-/** Define a schedule for how long to wait between retrying
- * application connections. Rather than waiting a fixed amount of
- * time between each retry, we wait only 5 seconds for the first,
- * 10 seconds for the second, and 15 seconds for each retry after
- * that. Hopefully this will improve the expected user experience. */
-static int
-compute_socks_timeout(edge_connection_t *conn)
-{
- if (conn->num_socks_retries == 0)
- return 5;
- if (conn->num_socks_retries == 1)
- return 10;
- return 15;
+ return connection_edge_process_inbuf(conn, 1);
}
/** Find all general-purpose AP streams waiting for a response that sent their
@@ -345,37 +320,34 @@ void
connection_ap_expire_beginning(void)
{
connection_t **carray;
- edge_connection_t *conn;
+ connection_t *conn;
circuit_t *circ;
const char *nickname;
int n, i;
time_t now = time(NULL);
or_options_t *options = get_options();
int severity;
- int cutoff;
get_connection_array(&carray, &n);
for (i = 0; i < n; ++i) {
- if (carray[i]->type != CONN_TYPE_AP)
+ conn = carray[i];
+ if (conn->type != CONN_TYPE_AP)
continue;
- conn = TO_EDGE_CONN(carray[i]);
/* if it's an internal bridge connection, don't yell its status. */
- severity = (!conn->_base.addr && !conn->_base.port)
- ? LOG_INFO : LOG_NOTICE;
- if (conn->_base.state == AP_CONN_STATE_CONTROLLER_WAIT) {
- if (now - conn->_base.timestamp_lastread >= options->SocksTimeout) {
+ severity = (!conn->addr && !conn->port) ? LOG_INFO : LOG_NOTICE;
+ if (conn->state == AP_CONN_STATE_CONTROLLER_WAIT) {
+ if (now - conn->timestamp_lastread >= options->SocksTimeout) {
log_fn(severity, LD_APP, "Closing unattached stream.");
connection_mark_unattached_ap(conn, END_STREAM_REASON_TIMEOUT);
}
continue;
}
- if (conn->_base.state != AP_CONN_STATE_RESOLVE_WAIT &&
- conn->_base.state != AP_CONN_STATE_CONNECT_WAIT)
+ else if (conn->state != AP_CONN_STATE_RESOLVE_WAIT &&
+ conn->state != AP_CONN_STATE_CONNECT_WAIT)
continue;
- cutoff = compute_socks_timeout(conn);
- if (now - conn->_base.timestamp_lastread < cutoff)
+ if (now - conn->timestamp_lastread < 15)
continue;
circ = circuit_get_by_edge_conn(conn);
if (!circ) { /* it's vanished? */
@@ -385,11 +357,11 @@ connection_ap_expire_beginning(void)
continue;
}
if (circ->purpose == CIRCUIT_PURPOSE_C_REND_JOINED) {
- if (now - conn->_base.timestamp_lastread > options->SocksTimeout) {
+ if (now - conn->timestamp_lastread > options->SocksTimeout) {
log_fn(severity, LD_REND,
"Rend stream is %d seconds late. Giving up on address"
" '%s.onion'.",
- (int)(now - conn->_base.timestamp_lastread),
+ (int)(now - conn->timestamp_lastread),
safe_str(conn->socks_request->address));
connection_edge_end(conn, END_STREAM_REASON_TIMEOUT,
conn->cpath_layer);
@@ -398,29 +370,26 @@ connection_ap_expire_beginning(void)
continue;
}
tor_assert(circ->purpose == CIRCUIT_PURPOSE_C_GENERAL);
- nickname = build_state_get_exit_nickname(
- TO_ORIGIN_CIRCUIT(circ)->build_state);
- log_fn(cutoff < 15 ? LOG_INFO : severity, LD_APP,
+ nickname = build_state_get_exit_nickname(circ->build_state);
+ log_fn(severity, LD_APP,
"We tried for %d seconds to connect to '%s' using exit '%s'."
" Retrying on a new circuit.",
- (int)(now - conn->_base.timestamp_lastread),
+ (int)(now - conn->timestamp_lastread),
safe_str(conn->socks_request->address),
nickname ? nickname : "*unnamed*");
/* send an end down the circuit */
connection_edge_end(conn, END_STREAM_REASON_TIMEOUT, conn->cpath_layer);
/* un-mark it as ending, since we're going to reuse it */
- conn->_base.edge_has_sent_end = 0;
+ conn->has_sent_end = 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 */
tor_assert(circ->timestamp_dirty);
circ->timestamp_dirty -= options->MaxCircuitDirtiness;
- /* give our stream another 'cutoff' seconds to try */
- conn->_base.timestamp_lastread += cutoff;
- if (conn->num_socks_retries < 250) /* avoid overflow */
- conn->num_socks_retries++;
+ /* give our stream another 15 seconds to try */
+ conn->timestamp_lastread += 15;
/* move it back into 'pending' state, and try to attach. */
- if (connection_ap_detach_retriable(conn, TO_ORIGIN_CIRCUIT(circ))<0) {
+ if (connection_ap_detach_retriable(conn, circ)<0) {
connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
}
} /* end for */
@@ -434,7 +403,6 @@ connection_ap_attach_pending(void)
{
connection_t **carray;
connection_t *conn;
- edge_connection_t *edge_conn;
int n, i;
get_connection_array(&carray, &n);
@@ -445,9 +413,8 @@ connection_ap_attach_pending(void)
conn->type != CONN_TYPE_AP ||
conn->state != AP_CONN_STATE_CIRCUIT_WAIT)
continue;
- edge_conn = TO_EDGE_CONN(conn);
- if (connection_ap_handshake_attach_circuit(edge_conn) < 0) {
- connection_mark_unattached_ap(edge_conn, END_STREAM_REASON_CANT_ATTACH);
+ if (connection_ap_handshake_attach_circuit(conn) < 0) {
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
}
}
}
@@ -460,17 +427,17 @@ connection_ap_attach_pending(void)
* Returns -1 on err, 1 on success, 0 on not-yet-sure.
*/
int
-connection_ap_detach_retriable(edge_connection_t *conn, origin_circuit_t *circ)
+connection_ap_detach_retriable(connection_t *conn, circuit_t *circ)
{
control_event_stream_status(conn, STREAM_EVENT_FAILED_RETRIABLE);
- conn->_base.timestamp_lastread = time(NULL);
+ conn->timestamp_lastread = time(NULL);
if (! get_options()->LeaveStreamsUnattached) {
- conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
- circuit_detach_stream(TO_CIRCUIT(circ),conn);
+ conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
+ circuit_detach_stream(circ,conn);
return connection_ap_handshake_attach_circuit(conn);
} else {
- conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT;
- circuit_detach_stream(TO_CIRCUIT(circ),conn);
+ conn->state = AP_CONN_STATE_CONTROLLER_WAIT;
+ circuit_detach_stream(circ,conn);
return 0;
}
}
@@ -645,9 +612,9 @@ addressmap_rewrite(char *address, size_t maxlen)
/** Return 1 if <b>address</b> is already registered, else return 0 */
int
-addressmap_have_mapping(const char *address)
+addressmap_already_mapped(const char *address)
{
- return strmap_get_lc(addressmap, address) ? 1 : 0;
+ return strmap_get(addressmap, address) ? 1 : 0;
}
/** Register a request to map <b>address</b> to <b>new_address</b>,
@@ -715,7 +682,7 @@ client_dns_incr_failures(const char *address)
addressmap_entry_t *ent = strmap_get(addressmap, address);
if (!ent) {
ent = tor_malloc_zero(sizeof(addressmap_entry_t));
- ent->expires = time(NULL) + MAX_DNS_ENTRY_AGE;
+ ent->expires = time(NULL)+MAX_DNS_ENTRY_AGE;
strmap_set(addressmap,address,ent);
}
++ent->num_resolve_failures;
@@ -745,7 +712,7 @@ client_dns_clear_failures(const char *address)
* ".exitname.exit" before registering the mapping.
*
* If <b>ttl</b> is nonnegative, the mapping will be valid for
- * <b>ttl</b>seconds; otherwise, we use the default.
+ * <b>ttl</b>seconds.
*/
void
client_dns_set_addressmap(const char *address, uint32_t val,
@@ -759,13 +726,10 @@ client_dns_set_addressmap(const char *address, uint32_t val,
char extendedval[INET_NTOA_BUF_LEN+MAX_HEX_NICKNAME_LEN+10];
char valbuf[INET_NTOA_BUF_LEN];
- tor_assert(address);
- tor_assert(val);
+ tor_assert(address); tor_assert(val);
- if (ttl<0)
- ttl = DEFAULT_DNS_TTL;
- else
- ttl = dns_clip_ttl(ttl);
+ if (ttl<0 || ttl>MAX_DNS_ENTRY_AGE)
+ ttl = MAX_DNS_ENTRY_AGE;
if (tor_inet_aton(address, &in))
return; /* If address was an IP address already, don't add a mapping. */
@@ -1041,8 +1005,8 @@ addressmap_get_mappings(smartlist_t *sl, time_t min_expires,
* rendezvous descriptor is already here and fresh enough).
*/
int
-connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
- origin_circuit_t *circ)
+connection_ap_handshake_rewrite_and_attach(connection_t *conn,
+ circuit_t *circ)
{
socks_request_t *socks = conn->socks_request;
hostname_type_t addresstype;
@@ -1141,7 +1105,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
return 0;
}
rep_hist_note_used_resolve(time(NULL)); /* help predict this next time */
- } else if (socks->command == SOCKS_COMMAND_CONNECT) {
+ } else { /* socks->command == SOCKS_COMMAND_CONNECT */
if (socks->port == 0) {
log_notice(LD_APP,"Application asked to connect to port 0. Refusing.");
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
@@ -1160,20 +1124,13 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
routers with this nickname */
conn->chosen_exit_name =
tor_strdup(hex_str(r->cache_info.identity_digest, DIGEST_LEN));
- conn->_base.chosen_exit_optional = 1;
}
}
/* help predict this next time */
rep_hist_note_used_port(socks->port, time(NULL));
- } else if (socks->command == SOCKS_COMMAND_RESOLVE_PTR) {
- // XXXX NM Do anything here?
-
- rep_hist_note_used_resolve(time(NULL)); /* help predict this next time */
- } else {
- tor_fragile_assert();
}
- conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
+ conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
if ((circ &&
connection_ap_handshake_attach_chosen_circuit(conn, circ) < 0) ||
(!circ &&
@@ -1187,7 +1144,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
rend_cache_entry_t *entry;
int r;
- if (socks->command != SOCKS_COMMAND_CONNECT) {
+ if (socks->command == SOCKS_COMMAND_RESOLVE) {
/* if it's a resolve request, fail it right now, rather than
* building all the circuits and then realizing it won't work. */
log_warn(LD_APP,
@@ -1218,21 +1175,21 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
return -1;
}
if (r==0) {
- conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT;
+ conn->state = AP_CONN_STATE_RENDDESC_WAIT;
log_info(LD_REND, "Unknown descriptor %s. Fetching.",
safe_str(conn->rend_query));
rend_client_refetch_renddesc(conn->rend_query);
} else { /* r > 0 */
#define NUM_SECONDS_BEFORE_REFETCH (60*15)
if (time(NULL) - entry->received < NUM_SECONDS_BEFORE_REFETCH) {
- conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
+ conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
log_info(LD_REND, "Descriptor is here and fresh enough. Great.");
if (connection_ap_handshake_attach_circuit(conn) < 0) {
connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
return -1;
}
} else {
- conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT;
+ conn->state = AP_CONN_STATE_RENDDESC_WAIT;
log_info(LD_REND, "Stale descriptor %s. Refetching.",
safe_str(conn->rend_query));
rend_client_refetch_renddesc(conn->rend_query);
@@ -1243,108 +1200,6 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
return 0; /* unreached but keeps the compiler happy */
}
-#ifdef TRANS_PF
-static int pf_socket = -1;
-static int
-get_pf_socket(void)
-{
- int pf;
- /* Ideally, this should be opened before dropping privs. */
- if (pf_socket >= 0)
- return pf_socket;
-
-#ifdef OPENBSD
- /* only works on OpenBSD */
- pf = open("/dev/pf", O_RDONLY);
-#else
- /* works on NetBSD and FreeBSD */
- pf = open("/dev/pf", O_RDWR);
-#endif
-
- if (pf < 0) {
- log_warn(LD_NET, "open(\"/dev/pf\") failed: %s", strerror(errno));
- return -1;
- }
-
- pf_socket = pf;
-}
-#endif
-
-/** Fetch the original destination address and port from a
- * system-specific interface and put them into a
- * socks_request_t as if they came from a socks request.
- *
- * Return -1 if an error prevents fetching the destination,
- * else return 0.
- */
-static int
-connection_ap_get_original_destination(edge_connection_t *conn,
- socks_request_t *req)
-{
-#ifdef TRANS_NETFILTER
- /* Linux 2.4+ */
- struct sockaddr_in orig_dst;
- socklen_t orig_dst_len = sizeof(orig_dst);
- char tmpbuf[INET_NTOA_BUF_LEN];
-
- if (getsockopt(conn->_base.s, SOL_IP, SO_ORIGINAL_DST,
- (struct sockaddr*)&orig_dst, &orig_dst_len) < 0) {
- int e = tor_socket_errno(conn->_base.s);
- log_warn(LD_NET, "getsockopt() failed: %s", tor_socket_strerror(e));
- return -1;
- }
-
- tor_inet_ntoa(&orig_dst.sin_addr, tmpbuf, sizeof(tmpbuf));
- strlcpy(req->address, tmpbuf, sizeof(req->address));
- req->port = ntohs(orig_dst.sin_port);
-
- return 0;
-#elif defined(TRANS_PF)
- struct sockaddr_in proxy_addr;
- socklen_t proxy_addr_len = sizeof(proxy_addr);
- char tmpbuf[INET_NTOA_BUF_LEN];
- struct pfioc_natlook pnl;
- int pf = -1;
-
- if (getsockname(conn->_base.s, (struct sockaddr*)&proxy_addr,
- &proxy_addr_len) < 0) {
- int e = tor_socket_errno(conn->_base.s);
- log_warn(LD_NET, "getsockname() failed: %s", tor_socket_strerror(e));
- return -1;
- }
-
- memset(&pnl, 0, sizeof(pnl));
- pnl.af = AF_INET;
- pnl.proto = IPPROTO_TCP;
- pnl.direction = PF_OUT;
- pnl.saddr.v4.s_addr = htonl(conn->_base.addr);
- pnl.sport = htons(conn->_base.port);
- pnl.daddr.v4.s_addr = proxy_addr.sin_addr.s_addr;
- pnl.dport = proxy_addr.sin_port;
-
- pf = get_pf_socket();
- if (pf<0)
- return -1;
-
- if (ioctl(pf, DIOCNATLOOK, &pnl) < 0) {
- log_warn(LD_NET, "ioctl(DIOCNATLOOK) failed: %s", strerror(errno));
- return -1;
- }
-
- tor_inet_ntoa(&pnl.rdaddr.v4, tmpbuf, sizeof(tmpbuf));
- strlcpy(req->address, tmpbuf, sizeof(req->address));
- req->port = ntohs(pnl.rdport);
-
- return 0;
-#else
- (void)conn;
- (void)req;
- log_warn(LD_BUG, "Called connection_ap_get_original_destination, but no "
- "transparent proxy method was configured.");
- return -1;
-#endif
-}
-
/** connection_edge_process_inbuf() found a conn in state
* socks_wait. See if conn->inbuf has the right bytes to proceed with
* the socks handshake.
@@ -1356,25 +1211,25 @@ connection_ap_get_original_destination(edge_connection_t *conn,
* for close), else return 0.
*/
static int
-connection_ap_handshake_process_socks(edge_connection_t *conn)
+connection_ap_handshake_process_socks(connection_t *conn)
{
socks_request_t *socks;
int sockshere;
or_options_t *options = get_options();
tor_assert(conn);
- tor_assert(conn->_base.type == CONN_TYPE_AP);
- tor_assert(conn->_base.state == AP_CONN_STATE_SOCKS_WAIT);
+ tor_assert(conn->type == CONN_TYPE_AP);
+ tor_assert(conn->state == AP_CONN_STATE_SOCKS_WAIT);
tor_assert(conn->socks_request);
socks = conn->socks_request;
log_debug(LD_APP,"entered.");
- sockshere = fetch_from_buf_socks(conn->_base.inbuf, socks,
+ sockshere = fetch_from_buf_socks(conn->inbuf, socks,
options->TestSocks, options->SafeSocks);
if (sockshere == 0) {
if (socks->replylen) {
- connection_write_to_buf(socks->reply, socks->replylen, TO_CONN(conn));
+ connection_write_to_buf(socks->reply, socks->replylen, conn);
/* zero it out so we can do another round of negotiation */
socks->replylen = 0;
} else {
@@ -1401,49 +1256,7 @@ connection_ap_handshake_process_socks(edge_connection_t *conn)
control_event_stream_status(conn, STREAM_EVENT_NEW_RESOLVE);
if (options->LeaveStreamsUnattached) {
- conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT;
- return 0;
- }
- return connection_ap_handshake_rewrite_and_attach(conn, NULL);
-}
-
-/** connection_edge_process_inbuf() found a conn in state
- * origdst_wait. Get the original destination and
- * send it to connection_ap_handshake_rewrite_and_attach().
- *
- * Return -1 if an unexpected error with conn (and it should be marked
- * for close), else return 0.
- */
-static int
-connection_ap_process_transparent(edge_connection_t *conn)
-{
- socks_request_t *socks;
- or_options_t *options = get_options();
-
- tor_assert(conn);
- tor_assert(conn->_base.type == CONN_TYPE_AP);
- tor_assert(conn->_base.state == AP_CONN_STATE_ORIGDST_WAIT);
- tor_assert(conn->socks_request);
- socks = conn->socks_request;
-
- /* pretend that a socks handshake completed so we don't try to
- * send a socks reply down a transparent conn */
- socks->command = SOCKS_COMMAND_CONNECT;
- socks->has_finished = 1;
-
- log_debug(LD_APP,"entered.");
-
- if (connection_ap_get_original_destination(conn, socks) < 0) {
- log_warn(LD_APP,"Fetching original destination failed. Closing.");
- connection_mark_unattached_ap(conn, 0);
- return -1;
- }
- /* we have the original destination */
-
- control_event_stream_status(conn, STREAM_EVENT_NEW);
-
- if (options->LeaveStreamsUnattached) {
- conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT;
+ conn->state = AP_CONN_STATE_CONTROLLER_WAIT;
return 0;
}
return connection_ap_handshake_rewrite_and_attach(conn, NULL);
@@ -1453,9 +1266,9 @@ connection_ap_process_transparent(edge_connection_t *conn)
* already in use; return it. Return 0 if can't get a unique stream_id.
*/
static uint16_t
-get_unique_stream_id_by_circ(origin_circuit_t *circ)
+get_unique_stream_id_by_circ(circuit_t *circ)
{
- edge_connection_t *tmpconn;
+ connection_t *tmpconn;
uint16_t test_stream_id;
uint32_t attempts=0;
@@ -1480,25 +1293,24 @@ again:
* If ap_conn is broken, mark it for close and return -1. Else return 0.
*/
int
-connection_ap_handshake_send_begin(edge_connection_t *ap_conn,
- origin_circuit_t *circ)
+connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ)
{
char payload[CELL_PAYLOAD_SIZE];
int payload_len;
- tor_assert(ap_conn->_base.type == CONN_TYPE_AP);
- tor_assert(ap_conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT);
+ tor_assert(ap_conn->type == CONN_TYPE_AP);
+ tor_assert(ap_conn->state == AP_CONN_STATE_CIRCUIT_WAIT);
tor_assert(ap_conn->socks_request);
ap_conn->stream_id = get_unique_stream_id_by_circ(circ);
if (ap_conn->stream_id==0) {
connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_RESOURCELIMIT);
+ circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
return -1;
}
tor_snprintf(payload,RELAY_PAYLOAD_SIZE, "%s:%d",
- (circ->_base.purpose == CIRCUIT_PURPOSE_C_GENERAL) ?
+ (circ->purpose == CIRCUIT_PURPOSE_C_GENERAL) ?
ap_conn->socks_request->address : "",
ap_conn->socks_request->port);
payload_len = strlen(payload)+1;
@@ -1506,17 +1318,16 @@ connection_ap_handshake_send_begin(edge_connection_t *ap_conn,
log_debug(LD_APP,
"Sending relay cell to begin stream %d.", ap_conn->stream_id);
- if (connection_edge_send_command(ap_conn, TO_CIRCUIT(circ),
- RELAY_COMMAND_BEGIN,
+ if (connection_edge_send_command(ap_conn, circ, RELAY_COMMAND_BEGIN,
payload, payload_len,
ap_conn->cpath_layer) < 0)
return -1; /* circuit is closed, don't continue */
ap_conn->package_window = STREAMWINDOW_START;
ap_conn->deliver_window = STREAMWINDOW_START;
- ap_conn->_base.state = AP_CONN_STATE_CONNECT_WAIT;
+ ap_conn->state = AP_CONN_STATE_CONNECT_WAIT;
log_info(LD_APP,"Address/port sent, ap socket %d, n_circ_id %d",
- ap_conn->_base.s, circ->_base.n_circ_id);
+ ap_conn->s, circ->n_circ_id);
control_event_stream_status(ap_conn, STREAM_EVENT_SENT_CONNECT);
return 0;
}
@@ -1527,62 +1338,38 @@ connection_ap_handshake_send_begin(edge_connection_t *ap_conn,
* If ap_conn is broken, mark it for close and return -1. Else return 0.
*/
int
-connection_ap_handshake_send_resolve(edge_connection_t *ap_conn,
- origin_circuit_t *circ)
+connection_ap_handshake_send_resolve(connection_t *ap_conn, circuit_t *circ)
{
- int payload_len, command;
+ int payload_len;
const char *string_addr;
- char inaddr_buf[32];
- command = ap_conn->socks_request->command;
-
- tor_assert(ap_conn->_base.type == CONN_TYPE_AP);
- tor_assert(ap_conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT);
+ tor_assert(ap_conn->type == CONN_TYPE_AP);
+ tor_assert(ap_conn->state == AP_CONN_STATE_CIRCUIT_WAIT);
tor_assert(ap_conn->socks_request);
- tor_assert(command == SOCKS_COMMAND_RESOLVE ||
- command == SOCKS_COMMAND_RESOLVE_PTR);
- tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_GENERAL);
+ tor_assert(ap_conn->socks_request->command == SOCKS_COMMAND_RESOLVE);
+ tor_assert(circ->purpose == CIRCUIT_PURPOSE_C_GENERAL);
ap_conn->stream_id = get_unique_stream_id_by_circ(circ);
if (ap_conn->stream_id==0) {
connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_RESOURCELIMIT);
+ circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
return -1;
}
- if (command == SOCKS_COMMAND_RESOLVE) {
- string_addr = ap_conn->socks_request->address;
- payload_len = strlen(string_addr)+1;
- tor_assert(payload_len <= RELAY_PAYLOAD_SIZE);
- } else {
- struct in_addr in;
- uint32_t a;
- if (tor_inet_aton(ap_conn->socks_request->address, &in) == 0) {
- connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
- return -1;
- }
- a = ntohl(in.s_addr);
- tor_snprintf(inaddr_buf, sizeof(inaddr_buf), "%d.%d.%d.%d.in-addr.arpa",
- (int)(uint8_t)((a )&0xff),
- (int)(uint8_t)((a>>8 )&0xff),
- (int)(uint8_t)((a>>16)&0xff),
- (int)(uint8_t)((a>>24)&0xff));
- string_addr = inaddr_buf;
- payload_len = strlen(inaddr_buf)+1;
- tor_assert(payload_len <= RELAY_PAYLOAD_SIZE);
- }
+ string_addr = ap_conn->socks_request->address;
+ payload_len = strlen(string_addr)+1;
+ tor_assert(payload_len <= RELAY_PAYLOAD_SIZE);
log_debug(LD_APP,
"Sending relay cell to begin stream %d.", ap_conn->stream_id);
- if (connection_edge_send_command(ap_conn, TO_CIRCUIT(circ),
- RELAY_COMMAND_RESOLVE,
+ if (connection_edge_send_command(ap_conn, circ, RELAY_COMMAND_RESOLVE,
string_addr, payload_len, ap_conn->cpath_layer) < 0)
return -1; /* circuit is closed, don't continue */
- ap_conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT;
+ ap_conn->state = AP_CONN_STATE_RESOLVE_WAIT;
log_info(LD_APP,"Address sent for resolve, ap socket %d, n_circ_id %d",
- ap_conn->_base.s, circ->_base.n_circ_id);
+ ap_conn->s, circ->n_circ_id);
control_event_stream_status(ap_conn, STREAM_EVENT_SENT_RESOLVE);
return 0;
}
@@ -1597,7 +1384,7 @@ int
connection_ap_make_bridge(char *address, uint16_t port)
{
int fd[2];
- edge_connection_t *conn;
+ connection_t *conn;
int err;
log_info(LD_APP,"Making AP bridge to %s:%d ...",safe_str(address),port);
@@ -1609,14 +1396,11 @@ connection_ap_make_bridge(char *address, uint16_t port)
return -1;
}
- tor_assert(fd[0] >= 0);
- tor_assert(fd[1] >= 0);
-
set_socket_nonblocking(fd[0]);
set_socket_nonblocking(fd[1]);
- conn = TO_EDGE_CONN(connection_new(CONN_TYPE_AP));
- conn->_base.s = fd[0];
+ conn = connection_new(CONN_TYPE_AP);
+ conn->s = fd[0];
/* populate conn->socks_request */
@@ -1628,18 +1412,18 @@ connection_ap_make_bridge(char *address, uint16_t port)
conn->socks_request->port = port;
conn->socks_request->command = SOCKS_COMMAND_CONNECT;
- conn->_base.address = tor_strdup("(local bridge)");
- conn->_base.addr = 0;
- conn->_base.port = 0;
+ conn->address = tor_strdup("(local bridge)");
+ conn->addr = 0;
+ conn->port = 0;
- if (connection_add(TO_CONN(conn)) < 0) { /* no space, forget it */
- connection_free(TO_CONN(conn)); /* this closes fd[0] */
+ if (connection_add(conn) < 0) { /* no space, forget it */
+ connection_free(conn); /* this closes fd[0] */
tor_close_socket(fd[1]);
return -1;
}
- conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
- connection_start_reading(TO_CONN(conn));
+ conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
+ connection_start_reading(conn);
/* attaching to a dirty circuit is fine */
if (connection_ap_handshake_attach_circuit(conn) < 0) {
@@ -1653,18 +1437,18 @@ connection_ap_make_bridge(char *address, uint16_t port)
}
/** Send an answer to an AP connection that has requested a DNS lookup
- * via SOCKS. The type should be one of RESOLVED_TYPE_(IPV4|IPV6|HOSTNAME) or
+ * via SOCKS. The type should be one of RESOLVED_TYPE_(IPV4|IPV6) or
* -1 for unreachable; the answer should be in the format specified
* in the socks extensions document.
**/
void
-connection_ap_handshake_socks_resolved(edge_connection_t *conn,
+connection_ap_handshake_socks_resolved(connection_t *conn,
int answer_type,
size_t answer_len,
const char *answer,
int ttl)
{
- char buf[384];
+ char buf[256];
size_t replylen;
if (answer_type == RESOLVED_TYPE_IPV4) {
@@ -1703,14 +1487,6 @@ connection_ap_handshake_socks_resolved(edge_connection_t *conn,
memcpy(buf+4, answer, 16); /* address */
set_uint16(buf+20, 0); /* port == 0. */
replylen = 22;
- } else if (answer_type == RESOLVED_TYPE_HOSTNAME && answer_len < 256) {
- buf[1] = SOCKS5_SUCCEEDED;
- buf[2] = 0; /* reserved */
- buf[3] = 0x03; /* Domainname address type */
- buf[4] = (char)answer_len;
- memcpy(buf+5, answer, answer_len); /* address */
- set_uint16(buf+5+answer_len, 0); /* port == 0. */
- replylen = 5+answer_len+2;
} else {
buf[1] = SOCKS5_HOST_UNREACHABLE;
memset(buf+2, 0, 8);
@@ -1733,10 +1509,9 @@ connection_ap_handshake_socks_resolved(edge_connection_t *conn,
* If <b>reply</b> is undefined, <b>status</b> can't be 0.
*/
void
-connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
+connection_ap_handshake_socks_reply(connection_t *conn, char *reply,
size_t replylen,
- socks5_reply_status_t status)
-{
+ socks5_reply_status_t status) {
char buf[256];
tor_assert(conn->socks_request); /* make sure it's an AP stream */
@@ -1749,7 +1524,7 @@ connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
return;
}
if (replylen) { /* we already have a reply in mind */
- connection_write_to_buf(reply, replylen, TO_CONN(conn));
+ connection_write_to_buf(reply, replylen, conn);
conn->socks_request->has_finished = 1;
return;
}
@@ -1759,7 +1534,7 @@ connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
#define SOCKS4_REJECT 91
buf[1] = (status==SOCKS5_SUCCEEDED ? SOCKS4_GRANTED : SOCKS4_REJECT);
/* leave version, destport, destip zero */
- connection_write_to_buf(buf, SOCKS4_NETWORK_LEN, TO_CONN(conn));
+ connection_write_to_buf(buf, SOCKS4_NETWORK_LEN, conn);
} else if (conn->socks_request->socks_version == 5) {
buf[0] = 5; /* version 5 */
buf[1] = (char)status;
@@ -1767,7 +1542,7 @@ connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
buf[3] = 1; /* ipv4 addr */
memset(buf+4,0,6); /* Set external addr/port to 0.
The spec doesn't seem to say what to do here. -RD */
- connection_write_to_buf(buf,10,TO_CONN(conn));
+ connection_write_to_buf(buf,10,conn);
}
/* If socks_version isn't 4 or 5, don't send anything.
* This can happen in the case of AP bridges. */
@@ -1794,7 +1569,7 @@ connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
int
connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
{
- edge_connection_t *n_stream;
+ connection_t *n_stream;
relay_header_t rh;
char *address=NULL;
uint16_t port;
@@ -1815,19 +1590,16 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
relay_header_unpack(&rh, cell->payload);
if (!memchr(cell->payload+RELAY_HEADER_SIZE, 0, rh.length)) {
- log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
- "Relay begin cell has no \\0. Dropping.");
+ log_warn(LD_PROTOCOL,"relay begin cell has no \\0. Dropping.");
return 0;
}
- if (parse_addr_port(LOG_PROTOCOL_WARN, cell->payload+RELAY_HEADER_SIZE,
- &address,NULL,&port)<0) {
- log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
- "Unable to parse addr:port in relay begin cell. Dropping.");
+ if (parse_addr_port(cell->payload+RELAY_HEADER_SIZE,&address,NULL,&port)<0) {
+ log_warn(LD_PROTOCOL,"Unable to parse addr:port in relay begin cell. "
+ "Dropping.");
return 0;
}
if (port==0) {
- log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
- "Missing port in relay begin cell. Dropping.");
+ log_warn(LD_PROTOCOL,"Missing port in relay begin cell. Dropping.");
tor_free(address);
return 0;
}
@@ -1842,30 +1614,29 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
#endif
log_debug(LD_EXIT,"Creating new exit connection.");
- n_stream = TO_EDGE_CONN(connection_new(CONN_TYPE_EXIT));
- n_stream->_base.purpose = EXIT_PURPOSE_CONNECT;
+ n_stream = connection_new(CONN_TYPE_EXIT);
+ n_stream->purpose = EXIT_PURPOSE_CONNECT;
n_stream->stream_id = rh.stream_id;
- n_stream->_base.port = port;
+ n_stream->port = port;
/* leave n_stream->s at -1, because it's not yet valid */
n_stream->package_window = STREAMWINDOW_START;
n_stream->deliver_window = STREAMWINDOW_START;
if (circ->purpose == CIRCUIT_PURPOSE_S_REND_JOINED) {
- origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
log_debug(LD_REND,"begin is for rendezvous. configuring stream.");
- n_stream->_base.address = tor_strdup("(rendezvous)");
- n_stream->_base.state = EXIT_CONN_STATE_CONNECTING;
- strlcpy(n_stream->rend_query, origin_circ->rend_query,
+ n_stream->address = tor_strdup("(rendezvous)");
+ n_stream->state = EXIT_CONN_STATE_CONNECTING;
+ strlcpy(n_stream->rend_query, circ->rend_query,
sizeof(n_stream->rend_query));
tor_assert(connection_edge_is_rendezvous_stream(n_stream));
assert_circuit_ok(circ);
- if (rend_service_set_connection_addr_port(n_stream, origin_circ) < 0) {
+ if (rend_service_set_connection_addr_port(n_stream, circ) < 0) {
log_info(LD_REND,"Didn't find rendezvous service (port %d)",
- n_stream->_base.port);
+ n_stream->port);
connection_edge_end(n_stream, END_STREAM_REASON_EXITPOLICY,
n_stream->cpath_layer);
- connection_free(TO_CONN(n_stream));
+ connection_free(n_stream);
/* knock the whole thing down, somebody screwed up */
circuit_mark_for_close(circ, END_CIRC_REASON_CONNECTFAILED);
tor_free(address);
@@ -1873,12 +1644,12 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
}
assert_circuit_ok(circ);
log_debug(LD_REND,"Finished assigning addr/port");
- n_stream->cpath_layer = origin_circ->cpath->prev; /* link it */
+ n_stream->cpath_layer = circ->cpath->prev; /* link it */
/* add it into the linked list of n_streams on this circuit */
- n_stream->next_stream = origin_circ->p_streams;
+ n_stream->next_stream = circ->n_streams;
n_stream->on_circuit = circ;
- origin_circ->p_streams = n_stream;
+ circ->n_streams = n_stream;
assert_circuit_ok(circ);
connection_exit_connect(n_stream);
@@ -1886,29 +1657,27 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
return 0;
}
tor_strlower(address);
- n_stream->_base.address = address;
- n_stream->_base.state = EXIT_CONN_STATE_RESOLVEFAILED;
+ n_stream->address = address;
+ n_stream->state = EXIT_CONN_STATE_RESOLVEFAILED;
/* default to failed, change in dns_resolve if it turns out not to fail */
if (we_are_hibernating()) {
connection_edge_end(n_stream, END_STREAM_REASON_HIBERNATING,
n_stream->cpath_layer);
- connection_free(TO_CONN(n_stream));
+ connection_free(n_stream);
return 0;
}
- log_debug(LD_EXIT,"about to start the dns_resolve().");
/* send it off to the gethostbyname farm */
switch (dns_resolve(n_stream)) {
case 1: /* resolve worked */
/* add it into the linked list of n_streams on this circuit */
- n_stream->next_stream = TO_OR_CIRCUIT(circ)->n_streams;
+ n_stream->next_stream = circ->n_streams;
n_stream->on_circuit = circ;
- TO_OR_CIRCUIT(circ)->n_streams = n_stream;
+ circ->n_streams = n_stream;
assert_circuit_ok(circ);
- log_debug(LD_EXIT,"about to call connection_exit_connect().");
connection_exit_connect(n_stream);
return 0;
case -1: /* resolve failed */
@@ -1916,9 +1685,9 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
break;
case 0: /* resolve added to pending list */
/* add it into the linked list of resolving_streams on this circuit */
- n_stream->next_stream = TO_OR_CIRCUIT(circ)->resolving_streams;
+ n_stream->next_stream = circ->resolving_streams;
n_stream->on_circuit = circ;
- TO_OR_CIRCUIT(circ)->resolving_streams = n_stream;
+ circ->resolving_streams = n_stream;
assert_circuit_ok(circ);
;
}
@@ -1930,12 +1699,12 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
* begin resolving the hostname, and (eventually) reply with a RESOLVED cell.
*/
int
-connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ)
+connection_exit_begin_resolve(cell_t *cell, circuit_t *circ)
{
- edge_connection_t *dummy_conn;
+ connection_t *dummy_conn;
relay_header_t rh;
- assert_circuit_ok(TO_CIRCUIT(circ));
+ assert_circuit_ok(circ);
relay_header_unpack(&rh, cell->payload);
/* This 'dummy_conn' only exists to remember the stream ID
@@ -1945,13 +1714,13 @@ connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ)
* resolved; but if we didn't store them in a connection like this,
* the housekeeping in dns.c would get way more complicated.)
*/
- dummy_conn = TO_EDGE_CONN(connection_new(CONN_TYPE_EXIT));
+ dummy_conn = connection_new(CONN_TYPE_EXIT);
dummy_conn->stream_id = rh.stream_id;
- dummy_conn->_base.address = tor_strndup(cell->payload+RELAY_HEADER_SIZE,
- rh.length);
- dummy_conn->_base.port = 0;
- dummy_conn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED;
- dummy_conn->_base.purpose = EXIT_PURPOSE_RESOLVE;
+ dummy_conn->address = tor_strndup(cell->payload+RELAY_HEADER_SIZE,
+ rh.length);
+ dummy_conn->port = 0;
+ dummy_conn->state = EXIT_CONN_STATE_RESOLVEFAILED;
+ dummy_conn->purpose = EXIT_PURPOSE_RESOLVE;
/* send it off to the gethostbyname farm */
switch (dns_resolve(dummy_conn)) {
@@ -1959,14 +1728,14 @@ connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ)
/* Connection freed; don't touch it. */
return 0;
case 1: /* The result was cached; a resolved cell was sent. */
- if (!dummy_conn->_base.marked_for_close)
- connection_free(TO_CONN(dummy_conn));
+ if (!dummy_conn->marked_for_close)
+ connection_free(dummy_conn);
return 0;
case 0: /* resolve added to pending list */
dummy_conn->next_stream = circ->resolving_streams;
- dummy_conn->on_circuit = TO_CIRCUIT(circ);
+ dummy_conn->on_circuit = circ;
circ->resolving_streams = dummy_conn;
- assert_circuit_ok(TO_CIRCUIT(circ));
+ assert_circuit_ok(circ);
break;
}
return 0;
@@ -1980,19 +1749,17 @@ connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ)
* streams must not reveal what IP they connected to.)
*/
void
-connection_exit_connect(edge_connection_t *edge_conn)
+connection_exit_connect(connection_t *conn)
{
uint32_t addr;
uint16_t port;
- connection_t *conn = TO_CONN(edge_conn);
- if (!connection_edge_is_rendezvous_stream(edge_conn) &&
- router_compare_to_my_exit_policy(edge_conn)) {
+ if (!connection_edge_is_rendezvous_stream(conn) &&
+ router_compare_to_my_exit_policy(conn)) {
log_info(LD_EXIT,"%s:%d failed exit policy. Closing.",
escaped_safe_str(conn->address), conn->port);
- connection_edge_end(edge_conn, END_STREAM_REASON_EXITPOLICY,
- edge_conn->cpath_layer);
- circuit_detach_stream(circuit_get_by_edge_conn(edge_conn), edge_conn);
+ connection_edge_end(conn, END_STREAM_REASON_EXITPOLICY, conn->cpath_layer);
+ circuit_detach_stream(circuit_get_by_edge_conn(conn), conn);
connection_free(conn);
return;
}
@@ -2023,8 +1790,8 @@ connection_exit_connect(edge_connection_t *edge_conn)
log_debug(LD_EXIT,"about to try connecting");
switch (connection_connect(conn, conn->address, addr, port)) {
case -1:
- connection_edge_end_errno(edge_conn, edge_conn->cpath_layer);
- circuit_detach_stream(circuit_get_by_edge_conn(edge_conn), edge_conn);
+ connection_edge_end_errno(conn, conn->cpath_layer);
+ circuit_detach_stream(circuit_get_by_edge_conn(conn), conn);
connection_free(conn);
return;
case 0:
@@ -2046,23 +1813,20 @@ connection_exit_connect(edge_connection_t *edge_conn)
connection_watch_events(conn, EV_READ);
/* also, deliver a 'connected' cell back through the circuit. */
- if (connection_edge_is_rendezvous_stream(edge_conn)) {
- /* rendezvous stream */
+ if (connection_edge_is_rendezvous_stream(conn)) { /* rendezvous stream */
/* don't send an address back! */
- connection_edge_send_command(edge_conn,
- circuit_get_by_edge_conn(edge_conn),
+ connection_edge_send_command(conn, circuit_get_by_edge_conn(conn),
RELAY_COMMAND_CONNECTED,
- NULL, 0, edge_conn->cpath_layer);
+ NULL, 0, conn->cpath_layer);
} else { /* normal stream */
/* This must be the original address, not the redirected address. */
char connected_payload[8];
set_uint32(connected_payload, htonl(conn->addr));
set_uint32(connected_payload+4,
- htonl(dns_clip_ttl(edge_conn->address_ttl)));
- connection_edge_send_command(edge_conn,
- circuit_get_by_edge_conn(edge_conn),
+ htonl(MAX_DNS_ENTRY_AGE)); /* XXXX fill with a real TTL */
+ connection_edge_send_command(conn, circuit_get_by_edge_conn(conn),
RELAY_COMMAND_CONNECTED,
- connected_payload, 8, edge_conn->cpath_layer);
+ connected_payload, 8, conn->cpath_layer);
}
}
@@ -2070,7 +1834,7 @@ connection_exit_connect(edge_connection_t *edge_conn)
* it is a general stream.
*/
int
-connection_edge_is_rendezvous_stream(edge_connection_t *conn)
+connection_edge_is_rendezvous_stream(connection_t *conn)
{
tor_assert(conn);
if (*conn->rend_query) /* XXX */
@@ -2084,10 +1848,10 @@ connection_edge_is_rendezvous_stream(edge_connection_t *conn)
* resolved.)
*/
int
-connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit)
+connection_ap_can_use_exit(connection_t *conn, routerinfo_t *exit)
{
tor_assert(conn);
- tor_assert(conn->_base.type == CONN_TYPE_AP);
+ tor_assert(conn->type == CONN_TYPE_AP);
tor_assert(conn->socks_request);
tor_assert(exit);
@@ -2103,13 +1867,13 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit)
if (conn->chosen_exit_name) {
if (router_get_by_nickname(conn->chosen_exit_name, 1) != exit) {
/* doesn't match */
-// log_debug(LD_APP,"Requested node '%s', considering node '%s'. No.",
-// conn->chosen_exit_name, exit->nickname);
+ log_debug(LD_APP,"Requested node '%s', considering node '%s'. No.",
+ conn->chosen_exit_name, exit->nickname);
return 0;
}
}
- if (conn->socks_request->command == SOCKS_COMMAND_CONNECT) {
+ if (conn->socks_request->command != SOCKS_COMMAND_RESOLVE) {
struct in_addr in;
uint32_t addr = 0;
addr_policy_result_t r;
@@ -2119,16 +1883,6 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit)
exit->exit_policy);
if (r == ADDR_POLICY_REJECTED || r == ADDR_POLICY_PROBABLY_REJECTED)
return 0;
- } else { /* Some kind of a resolve. */
-
- /* Can't support reverse lookups without eventdns. */
- if (conn->socks_request->command == SOCKS_COMMAND_RESOLVE_PTR &&
- exit->has_old_dnsworkers)
- return 0;
-
- /* Don't send DNS requests to non-exit servers by default. */
- if (policy_is_reject_star(exit->exit_policy))
- return 0;
}
return 1;
}
@@ -2163,14 +1917,14 @@ parse_extended_hostname(char *address)
s = strrchr(address,'.');
if (!s) return 0; /* no dot, thus normal */
if (!strcmp(s+1,"exit")) {
- *s = 0; /* nul-terminate it */
+ *s = 0; /* null-terminate it */
return EXIT_HOSTNAME; /* .exit */
}
if (strcmp(s+1,"onion"))
return NORMAL_HOSTNAME; /* neither .exit nor .onion, thus normal */
/* so it is .onion */
- *s = 0; /* nul-terminate it */
+ *s = 0; /* null-terminate it */
if (strlcpy(query, address, REND_SERVICE_ID_LEN+1) >=
REND_SERVICE_ID_LEN+1)
goto failed;
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index 76c2abbf13..6d1a151d3c 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -19,23 +19,24 @@ const char connection_or_c_id[] =
#define TIGHT_CERT_ALLOW_SKEW (90*60)
-static int connection_tls_finish_handshake(or_connection_t *conn);
-static int connection_or_process_cells_from_inbuf(or_connection_t *conn);
+static int connection_tls_finish_handshake(connection_t *conn);
+static int connection_or_process_cells_from_inbuf(connection_t *conn);
/**************************************************************/
/** Map from identity digest of connected OR or desired OR to a connection_t
* with that identity digest. If there is more than one such connection_t,
- * they form a linked list, with next_with_same_id as the next pointer. */
+ * they form a linked list, with next_with_same_id as the next pointer.*/
static digestmap_t *orconn_identity_map = NULL;
/** If conn is listed in orconn_identity_map, remove it, and clear
* conn->identity_digest. */
void
-connection_or_remove_from_identity_map(or_connection_t *conn)
+connection_or_remove_from_identity_map(connection_t *conn)
{
- or_connection_t *tmp;
+ connection_t *tmp;
tor_assert(conn);
+ tor_assert(conn->type == CONN_TYPE_OR);
if (!orconn_identity_map)
return;
tmp = digestmap_get(orconn_identity_map, conn->identity_digest);
@@ -72,9 +73,8 @@ connection_or_clear_identity_map(void)
for (i = 0; i < n; ++i) {
connection_t* conn = carray[i];
if (conn->type == CONN_TYPE_OR) {
- or_connection_t *or_conn = TO_OR_CONN(conn);
- memset(or_conn->identity_digest, 0, DIGEST_LEN);
- or_conn->next_with_same_id = NULL;
+ memset(conn->identity_digest, 0, DIGEST_LEN);
+ conn->next_with_same_id = NULL;
}
}
@@ -87,10 +87,11 @@ connection_or_clear_identity_map(void)
/** Change conn->identity_digest to digest, and add conn into
* orconn_digest_map. */
static void
-connection_or_set_identity_digest(or_connection_t *conn, const char *digest)
+connection_or_set_identity_digest(connection_t *conn, const char *digest)
{
- or_connection_t *tmp;
+ connection_t *tmp;
tor_assert(conn);
+ tor_assert(conn->type == CONN_TYPE_OR);
tor_assert(digest);
if (!orconn_identity_map)
@@ -135,10 +136,10 @@ cell_unpack(cell_t *dest, const char *src)
}
int
-connection_or_reached_eof(or_connection_t *conn)
+connection_or_reached_eof(connection_t *conn)
{
log_info(LD_OR,"OR connection reached EOF. Closing.");
- connection_mark_for_close(TO_CONN(conn));
+ connection_mark_for_close(conn);
return 0;
}
@@ -148,14 +149,13 @@ connection_or_reached_eof(or_connection_t *conn)
* and hope for better luck next time.
*/
static int
-connection_or_read_proxy_response(or_connection_t *or_conn)
+connection_or_read_proxy_response(connection_t *conn)
{
char *headers;
char *reason=NULL;
int status_code;
time_t date_header;
int compression;
- connection_t *conn = TO_CONN(or_conn);
switch (fetch_from_buf_http(conn->inbuf,
&headers, MAX_HEADERS_SIZE,
@@ -185,7 +185,7 @@ connection_or_read_proxy_response(or_connection_t *or_conn)
"HTTPS connect to '%s' successful! (200 %s) Starting TLS.",
conn->address, escaped(reason));
tor_free(reason);
- if (connection_tls_start_handshake(or_conn, 0) < 0) {
+ if (connection_tls_start_handshake(conn, 0) < 0) {
/* TLS handshaking error of some kind. */
connection_mark_for_close(conn);
@@ -209,11 +209,12 @@ connection_or_read_proxy_response(or_connection_t *or_conn)
* (else do nothing).
*/
int
-connection_or_process_inbuf(or_connection_t *conn)
+connection_or_process_inbuf(connection_t *conn)
{
tor_assert(conn);
+ tor_assert(conn->type == CONN_TYPE_OR);
- switch (conn->_base.state) {
+ switch (conn->state) {
case OR_CONN_STATE_PROXY_READING:
return connection_or_read_proxy_response(conn);
case OR_CONN_STATE_OPEN:
@@ -232,22 +233,24 @@ connection_or_process_inbuf(or_connection_t *conn)
* return 0.
*/
int
-connection_or_finished_flushing(or_connection_t *conn)
+connection_or_finished_flushing(connection_t *conn)
{
tor_assert(conn);
- assert_connection_ok(TO_CONN(conn),0);
+ tor_assert(conn->type == CONN_TYPE_OR);
+
+ assert_connection_ok(conn,0);
- switch (conn->_base.state) {
+ switch (conn->state) {
case OR_CONN_STATE_PROXY_FLUSHING:
log_debug(LD_OR,"finished sending CONNECT to proxy.");
- conn->_base.state = OR_CONN_STATE_PROXY_READING;
- connection_stop_writing(TO_CONN(conn));
+ conn->state = OR_CONN_STATE_PROXY_READING;
+ connection_stop_writing(conn);
break;
case OR_CONN_STATE_OPEN:
- connection_stop_writing(TO_CONN(conn));
+ connection_stop_writing(conn);
break;
default:
- log_err(LD_BUG,"BUG: called in unexpected state %d.", conn->_base.state);
+ log_err(LD_BUG,"BUG: called in unexpected state %d.", conn->state);
tor_fragile_assert();
return -1;
}
@@ -257,11 +260,10 @@ connection_or_finished_flushing(or_connection_t *conn)
/** Connected handler for OR connections: begin the TLS handshake.
*/
int
-connection_or_finished_connecting(or_connection_t *or_conn)
+connection_or_finished_connecting(connection_t *conn)
{
- connection_t *conn;
- tor_assert(or_conn);
- conn = TO_CONN(or_conn);
+ tor_assert(conn);
+ tor_assert(conn->type == CONN_TYPE_OR);
tor_assert(conn->state == OR_CONN_STATE_CONNECTING);
log_debug(LD_OR,"OR connect() to router at %s:%u finished.",
@@ -296,7 +298,7 @@ connection_or_finished_connecting(or_connection_t *or_conn)
return 0;
}
- if (connection_tls_start_handshake(or_conn, 0) < 0) {
+ if (connection_tls_start_handshake(conn, 0) < 0) {
/* TLS handshaking error of some kind. */
connection_mark_for_close(conn);
return -1;
@@ -304,49 +306,63 @@ connection_or_finished_connecting(or_connection_t *or_conn)
return 0;
}
+/** Initialize <b>conn</b> to include all the relevant data from <b>router</b>.
+ * This function is called either from connection_or_connect(), if
+ * we initiated the connect, or from connection_tls_finish_handshake()
+ * if the other side initiated it.
+ */
+static void
+connection_or_init_conn_from_router(connection_t *conn, routerinfo_t *router,
+ int started_here)
+{
+ or_options_t *options = get_options();
+
+ if (!started_here) {
+ conn->addr = router->addr;
+ conn->port = router->or_port;
+ }
+ conn->receiver_bucket = conn->bandwidth = (int)options->BandwidthBurst;
+ conn->identity_pkey = crypto_pk_dup_key(router->identity_pkey);
+ connection_or_set_identity_digest(conn, router->cache_info.identity_digest);
+ conn->nickname = tor_strdup(router->nickname);
+ tor_free(conn->address);
+ conn->address = tor_strdup(router->address);
+}
+
/** If we don't necessarily know the router we're connecting to, but we
* have an addr/port/id_digest, then fill in as much as we can. Start
* by checking to see if this describes a router we know. */
static void
-connection_or_init_conn_from_address(or_connection_t *conn,
+connection_or_init_conn_from_address(connection_t *conn,
uint32_t addr, uint16_t port,
const char *id_digest,
int started_here)
{
+ const char *n;
or_options_t *options = get_options();
routerinfo_t *r = router_get_by_digest(id_digest);
- conn->bandwidthrate = (int)options->BandwidthRate;
- conn->receiver_bucket = conn->bandwidthburst = (int)options->BandwidthBurst;
- connection_or_set_identity_digest(conn, id_digest);
- conn->_base.addr = addr;
- conn->_base.port = port;
+ conn->addr = addr;
+ conn->port = port;
if (r) {
- if (!started_here) {
- /* Override the addr/port, so our log messages will make sense.
- * This is dangerous, since if we ever try looking up a conn by
- * its actual addr/port, we won't remember. Careful! */
- conn->_base.addr = r->addr;
- conn->_base.port = r->or_port;
- }
- conn->nickname = tor_strdup(r->nickname);
- tor_free(conn->_base.address);
- conn->_base.address = tor_strdup(r->address);
+ connection_or_init_conn_from_router(conn, r, started_here);
+ return;
+ }
+ /* This next part isn't really right, but it's good enough for now. */
+ conn->receiver_bucket = conn->bandwidth = (int)options->BandwidthBurst;
+ connection_or_set_identity_digest(conn, id_digest);
+ /* If we're an authoritative directory server, we may know a
+ * nickname for this router. */
+ n = dirserv_get_nickname_by_digest(id_digest);
+ if (n) {
+ conn->nickname = tor_strdup(n);
} else {
- const char *n;
- /* If we're an authoritative directory server, we may know a
- * nickname for this router. */
- n = dirserv_get_nickname_by_digest(id_digest);
- if (n) {
- conn->nickname = tor_strdup(n);
- } else {
- conn->nickname = tor_malloc(HEX_DIGEST_LEN+2);
- conn->nickname[0] = '$';
- base16_encode(conn->nickname+1, HEX_DIGEST_LEN+1,
- conn->identity_digest, DIGEST_LEN);
- }
- tor_free(conn->_base.address);
- conn->_base.address = tor_dup_addr(addr);
+ conn->nickname = tor_malloc(HEX_DIGEST_LEN+2);
+ conn->nickname[0] = '$';
+ base16_encode(conn->nickname+1, HEX_DIGEST_LEN+1,
+ conn->identity_digest, DIGEST_LEN);
}
+ tor_free(conn->address);
+ conn->address = tor_dup_addr(addr);
}
/** Return the best connection of type OR with the
@@ -358,11 +374,11 @@ connection_or_init_conn_from_address(or_connection_t *conn,
* 4) Then if there are any non-empty conns, ignore empty conns.
* 5) Of the remaining conns, prefer newer conns.
*/
-or_connection_t *
+connection_t *
connection_or_get_by_identity_digest(const char *digest)
{
int newer;
- or_connection_t *conn, *best=NULL;
+ connection_t *conn, *best=NULL;
if (!orconn_identity_map)
return NULL;
@@ -370,26 +386,26 @@ connection_or_get_by_identity_digest(const char *digest)
conn = digestmap_get(orconn_identity_map, digest);
for (; conn; conn = conn->next_with_same_id) {
- tor_assert(conn->_base.magic == OR_CONNECTION_MAGIC);
- tor_assert(conn->_base.type == CONN_TYPE_OR);
+ tor_assert(conn->magic == CONNECTION_MAGIC);
+ tor_assert(conn->type == CONN_TYPE_OR);
tor_assert(!memcmp(conn->identity_digest, digest, DIGEST_LEN));
- if (conn->_base.marked_for_close)
+ if (conn->marked_for_close)
continue;
if (!best) {
best = conn; /* whatever it is, it's better than nothing. */
continue;
}
- if (best->_base.state == OR_CONN_STATE_OPEN &&
- conn->_base.state != OR_CONN_STATE_OPEN)
+ if (best->state == OR_CONN_STATE_OPEN &&
+ conn->state != OR_CONN_STATE_OPEN)
continue; /* avoid non-open conns if we can */
- newer = best->_base.timestamp_created < conn->_base.timestamp_created;
+ newer = best->timestamp_created < conn->timestamp_created;
- if (!best->_base.or_is_obsolete && conn->_base.or_is_obsolete)
+ if (!best->is_obsolete && conn->is_obsolete)
continue; /* We never prefer obsolete over non-obsolete connections. */
if (
/* We prefer non-obsolete connections: */
- (best->_base.or_is_obsolete && !conn->_base.or_is_obsolete) ||
+ (best->is_obsolete && !conn->is_obsolete) ||
/* If both have circuits we prefer the newer: */
(best->n_circuits && conn->n_circuits && newer) ||
/* If neither has circuits we prefer the newer: */
@@ -416,24 +432,26 @@ connection_or_get_by_identity_digest(const char *digest)
*
* Return the launched conn, or NULL if it failed.
*/
-or_connection_t *
+connection_t *
connection_or_connect(uint32_t addr, uint16_t port, const char *id_digest)
{
- or_connection_t *conn;
+ connection_t *conn;
+ routerinfo_t *me;
or_options_t *options = get_options();
tor_assert(id_digest);
- if (server_mode(options) && router_digest_is_me(id_digest)) {
+ if (server_mode(options) && (me=router_get_my_routerinfo()) &&
+ router_digest_is_me(id_digest)) {
log_info(LD_PROTOCOL,"Client asked me to connect to myself. Refusing.");
return NULL;
}
- conn = TO_OR_CONN(connection_new(CONN_TYPE_OR));
+ conn = connection_new(CONN_TYPE_OR);
/* set up conn so it's got all the data we need to remember */
connection_or_init_conn_from_address(conn, addr, port, id_digest, 1);
- conn->_base.state = OR_CONN_STATE_CONNECTING;
+ conn->state = OR_CONN_STATE_CONNECTING;
control_event_or_conn_status(conn, OR_CONN_EVENT_LAUNCHED);
if (options->HttpsProxy) {
@@ -442,7 +460,7 @@ connection_or_connect(uint32_t addr, uint16_t port, const char *id_digest)
port = options->HttpsProxyPort;
}
- switch (connection_connect(TO_CONN(conn), conn->_base.address, addr, port)) {
+ switch (connection_connect(conn, conn->address, addr, port)) {
case -1:
/* If the connection failed immediately, and we're using
* an https proxy, our https proxy is down. Don't blame the
@@ -452,10 +470,10 @@ connection_or_connect(uint32_t addr, uint16_t port, const char *id_digest)
router_set_status(conn->identity_digest, 0);
}
control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED);
- connection_free(TO_CONN(conn));
+ connection_free(conn);
return NULL;
case 0:
- connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
+ connection_watch_events(conn, EV_READ | EV_WRITE);
/* writable indicates finish, readable indicates broken link,
error indicates broken link on windows */
return conn;
@@ -478,16 +496,16 @@ connection_or_connect(uint32_t addr, uint16_t port, const char *id_digest)
* Return -1 if <b>conn</b> is broken, else return 0.
*/
int
-connection_tls_start_handshake(or_connection_t *conn, int receiving)
+connection_tls_start_handshake(connection_t *conn, int receiving)
{
- conn->_base.state = OR_CONN_STATE_HANDSHAKING;
- conn->tls = tor_tls_new(conn->_base.s, receiving);
+ conn->state = OR_CONN_STATE_HANDSHAKING;
+ conn->tls = tor_tls_new(conn->s, receiving, 0);
if (!conn->tls) {
log_warn(LD_BUG,"tor_tls_new failed. Closing.");
return -1;
}
- connection_start_reading(TO_CONN(conn));
- log_debug(LD_OR,"starting TLS handshake on fd %d", conn->_base.s);
+ connection_start_reading(conn);
+ log_debug(LD_OR,"starting TLS handshake on fd %d", conn->s);
if (connection_tls_continue_handshake(conn) < 0) {
return -1;
}
@@ -500,7 +518,7 @@ connection_tls_start_handshake(or_connection_t *conn, int receiving)
* Return -1 if <b>conn</b> is broken, else return 0.
*/
int
-connection_tls_continue_handshake(or_connection_t *conn)
+connection_tls_continue_handshake(connection_t *conn)
{
check_no_tls_errors();
switch (tor_tls_handshake(conn->tls)) {
@@ -511,7 +529,7 @@ connection_tls_continue_handshake(or_connection_t *conn)
case TOR_TLS_DONE:
return connection_tls_finish_handshake(conn);
case TOR_TLS_WANTWRITE:
- connection_start_writing(TO_CONN(conn));
+ connection_start_writing(conn);
log_debug(LD_OR,"wanted write");
return 0;
case TOR_TLS_WANTREAD: /* handshaking conns are *always* reading */
@@ -529,12 +547,14 @@ connection_tls_continue_handshake(or_connection_t *conn)
* one day so we're clearer.
*/
int
-connection_or_nonopen_was_started_here(or_connection_t *conn)
+connection_or_nonopen_was_started_here(connection_t *conn)
{
- tor_assert(conn->_base.type == CONN_TYPE_OR);
- if (!conn->tls)
- return 1; /* it's still in proxy states or something */
- return !tor_tls_is_server(conn->tls);
+ tor_assert(conn->type == CONN_TYPE_OR);
+
+ if (tor_digest_is_zero(conn->identity_digest))
+ return 0;
+ else
+ return 1;
}
/** Conn just completed its handshake. Return 0 if all is well, and
@@ -549,13 +569,13 @@ connection_or_nonopen_was_started_here(or_connection_t *conn)
* buffer is undefined.)
*
* As side effects,
- * 1) Set conn->circ_id_type according to tor-spec.txt.
+ * 1) Set conn->circ_id_type according to tor-spec.txt
* 2) If we're an authdirserver and we initiated the connection: drop all
* descriptors that claim to be on that IP/port but that aren't
* this guy; and note that this guy is reachable.
*/
static int
-connection_or_check_valid_handshake(or_connection_t *conn, char *digest_rcvd)
+connection_or_check_valid_handshake(connection_t *conn, char *digest_rcvd)
{
routerinfo_t *router;
crypto_pk_env_t *identity_rcvd=NULL;
@@ -566,7 +586,7 @@ connection_or_check_valid_handshake(or_connection_t *conn, char *digest_rcvd)
check_no_tls_errors();
if (! tor_tls_peer_has_cert(conn->tls)) {
log_info(LD_PROTOCOL,"Peer (%s:%d) didn't send a cert! Closing.",
- conn->_base.address, conn->_base.port);
+ conn->address, conn->port);
return -1;
}
check_no_tls_errors();
@@ -574,17 +594,17 @@ connection_or_check_valid_handshake(or_connection_t *conn, char *digest_rcvd)
sizeof(nickname))) {
log_fn(severity,LD_PROTOCOL,"Other side (%s:%d) has a cert without a "
"valid nickname. Closing.",
- conn->_base.address, conn->_base.port);
+ conn->address, conn->port);
return -1;
}
check_no_tls_errors();
log_debug(LD_OR, "Other side (%s:%d) claims to be router '%s'",
- conn->_base.address, conn->_base.port, nickname);
+ conn->address, conn->port, nickname);
if (tor_tls_verify(severity, conn->tls, &identity_rcvd) < 0) {
log_fn(severity,LD_OR,"Other side, which claims to be router '%s' (%s:%d),"
" has a cert but it's invalid. Closing.",
- nickname, conn->_base.address, conn->_base.port);
+ nickname, conn->address, conn->port);
return -1;
}
check_no_tls_errors();
@@ -605,7 +625,7 @@ connection_or_check_valid_handshake(or_connection_t *conn, char *digest_rcvd)
log_fn(severity, LD_OR,
"Identity key not as expected for router claiming to be "
"'%s' (%s:%d)",
- nickname, conn->_base.address, conn->_base.port);
+ nickname, conn->address, conn->port);
return -1;
}
@@ -621,7 +641,7 @@ connection_or_check_valid_handshake(or_connection_t *conn, char *digest_rcvd)
log_fn(severity, LD_OR,
"Identity key not as expected for router at %s:%d: wanted %s "
"but got %s",
- conn->_base.address, conn->_base.port, expected, seen);
+ conn->address, conn->port, expected, seen);
entry_guard_set_status(conn->identity_digest, 0);
router_set_status(conn->identity_digest, 0);
control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED);
@@ -631,7 +651,7 @@ connection_or_check_valid_handshake(or_connection_t *conn, char *digest_rcvd)
/* We initiated this connection to address:port. Drop all routers
* with the same address:port and a different key or nickname.
*/
- dirserv_orconn_tls_done(conn->_base.address, conn->_base.port,
+ dirserv_orconn_tls_done(conn->address, conn->port,
digest_rcvd, nickname, as_advertised);
}
if (!as_advertised)
@@ -647,12 +667,14 @@ connection_or_check_valid_handshake(or_connection_t *conn, char *digest_rcvd)
* If he initiated the connection, make sure he's not already connected,
* then initialize conn from the information in router.
*
+ * If I'm not a server, set bandwidth to the default OP bandwidth.
+ *
* If all is successful, call circuit_n_conn_done() to handle events
* that have been pending on the tls handshake completion. Also set the
* directory to be dirty (only matters if I'm an authdirserver).
*/
static int
-connection_tls_finish_handshake(or_connection_t *conn)
+connection_tls_finish_handshake(connection_t *conn)
{
char digest_rcvd[DIGEST_LEN];
int started_here = connection_or_nonopen_was_started_here(conn);
@@ -662,9 +684,17 @@ connection_tls_finish_handshake(or_connection_t *conn)
return -1;
if (!started_here) {
- connection_or_init_conn_from_address(conn,conn->_base.addr,
- conn->_base.port, digest_rcvd, 0);
-
+#if 0
+ connection_t *c;
+ if ((c=connection_or_get_by_identity_digest(digest_rcvd))) {
+ log_debug(LD_OR,
+ "Router '%s' is already connected on fd %d. Dropping fd %d.",
+ c->nickname, c->s, conn->s);
+ return -1;
+ }
+#endif
+ connection_or_init_conn_from_address(conn,conn->addr,conn->port,
+ digest_rcvd, 0);
/* Annotate that we received a TLS connection.
* (Todo: only actually consider ourselves reachable if there
* exists a testing circuit using conn.)
@@ -675,12 +705,16 @@ connection_tls_finish_handshake(or_connection_t *conn)
* The reason this bandaid is here is because there's a bug in
* Tor 0.1.1.x where middle hops don't always send their create
* cell; so some servers rarely find themselves reachable. */
-// if (!is_local_IP(conn->_base.addr))
+// if (!is_local_IP(conn->addr))
// router_orport_found_reachable();
}
+ if (!server_mode(get_options())) { /* If I'm an OP... */
+ conn->receiver_bucket = conn->bandwidth = DEFAULT_BANDWIDTH_OP;
+ }
+
directory_set_dirty();
- conn->_base.state = OR_CONN_STATE_OPEN;
+ conn->state = OR_CONN_STATE_OPEN;
control_event_or_conn_status(conn, OR_CONN_EVENT_CONNECTED);
if (started_here) {
rep_hist_note_connect_succeeded(conn->identity_digest, time(NULL));
@@ -690,7 +724,7 @@ connection_tls_finish_handshake(or_connection_t *conn)
}
router_set_status(conn->identity_digest, 1);
}
- connection_watch_events(TO_CONN(conn), EV_READ);
+ connection_watch_events(conn, EV_READ);
circuit_n_conn_done(conn, 1); /* send the pending creates, if any. */
return 0;
}
@@ -702,17 +736,18 @@ connection_tls_finish_handshake(or_connection_t *conn)
* ready, then try to flush the record now.
*/
void
-connection_or_write_cell_to_buf(const cell_t *cell, or_connection_t *conn)
+connection_or_write_cell_to_buf(const cell_t *cell, connection_t *conn)
{
char networkcell[CELL_NETWORK_SIZE];
char *n = networkcell;
tor_assert(cell);
tor_assert(conn);
+ tor_assert(connection_speaks_cells(conn));
cell_pack(n, cell);
- connection_write_to_buf(n, CELL_NETWORK_SIZE, TO_CONN(conn));
+ connection_write_to_buf(n, CELL_NETWORK_SIZE, conn);
#define MIN_TLS_FLUSHLEN 15872
/* openssl tls record size is 16383, this is close. The goal here is to
@@ -720,28 +755,26 @@ connection_or_write_cell_to_buf(const cell_t *cell, or_connection_t *conn)
* during periods of high load we won't read the entire megabyte from
* input before pushing any data out. It also has the feature of not
* growing huge outbufs unless something is slow. */
- if (conn->_base.outbuf_flushlen-CELL_NETWORK_SIZE < MIN_TLS_FLUSHLEN &&
- conn->_base.outbuf_flushlen >= MIN_TLS_FLUSHLEN) {
- int extra = conn->_base.outbuf_flushlen - MIN_TLS_FLUSHLEN;
- conn->_base.outbuf_flushlen = MIN_TLS_FLUSHLEN;
- if (connection_handle_write(TO_CONN(conn)) < 0) {
- if (!conn->_base.marked_for_close) {
+ if (conn->outbuf_flushlen-CELL_NETWORK_SIZE < MIN_TLS_FLUSHLEN &&
+ conn->outbuf_flushlen >= MIN_TLS_FLUSHLEN) {
+ int extra = conn->outbuf_flushlen - MIN_TLS_FLUSHLEN;
+ conn->outbuf_flushlen = MIN_TLS_FLUSHLEN;
+ if (connection_handle_write(conn) < 0) {
+ if (!conn->marked_for_close) {
/* this connection is broken. remove it. */
log_warn(LD_BUG,
"Bug: unhandled error on write for OR conn (fd %d); removing",
- conn->_base.s);
+ conn->s);
tor_fragile_assert();
- // XXX This was supposed to be edge-only!
- // conn->has_sent_end = 1; /* don't cry wolf about duplicate close */
-
+ conn->has_sent_end = 1; /* don't cry wolf about duplicate close */
/* XXX do we need a close-immediate here, so we don't try to flush? */
- connection_mark_for_close(TO_CONN(conn));
+ connection_mark_for_close(conn);
}
return;
}
if (extra) {
- conn->_base.outbuf_flushlen += extra;
- connection_start_writing(TO_CONN(conn));
+ conn->outbuf_flushlen += extra;
+ connection_start_writing(conn);
}
}
}
@@ -754,7 +787,7 @@ connection_or_write_cell_to_buf(const cell_t *cell, or_connection_t *conn)
* Always return 0.
*/
static int
-connection_or_process_cells_from_inbuf(or_connection_t *conn)
+connection_or_process_cells_from_inbuf(connection_t *conn)
{
char buf[CELL_NETWORK_SIZE];
cell_t cell;
@@ -762,13 +795,13 @@ connection_or_process_cells_from_inbuf(or_connection_t *conn)
loop:
log_debug(LD_OR,
"%d: starting, inbuf_datalen %d (%d pending in tls object).",
- conn->_base.s,(int)buf_datalen(conn->_base.inbuf),
+ conn->s,(int)buf_datalen(conn->inbuf),
tor_tls_get_pending_bytes(conn->tls));
- if (buf_datalen(conn->_base.inbuf) < CELL_NETWORK_SIZE) /* whole response
- available? */
+ if (buf_datalen(conn->inbuf) < CELL_NETWORK_SIZE) /* whole response
+ available? */
return 0; /* not yet */
- connection_fetch_from_buf(buf, CELL_NETWORK_SIZE, TO_CONN(conn));
+ connection_fetch_from_buf(buf, CELL_NETWORK_SIZE, conn);
/* retrieve cell info from buf (create the host-order struct from the
* network-order string) */
@@ -786,11 +819,12 @@ loop:
* Return 0.
*/
int
-connection_or_send_destroy(uint16_t circ_id, or_connection_t *conn, int reason)
+connection_or_send_destroy(uint16_t circ_id, connection_t *conn, int reason)
{
cell_t cell;
tor_assert(conn);
+ tor_assert(connection_speaks_cells(conn));
memset(&cell, 0, sizeof(cell_t));
cell.circ_id = circ_id;
diff --git a/src/or/control.c b/src/or/control.c
index b67cd1ce7c..55b4fc01bb 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -131,64 +131,57 @@ static int disable_log_messages = 0;
static int authentication_cookie_is_set = 0;
static char authentication_cookie[AUTHENTICATION_COOKIE_LEN];
-static void connection_printf_to_buf(control_connection_t *conn,
+static void connection_printf_to_buf(connection_t *conn,
const char *format, ...)
CHECK_PRINTF(2,3);
/*static*/ size_t write_escaped_data(const char *data, size_t len,
int translate_newlines, char **out);
/*static*/ size_t read_escaped_data(const char *data, size_t len,
int translate_newlines, char **out);
-static void send_control0_message(control_connection_t *conn, uint16_t type,
+static void send_control0_message(connection_t *conn, uint16_t type,
uint32_t len, const char *body);
-static void send_control_done(control_connection_t *conn);
-static void send_control_done2(control_connection_t *conn, const char *msg,
+static void send_control_done(connection_t *conn);
+static void send_control_done2(connection_t *conn, const char *msg,
size_t len);
-static void send_control0_error(control_connection_t *conn, uint16_t error,
+static void send_control0_error(connection_t *conn, uint16_t error,
const char *message);
static void send_control0_event(uint16_t event, uint32_t len,
const char *body);
static void send_control1_event(uint16_t event, const char *format, ...)
CHECK_PRINTF(2,3);
-static int handle_control_setconf(control_connection_t *conn, uint32_t len,
+static int handle_control_setconf(connection_t *conn, uint32_t len,
char *body);
-static int handle_control_resetconf(control_connection_t *conn, uint32_t len,
+static int handle_control_resetconf(connection_t *conn, uint32_t len,
char *body);
-static int handle_control_getconf(control_connection_t *conn, uint32_t len,
+static int handle_control_getconf(connection_t *conn, uint32_t len,
const char *body);
-static int handle_control_setevents(control_connection_t *conn, uint32_t len,
+static int handle_control_setevents(connection_t *conn, uint32_t len,
const char *body);
-static int handle_control_authenticate(control_connection_t *conn,
- uint32_t len,
+static int handle_control_authenticate(connection_t *conn, uint32_t len,
const char *body);
-static int handle_control_saveconf(control_connection_t *conn, uint32_t len,
+static int handle_control_saveconf(connection_t *conn, uint32_t len,
const char *body);
-static int handle_control_signal(control_connection_t *conn, uint32_t len,
+static int handle_control_signal(connection_t *conn, uint32_t len,
const char *body);
-static int handle_control_mapaddress(control_connection_t *conn, uint32_t len,
+static int handle_control_mapaddress(connection_t *conn, uint32_t len,
const char *body);
-static int handle_control_getinfo(control_connection_t *conn, uint32_t len,
+static int handle_control_getinfo(connection_t *conn, uint32_t len,
const char *body);
-static int handle_control_extendcircuit(control_connection_t *conn,
- uint32_t len,
+static int handle_control_extendcircuit(connection_t *conn, uint32_t len,
const char *body);
-static int handle_control_setpurpose(control_connection_t *conn,
- int for_circuits,
+static int handle_control_setpurpose(connection_t *conn, int for_circuits,
uint32_t len, const char *body);
-static int handle_control_attachstream(control_connection_t *conn,
- uint32_t len,
+static int handle_control_attachstream(connection_t *conn, uint32_t len,
const char *body);
-static int handle_control_postdescriptor(control_connection_t *conn,
- uint32_t len,
+static int handle_control_postdescriptor(connection_t *conn, uint32_t len,
const char *body);
-static int handle_control_redirectstream(control_connection_t *conn,
- uint32_t len,
+static int handle_control_redirectstream(connection_t *conn, uint32_t len,
const char *body);
-static int handle_control_closestream(control_connection_t *conn, uint32_t len,
+static int handle_control_closestream(connection_t *conn, uint32_t len,
const char *body);
-static int handle_control_closecircuit(control_connection_t *conn,
- uint32_t len,
+static int handle_control_closecircuit(connection_t *conn, uint32_t len,
const char *body);
-static int write_stream_target_to_buf(edge_connection_t *conn, char *buf,
+static int write_stream_target_to_buf(connection_t *conn, char *buf,
size_t len);
/** Given a possibly invalid message type code <b>cmd</b>, return a
@@ -242,11 +235,10 @@ control_update_global_event_mask(void)
for (i = 0; i < n_conns; ++i) {
if (conns[i]->type == CONN_TYPE_CONTROL &&
STATE_IS_OPEN(conns[i]->state)) {
- control_connection_t *conn = TO_CONTROL_CONN(conns[i]);
- if (STATE_IS_V0(conn->_base.state))
- global_event_mask0 |= conn->event_mask;
+ if (STATE_IS_V0(conns[i]->state))
+ global_event_mask0 |= conns[i]->event_mask;
else
- global_event_mask1 |= conn->event_mask;
+ global_event_mask1 |= conns[i]->event_mask;
}
}
@@ -289,10 +281,10 @@ control_adjust_event_log_severity(void)
* <b>conn</b>-\>outbuf
*/
static INLINE void
-connection_write_str_to_buf(const char *s, control_connection_t *conn)
+connection_write_str_to_buf(const char *s, connection_t *conn)
{
size_t len = strlen(s);
- connection_write_to_buf(s, len, TO_CONN(conn));
+ connection_write_to_buf(s, len, conn);
}
/** Given a <b>len</b>-character string in <b>data</b>, made of lines
@@ -454,7 +446,7 @@ get_escaped_string(const char *start, size_t in_len_max,
* Currently the length of the message is limited to 1024 (including the
* ending \n\r\0. */
static void
-connection_printf_to_buf(control_connection_t *conn, const char *format, ...)
+connection_printf_to_buf(connection_t *conn, const char *format, ...)
{
#define CONNECTION_PRINTF_TO_BUF_BUFFERSIZE 1024
va_list ap;
@@ -470,41 +462,41 @@ connection_printf_to_buf(control_connection_t *conn, const char *format, ...)
buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-2] = '\n';
buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-3] = '\r';
}
- connection_write_to_buf(buf, len, TO_CONN(conn));
+ connection_write_to_buf(buf, len, conn);
}
/** Send a message of type <b>type</b> containing <b>len</b> bytes
* from <b>body</b> along the control connection <b>conn</b> */
static void
-send_control0_message(control_connection_t *conn, uint16_t type, uint32_t len,
- const char *body)
+send_control0_message(connection_t *conn, uint16_t type, uint32_t len,
+ const char *body)
{
char buf[10];
tor_assert(conn);
- tor_assert(STATE_IS_V0(conn->_base.state));
+ tor_assert(STATE_IS_V0(conn->state));
tor_assert(len || !body);
tor_assert(type <= _CONTROL0_CMD_MAX_RECOGNIZED);
if (len < 65536) {
set_uint16(buf, htons(len));
set_uint16(buf+2, htons(type));
- connection_write_to_buf(buf, 4, TO_CONN(conn));
+ connection_write_to_buf(buf, 4, conn);
if (len)
- connection_write_to_buf(body, len, TO_CONN(conn));
+ connection_write_to_buf(body, len, conn);
} else {
set_uint16(buf, htons(65535));
set_uint16(buf+2, htons(CONTROL0_CMD_FRAGMENTHEADER));
set_uint16(buf+4, htons(type));
set_uint32(buf+6, htonl(len));
- connection_write_to_buf(buf, 10, TO_CONN(conn));
- connection_write_to_buf(body, 65535-6, TO_CONN(conn));
+ connection_write_to_buf(buf, 10, conn);
+ connection_write_to_buf(body, 65535-6, conn);
len -= (65535-6);
body += (65535-6);
while (len) {
size_t chunklen = (len<65535)?len:65535;
set_uint16(buf, htons((uint16_t)chunklen));
set_uint16(buf+2, htons(CONTROL0_CMD_FRAGMENT));
- connection_write_to_buf(buf, 4, TO_CONN(conn));
- connection_write_to_buf(body, chunklen, TO_CONN(conn));
+ connection_write_to_buf(buf, 4, conn);
+ connection_write_to_buf(body, chunklen, conn);
len -= chunklen;
body += chunklen;
}
@@ -513,9 +505,9 @@ send_control0_message(control_connection_t *conn, uint16_t type, uint32_t len,
/** Send a "DONE" message down the control connection <b>conn</b> */
static void
-send_control_done(control_connection_t *conn)
+send_control_done(connection_t *conn)
{
- if (STATE_IS_V0(conn->_base.state)) {
+ if (STATE_IS_V0(conn->state)) {
send_control0_message(conn, CONTROL0_CMD_DONE, 0, NULL);
} else {
connection_write_str_to_buf("250 OK\r\n", conn);
@@ -526,7 +518,7 @@ send_control_done(control_connection_t *conn)
* as provided in the <b>len</b> bytes at <b>msg</b>.
*/
static void
-send_control_done2(control_connection_t *conn, const char *msg, size_t len)
+send_control_done2(connection_t *conn, const char *msg, size_t len)
{
if (len==0)
len = strlen(msg);
@@ -536,8 +528,7 @@ send_control_done2(control_connection_t *conn, const char *msg, size_t len)
/** Send an error message with error code <b>error</b> and body
* <b>message</b> down the connection <b>conn</b> */
static void
-send_control0_error(control_connection_t *conn, uint16_t error,
- const char *message)
+send_control0_error(connection_t *conn, uint16_t error, const char *message)
{
char buf[256];
size_t len;
@@ -570,13 +561,11 @@ send_control0_event(uint16_t event, uint32_t len, const char *body)
for (i = 0; i < n_conns; ++i) {
if (conns[i]->type == CONN_TYPE_CONTROL &&
!conns[i]->marked_for_close &&
- conns[i]->state == CONTROL_CONN_STATE_OPEN_V0) {
- control_connection_t *control_conn = TO_CONTROL_CONN(conns[i]);
- if (control_conn->event_mask & (1<<event)) {
- send_control0_message(control_conn, CONTROL0_CMD_EVENT, buflen, buf);
- if (event == EVENT_ERR_MSG)
- _connection_controller_force_write(control_conn);
- }
+ conns[i]->state == CONTROL_CONN_STATE_OPEN_V0 &&
+ conns[i]->event_mask & (1<<event)) {
+ send_control0_message(conns[i], CONTROL0_CMD_EVENT, buflen, buf);
+ if (event == EVENT_ERR_MSG)
+ _connection_controller_force_write(conns[i]);
}
}
@@ -597,13 +586,11 @@ send_control1_event_string(uint16_t event, const char *msg)
for (i = 0; i < n_conns; ++i) {
if (conns[i]->type == CONN_TYPE_CONTROL &&
!conns[i]->marked_for_close &&
- conns[i]->state == CONTROL_CONN_STATE_OPEN_V1) {
- control_connection_t *control_conn = TO_CONTROL_CONN(conns[i]);
- if (control_conn->event_mask & (1<<event)) {
- connection_write_to_buf(msg, strlen(msg), TO_CONN(control_conn));
- if (event == EVENT_ERR_MSG)
- _connection_controller_force_write(control_conn);
- }
+ conns[i]->state == CONTROL_CONN_STATE_OPEN_V1 &&
+ conns[i]->event_mask & (1<<event)) {
+ connection_write_to_buf(msg, strlen(msg), conns[i]);
+ if (event == EVENT_ERR_MSG)
+ _connection_controller_force_write(conns[i]);
}
}
}
@@ -639,7 +626,7 @@ send_control1_event(uint16_t event, const char *format, ...)
}
/** Given a text circuit <b>id</b>, return the corresponding circuit. */
-static origin_circuit_t *
+static circuit_t *
get_circ(const char *id)
{
unsigned long n_id;
@@ -651,17 +638,17 @@ get_circ(const char *id)
}
/** Given a text stream <b>id</b>, return the corresponding AP connection. */
-static edge_connection_t *
+static connection_t *
get_stream(const char *id)
{
unsigned long n_id;
int ok;
- edge_connection_t *conn;
+ connection_t *conn;
n_id = tor_parse_ulong(id, 10, 0, ULONG_MAX, &ok, NULL);
if (!ok)
return NULL;
conn = connection_get_by_global_id(n_id);
- if (!conn || conn->_base.type != CONN_TYPE_AP)
+ if (!conn || conn->type != CONN_TYPE_AP)
return NULL;
return conn;
}
@@ -670,14 +657,14 @@ get_stream(const char *id)
* it passes <b>use_defaults</b> on to options_trial_assign().
*/
static int
-control_setconf_helper(control_connection_t *conn, uint32_t len, char *body,
+control_setconf_helper(connection_t *conn, uint32_t len, char *body,
int use_defaults, int clear_first)
{
int r;
config_line_t *lines=NULL;
char *start = body;
char *errstring = NULL;
- int v0 = STATE_IS_V0(conn->_base.state);
+ int v0 = STATE_IS_V0(conn->state);
if (!v0) {
char *config = tor_malloc(len+1);
@@ -774,7 +761,7 @@ control_setconf_helper(control_connection_t *conn, uint32_t len, char *body,
/** Called when we receive a SETCONF message: parse the body and try
* to update our configuration. Reply with a DONE or ERROR message. */
static int
-handle_control_setconf(control_connection_t *conn, uint32_t len, char *body)
+handle_control_setconf(connection_t *conn, uint32_t len, char *body)
{
return control_setconf_helper(conn, len, body, 0, 1);
}
@@ -782,9 +769,9 @@ handle_control_setconf(control_connection_t *conn, uint32_t len, char *body)
/** Called when we receive a RESETCONF message: parse the body and try
* to update our configuration. Reply with a DONE or ERROR message. */
static int
-handle_control_resetconf(control_connection_t *conn, uint32_t len, char *body)
+handle_control_resetconf(connection_t *conn, uint32_t len, char *body)
{
- int v0 = STATE_IS_V0(conn->_base.state);
+ int v0 = STATE_IS_V0(conn->state);
tor_assert(!v0);
return control_setconf_helper(conn, len, body, 1, 1);
}
@@ -792,8 +779,7 @@ handle_control_resetconf(control_connection_t *conn, uint32_t len, char *body)
/** Called when we receive a GETCONF message. Parse the request, and
* reply with a CONFVALUE or an ERROR message */
static int
-handle_control_getconf(control_connection_t *conn, uint32_t body_len,
- const char *body)
+handle_control_getconf(connection_t *conn, uint32_t body_len, const char *body)
{
smartlist_t *questions = NULL;
smartlist_t *answers = NULL;
@@ -801,10 +787,9 @@ handle_control_getconf(control_connection_t *conn, uint32_t body_len,
char *msg = NULL;
size_t msg_len;
or_options_t *options = get_options();
- int v0 = STATE_IS_V0(conn->_base.state);
+ int v0 = STATE_IS_V0(conn->state);
questions = smartlist_create();
- (void) body_len; /* body is nul-terminated; so we can ignore len. */
if (v0) {
smartlist_split_string(questions, body, "\n",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
@@ -872,7 +857,7 @@ handle_control_getconf(control_connection_t *conn, uint32_t body_len,
tor_assert(strlen(tmp)>4);
tmp[3] = ' ';
msg = smartlist_join_strings(answers, "", 0, &msg_len);
- connection_write_to_buf(msg, msg_len, TO_CONN(conn));
+ connection_write_to_buf(msg, msg_len, conn);
} else {
connection_write_str_to_buf("250 OK\r\n", conn);
}
@@ -896,14 +881,13 @@ handle_control_getconf(control_connection_t *conn, uint32_t body_len,
/** Called when we get a SETEVENTS message: update conn->event_mask,
* and reply with DONE or ERROR. */
static int
-handle_control_setevents(control_connection_t *conn, uint32_t len,
- const char *body)
+handle_control_setevents(connection_t *conn, uint32_t len, const char *body)
{
uint16_t event_code;
uint32_t event_mask = 0;
unsigned int extended = 0;
- if (STATE_IS_V0(conn->_base.state)) {
+ if (STATE_IS_V0(conn->state)) {
if (len % 2) {
send_control0_error(conn, ERR_SYNTAX,
"Odd number of bytes in setevents message");
@@ -965,7 +949,7 @@ handle_control_setevents(control_connection_t *conn, uint32_t len,
smartlist_free(events);
}
conn->event_mask = event_mask;
- conn->_base.control_events_are_extended = extended;
+ conn->control_events_are_extended = extended;
control_update_global_event_mask();
send_control_done(conn);
@@ -1002,14 +986,13 @@ decode_hashed_password(char *buf, const char *hashed)
* OPEN. Reply with DONE or ERROR.
*/
static int
-handle_control_authenticate(control_connection_t *conn, uint32_t len,
- const char *body)
+handle_control_authenticate(connection_t *conn, uint32_t len, const char *body)
{
int used_quoted_string = 0;
or_options_t *options = get_options();
char *password;
size_t password_len;
- if (STATE_IS_V0(conn->_base.state)) {
+ if (STATE_IS_V0(conn->state)) {
password = (char*)body;
password_len = len;
} else {
@@ -1063,7 +1046,7 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len,
}
err:
- if (STATE_IS_V0(conn->_base.state))
+ if (STATE_IS_V0(conn->state))
send_control0_error(conn,ERR_REJECTED_AUTHENTICATION,
"Authentication failed");
else {
@@ -1077,12 +1060,12 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len,
}
return 0;
ok:
- log_info(LD_CONTROL, "Authenticated control connection (%d)", conn->_base.s);
+ log_info(LD_CONTROL, "Authenticated control connection (%d)", conn->s);
send_control_done(conn);
- if (STATE_IS_V0(conn->_base.state))
- conn->_base.state = CONTROL_CONN_STATE_OPEN_V0;
+ if (STATE_IS_V0(conn->state))
+ conn->state = CONTROL_CONN_STATE_OPEN_V0;
else {
- conn->_base.state = CONTROL_CONN_STATE_OPEN_V1;
+ conn->state = CONTROL_CONN_STATE_OPEN_V1;
tor_free(password);
}
return 0;
@@ -1091,13 +1074,11 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len,
/** Called when we get a SAVECONF command. Try to flush the current options to
* disk, and report success or failure. */
static int
-handle_control_saveconf(control_connection_t *conn, uint32_t len,
+handle_control_saveconf(connection_t *conn, uint32_t len,
const char *body)
{
- (void) len;
- (void) body;
if (options_save_current()<0) {
- if (STATE_IS_V0(conn->_base.state))
+ if (STATE_IS_V0(conn->state))
send_control0_error(conn, ERR_INTERNAL,
"Unable to write configuration to disk.");
else
@@ -1113,11 +1094,11 @@ handle_control_saveconf(control_connection_t *conn, uint32_t len,
* report success or failure. (If the signal results in a shutdown, success
* may not be reported.) */
static int
-handle_control_signal(control_connection_t *conn, uint32_t len,
+handle_control_signal(connection_t *conn, uint32_t len,
const char *body)
{
int sig;
- if (STATE_IS_V0(conn->_base.state)) {
+ if (STATE_IS_V0(conn->state)) {
if (len != 1) {
send_control0_error(conn, ERR_SYNTAX,
"Body of SIGNAL command too long or too short.");
@@ -1153,16 +1134,14 @@ handle_control_signal(control_connection_t *conn, uint32_t len,
return 0;
}
- if (!control_signal_check(sig)) {
- if (STATE_IS_V0(conn->_base.state))
+ if (control_signal_act(sig) < 0) {
+ if (STATE_IS_V0(conn->state))
send_control0_error(conn, ERR_SYNTAX, "Unrecognized signal number.");
else
- connection_write_str_to_buf("551 Unable to act on signal\r\n",
+ connection_write_str_to_buf("551 Internal error acting on signal\r\n",
conn);
} else {
- /* Send DONE first, in case the signal makes us shut down. */
send_control_done(conn);
- control_signal_act(sig);
}
return 0;
}
@@ -1170,17 +1149,14 @@ handle_control_signal(control_connection_t *conn, uint32_t len,
/** Called when we get a MAPADDRESS command; try to bind all listed addresses,
* and report success or failrue. */
static int
-handle_control_mapaddress(control_connection_t *conn, uint32_t len,
- const char *body)
+handle_control_mapaddress(connection_t *conn, uint32_t len, const char *body)
{
smartlist_t *elts;
smartlist_t *lines;
smartlist_t *reply;
char *r;
size_t sz;
- int v0 = STATE_IS_V0(conn->_base.state);
- (void) len; /* body is nul-terminated, so it's safe to ignore the length. */
-
+ int v0 = STATE_IS_V0(conn->state);
lines = smartlist_create();
elts = smartlist_create();
reply = smartlist_create();
@@ -1276,12 +1252,12 @@ handle_control_mapaddress(control_connection_t *conn, uint32_t len,
if (smartlist_len(reply)) {
((char*)smartlist_get(reply,smartlist_len(reply)-1))[3] = ' ';
r = smartlist_join_strings(reply, "\r\n", 1, &sz);
- connection_write_to_buf(r, sz, TO_CONN(conn));
+ connection_write_to_buf(r, sz, conn);
tor_free(r);
} else {
const char *response =
"512 syntax error: not enough arguments to mapaddress.\r\n";
- connection_write_to_buf(response, strlen(response), TO_CONN(conn));
+ connection_write_to_buf(response, strlen(response), conn);
}
}
@@ -1307,16 +1283,13 @@ list_getinfo_options(void)
"addr-mappings/cache Addresses remapped by DNS cache.\n"
"addr-mappings/configl Addresses remapped from configuration options.\n"
"addr-mappings/control Addresses remapped by a controller.\n"
- "address The best guess at our external IP address.\n"
"circuit-status Status of each current circuit.\n"
- "config-file Current location of the \"torrc\" file.\n"
"config/names List of configuration options, types, and documentation.\n"
"desc/id/* Server descriptor by hex ID\n"
"desc/name/* Server descriptor by nickname.\n"
"desc/all-recent Latest server descriptor for every router\n"
"dir/server/* Fetch server descriptors -- see dir-spec.txt\n"
"entry-guards Which nodes will we use as entry guards?\n"
- "exit-policy/default Default lines appended to config->ExitPolicy\n"
"info/names List of GETINFO options, types, and documentation.\n"
"network-status List of hex IDs, nicknames, server statuses.\n"
"orconn-status Status of each current OR connection.\n"
@@ -1326,7 +1299,7 @@ list_getinfo_options(void)
/** Lookup the 'getinfo' entry <b>question</b>, and return
* the answer in <b>*answer</b> (or NULL if key not recognized).
- * Return 0 if success, or -1 if recognized but internal error. */
+ * Return 0 if success, or -1 if internal error. */
static int
handle_getinfo_helper(const char *question, char **answer)
{
@@ -1350,14 +1323,14 @@ handle_getinfo_helper(const char *question, char **answer)
if (ri) {
const char *body = signed_descriptor_get_body(&ri->cache_info);
if (body)
- *answer = tor_strndup(body, ri->cache_info.signed_descriptor_len);
+ *answer = tor_strdup(body);
}
} else if (!strcmpstart(question, "desc/name/")) {
routerinfo_t *ri = router_get_by_nickname(question+strlen("desc/name/"),1);
if (ri) {
const char *body = signed_descriptor_get_body(&ri->cache_info);
if (body)
- *answer = tor_strndup(body, ri->cache_info.signed_descriptor_len);
+ *answer = tor_strdup(body);
}
} else if (!strcmp(question, "desc/all-recent")) {
routerlist_t *routerlist = router_get_routerlist();
@@ -1367,8 +1340,7 @@ handle_getinfo_helper(const char *question, char **answer)
{
const char *body = signed_descriptor_get_body(&ri->cache_info);
if (body)
- smartlist_add(sl,
- tor_strndup(body, ri->cache_info.signed_descriptor_len));
+ smartlist_add(sl, tor_strdup(body));
});
}
*answer = smartlist_join_strings(sl, "", 0, NULL);
@@ -1392,7 +1364,7 @@ handle_getinfo_helper(const char *question, char **answer)
const char *state;
if (! CIRCUIT_IS_ORIGIN(circ) || circ->marked_for_close)
continue;
- path = circuit_list_path(TO_ORIGIN_CIRCUIT(circ),0);
+ path = circuit_list_path(circ,0);
if (circ->state == CIRCUIT_STATE_OPEN)
state = "BUILT";
else if (strlen(path))
@@ -1403,7 +1375,7 @@ handle_getinfo_helper(const char *question, char **answer)
slen = strlen(path)+strlen(state)+20;
s = tor_malloc(slen+1);
tor_snprintf(s, slen, "%lu %s %s",
- (unsigned long)TO_ORIGIN_CIRCUIT(circ)->global_identifier,
+ (unsigned long)circ->global_identifier,
state, path);
smartlist_add(status, s);
tor_free(path);
@@ -1419,24 +1391,19 @@ handle_getinfo_helper(const char *question, char **answer)
get_connection_array(&conns, &n_conns);
for (i=0; i < n_conns; ++i) {
const char *state;
- edge_connection_t *conn;
char *s;
size_t slen;
circuit_t *circ;
- origin_circuit_t *origin_circ = NULL;
if (conns[i]->type != CONN_TYPE_AP ||
conns[i]->marked_for_close ||
- conns[i]->state == AP_CONN_STATE_SOCKS_WAIT ||
- conns[i]->state == AP_CONN_STATE_ORIGDST_WAIT)
+ conns[i]->state == AP_CONN_STATE_SOCKS_WAIT)
continue;
- conn = TO_EDGE_CONN(conns[i]);
- switch (conn->_base.state)
+ switch (conns[i]->state)
{
case AP_CONN_STATE_CONTROLLER_WAIT:
case AP_CONN_STATE_CIRCUIT_WAIT:
- if (conn->socks_request &&
- (conn->socks_request->command == SOCKS_COMMAND_RESOLVE ||
- conn->socks_request->command == SOCKS_COMMAND_RESOLVE_PTR))
+ if (conns[i]->socks_request &&
+ conns[i]->socks_request->command == SOCKS_COMMAND_RESOLVE)
state = "NEWRESOLVE";
else
state = "NEW";
@@ -1450,19 +1417,16 @@ handle_getinfo_helper(const char *question, char **answer)
state = "SUCCEEDED"; break;
default:
log_warn(LD_BUG, "Asked for stream in unknown state %d",
- conn->_base.state);
+ conns[i]->state);
continue;
}
- circ = circuit_get_by_edge_conn(conn);
- if (circ && CIRCUIT_IS_ORIGIN(circ))
- origin_circ = TO_ORIGIN_CIRCUIT(circ);
- write_stream_target_to_buf(conn, buf, sizeof(buf));
+ circ = circuit_get_by_edge_conn(conns[i]);
+ write_stream_target_to_buf(conns[i], buf, sizeof(buf));
slen = strlen(buf)+strlen(state)+32;
s = tor_malloc(slen+1);
tor_snprintf(s, slen, "%lu %s %lu %s",
- (unsigned long) conn->global_identifier,state,
- origin_circ?
- (unsigned long)origin_circ->global_identifier : 0ul,
+ (unsigned long) conns[i]->global_identifier,state,
+ circ?(unsigned long)circ->global_identifier : 0ul,
buf);
smartlist_add(status, s);
}
@@ -1479,11 +1443,10 @@ handle_getinfo_helper(const char *question, char **answer)
char *s;
char name[128];
size_t slen;
- or_connection_t *conn;
- if (conns[i]->type != CONN_TYPE_OR || conns[i]->marked_for_close)
+ connection_t *conn = conns[i];
+ if (conn->type != CONN_TYPE_OR || conn->marked_for_close)
continue;
- conn = TO_OR_CONN(conns[i]);
- if (conn->_base.state == OR_CONN_STATE_OPEN)
+ if (conn->state == OR_CONN_STATE_OPEN)
state = "CONNECTED";
else if (conn->nickname)
state = "LAUNCHED";
@@ -1493,7 +1456,7 @@ handle_getinfo_helper(const char *question, char **answer)
strlcpy(name, conn->nickname, sizeof(name));
else
tor_snprintf(name, sizeof(name), "%s:%d",
- conn->_base.address, conn->_base.port);
+ conn->address, conn->port);
slen = strlen(name)+strlen(state)+2;
s = tor_malloc(slen+1);
@@ -1519,14 +1482,9 @@ handle_getinfo_helper(const char *question, char **answer)
}
mappings = smartlist_create();
addressmap_get_mappings(mappings, min_e, max_e);
- *answer = smartlist_join_strings(mappings, "\r\n", 0, NULL);
+ *answer = smartlist_join_strings(mappings, "\n", 0, NULL);
SMARTLIST_FOREACH(mappings, char *, cp, tor_free(cp));
smartlist_free(mappings);
- } else if (!strcmp(question, "address")) {
- uint32_t addr;
- if (router_pick_published_address(get_options(), &addr) < 0)
- return -1;
- *answer = tor_dup_addr(addr);
} else if (!strcmp(question, "dir-usage")) {
*answer = directory_dump_request_log();
} else if (!strcmpstart(question, "dir/server/")) {
@@ -1556,7 +1514,7 @@ handle_getinfo_helper(const char *question, char **answer)
char *cp;
if (!get_options()->DirPort) {
log_warn(LD_CONTROL, "getinfo dir/status/ requires an open dirport.");
- return -1;
+ return 0;
}
status_list = smartlist_create();
dirserv_get_networkstatus_v2(status_list,
@@ -1569,8 +1527,6 @@ handle_getinfo_helper(const char *question, char **answer)
cp += d->dir_len;
});
*cp = '\0';
- } else if (!strcmpstart(question, "exit-policy/")) {
- return policies_getinfo_helper(question, answer);
}
return 0;
}
@@ -1578,16 +1534,14 @@ handle_getinfo_helper(const char *question, char **answer)
/** Called when we receive a GETINFO command. Try to fetch all requested
* information, and reply with information or error message. */
static int
-handle_control_getinfo(control_connection_t *conn, uint32_t len,
- const char *body)
+handle_control_getinfo(connection_t *conn, uint32_t len, const char *body)
{
smartlist_t *questions = NULL;
smartlist_t *answers = NULL;
smartlist_t *unrecognized = NULL;
char *msg = NULL, *ans = NULL;
size_t msg_len;
- int v0 = STATE_IS_V0(conn->_base.state);
- (void) len; /* body is nul-terminated, so it's safe to ignore the length. */
+ int v0 = STATE_IS_V0(conn->state);
questions = smartlist_create();
if (v0)
@@ -1650,7 +1604,7 @@ handle_control_getinfo(control_connection_t *conn, uint32_t len,
size_t len;
len = write_escaped_data(v, strlen(v), 1, &esc);
connection_printf_to_buf(conn, "250+%s=\r\n", k);
- connection_write_to_buf(esc, len, TO_CONN(conn));
+ connection_write_to_buf(esc, len, conn);
tor_free(esc);
}
}
@@ -1672,23 +1626,20 @@ handle_control_getinfo(control_connection_t *conn, uint32_t len,
return 0;
}
-/** If *<b>string</b> contains a recognized purpose (for
+/** If <b>string</b> contains a recognized purpose (for
* circuits if <b>for_circuits</b> is 1, else for routers),
* possibly prefaced with the string "purpose=", then assign it
- * and return 0. Otherwise return -1.
- *
- * If it's prefaced with "purpose=", then set *<b>string</b> to
- * the remainder of the string. */
+ * and return 0. Otherwise return -1. */
static int
-get_purpose(char **string, int for_circuits, uint8_t *purpose)
+get_purpose(char *string, int for_circuits, uint8_t *purpose)
{
- if (!strcmpstart(*string, "purpose="))
- *string += strlen("purpose=");
+ if (!strcmpstart(string, "purpose="))
+ string += strlen("purpose=");
- if (!strcmp(*string, "general"))
+ if (!strcmp(string, "general"))
*purpose = for_circuits ? CIRCUIT_PURPOSE_C_GENERAL :
ROUTER_PURPOSE_GENERAL;
- else if (!strcmp(*string, "controller"))
+ else if (!strcmp(string, "controller"))
*purpose = for_circuits ? CIRCUIT_PURPOSE_CONTROLLER :
ROUTER_PURPOSE_GENERAL;
else { /* not a recognized purpose */
@@ -1700,17 +1651,17 @@ get_purpose(char **string, int for_circuits, uint8_t *purpose)
/** Called when we get an EXTENDCIRCUIT message. Try to extend the listed
* circuit, and report success or failure. */
static int
-handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
+handle_control_extendcircuit(connection_t *conn, uint32_t len,
const char *body)
{
smartlist_t *router_nicknames=NULL, *routers=NULL;
uint32_t circ_id;
- origin_circuit_t *circ = NULL;
+ circuit_t *circ = NULL;
int zero_circ, v0;
char reply[4];
uint8_t intended_purpose = CIRCUIT_PURPOSE_C_GENERAL;
- v0 = STATE_IS_V0(conn->_base.state);
+ v0 = STATE_IS_V0(conn->state);
router_nicknames = smartlist_create();
if (v0) {
@@ -1753,9 +1704,9 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
smartlist_split_string(router_nicknames, smartlist_get(args,1), ",", 0, 0);
if (zero_circ && smartlist_len(args)>2) {
- char *purp = smartlist_get(args,2);
- if (get_purpose(&purp, 1, &intended_purpose) < 0) {
- connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n", purp);
+ if (get_purpose(smartlist_get(args,2), 1, &intended_purpose) < 0) {
+ connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n",
+ (char *)smartlist_get(args,2));
SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
smartlist_free(args);
goto done;
@@ -1766,11 +1717,6 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
if (!zero_circ && !circ) {
goto done;
}
- SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
- smartlist_free(args);
- if (!zero_circ && !circ) {
- goto done;
- }
}
routers = smartlist_create();
@@ -1796,7 +1742,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
if (zero_circ) {
/* start a new circuit */
- circ = origin_circuit_init(intended_purpose, 0, 0, 0);
+ circ = circuit_init(intended_purpose, 0, 0, 0);
}
/* now circ refers to something that is ready to be extended */
@@ -1810,7 +1756,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
/* now that we've populated the cpath, start extending */
if (zero_circ) {
if (circuit_handle_first_hop(circ) < 0) {
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
if (v0)
send_control0_error(conn, ERR_INTERNAL, "couldn't start circuit");
else
@@ -1818,12 +1764,12 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
goto done;
}
} else {
- if (circ->_base.state == CIRCUIT_STATE_OPEN) {
- circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING);
+ if (circ->state == CIRCUIT_STATE_OPEN) {
+ circuit_set_state(circ, CIRCUIT_STATE_BUILDING);
if (circuit_send_next_onion_skin(circ) < 0) {
log_info(LD_CONTROL,
"send_next_onion_skin failed; circuit marked for closing.");
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
if (v0)
send_control0_error(conn, ERR_INTERNAL, "couldn't send onion skin");
else
@@ -1852,14 +1798,13 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
* is 1) or SETROUTERPURPOSE message. If we can find
* the circuit/router and it's a valid purpose, change it. */
static int
-handle_control_setpurpose(control_connection_t *conn, int for_circuits,
+handle_control_setpurpose(connection_t *conn, int for_circuits,
uint32_t len, const char *body)
{
- origin_circuit_t *circ = NULL;
+ circuit_t *circ = NULL;
routerinfo_t *ri = NULL;
uint8_t new_purpose;
smartlist_t *args = smartlist_create();
- (void) len; /* body is nul-terminated, so it's safe to ignore the length. */
smartlist_split_string(args, body, " ",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
if (smartlist_len(args)<2) {
@@ -1883,16 +1828,14 @@ handle_control_setpurpose(control_connection_t *conn, int for_circuits,
}
}
- {
- char *purp = smartlist_get(args,1);
- if (get_purpose(&purp, for_circuits, &new_purpose) < 0) {
- connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n", purp);
- goto done;
- }
+ if (get_purpose(smartlist_get(args,1), for_circuits, &new_purpose) < 0) {
+ connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n",
+ (char *)smartlist_get(args,1));
+ goto done;
}
if (for_circuits)
- circ->_base.purpose = new_purpose;
+ circ->purpose = new_purpose;
else
ri->purpose = new_purpose;
connection_write_str_to_buf("250 OK\r\n", conn);
@@ -1906,14 +1849,14 @@ done:
/** Called when we get an ATTACHSTREAM message. Try to attach the requested
* stream, and report success or failure. */
static int
-handle_control_attachstream(control_connection_t *conn, uint32_t len,
+handle_control_attachstream(connection_t *conn, uint32_t len,
const char *body)
{
- edge_connection_t *ap_conn = NULL;
- origin_circuit_t *circ = NULL;
+ connection_t *ap_conn = NULL;
+ circuit_t *circ = NULL;
int zero_circ;
- if (STATE_IS_V0(conn->_base.state)) {
+ if (STATE_IS_V0(conn->state)) {
uint32_t conn_id;
uint32_t circ_id;
if (len < 8) {
@@ -1962,10 +1905,10 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len,
return 0;
}
- if (ap_conn->_base.state != AP_CONN_STATE_CONTROLLER_WAIT &&
- ap_conn->_base.state != AP_CONN_STATE_CONNECT_WAIT &&
- ap_conn->_base.state != AP_CONN_STATE_RESOLVE_WAIT) {
- if (STATE_IS_V0(conn->_base.state)) {
+ if (ap_conn->state != AP_CONN_STATE_CONTROLLER_WAIT &&
+ ap_conn->state != AP_CONN_STATE_CONNECT_WAIT &&
+ ap_conn->state != AP_CONN_STATE_RESOLVE_WAIT) {
+ if (STATE_IS_V0(conn->state)) {
send_control0_error(conn, ERR_NO_STREAM,
"Connection is not managed by controller.");
} else {
@@ -1977,29 +1920,28 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len,
}
/* Do we need to detach it first? */
- if (ap_conn->_base.state != AP_CONN_STATE_CONTROLLER_WAIT) {
+ if (ap_conn->state != AP_CONN_STATE_CONTROLLER_WAIT) {
circuit_t *tmpcirc = circuit_get_by_edge_conn(ap_conn);
- connection_edge_end(ap_conn, END_STREAM_REASON_TIMEOUT,
- ap_conn->cpath_layer);
+ connection_edge_end(ap_conn, END_STREAM_REASON_TIMEOUT, conn->cpath_layer);
/* Un-mark it as ending, since we're going to reuse it. */
- ap_conn->_base.edge_has_sent_end = 0;
+ ap_conn->has_sent_end = 0;
if (tmpcirc)
circuit_detach_stream(tmpcirc,ap_conn);
- ap_conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT;
+ ap_conn->state = AP_CONN_STATE_CONTROLLER_WAIT;
}
- if (circ && (circ->_base.state != CIRCUIT_STATE_OPEN)) {
- if (STATE_IS_V0(conn->_base.state))
+ if (circ && circ->state != CIRCUIT_STATE_OPEN) {
+ if (STATE_IS_V0(conn->state))
send_control0_error(conn, ERR_INTERNAL,
- "Refuse to attach stream to non-open, origin circ.");
+ "Refuse to attach stream to non-open circ.");
else
connection_write_str_to_buf(
- "551 Can't attach stream to non-open, origin circuit\r\n",
- conn);
+ "551 Can't attach stream to non-open circuit\r\n",
+ conn);
return 0;
}
if (connection_ap_handshake_rewrite_and_attach(ap_conn, circ) < 0) {
- if (STATE_IS_V0(conn->_base.state))
+ if (STATE_IS_V0(conn->state))
send_control0_error(conn, ERR_INTERNAL, "Unable to attach stream.");
else
connection_write_str_to_buf("551 Unable to attach stream\r\n", conn);
@@ -2012,11 +1954,11 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len,
/** Called when we get a POSTDESCRIPTOR message. Try to learn the provided
* descriptor, and report success or failure. */
static int
-handle_control_postdescriptor(control_connection_t *conn, uint32_t len,
+handle_control_postdescriptor(connection_t *conn, uint32_t len,
const char *body)
{
char *desc;
- int v0 = STATE_IS_V0(conn->_base.state);
+ int v0 = STATE_IS_V0(conn->state);
const char *msg=NULL;
uint8_t purpose = ROUTER_PURPOSE_GENERAL;
@@ -2030,10 +1972,9 @@ handle_control_postdescriptor(control_connection_t *conn, uint32_t len,
smartlist_split_string(args, body, " ",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
if (smartlist_len(args)) {
- char *purp = smartlist_get(args,0);
- if (get_purpose(&purp, 0, &purpose) < 0) {
+ if (get_purpose(smartlist_get(args,0), 0, &purpose) < 0) {
connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n",
- purp);
+ (char *)smartlist_get(args,0));
SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
smartlist_free(args);
return 0;
@@ -2072,14 +2013,14 @@ handle_control_postdescriptor(control_connection_t *conn, uint32_t len,
/** Called when we receive a REDIRECTSTERAM command. Try to change the target
* address of the named AP stream, and report success or failure. */
static int
-handle_control_redirectstream(control_connection_t *conn, uint32_t len,
+handle_control_redirectstream(connection_t *conn, uint32_t len,
const char *body)
{
- edge_connection_t *ap_conn = NULL;
+ connection_t *ap_conn = NULL;
uint32_t conn_id;
char *new_addr = NULL;
uint16_t new_port = 0;
- if (STATE_IS_V0(conn->_base.state)) {
+ if (STATE_IS_V0(conn->state)) {
if (len < 6) {
send_control0_error(conn, ERR_SYNTAX,
"redirectstream message too short");
@@ -2088,8 +2029,8 @@ handle_control_redirectstream(control_connection_t *conn, uint32_t len,
conn_id = ntohl(get_uint32(body));
if (!(ap_conn = connection_get_by_global_id(conn_id))
- || ap_conn->_base.state != CONN_TYPE_AP
- || ap_conn->socks_request) {
+ || ap_conn->state != CONN_TYPE_AP
+ || !ap_conn->socks_request) {
send_control0_error(conn, ERR_NO_STREAM,
"No AP connection found with given ID");
return 0;
@@ -2139,13 +2080,13 @@ handle_control_redirectstream(control_connection_t *conn, uint32_t len,
/** Called when we get a CLOSESTREAM command; try to close the named stream
* and report success or failure. */
static int
-handle_control_closestream(control_connection_t *conn, uint32_t len,
+handle_control_closestream(connection_t *conn, uint32_t len,
const char *body)
{
- edge_connection_t *ap_conn=NULL;
+ connection_t *ap_conn=NULL;
uint8_t reason=0;
- if (STATE_IS_V0(conn->_base.state)) {
+ if (STATE_IS_V0(conn->state)) {
uint32_t conn_id;
if (len < 6) {
send_control0_error(conn, ERR_SYNTAX, "closestream message too short");
@@ -2156,8 +2097,8 @@ handle_control_closestream(control_connection_t *conn, uint32_t len,
reason = *(uint8_t*)(body+4);
if (!(ap_conn = connection_get_by_global_id(conn_id))
- || ap_conn->_base.state != CONN_TYPE_AP
- || ap_conn->socks_request) {
+ || ap_conn->state != CONN_TYPE_AP
+ || !ap_conn->socks_request) {
send_control0_error(conn, ERR_NO_STREAM,
"No AP connection found with given ID");
return 0;
@@ -2197,13 +2138,13 @@ handle_control_closestream(control_connection_t *conn, uint32_t len,
/** Called when we get a CLOSECIRCUIT command; try to close the named circuit
* and report success or failure. */
static int
-handle_control_closecircuit(control_connection_t *conn, uint32_t len,
+handle_control_closecircuit(connection_t *conn, uint32_t len,
const char *body)
{
- origin_circuit_t *circ = NULL;
+ circuit_t *circ = NULL;
int safe = 0;
- if (STATE_IS_V0(conn->_base.state)) {
+ if (STATE_IS_V0(conn->state)) {
uint32_t circ_id;
if (len < 5) {
send_control0_error(conn, ERR_SYNTAX, "closecircuit message too short");
@@ -2245,7 +2186,7 @@ handle_control_closecircuit(control_connection_t *conn, uint32_t len,
}
if (!safe || !circ->p_streams) {
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_NONE);
+ circuit_mark_for_close(circ, END_CIRC_REASON_NONE);
}
send_control_done(conn);
@@ -2258,7 +2199,7 @@ handle_control_closecircuit(control_connection_t *conn, uint32_t len,
* fragments and report failure.
*/
static int
-handle_control_fragments(control_connection_t *conn, uint16_t command_type,
+handle_control_fragments(connection_t *conn, uint16_t command_type,
uint32_t body_len, char *body)
{
if (command_type == CONTROL0_CMD_FRAGMENTHEADER) {
@@ -2299,22 +2240,24 @@ handle_control_fragments(control_connection_t *conn, uint16_t command_type,
/** Called when <b>conn</b> has no more bytes left on its outbuf. */
int
-connection_control_finished_flushing(control_connection_t *conn)
+connection_control_finished_flushing(connection_t *conn)
{
tor_assert(conn);
+ tor_assert(conn->type == CONN_TYPE_CONTROL);
- connection_stop_writing(TO_CONN(conn));
+ connection_stop_writing(conn);
return 0;
}
/** Called when <b>conn</b> has gotten its socket closed. */
int
-connection_control_reached_eof(control_connection_t *conn)
+connection_control_reached_eof(connection_t *conn)
{
tor_assert(conn);
+ tor_assert(conn->type == CONN_TYPE_CONTROL);
log_info(LD_CONTROL,"Control connection reached EOF. Closing.");
- connection_mark_for_close(TO_CONN(conn));
+ connection_mark_for_close(conn);
return 0;
}
@@ -2322,15 +2265,16 @@ connection_control_reached_eof(control_connection_t *conn)
* commands from conn->inbuf, and execute them.
*/
static int
-connection_control_process_inbuf_v1(control_connection_t *conn)
+connection_control_process_inbuf_v1(connection_t *conn)
{
size_t data_len;
int cmd_len;
char *args;
tor_assert(conn);
- tor_assert(conn->_base.state == CONTROL_CONN_STATE_OPEN_V1 ||
- conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH_V1);
+ tor_assert(conn->type == CONN_TYPE_CONTROL);
+ tor_assert(conn->state == CONTROL_CONN_STATE_OPEN_V1 ||
+ conn->state == CONTROL_CONN_STATE_NEEDAUTH_V1);
if (!conn->incoming_cmd) {
conn->incoming_cmd = tor_malloc(1024);
@@ -2345,7 +2289,7 @@ connection_control_process_inbuf_v1(control_connection_t *conn)
/* First, fetch a line. */
do {
data_len = conn->incoming_cmd_len - conn->incoming_cmd_cur_len;
- r = fetch_from_buf_line(conn->_base.inbuf,
+ r = fetch_from_buf_line(conn->inbuf,
conn->incoming_cmd+conn->incoming_cmd_cur_len,
&data_len);
if (r == 0)
@@ -2395,11 +2339,11 @@ connection_control_process_inbuf_v1(control_connection_t *conn)
if (!strcasecmp(conn->incoming_cmd, "QUIT")) {
connection_write_str_to_buf("250 closing connection\r\n", conn);
- connection_mark_for_close(TO_CONN(conn));
+ connection_mark_for_close(conn);
return 0;
}
- if (conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH_V1 &&
+ if (conn->state == CONTROL_CONN_STATE_NEEDAUTH_V1 &&
strcasecmp(conn->incoming_cmd, "AUTHENTICATE")) {
connection_write_str_to_buf("514 Authentication required.\r\n", conn);
conn->incoming_cmd_cur_len = 0;
@@ -2470,7 +2414,7 @@ connection_control_process_inbuf_v1(control_connection_t *conn)
* commands from conn->inbuf, and execute them.
*/
static int
-connection_control_process_inbuf_v0(control_connection_t *conn)
+connection_control_process_inbuf_v0(connection_t *conn)
{
uint32_t body_len;
uint16_t command_type;
@@ -2478,16 +2422,15 @@ connection_control_process_inbuf_v0(control_connection_t *conn)
again:
/* Try to suck a control message from the buffer. */
- switch (fetch_from_buf_control0(conn->_base.inbuf, &body_len, &command_type,
- &body,
- conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH_V0))
+ switch (fetch_from_buf_control0(conn->inbuf, &body_len, &command_type, &body,
+ conn->state == CONTROL_CONN_STATE_NEEDAUTH_V0))
{
case -2:
tor_free(body);
log_info(LD_CONTROL,
"Detected v1 control protocol on connection (fd %d)",
- conn->_base.s);
- conn->_base.state = CONTROL_CONN_STATE_NEEDAUTH_V1;
+ conn->s);
+ conn->state = CONTROL_CONN_STATE_NEEDAUTH_V1;
return connection_control_process_inbuf_v1(conn);
case -1:
tor_free(body);
@@ -2505,7 +2448,7 @@ connection_control_process_inbuf_v0(control_connection_t *conn)
/* We got a command. If we need authentication, only authentication
* commands will be considered. */
- if (conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH_V0 &&
+ if (conn->state == CONTROL_CONN_STATE_NEEDAUTH_V0 &&
command_type != CONTROL0_CMD_AUTHENTICATE) {
log_info(LD_CONTROL, "Rejecting '%s' command; authentication needed.",
control_cmd_to_string(command_type));
@@ -2619,11 +2562,12 @@ connection_control_process_inbuf_v0(control_connection_t *conn)
/** Called when <b>conn</b> has received more bytes on its inbuf.
*/
int
-connection_control_process_inbuf(control_connection_t *conn)
+connection_control_process_inbuf(connection_t *conn)
{
tor_assert(conn);
+ tor_assert(conn->type == CONN_TYPE_CONTROL);
- if (STATE_IS_V0(conn->_base.state))
+ if (STATE_IS_V0(conn->state))
return connection_control_process_inbuf_v0(conn);
else
return connection_control_process_inbuf_v1(conn);
@@ -2632,12 +2576,13 @@ connection_control_process_inbuf(control_connection_t *conn)
/** Something has happened to circuit <b>circ</b>: tell any interested
* control connections. */
int
-control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp)
+control_event_circuit_status(circuit_t *circ, circuit_status_event_t tp)
{
char *path, *msg;
if (!EVENT_IS_INTERESTING(EVENT_CIRCUIT_STATUS))
return 0;
tor_assert(circ);
+ tor_assert(CIRCUIT_IS_ORIGIN(circ));
path = circuit_list_path(circ,0);
if (EVENT_IS_INTERESTING0(EVENT_CIRCUIT_STATUS)) {
@@ -2678,7 +2623,7 @@ control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp)
* <b>conn</b>, and write it to <b>buf</b>. Return 0 on success, -1 on
* failure. */
static int
-write_stream_target_to_buf(edge_connection_t *conn, char *buf, size_t len)
+write_stream_target_to_buf(connection_t *conn, char *buf, size_t len)
{
char buf2[256];
if (conn->chosen_exit_name)
@@ -2697,11 +2642,12 @@ write_stream_target_to_buf(edge_connection_t *conn, char *buf, size_t len)
/** Something has happened to the stream associated with AP connection
* <b>conn</b>: tell any interested control connections. */
int
-control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp)
+control_event_stream_status(connection_t *conn, stream_status_event_t tp)
{
char *msg;
size_t len;
char buf[256];
+ tor_assert(conn->type == CONN_TYPE_AP);
tor_assert(conn->socks_request);
if (!EVENT_IS_INTERESTING(EVENT_STREAM_STATUS))
@@ -2721,7 +2667,6 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp)
if (EVENT_IS_INTERESTING1(EVENT_STREAM_STATUS)) {
const char *status;
circuit_t *circ;
- origin_circuit_t *origin_circ = NULL;
switch (tp)
{
case STREAM_EVENT_SENT_CONNECT: status = "SENTCONNECT"; break;
@@ -2737,13 +2682,10 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp)
return 0;
}
circ = circuit_get_by_edge_conn(conn);
- if (circ && CIRCUIT_IS_ORIGIN(circ))
- origin_circ = TO_ORIGIN_CIRCUIT(circ);
send_control1_event(EVENT_STREAM_STATUS,
"650 STREAM %lu %s %lu %s\r\n",
(unsigned long)conn->global_identifier, status,
- origin_circ?
- (unsigned long)origin_circ->global_identifier : 0ul,
+ circ?(unsigned long)circ->global_identifier : 0ul,
buf);
/* XXX need to specify its intended exit, etc? */
}
@@ -2753,11 +2695,13 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp)
/** Something has happened to the OR connection <b>conn</b>: tell any
* interested control connections. */
int
-control_event_or_conn_status(or_connection_t *conn,or_conn_status_event_t tp)
+control_event_or_conn_status(connection_t *conn,or_conn_status_event_t tp)
{
char buf[HEX_DIGEST_LEN+3]; /* status, dollar, identity, NUL */
size_t len;
+ tor_assert(conn->type == CONN_TYPE_OR);
+
if (!EVENT_IS_INTERESTING(EVENT_OR_CONN_STATUS))
return 0;
@@ -2774,14 +2718,13 @@ control_event_or_conn_status(or_connection_t *conn,or_conn_status_event_t tp)
strlcpy(name, conn->nickname, sizeof(name));
else
tor_snprintf(name, sizeof(name), "%s:%d",
- conn->_base.address, conn->_base.port);
+ conn->address, conn->port);
switch (tp)
{
case OR_CONN_EVENT_LAUNCHED: status = "LAUNCHED"; break;
case OR_CONN_EVENT_CONNECTED: status = "CONNECTED"; break;
case OR_CONN_EVENT_FAILED: status = "FAILED"; break;
case OR_CONN_EVENT_CLOSED: status = "CLOSED"; break;
- case OR_CONN_EVENT_NEW: status = "NEW"; break;
default:
log_warn(LD_BUG, "Unrecognized status code %d", (int)tp);
return 0;
@@ -2838,7 +2781,6 @@ void
control_event_logmsg(int severity, unsigned int domain, const char *msg)
{
int oldlog, event;
- (void) domain;
if (disable_log_messages)
return;
@@ -2916,12 +2858,8 @@ control_event_descriptors_changed(smartlist_t *routers)
tor_free(msg);
}
if (EVENT_IS_INTERESTING1(EVENT_NEW_DESC)) {
- char *ids = smartlist_join_strings(identities, " ", 0, &len);
- size_t len = strlen(ids)+32;
- msg = tor_malloc(len);
- tor_snprintf(msg, len, "650 NEWDESC %s\r\n", ids);
- send_control1_event_string(EVENT_NEW_DESC, msg);
- tor_free(ids);
+ msg = smartlist_join_strings(identities, " ", 0, &len);
+ send_control1_event(EVENT_NEW_DESC, "650 NEWDESC %s\r\n", msg);
tor_free(msg);
}
SMARTLIST_FOREACH(identities, char *, cp, tor_free(cp));
diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c
index 17c176ae11..bece3456bc 100644
--- a/src/or/cpuworker.c
+++ b/src/or/cpuworker.c
@@ -36,7 +36,7 @@ static int num_cpuworkers_busy=0;
* the last time we got a key rotation event. */
static time_t last_rotation_time=0;
-static void cpuworker_main(void *data);
+static int cpuworker_main(void *data);
static int spawn_cpuworker(void);
static void spawn_enough_cpuworkers(void);
static void process_pending_task(connection_t *cpuworker);
@@ -137,7 +137,7 @@ connection_cpu_process_inbuf(connection_t *conn)
uint32_t addr;
uint16_t port;
uint16_t circ_id;
- or_connection_t *p_conn;
+ connection_t *p_conn;
circuit_t *circ;
tor_assert(conn);
@@ -181,8 +181,8 @@ connection_cpu_process_inbuf(connection_t *conn)
log_debug(LD_OR,"processed onion for a circ that's gone. Dropping.");
goto done_processing;
}
- tor_assert(! CIRCUIT_IS_ORIGIN(circ));
- if (onionskin_answer(TO_OR_CIRCUIT(circ), CELL_CREATED, buf+TAG_LEN,
+ tor_assert(circ->p_conn);
+ if (onionskin_answer(circ, CELL_CREATED, buf+TAG_LEN,
buf+TAG_LEN+ONIONSKIN_REPLY_LEN) < 0) {
log_warn(LD_OR,"onionskin_answer failed. Closing.");
circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
@@ -222,7 +222,7 @@ done_processing:
* (Note: this _should_ be by addr/port, since we're concerned with specific
* connections, not with routers (where we'd use identity).)
*/
-static void
+static int
cpuworker_main(void *data)
{
char question[ONIONSKIN_CHALLENGE_LEN];
@@ -308,6 +308,7 @@ cpuworker_main(void *data)
tor_close_socket(fd);
crypto_thread_cleanup();
spawn_exit();
+ return 0; /* windows wants this function to return an int */
}
/** Launch a new cpuworker. Return 0 if we're happy, -1 if we failed.
@@ -328,9 +329,6 @@ spawn_cpuworker(void)
return -1;
}
- tor_assert(fdarray[0] >= 0);
- tor_assert(fdarray[1] >= 0);
-
fd = fdarray[0];
spawn_func(cpuworker_main, (void*)fdarray);
log_debug(LD_OR,"just spawned a cpu worker.");
@@ -385,7 +383,7 @@ spawn_enough_cpuworkers(void)
static void
process_pending_task(connection_t *cpuworker)
{
- or_circuit_t *circ;
+ circuit_t *circ;
tor_assert(cpuworker);
@@ -443,7 +441,7 @@ int
assign_to_cpuworker(connection_t *cpuworker, uint8_t question_type,
void *task)
{
- or_circuit_t *circ;
+ circuit_t *circ;
char tag[TAG_LEN];
tor_assert(question_type == CPUWORKER_TASK_ONION);
@@ -453,7 +451,7 @@ assign_to_cpuworker(connection_t *cpuworker, uint8_t question_type,
if (question_type == CPUWORKER_TASK_ONION) {
circ = task;
- tor_assert(circ->_base.onionskin);
+ tor_assert(circ->onionskin);
if (num_cpuworkers_busy == num_cpuworkers) {
log_debug(LD_OR,"No idle cpuworkers. Queuing.");
@@ -472,8 +470,7 @@ assign_to_cpuworker(connection_t *cpuworker, uint8_t question_type,
log_info(LD_OR,"circ->p_conn gone. Failing circ.");
return -1;
}
- tag_pack(tag, circ->p_conn->_base.addr, circ->p_conn->_base.port,
- circ->p_circ_id);
+ tag_pack(tag, circ->p_conn->addr, circ->p_conn->port, circ->p_circ_id);
cpuworker->state = CPUWORKER_STATE_BUSY_ONION;
/* touch the lastwritten timestamp, since that's how we check to
@@ -484,9 +481,9 @@ assign_to_cpuworker(connection_t *cpuworker, uint8_t question_type,
connection_write_to_buf((char*)&question_type, 1, cpuworker);
connection_write_to_buf(tag, sizeof(tag), cpuworker);
- connection_write_to_buf(circ->_base.onionskin, ONIONSKIN_CHALLENGE_LEN,
+ connection_write_to_buf(circ->onionskin, ONIONSKIN_CHALLENGE_LEN,
cpuworker);
- tor_free(circ->_base.onionskin);
+ tor_free(circ->onionskin);
}
return 0;
}
diff --git a/src/or/directory.c b/src/or/directory.c
index 91b5322bcf..3a3f3a0012 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -38,17 +38,16 @@ directory_initiate_command(const char *address, uint32_t addr, uint16_t port,
const char *payload, size_t payload_len);
static void
-directory_send_command(dir_connection_t *conn, const char *platform,
+directory_send_command(connection_t *conn, const char *platform,
int purpose, const char *resource,
const char *payload, size_t payload_len);
-static int directory_handle_command(dir_connection_t *conn);
+static int directory_handle_command(connection_t *conn);
static int body_is_plausible(const char *body, size_t body_len, int purpose);
static int purpose_is_private(uint8_t purpose);
static char *http_get_header(const char *headers, const char *which);
-static void http_set_address_origin(const char *headers, connection_t *conn);
-static void connection_dir_download_networkstatus_failed(
- dir_connection_t *conn);
-static void connection_dir_download_routerdesc_failed(dir_connection_t *conn);
+static char *http_get_origin(const char *headers, connection_t *conn);
+static void connection_dir_download_networkstatus_failed(connection_t *conn);
+static void connection_dir_download_routerdesc_failed(connection_t *conn);
static void dir_networkstatus_download_failed(smartlist_t *failed);
static void dir_routerdesc_download_failed(smartlist_t *failed);
static void note_request(const char *key, size_t bytes);
@@ -59,8 +58,6 @@ static void note_request(const char *key, size_t bytes);
* before deciding that one of us has the wrong time? */
#define ALLOW_DIRECTORY_TIME_SKEW (30*60)
-#define X_ADDRESS_HEADER "X-Your-Address-Is: "
-
/********* END VARIABLES ************/
/** Return true iff the directory purpose 'purpose' must use an
@@ -241,7 +238,7 @@ directory_initiate_command_routerstatus(routerstatus_t *status,
{
const char *platform = NULL;
routerinfo_t *router;
- char address_buf[INET_NTOA_BUF_LEN+1];
+ char address_buf[INET_NTOA_BUF_LEN];
struct in_addr in;
const char *address;
if ((router = router_get_by_digest(status->identity_digest))) {
@@ -262,24 +259,24 @@ directory_initiate_command_routerstatus(routerstatus_t *status,
* directory server: Mark the router as down and try again if possible.
*/
void
-connection_dir_request_failed(dir_connection_t *conn)
+connection_dir_request_failed(connection_t *conn)
{
if (router_digest_is_me(conn->identity_digest))
return; /* this was a test fetch. don't retry. */
router_set_status(conn->identity_digest, 0); /* don't try him again */
- if (conn->_base.purpose == DIR_PURPOSE_FETCH_DIR ||
- conn->_base.purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
+ if (conn->purpose == DIR_PURPOSE_FETCH_DIR ||
+ conn->purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
log_info(LD_DIR, "Giving up on directory server at '%s:%d'; retrying",
- conn->_base.address, conn->_base.port);
- directory_get_from_dirserver(conn->_base.purpose, NULL,
+ conn->address, conn->port);
+ directory_get_from_dirserver(conn->purpose, NULL,
0 /* don't retry_if_no_servers */);
- } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
+ } else if (conn->purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
- conn->_base.address);
+ conn->address);
connection_dir_download_networkstatus_failed(conn);
- } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC) {
+ } else if (conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC) {
log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
- conn->_base.address);
+ conn->address);
connection_dir_download_routerdesc_failed(conn);
}
}
@@ -289,7 +286,7 @@ connection_dir_request_failed(dir_connection_t *conn)
* retry the fetch now, later, or never.
*/
static void
-connection_dir_download_networkstatus_failed(dir_connection_t *conn)
+connection_dir_download_networkstatus_failed(connection_t *conn)
{
if (!conn->requested_resource) {
/* We never reached directory_send_command, which means that we never
@@ -302,14 +299,14 @@ connection_dir_download_networkstatus_failed(dir_connection_t *conn)
smartlist_t *trusted_dirs = router_get_trusted_dir_servers();
SMARTLIST_FOREACH(trusted_dirs, trusted_dir_server_t *, ds,
++ds->n_networkstatus_failures);
- directory_get_from_dirserver(conn->_base.purpose, "all.z",
+ directory_get_from_dirserver(conn->purpose, "all.z",
0 /* don't retry_if_no_servers */);
} else if (!strcmpstart(conn->requested_resource, "fp/")) {
/* We were trying to download by fingerprint; mark them all as having
* failed, and possibly retry them later.*/
smartlist_t *failed = smartlist_create();
dir_split_resource_into_fingerprints(conn->requested_resource+3,
- failed, NULL, 0, 0);
+ failed, NULL, 0);
if (smartlist_len(failed)) {
dir_networkstatus_download_failed(failed);
SMARTLIST_FOREACH(failed, char *, cp, tor_free(cp));
@@ -322,13 +319,11 @@ connection_dir_download_networkstatus_failed(dir_connection_t *conn)
* on connection <b>conn</b> failed.
*/
static void
-connection_dir_download_routerdesc_failed(dir_connection_t *conn)
+connection_dir_download_routerdesc_failed(connection_t *conn)
{
/* Try again. No need to increment the failure count for routerdescs, since
* it's not their fault.*/
/* update_router_descriptor_downloads(time(NULL)); */
- (void) conn;
- /* XXXX Why did the above get commented out? -NM */
}
/** Helper for directory_initiate_command_(router|trusted_dir): send the
@@ -343,7 +338,7 @@ directory_initiate_command(const char *address, uint32_t addr,
int private_connection, const char *resource,
const char *payload, size_t payload_len)
{
- dir_connection_t *conn;
+ connection_t *conn;
tor_assert(address);
tor_assert(addr);
@@ -377,19 +372,18 @@ directory_initiate_command(const char *address, uint32_t addr,
tor_assert(0);
}
- conn = TO_DIR_CONN(connection_new(CONN_TYPE_DIR));
+ conn = connection_new(CONN_TYPE_DIR);
/* set up conn so it's got all the data we need to remember */
- conn->_base.addr = addr;
- conn->_base.port = dir_port;
- conn->_base.address = tor_strdup(address);
+ conn->addr = addr;
+ conn->port = dir_port;
+ conn->address = tor_strdup(address);
memcpy(conn->identity_digest, digest, DIGEST_LEN);
- conn->_base.purpose = purpose;
+ conn->purpose = purpose;
/* give it an initial state */
- conn->_base.state = DIR_CONN_STATE_CONNECTING;
- conn->dirconn_direct = (private_connection == 0);
+ conn->state = DIR_CONN_STATE_CONNECTING;
if (!private_connection) {
/* then we want to connect directly */
@@ -399,21 +393,19 @@ directory_initiate_command(const char *address, uint32_t addr,
dir_port = get_options()->HttpProxyPort;
}
- switch (connection_connect(TO_CONN(conn), conn->_base.address, addr,
- dir_port)) {
+ switch (connection_connect(conn, conn->address, addr, dir_port)) {
case -1:
connection_dir_request_failed(conn); /* retry if we want */
- connection_free(TO_CONN(conn));
+ connection_free(conn);
return;
case 1:
- /* start flushing conn */
- conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
+ conn->state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
/* fall through */
case 0:
/* queue the command on the outbuf */
directory_send_command(conn, platform, purpose, resource,
payload, payload_len);
- connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
+ connection_watch_events(conn, EV_READ | EV_WRITE);
/* writable indicates finish, readable indicates broken link,
error indicates broken link in windowsland. */
}
@@ -422,24 +414,23 @@ directory_initiate_command(const char *address, uint32_t addr,
* populate it and add it at the right state
* socketpair and hook up both sides
*/
- conn->_base.s = connection_ap_make_bridge(conn->_base.address,
- conn->_base.port);
- if (conn->_base.s < 0) {
+ conn->s = connection_ap_make_bridge(conn->address, conn->port);
+ if (conn->s < 0) {
log_warn(LD_NET,"Making AP bridge to dirserver failed.");
- connection_mark_for_close(TO_CONN(conn));
+ connection_mark_for_close(conn);
return;
}
- if (connection_add(TO_CONN(conn)) < 0) {
+ if (connection_add(conn) < 0) {
log_warn(LD_NET,"Unable to add AP bridge to dirserver.");
- connection_mark_for_close(TO_CONN(conn));
+ connection_mark_for_close(conn);
return;
}
- conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
+ conn->state = DIR_CONN_STATE_CLIENT_SENDING;
/* queue the command on the outbuf */
directory_send_command(conn, platform, purpose, resource,
payload, payload_len);
- connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
+ connection_watch_events(conn, EV_READ | EV_WRITE);
}
}
@@ -447,7 +438,7 @@ directory_initiate_command(const char *address, uint32_t addr,
* are as in directory_initiate_command.
*/
static void
-directory_send_command(dir_connection_t *conn, const char *platform,
+directory_send_command(connection_t *conn, const char *platform,
int purpose, const char *resource,
const char *payload, size_t payload_len)
{
@@ -460,18 +451,18 @@ directory_send_command(dir_connection_t *conn, const char *platform,
size_t len;
tor_assert(conn);
- tor_assert(conn->_base.type == CONN_TYPE_DIR);
+ tor_assert(conn->type == CONN_TYPE_DIR);
tor_free(conn->requested_resource);
if (resource)
conn->requested_resource = tor_strdup(resource);
/* come up with a string for which Host: we want */
- if (conn->_base.port == 80) {
- strlcpy(hoststring, conn->_base.address, sizeof(hoststring));
+ if (conn->port == 80) {
+ strlcpy(hoststring, conn->address, sizeof(hoststring));
} else {
tor_snprintf(hoststring, sizeof(hoststring),"%s:%d",
- conn->_base.address, conn->_base.port);
+ conn->address, conn->port);
}
/* come up with some proxy lines, if we're using one. */
@@ -568,8 +559,8 @@ directory_send_command(dir_connection_t *conn, const char *platform,
}
tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring);
- connection_write_to_buf(request, strlen(request), TO_CONN(conn));
- connection_write_to_buf(url, strlen(url), TO_CONN(conn));
+ connection_write_to_buf(request, strlen(request), conn);
+ connection_write_to_buf(url, strlen(url), conn);
tor_free(url);
if (!strcmp(httpcommand, "GET") && !payload) {
@@ -584,11 +575,11 @@ directory_send_command(dir_connection_t *conn, const char *platform,
hoststring,
proxyauthstring);
}
- connection_write_to_buf(request, strlen(request), TO_CONN(conn));
+ connection_write_to_buf(request, strlen(request), conn);
if (payload) {
/* then send the payload afterwards too */
- connection_write_to_buf(payload, payload_len, TO_CONN(conn));
+ connection_write_to_buf(payload, payload_len, conn);
}
}
@@ -597,7 +588,7 @@ directory_send_command(dir_connection_t *conn, const char *platform,
* "\%s [http[s]://]\%s HTTP/1..."
* \endverbatim
* If it's well-formed, strdup the second \%s into *<b>url</b>, and
- * nul-terminate it. If the url doesn't start with "/tor/", rewrite it
+ * null-terminate it. If the url doesn't start with "/tor/", rewrite it
* so it does. Return 0.
* Otherwise, return -1.
*/
@@ -664,11 +655,12 @@ http_get_header(const char *headers, const char *which)
return NULL;
}
-/** If <b>headers</b> indicates that a proxy was involved, then rewrite
- * <b>conn</b>-\>address to describe our best guess of the address that
- * originated this HTTP request. */
-static void
-http_set_address_origin(const char *headers, connection_t *conn)
+/** Allocate and return a string describing the source of an HTTP request with
+ * headers <b>headers</b> received on <b>conn</b>. The format is either
+ * "'1.2.3.4'", or "'1.2.3.4' (forwarded for '5.6.7.8')".
+ */
+static char *
+http_get_origin(const char *headers, connection_t *conn)
{
char *fwd;
@@ -676,9 +668,17 @@ http_set_address_origin(const char *headers, connection_t *conn)
if (!fwd)
fwd = http_get_header(headers, "X-Forwarded-For: ");
if (fwd) {
- tor_free(conn->address);
- conn->address = tor_strdup(escaped(fwd));
+ size_t len = strlen(fwd)+strlen(conn->address)+32;
+ char *result = tor_malloc(len);
+ tor_snprintf(result, len, "'%s' (forwarded for %s)", conn->address,
+ escaped(fwd));
tor_free(fwd);
+ return result;
+ } else {
+ size_t len = strlen(conn->address)+3;
+ char *result = tor_malloc(len);
+ tor_snprintf(result, len, "'%s'", conn->address);
+ return result;
}
}
@@ -808,7 +808,7 @@ body_is_plausible(const char *body, size_t len, int purpose)
* The caller will take care of marking the connection for close.
*/
static int
-connection_dir_client_reached_eof(dir_connection_t *conn)
+connection_dir_client_reached_eof(connection_t *conn)
{
char *body;
char *headers;
@@ -820,18 +820,17 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
int compression;
int plausible;
int skewed=0;
- int allow_partial = conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC;
+ int allow_partial = conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC;
int was_compressed=0;
- char *guess;
- switch (fetch_from_buf_http(conn->_base.inbuf,
+ switch (fetch_from_buf_http(conn->inbuf,
&headers, MAX_HEADERS_SIZE,
&body, &body_len, MAX_DIR_SIZE,
allow_partial)) {
case -1: /* overflow */
log_warn(LD_PROTOCOL,
"'fetch' response too large (server '%s:%d'). Closing.",
- conn->_base.address, conn->_base.port);
+ conn->address, conn->port);
return -1;
case 0:
log_info(LD_HTTP,
@@ -844,7 +843,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
if (parse_http_response(headers, &status_code, &date_header,
&compression, &reason) < 0) {
log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.",
- conn->_base.address, conn->_base.port);
+ conn->address, conn->port);
tor_free(body); tor_free(headers);
return -1;
}
@@ -852,15 +851,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
log_debug(LD_DIR,
"Received response from directory server '%s:%d': %d %s",
- conn->_base.address, conn->_base.port, status_code,
- escaped(reason));
-
- /* now check if it's got any hints for us about our IP address. */
- guess = http_get_header(headers, X_ADDRESS_HEADER);
- if (guess) {
- router_new_address_suggestion(guess);
- tor_free(guess);
- }
+ conn->address, conn->port, status_code, escaped(reason));
if (date_header > 0) {
now = time(NULL);
@@ -871,7 +862,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
LD_HTTP,
"Received directory with skewed time (server '%s:%d'): "
"we are %d minutes %s, or the directory is %d minutes %s.",
- conn->_base.address, conn->_base.port,
+ conn->address, conn->port,
abs(delta)/60, delta>0 ? "ahead" : "behind",
abs(delta)/60, delta>0 ? "behind" : "ahead");
skewed = 1; /* don't check the recommended-versions line */
@@ -884,13 +875,12 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
if (status_code == 503) {
log_info(LD_DIR,"Received http status code %d (%s) from server "
"'%s:%d'. I'll try again soon.",
- status_code, escaped(reason), conn->_base.address,
- conn->_base.port);
+ status_code, escaped(reason), conn->address, conn->port);
tor_free(body); tor_free(headers); tor_free(reason);
return -1;
}
- plausible = body_is_plausible(body, body_len, conn->_base.purpose);
+ plausible = body_is_plausible(body, body_len, conn->purpose);
if (compression || !plausible) {
char *new_body = NULL;
size_t new_len = 0;
@@ -917,8 +907,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
log_info(LD_HTTP, "HTTP body from server '%s:%d' was labeled %s, "
"but it seems to be %s.%s",
- conn->_base.address, conn->_base.port, description1,
- description2,
+ conn->address, conn->port, description1, description2,
(compression>0 && guessed>0)?" Trying both.":"");
}
/* Try declared compression first if we can. */
@@ -935,7 +924,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
if (!plausible && !new_body) {
log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
"Unable to decompress HTTP body (server '%s:%d').",
- conn->_base.address, conn->_base.port);
+ conn->address, conn->port);
tor_free(body); tor_free(headers); tor_free(reason);
return -1;
}
@@ -947,40 +936,38 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
}
}
- if (conn->_base.purpose == DIR_PURPOSE_FETCH_DIR) {
+ if (conn->purpose == DIR_PURPOSE_FETCH_DIR) {
/* fetch/process the directory to cache it. */
log_info(LD_DIR,"Received directory (size %d) from server '%s:%d'",
- (int)body_len, conn->_base.address, conn->_base.port);
+ (int)body_len, conn->address, conn->port);
if (status_code != 200) {
log_warn(LD_DIR,"Received http status code %d (%s) from server "
"'%s:%d'. I'll try again soon.",
- status_code, escaped(reason), conn->_base.address,
- conn->_base.port);
+ status_code, escaped(reason), conn->address, conn->port);
tor_free(body); tor_free(headers); tor_free(reason);
return -1;
}
if (router_parse_directory(body) < 0) {
log_notice(LD_DIR,"I failed to parse the directory I fetched from "
- "'%s:%d'. Ignoring.", conn->_base.address, conn->_base.port);
+ "'%s:%d'. Ignoring.", conn->address, conn->port);
}
note_request(was_compressed?"dl/dir.z":"dl/dir", orig_len);
}
- if (conn->_base.purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
+ if (conn->purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
/* just update our list of running routers, if this list is new info */
log_info(LD_DIR,"Received running-routers list (size %d)", (int)body_len);
if (status_code != 200) {
log_warn(LD_DIR,"Received http status code %d (%s) from server "
"'%s:%d'. I'll try again soon.",
- status_code, escaped(reason), conn->_base.address,
- conn->_base.port);
+ status_code, escaped(reason), conn->address, conn->port);
tor_free(body); tor_free(headers); tor_free(reason);
return -1;
}
if (router_parse_runningrouters(body)<0) {
log_warn(LD_DIR,
"Bad running-routers from server '%s:%d'. I'll try again soon.",
- conn->_base.address, conn->_base.port);
+ conn->address, conn->port);
tor_free(body); tor_free(headers); tor_free(reason);
return -1;
}
@@ -988,18 +975,17 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
"dl/running-routers", orig_len);
}
- if (conn->_base.purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
+ if (conn->purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
smartlist_t *which = NULL;
- int source;
char *cp;
log_info(LD_DIR,"Received networkstatus objects (size %d) from server "
- "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
+ "'%s:%d'",(int) body_len, conn->address, conn->port);
if (status_code != 200) {
log_warn(LD_DIR,
"Received http status code %d (%s) from server "
"'%s:%d' while fetching \"/tor/status/%s\". I'll try again soon.",
- status_code, escaped(reason), conn->_base.address,
- conn->_base.port, conn->requested_resource);
+ status_code, escaped(reason), conn->address, conn->port,
+ conn->requested_resource);
tor_free(body); tor_free(headers); tor_free(reason);
connection_dir_download_networkstatus_failed(conn);
return -1;
@@ -1007,13 +993,11 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
note_request(was_compressed?"dl/status.z":"dl/status", orig_len);
if (conn->requested_resource &&
!strcmpstart(conn->requested_resource,"fp/")) {
- source = NS_FROM_DIR_BY_FP;
which = smartlist_create();
dir_split_resource_into_fingerprints(conn->requested_resource+3,
- which, NULL, 0, 0);
+ which, NULL, 0);
} else if (conn->requested_resource &&
!strcmpstart(conn->requested_resource, "all")) {
- source = NS_FROM_DIR_ALL;
which = smartlist_create();
SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
trusted_dir_server_t *, ds,
@@ -1022,11 +1006,6 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
base16_encode(cp, HEX_DIGEST_LEN+1, ds->digest, DIGEST_LEN);
smartlist_add(which, cp);
});
- } else {
- /* Can we even end up here? -- weasel*/
- source = NS_FROM_DIR_BY_FP;
- log_warn(LD_BUG, "we received a networkstatus but we did neither ask"
- "for it by fp/ nor did we ask for all.");
}
cp = body;
while (*cp) {
@@ -1034,7 +1013,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
if (next)
next[1] = '\0';
/* learn from it, and then remove it from 'which' */
- if (router_set_networkstatus(cp, time(NULL), source, which)<0)
+ if (router_set_networkstatus(cp, time(NULL), NS_FROM_DIR, which)<0)
break;
if (next) {
next[1] = 'n';
@@ -1054,17 +1033,17 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
}
}
- if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC) {
+ if (conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC) {
smartlist_t *which = NULL;
int n_asked_for = 0;
log_info(LD_DIR,"Received server info (size %d) from server '%s:%d'",
- (int)body_len, conn->_base.address, conn->_base.port);
+ (int)body_len, conn->address, conn->port);
note_request(was_compressed?"dl/server.z":"dl/server", orig_len);
if (conn->requested_resource &&
!strcmpstart(conn->requested_resource,"d/")) {
which = smartlist_create();
dir_split_resource_into_fingerprints(conn->requested_resource+2,
- which, NULL, 0, 0);
+ which, NULL, 0);
n_asked_for = smartlist_len(which);
}
if (status_code != 200) {
@@ -1075,8 +1054,8 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR,
"Received http status code %d (%s) from server '%s:%d' "
"while fetching \"/tor/server/%s\". I'll try again soon.",
- status_code, escaped(reason), conn->_base.address,
- conn->_base.port, conn->requested_resource);
+ status_code, escaped(reason), conn->address, conn->port,
+ conn->requested_resource);
if (!which) {
connection_dir_download_routerdesc_failed(conn);
} else {
@@ -1095,13 +1074,13 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
if (which || (conn->requested_resource &&
!strcmpstart(conn->requested_resource, "all"))) {
/* as we learn from them, we remove them from 'which' */
- router_load_routers_from_string(body, SAVED_NOWHERE, which);
+ router_load_routers_from_string(body, 0, which);
directory_info_has_arrived(time(NULL), 0);
}
if (which) { /* mark remaining ones as failed */
log_info(LD_DIR, "Received %d/%d routers requested from %s:%d",
n_asked_for-smartlist_len(which), n_asked_for,
- conn->_base.address, (int)conn->_base.port);
+ conn->address, (int)conn->port);
if (smartlist_len(which)) {
dir_routerdesc_download_failed(which);
}
@@ -1114,13 +1093,13 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
routerinfo_t *me = router_get_my_routerinfo();
if (me &&
router_digest_is_me(conn->identity_digest) &&
- me->addr == conn->_base.addr &&
- me->dir_port == conn->_base.port)
+ me->addr == conn->addr &&
+ me->dir_port == conn->port)
router_dirport_found_reachable();
}
}
- if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_DIR) {
+ if (conn->purpose == DIR_PURPOSE_UPLOAD_DIR) {
switch (status_code) {
case 200:
log_info(LD_GENERAL,"eof (status 200) after uploading server "
@@ -1129,7 +1108,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
case 400:
log_warn(LD_GENERAL,"http status 400 (%s) response from "
"dirserver '%s:%d'. Please correct.",
- escaped(reason), conn->_base.address, conn->_base.port);
+ escaped(reason), conn->address, conn->port);
break;
case 403:
log_warn(LD_GENERAL,
@@ -1137,21 +1116,19 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
"'%s:%d'. Is your clock skewed? Have you mailed us your key "
"fingerprint? Are you using the right key? Are you using a "
"private IP address? See http://tor.eff.org/doc/"
- "tor-doc-server.html",escaped(reason), conn->_base.address,
- conn->_base.port);
+ "tor-doc-server.html",escaped(reason), conn->address, conn->port);
break;
default:
log_warn(LD_GENERAL,
"http status %d (%s) reason unexpected (server '%s:%d').",
- status_code, escaped(reason), conn->_base.address,
- conn->_base.port);
+ status_code, escaped(reason), conn->address, conn->port);
break;
}
/* return 0 in all cases, since we don't want to mark any
* dirservers down just because they don't like us. */
}
- if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC) {
+ if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC) {
log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
"(%s))",
(int)body_len, status_code, escaped(reason));
@@ -1163,7 +1140,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
* cleans it up */
} else {
/* success. notify pending connections about this. */
- conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
+ conn->purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
rend_client_desc_here(conn->rend_query);
}
break;
@@ -1179,13 +1156,12 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
default:
log_warn(LD_REND,"http status %d (%s) response unexpected (server "
"'%s:%d').",
- status_code, escaped(reason), conn->_base.address,
- conn->_base.port);
+ status_code, escaped(reason), conn->address, conn->port);
break;
}
}
- if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC) {
+ if (conn->purpose == DIR_PURPOSE_UPLOAD_RENDDESC) {
switch (status_code) {
case 200:
log_info(LD_REND,
@@ -1195,13 +1171,12 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
case 400:
log_warn(LD_REND,"http status 400 (%s) response from dirserver "
"'%s:%d'. Malformed rendezvous descriptor?",
- escaped(reason), conn->_base.address, conn->_base.port);
+ escaped(reason), conn->address, conn->port);
break;
default:
log_warn(LD_REND,"http status %d (%s) response unexpected (server "
"'%s:%d').",
- status_code, escaped(reason), conn->_base.address,
- conn->_base.port);
+ status_code, escaped(reason), conn->address, conn->port);
break;
}
}
@@ -1211,20 +1186,20 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
/** Called when a directory connection reaches EOF */
int
-connection_dir_reached_eof(dir_connection_t *conn)
+connection_dir_reached_eof(connection_t *conn)
{
int retval;
- if (conn->_base.state != DIR_CONN_STATE_CLIENT_READING) {
+ if (conn->state != DIR_CONN_STATE_CLIENT_READING) {
log_info(LD_HTTP,"conn reached eof, not reading. Closing.");
- connection_close_immediate(TO_CONN(conn)); /* error: give up on flushing */
- connection_mark_for_close(TO_CONN(conn));
+ connection_close_immediate(conn); /* error: give up on flushing */
+ connection_mark_for_close(conn);
return -1;
}
retval = connection_dir_client_reached_eof(conn);
if (retval == 0) /* success */
- conn->_base.state = DIR_CONN_STATE_CLIENT_FINISHED;
- connection_mark_for_close(TO_CONN(conn));
+ conn->state = DIR_CONN_STATE_CLIENT_FINISHED;
+ connection_mark_for_close(conn);
return retval;
}
@@ -1232,10 +1207,10 @@ connection_dir_reached_eof(dir_connection_t *conn)
* directory servers and connections <em>at</em> directory servers.)
*/
int
-connection_dir_process_inbuf(dir_connection_t *conn)
+connection_dir_process_inbuf(connection_t *conn)
{
tor_assert(conn);
- tor_assert(conn->_base.type == CONN_TYPE_DIR);
+ tor_assert(conn->type == CONN_TYPE_DIR);
/* Directory clients write, then read data until they receive EOF;
* directory servers read data until they get an HTTP command, then
@@ -1244,9 +1219,9 @@ connection_dir_process_inbuf(dir_connection_t *conn)
*/
/* If we're on the dirserver side, look for a command. */
- if (conn->_base.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
+ if (conn->state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
if (directory_handle_command(conn) < 0) {
- connection_mark_for_close(TO_CONN(conn));
+ connection_mark_for_close(conn);
return -1;
}
return 0;
@@ -1254,7 +1229,7 @@ connection_dir_process_inbuf(dir_connection_t *conn)
/* XXX for READ states, might want to make sure inbuf isn't too big */
- if (!conn->_base.inbuf_reached_eof)
+ if (!conn->inbuf_reached_eof)
log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
return 0;
}
@@ -1263,7 +1238,7 @@ connection_dir_process_inbuf(dir_connection_t *conn)
* <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
*/
static void
-write_http_status_line(dir_connection_t *conn, int status,
+write_http_status_line(connection_t *conn, int status,
const char *reason_phrase)
{
char buf[256];
@@ -1272,43 +1247,7 @@ write_http_status_line(dir_connection_t *conn, int status,
log_warn(LD_BUG,"Bug: status line too long.");
return;
}
- connection_write_to_buf(buf, strlen(buf), TO_CONN(conn));
-}
-
-/** DOCDOC */
-static void
-write_http_response_header(dir_connection_t *conn, ssize_t length,
- const char *type, const char *encoding)
-{
- char date[RFC1123_TIME_LEN+1];
- char tmp[1024];
- char *cp;
-
- tor_assert(conn);
- tor_assert(type);
-
- format_rfc1123_time(date, time(NULL));
- cp = tmp;
- tor_snprintf(cp, sizeof(tmp),
- "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Type: %s\r\n"
- X_ADDRESS_HEADER "%s\r\n",
- date, type, conn->_base.address);
- cp += strlen(tmp);
- if (encoding) {
- tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
- "Content-Encoding: %s\r\n", encoding);
- cp += strlen(cp);
- }
- if (length >= 0) {
- tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
- "Content-Length: %ld\r\n", (long)length);
- cp += strlen(cp);
- }
- if (sizeof(tmp)-(cp-tmp) > 3)
- memcpy(cp, "\r\n", 3);
- else
- tor_assert(0);
- connection_write_to_buf(tmp, strlen(tmp), TO_CONN(conn));
+ connection_write_to_buf(buf, strlen(buf), conn);
}
/** Helper function: return 1 if there are any dir conns of purpose
@@ -1328,7 +1267,7 @@ already_fetching_directory(int purpose)
if (conn->type == CONN_TYPE_DIR &&
conn->purpose == purpose &&
!conn->marked_for_close &&
- !router_digest_is_me(TO_DIR_CONN(conn)->identity_digest))
+ !router_digest_is_me(conn->identity_digest))
return 1;
}
return 0;
@@ -1392,8 +1331,7 @@ directory_dump_request_log(void)
static void
note_request(const char *key, size_t bytes)
{
- (void)key;
- (void)bytes;
+ return;
}
char *
@@ -1409,19 +1347,18 @@ directory_dump_request_log(void)
* conn-\>outbuf. If the request is unrecognized, send a 400.
* Always return 0. */
static int
-directory_handle_command_get(dir_connection_t *conn, char *headers,
+directory_handle_command_get(connection_t *conn, char *headers,
char *body, size_t body_len)
{
size_t dlen;
const char *cp;
char *url = NULL;
- /* We ignore the body of a GET request. */
- (void)body;
- (void)body_len;
+ char tmp[8192];
+ char date[RFC1123_TIME_LEN+1];
log_debug(LD_DIRSERV,"Received GET command.");
- conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
+ conn->state = DIR_CONN_STATE_SERVER_WRITING;
if (parse_http_url(headers, &url) < 0) {
write_http_status_line(conn, 400, "Bad request");
@@ -1431,9 +1368,9 @@ directory_handle_command_get(dir_connection_t *conn, char *headers,
if (!strcmp(url,"/tor/") || !strcmp(url,"/tor/dir.z")) { /* dir fetch */
int deflated = !strcmp(url,"/tor/dir.z");
- cached_dir_t *d = dirserv_get_directory();
+ dlen = dirserv_get_directory(&cp, deflated);
- if (!d) {
+ if (dlen == 0) {
log_notice(LD_DIRSERV,"Client asked for the mirrored directory, but we "
"don't have a good one yet. Sending 503 Dir not available.");
write_http_status_line(conn, 503, "Directory unavailable");
@@ -1443,7 +1380,6 @@ directory_handle_command_get(dir_connection_t *conn, char *headers,
tor_free(url);
return 0;
}
- dlen = deflated ? d->dir_z_len : d->dir_len;
if (global_write_bucket_empty()) {
log_info(LD_DIRSERV,
@@ -1459,18 +1395,16 @@ directory_handle_command_get(dir_connection_t *conn, char *headers,
log_debug(LD_DIRSERV,"Dumping %sdirectory to client.",
deflated?"deflated ":"");
- write_http_response_header(conn, dlen,
- deflated?"application/octet-stream":"text/plain",
- deflated?"deflate":"identity");
- conn->cached_dir = d;
- conn->cached_dir_offset = 0;
- if (! deflated)
- conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
- ++d->refcnt;
-
- /* Prime the connection with some data. */
- conn->dir_spool_src = DIR_SPOOL_CACHED_DIR;
- connection_dirserv_flushed_some(conn);
+ format_rfc1123_time(date, time(NULL));
+ tor_snprintf(tmp, sizeof(tmp),
+ "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
+ "Content-Type: %s\r\nContent-Encoding: %s\r\n\r\n",
+ date,
+ (int)dlen,
+ deflated?"application/octet-stream":"text/plain",
+ deflated?"deflate":"identity");
+ connection_write_to_buf(tmp, strlen(tmp), conn);
+ connection_write_to_buf(cp, dlen, conn);
return 0;
}
@@ -1488,10 +1422,16 @@ directory_handle_command_get(dir_connection_t *conn, char *headers,
return 0;
}
- write_http_response_header(conn, dlen,
+ format_rfc1123_time(date, time(NULL));
+ tor_snprintf(tmp, sizeof(tmp),
+ "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
+ "Content-Type: %s\r\nContent-Encoding: %s\r\n\r\n",
+ date,
+ (int)dlen,
deflated?"application/octet-stream":"text/plain",
deflated?"deflate":"identity");
- connection_write_to_buf(cp, strlen(cp), TO_CONN(conn));
+ connection_write_to_buf(tmp, strlen(tmp), conn);
+ connection_write_to_buf(cp, strlen(cp), conn);
return 0;
}
@@ -1499,12 +1439,12 @@ directory_handle_command_get(dir_connection_t *conn, char *headers,
/* v2 network status fetch. */
size_t url_len = strlen(url);
int deflated = !strcmp(url+url_len-2, ".z");
- smartlist_t *dir_fps = smartlist_create();
+ smartlist_t *dir_objs = smartlist_create();
const char *request_type = NULL;
const char *key = url + strlen("/tor/status/");
if (deflated)
url[url_len-2] = '\0';
- dirserv_get_networkstatus_v2_fingerprints(dir_fps, key);
+ dirserv_get_networkstatus_v2(dir_objs, key);
if (!strcmpstart(key, "fp/"))
request_type = deflated?"/tor/status/fp.z":"/tor/status/fp";
else if (!strcmpstart(key, "authority"))
@@ -1515,24 +1455,32 @@ directory_handle_command_get(dir_connection_t *conn, char *headers,
else
request_type = "/tor/status/?";
tor_free(url);
- if (!smartlist_len(dir_fps)) { /* we failed to create/cache cp */
+ if (!smartlist_len(dir_objs)) { /* we failed to create/cache cp */
write_http_status_line(conn, 503, "Network status object unavailable");
- smartlist_free(dir_fps);
+ smartlist_free(dir_objs);
return 0;
}
- // note_request(request_type,dlen);
- write_http_response_header(conn, -1,
- deflated?"application/octet_stream":"text/plain",
- deflated?"deflate":NULL);
-
- conn->fingerprint_stack = dir_fps;
- if (! deflated)
- conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
-
- /* Prime the connection with some data. */
- conn->dir_spool_src = DIR_SPOOL_NETWORKSTATUS;
- connection_dirserv_flushed_some(conn);
-
+ dlen = 0;
+ SMARTLIST_FOREACH(dir_objs, cached_dir_t *, d,
+ dlen += deflated?d->dir_z_len:d->dir_len);
+ note_request(request_type,dlen);
+ format_rfc1123_time(date, time(NULL));
+ tor_snprintf(tmp, sizeof(tmp),
+ "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
+ "Content-Type: %s\r\nContent-Encoding: %s\r\n\r\n",
+ date,
+ (int)dlen,
+ deflated?"application/octet-stream":"text/plain",
+ deflated?"deflate":"identity");
+ connection_write_to_buf(tmp, strlen(tmp), conn);
+ SMARTLIST_FOREACH(dir_objs, cached_dir_t *, d,
+ {
+ if (deflated)
+ connection_write_to_buf(d->dir_z, d->dir_z_len, conn);
+ else
+ connection_write_to_buf(d->dir, d->dir_len, conn);
+ });
+ smartlist_free(dir_objs);
return 0;
}
@@ -1541,12 +1489,11 @@ directory_handle_command_get(dir_connection_t *conn, char *headers,
int deflated = !strcmp(url+url_len-2, ".z");
int res;
const char *msg;
+ smartlist_t *descs = smartlist_create();
const char *request_type = NULL;
if (deflated)
url[url_len-2] = '\0';
- conn->fingerprint_stack = smartlist_create();
- res = dirserv_get_routerdesc_fingerprints(conn->fingerprint_stack, url,
- &msg);
+ res = dirserv_get_routerdescs(descs, url, &msg);
if (!strcmpstart(url, "/tor/server/fp/"))
request_type = deflated?"/tor/server/fp.z":"/tor/server/fp";
@@ -1559,22 +1506,62 @@ directory_handle_command_get(dir_connection_t *conn, char *headers,
request_type = deflated?"/tor/server/d.z":"/tor/server/d";
else
request_type = "/tor/server/?";
- if (!strcmpstart(url, "/tor/server/d/"))
- conn->dir_spool_src = DIR_SPOOL_SERVER_BY_DIGEST;
- else
- conn->dir_spool_src = DIR_SPOOL_SERVER_BY_FP;
tor_free(url);
if (res < 0)
write_http_status_line(conn, 404, msg);
else {
- write_http_response_header(conn, -1,
- deflated?"application/octet_stream":"text/plain",
- deflated?"deflate":NULL);
- if (deflated)
- conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
- /* Prime the connection with some data. */
- connection_dirserv_flushed_some(conn);
+ size_t len = 0;
+ format_rfc1123_time(date, time(NULL));
+ SMARTLIST_FOREACH(descs, signed_descriptor_t *, ri,
+ len += ri->signed_descriptor_len);
+ if (deflated) {
+ size_t compressed_len;
+ char *compressed;
+ char *inp = tor_malloc(len+smartlist_len(descs)+1);
+ char *cp = inp;
+ SMARTLIST_FOREACH(descs, signed_descriptor_t *, ri,
+ {
+ const char *body = signed_descriptor_get_body(ri);
+ memcpy(cp, body, ri->signed_descriptor_len);
+ cp += ri->signed_descriptor_len;
+ *cp++ = '\n';
+ });
+ *cp = '\0';
+ /* XXXX This could be way more efficiently handled; let's see if it
+ * shows up under oprofile. */
+ if (tor_gzip_compress(&compressed, &compressed_len,
+ inp, cp-inp, ZLIB_METHOD)<0) {
+ tor_free(inp);
+ smartlist_free(descs);
+ return -1;
+ }
+ tor_free(inp);
+ tor_snprintf(tmp, sizeof(tmp),
+ "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
+ "Content-Type: application/octet-stream\r\n"
+ "Content-Encoding: deflate\r\n\r\n",
+ date,
+ (int)compressed_len);
+ note_request(request_type, compressed_len);
+ connection_write_to_buf(tmp, strlen(tmp), conn);
+ connection_write_to_buf(compressed, compressed_len, conn);
+ tor_free(compressed);
+ } else {
+ tor_snprintf(tmp, sizeof(tmp),
+ "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
+ "Content-Type: text/plain\r\n\r\n",
+ date,
+ (int)len);
+ note_request(request_type, len);
+ connection_write_to_buf(tmp, strlen(tmp), conn);
+ SMARTLIST_FOREACH(descs, signed_descriptor_t *, ri,
+ {
+ const char *body = signed_descriptor_get_body(ri);
+ connection_write_to_buf(body, ri->signed_descriptor_len, conn);
+ });
+ }
}
+ smartlist_free(descs);
return 0;
}
@@ -1599,11 +1586,16 @@ directory_handle_command_get(dir_connection_t *conn, char *headers,
}
switch (rend_cache_lookup_desc(query, versioned?-1:0, &descp, &desc_len)) {
case 1: /* valid */
- write_http_response_header(conn, desc_len, "application/octet-stream",
- NULL);
+ format_rfc1123_time(date, time(NULL));
+ tor_snprintf(tmp, sizeof(tmp),
+ "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
+ "Content-Type: application/octet-stream\r\n\r\n",
+ date,
+ (int)desc_len);
note_request("/tor/rendezvous?/", desc_len);
+ connection_write_to_buf(tmp, strlen(tmp), conn);
/* need to send descp separately, because it may include nuls */
- connection_write_to_buf(descp, desc_len, TO_CONN(conn));
+ connection_write_to_buf(descp, desc_len, conn);
break;
case 0: /* well-formed but not present */
write_http_status_line(conn, 404, "Not found");
@@ -1619,8 +1611,14 @@ directory_handle_command_get(dir_connection_t *conn, char *headers,
if (!strcmpstart(url,"/tor/bytes.txt")) {
char *bytes = directory_dump_request_log();
size_t len = strlen(bytes);
- write_http_response_header(conn, len, "text/plain", NULL);
- connection_write_to_buf(bytes, len, TO_CONN(conn));
+ format_rfc1123_time(date, time(NULL));
+ tor_snprintf(tmp, sizeof(tmp),
+ "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
+ "Content-Type: text/plain\r\n\r\n",
+ date,
+ (int)len);
+ connection_write_to_buf(tmp, strlen(tmp), conn);
+ connection_write_to_buf(bytes, len, conn);
tor_free(bytes);
tor_free(url);
return 0;
@@ -1630,32 +1628,14 @@ directory_handle_command_get(dir_connection_t *conn, char *headers,
rewritten to /tor/robots.txt */
char robots[] = "User-agent: *\r\nDisallow: /\r\n";
size_t len = strlen(robots);
- write_http_response_header(conn, len, "text/plain", NULL);
- connection_write_to_buf(robots, len, TO_CONN(conn));
- tor_free(url);
- return 0;
- }
-
- if (!strcmp(url,"/tor/dir-all-weaselhack") &&
- (conn->_base.addr == 0x7f000001ul) &&
- authdir_mode(get_options())) {
- /* XXX until weasel rewrites his scripts XXXX012 */
- char *new_directory=NULL;
-
- if (dirserv_dump_directory_to_string(&new_directory,
- get_identity_key(), 1)) {
- log_warn(LD_BUG, "Error creating full v1 directory.");
- tor_free(new_directory);
- write_http_status_line(conn, 503, "Directory unavailable");
- return 0;
- }
-
- dlen = strlen(new_directory);
-
- write_http_response_header(conn, dlen, "text/plain", "identity");
-
- connection_write_to_buf(new_directory, dlen, TO_CONN(conn));
- tor_free(new_directory);
+ format_rfc1123_time(date, time(NULL));
+ tor_snprintf(tmp, sizeof(tmp),
+ "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
+ "Content-Type: text/plain\r\n\r\n",
+ date,
+ (int)len);
+ connection_write_to_buf(tmp, strlen(tmp), conn);
+ connection_write_to_buf(robots, len, conn);
tor_free(url);
return 0;
}
@@ -1672,14 +1652,16 @@ directory_handle_command_get(dir_connection_t *conn, char *headers,
* response into conn-\>outbuf. If the request is unrecognized, send a
* 400. Always return 0. */
static int
-directory_handle_command_post(dir_connection_t *conn, char *headers,
+directory_handle_command_post(connection_t *conn, char *headers,
char *body, size_t body_len)
{
+ const char *cp;
+ char *origin = NULL;
char *url = NULL;
log_debug(LD_DIRSERV,"Received POST command.");
- conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
+ conn->state = DIR_CONN_STATE_SERVER_WRITING;
if (!authdir_mode(get_options())) {
/* we just provide cached directories; we don't want to
@@ -1694,19 +1676,19 @@ directory_handle_command_post(dir_connection_t *conn, char *headers,
return 0;
}
log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
+ origin = http_get_origin(headers, conn);
if (!strcmp(url,"/tor/")) { /* server descriptor post */
const char *msg;
int r = dirserv_add_descriptor(body, &msg);
tor_assert(msg);
if (r > 0)
- dirserv_get_directory(); /* rebuild and write to disk */
+ dirserv_get_directory(&cp, 0); /* rebuild and write to disk */
switch (r) {
case -2:
case -1:
case 1:
- log_notice(LD_DIRSERV,"Rejected router descriptor from %s.",
- conn->_base.address);
+ log_notice(LD_DIRSERV,"Rejected router descriptor from %s.", origin);
/* malformed descriptor, or something wrong */
write_http_status_line(conn, 400, msg);
break;
@@ -1724,7 +1706,7 @@ directory_handle_command_post(dir_connection_t *conn, char *headers,
// char tmp[1024*2+1];
log_fn(LOG_PROTOCOL_WARN, LD_DIRSERV,
"Rejected rend descriptor (length %d) from %s.",
- (int)body_len, conn->_base.address);
+ (int)body_len, origin);
#if 0
if (body_len <= 1024) {
base16_encode(tmp, sizeof(tmp), body, body_len);
@@ -1743,6 +1725,7 @@ directory_handle_command_post(dir_connection_t *conn, char *headers,
done:
tor_free(url);
+ tor_free(origin);
return 0;
}
@@ -1752,22 +1735,21 @@ directory_handle_command_post(dir_connection_t *conn, char *headers,
* buffer. Return a 0 on success, or -1 on error.
*/
static int
-directory_handle_command(dir_connection_t *conn)
+directory_handle_command(connection_t *conn)
{
char *headers=NULL, *body=NULL;
size_t body_len=0;
int r;
tor_assert(conn);
- tor_assert(conn->_base.type == CONN_TYPE_DIR);
+ tor_assert(conn->type == CONN_TYPE_DIR);
- switch (fetch_from_buf_http(conn->_base.inbuf,
+ switch (fetch_from_buf_http(conn->inbuf,
&headers, MAX_HEADERS_SIZE,
&body, &body_len, MAX_BODY_SIZE, 0)) {
case -1: /* overflow */
log_warn(LD_DIRSERV,
- "Invalid input from address '%s'. Closing.",
- conn->_base.address);
+ "Invalid input from address '%s'. Closing.", conn->address);
return -1;
case 0:
log_debug(LD_DIRSERV,"command not all here yet.");
@@ -1775,7 +1757,6 @@ directory_handle_command(dir_connection_t *conn)
/* case 1, fall through */
}
- http_set_address_origin(headers, TO_CONN(conn));
//log_debug(LD_DIRSERV,"headers %s, body %s.", headers, body);
if (!strncasecmp(headers,"GET",3))
@@ -1798,24 +1779,23 @@ directory_handle_command(dir_connection_t *conn)
* appropriate.
*/
int
-connection_dir_finished_flushing(dir_connection_t *conn)
+connection_dir_finished_flushing(connection_t *conn)
{
tor_assert(conn);
- tor_assert(conn->_base.type == CONN_TYPE_DIR);
+ tor_assert(conn->type == CONN_TYPE_DIR);
- switch (conn->_base.state) {
+ switch (conn->state) {
case DIR_CONN_STATE_CLIENT_SENDING:
log_debug(LD_DIR,"client finished sending command.");
- conn->_base.state = DIR_CONN_STATE_CLIENT_READING;
- connection_stop_writing(TO_CONN(conn));
+ conn->state = DIR_CONN_STATE_CLIENT_READING;
+ connection_stop_writing(conn);
return 0;
case DIR_CONN_STATE_SERVER_WRITING:
log_debug(LD_DIRSERV,"Finished writing server response. Closing.");
- connection_mark_for_close(TO_CONN(conn));
+ connection_mark_for_close(conn);
return 0;
default:
- log_warn(LD_BUG,"Bug: called in unexpected state %d.",
- conn->_base.state);
+ log_warn(LD_BUG,"Bug: called in unexpected state %d.", conn->state);
tor_fragile_assert();
return -1;
}
@@ -1825,16 +1805,16 @@ connection_dir_finished_flushing(dir_connection_t *conn)
/** Connected handler for directory connections: begin sending data to the
* server */
int
-connection_dir_finished_connecting(dir_connection_t *conn)
+connection_dir_finished_connecting(connection_t *conn)
{
tor_assert(conn);
- tor_assert(conn->_base.type == CONN_TYPE_DIR);
- tor_assert(conn->_base.state == DIR_CONN_STATE_CONNECTING);
+ tor_assert(conn->type == CONN_TYPE_DIR);
+ tor_assert(conn->state == DIR_CONN_STATE_CONNECTING);
log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
- conn->_base.address,conn->_base.port);
+ conn->address,conn->port);
- conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
+ conn->state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
return 0;
}
@@ -1912,21 +1892,21 @@ dir_routerdesc_download_failed(smartlist_t *failed)
* the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
* non-NULL, set it to 1 if the resource ends in ".z", else set it to 0. If
* decode_hex is true, then delete all elements that aren't hex digests, and
- * decode the rest. If sort_uniq is true, then sort the list and remove
- * all duplicates.
+ * decode the rest.
*/
int
dir_split_resource_into_fingerprints(const char *resource,
smartlist_t *fp_out, int *compressed_out,
- int decode_hex, int sort_uniq)
+ int decode_hex)
{
- smartlist_t *fp_tmp = smartlist_create();
+ int old_len;
tor_assert(fp_out);
- smartlist_split_string(fp_tmp, resource, "+", 0, 0);
+ old_len = smartlist_len(fp_out);
+ smartlist_split_string(fp_out, resource, "+", 0, 0);
if (compressed_out)
*compressed_out = 0;
- if (smartlist_len(fp_tmp)) {
- char *last = smartlist_get(fp_tmp,smartlist_len(fp_tmp)-1);
+ if (smartlist_len(fp_out) > old_len) {
+ char *last = smartlist_get(fp_out,smartlist_len(fp_out)-1);
size_t last_len = strlen(last);
if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
last[last_len-2] = '\0';
@@ -1937,51 +1917,27 @@ dir_split_resource_into_fingerprints(const char *resource,
if (decode_hex) {
int i;
char *cp, *d = NULL;
- for (i = 0; i < smartlist_len(fp_tmp); ++i) {
- cp = smartlist_get(fp_tmp, i);
+ for (i = old_len; i < smartlist_len(fp_out); ++i) {
+ cp = smartlist_get(fp_out, i);
if (strlen(cp) != HEX_DIGEST_LEN) {
log_info(LD_DIR,
"Skipping digest %s with non-standard length.", escaped(cp));
- smartlist_del_keeporder(fp_tmp, i--);
+ smartlist_del(fp_out, i--);
goto again;
}
d = tor_malloc_zero(DIGEST_LEN);
if (base16_decode(d, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0) {
log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp));
- smartlist_del_keeporder(fp_tmp, i--);
+ smartlist_del(fp_out, i--);
goto again;
}
- smartlist_set(fp_tmp, i, d);
+ smartlist_set(fp_out, i, d);
d = NULL;
again:
tor_free(cp);
tor_free(d);
}
}
- if (sort_uniq) {
- smartlist_t *fp_tmp2 = smartlist_create();
- int i;
- if (decode_hex)
- smartlist_sort_digests(fp_tmp);
- else
- smartlist_sort_strings(fp_tmp);
- if (smartlist_len(fp_tmp))
- smartlist_add(fp_tmp2, smartlist_get(fp_tmp, 0));
- for (i = 1; i < smartlist_len(fp_tmp); ++i) {
- char *cp = smartlist_get(fp_tmp, i);
- char *last = smartlist_get(fp_tmp2, smartlist_len(fp_tmp2)-1);
-
- if ((decode_hex && memcmp(cp, last, DIGEST_LEN))
- || (!decode_hex && strcasecmp(cp, last)))
- smartlist_add(fp_tmp2, cp);
- else
- tor_free(cp);
- }
- smartlist_free(fp_tmp);
- fp_tmp = fp_tmp2;
- }
- smartlist_add_all(fp_out, fp_tmp);
- smartlist_free(fp_tmp);
return 0;
}
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index b159afed97..e85575e6f9 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -36,7 +36,7 @@ static int runningrouters_is_dirty = 1;
static int the_v2_networkstatus_is_dirty = 1;
static void directory_remove_invalid(void);
-static cached_dir_t *dirserv_regenerate_directory(void);
+static int dirserv_regenerate_directory(void);
static char *format_versions_list(config_line_t *ln);
/* Should be static; exposed for testing */
int add_fingerprint_to_dir(const char *nickname, const char *fp,
@@ -51,7 +51,6 @@ dirserv_get_status_impl(const char *fp, const char *nickname,
const char **msg, int should_log);
static int dirserv_thinks_router_is_reachable(routerinfo_t *router,
time_t now);
-static void clear_cached_dir(cached_dir_t *d);
/************** Fingerprint handling code ************/
@@ -122,31 +121,24 @@ dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk)
return 0;
}
-/** Load the nickname-\>fingerprint mappings stored in the approved-routers
- * file. The file format is line-based, with each non-blank holding one
- * nickname, some space, and a fingerprint for that nickname. On success,
- * replace the current fingerprint list with the new list and return 0. On
- * failure, leave the current fingerprint list untouched, and
- * return -1. */
+/** Parse the nickname-\>fingerprint mappings stored in the file named
+ * <b>fname</b>. The file format is line-based, with each non-blank
+ * holding one nickname, some space, and a fingerprint for that
+ * nickname. On success, replace the current fingerprint list with
+ * the contents of <b>fname</b> and return 0. On failure, leave the
+ * current fingerprint list untouched, and return -1. */
int
-dirserv_load_fingerprint_file(void)
+dirserv_parse_fingerprint_file(const char *fname)
{
- char fname[512];
char *cf;
char *nickname, *fingerprint;
smartlist_t *fingerprint_list_new;
int result;
config_line_t *front=NULL, *list;
- or_options_t *options = get_options();
-
- tor_snprintf(fname, sizeof(fname),
- "%s/approved-routers", options->DataDirectory);
- log_info(LD_GENERAL,
- "Reloading approved fingerprints from \"%s\"...", fname);
cf = read_file_to_str(fname, 0);
if (!cf) {
- if (options->NamingAuthoritativeDir) {
+ if (get_options()->NamingAuthoritativeDir) {
log_warn(LD_FS, "Cannot open fingerprint file '%s'. Failing.", fname);
return -1;
} else {
@@ -462,7 +454,6 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
case FP_INVALID:
ri->is_named = ri->is_valid = 0;
break;
- case FP_REJECT:
default:
tor_assert(0);
}
@@ -489,7 +480,7 @@ dirserv_add_descriptor(const char *desc, const char **msg)
*msg = NULL;
/* Check: is the descriptor syntactically valid? */
- ri = router_parse_entry_from_string(desc, NULL, 1);
+ ri = router_parse_entry_from_string(desc, NULL);
if (!ri) {
log_warn(LD_DIRSERV, "Couldn't parse uploaded server descriptor");
*msg = "Rejected: Couldn't parse server descriptor.";
@@ -665,7 +656,7 @@ list_single_server_status(routerinfo_t *desc, int is_live)
/** Each server needs to have passed a reachability test no more
* than this number of seconds ago, or he is listed as down in
* the directory. */
-#define REACHABLE_TIMEOUT (45*60)
+#define REACHABLE_TIMEOUT (30*60)
/** Treat a router as alive if
* - It's me, and I'm not hibernating.
@@ -769,12 +760,11 @@ live_enough_for_v1_dir(routerinfo_t *ri, time_t now)
/** Generate a new v1 directory and write it into a newly allocated string.
* Point *<b>dir_out</b> to the allocated string. Sign the
* directory with <b>private_key</b>. Return 0 on success, -1 on
- * failure. If <b>complete</b> is set, give us all the descriptors;
- * otherwise leave out non-running and non-valid ones.
+ * failure.
*/
int
dirserv_dump_directory_to_string(char **dir_out,
- crypto_pk_env_t *private_key, int complete)
+ crypto_pk_env_t *private_key)
{
char *cp;
char *router_status;
@@ -808,7 +798,7 @@ dirserv_dump_directory_to_string(char **dir_out,
buf_len = 2048+strlen(recommended_versions)+
strlen(router_status);
SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri,
- if (complete || live_enough_for_v1_dir(ri, now))
+ if (live_enough_for_v1_dir(ri, now))
buf_len += ri->cache_info.signed_descriptor_len+1);
buf = tor_malloc(buf_len);
/* We'll be comparing against buf_len throughout the rest of the
@@ -834,7 +824,7 @@ dirserv_dump_directory_to_string(char **dir_out,
{
size_t len = ri->cache_info.signed_descriptor_len;
const char *body;
- if (!complete && !live_enough_for_v1_dir(ri, now))
+ if (!live_enough_for_v1_dir(ri, now))
continue;
if (cp+len+1 >= buf+buf_len)
goto truncated;
@@ -874,12 +864,12 @@ dirserv_dump_directory_to_string(char **dir_out,
}
/** Most recently generated encoded signed directory. (auth dirservers only.)*/
-static cached_dir_t *the_directory = NULL;
+static cached_dir_t the_directory = { NULL, NULL, 0, 0, 0 };
/* Used only by non-auth dirservers: The directory and runningrouters we'll
* serve when requested. */
-static cached_dir_t *cached_directory = NULL;
-static cached_dir_t cached_runningrouters = { NULL, NULL, 0, 0, 0, -1 };
+static cached_dir_t cached_directory = { NULL, NULL, 0, 0, 0 };
+static cached_dir_t cached_runningrouters = { NULL, NULL, 0, 0, 0 };
/* Used for other dirservers' v2 network statuses. Map from hexdigest to
* cached_dir_t. */
@@ -889,7 +879,7 @@ static digestmap_t *cached_v2_networkstatus = NULL;
* <b>directory</b> published on <b>when</b>, unless <b>when</b> is older than
* the last value, or too far in the future.
*
- * Does not copy <b>directory</b>; frees it if it isn't used.
+ * Does not copy <b>directory</b>; free it if it isn't used.
*/
static void
set_cached_dir(cached_dir_t *d, char *directory, time_t when)
@@ -916,32 +906,6 @@ set_cached_dir(cached_dir_t *d, char *directory, time_t when)
}
}
-/** DOCDOC */
-void
-cached_dir_decref(cached_dir_t *d)
-{
- if (!d || --d->refcnt > 0)
- return;
- clear_cached_dir(d);
- tor_free(d);
-}
-
-/** DOCDOC */
-static cached_dir_t *
-new_cached_dir(char *s, time_t published)
-{
- cached_dir_t *d = tor_malloc_zero(sizeof(cached_dir_t));
- d->refcnt = 1;
- d->dir = s;
- d->dir_len = strlen(s);
- d->published = published;
- if (tor_gzip_compress(&(d->dir_z), &(d->dir_z_len), d->dir, d->dir_len,
- ZLIB_METHOD)) {
- log_warn(LD_BUG, "Error compressing directory");
- }
- return d;
-}
-
/** Remove all storage held in <b>d</b>, but do not free <b>d</b> itself. */
static void
clear_cached_dir(cached_dir_t *d)
@@ -953,10 +917,11 @@ clear_cached_dir(cached_dir_t *d)
/** Free all storage held by the cached_dir_t in <b>d</b>. */
static void
-_free_cached_dir(void *_d)
+free_cached_dir(void *_d)
{
cached_dir_t *d = (cached_dir_t *)_d;
- cached_dir_decref(d);
+ clear_cached_dir(d);
+ tor_free(d);
}
/** If we have no cached directory, or it is older than <b>when</b>, then
@@ -966,12 +931,9 @@ void
dirserv_set_cached_directory(const char *directory, time_t published,
int is_running_routers)
{
- if (is_running_routers) {
- set_cached_dir(&cached_runningrouters, tor_strdup(directory), published);
- } else {
- cached_dir_decref(cached_directory);
- cached_directory = new_cached_dir(tor_strdup(directory), published);
- }
+ cached_dir_t *d;
+ d = is_running_routers ? &cached_runningrouters : &cached_directory;
+ set_cached_dir(d, tor_strdup(directory), published);
}
/** We've just received a v2 network-status for an authoritative directory
@@ -985,30 +947,28 @@ dirserv_set_cached_networkstatus_v2(const char *networkstatus,
const char *identity,
time_t published)
{
- cached_dir_t *d, *old_d;
+ cached_dir_t *d;
smartlist_t *trusted_dirs;
if (!cached_v2_networkstatus)
cached_v2_networkstatus = digestmap_new();
- old_d = digestmap_get(cached_v2_networkstatus, identity);
- if (!old_d && !networkstatus)
- return;
+ if (!(d = digestmap_get(cached_v2_networkstatus, identity))) {
+ if (!networkstatus)
+ return;
+ d = tor_malloc_zero(sizeof(cached_dir_t));
+ digestmap_set(cached_v2_networkstatus, identity, d);
+ }
+ tor_assert(d);
if (networkstatus) {
- if (!old_d || published > old_d->published) {
- d = new_cached_dir(tor_strdup(networkstatus), published);
- digestmap_set(cached_v2_networkstatus, identity, d);
- if (old_d)
- cached_dir_decref(old_d);
+ if (published > d->published) {
+ set_cached_dir(d, tor_strdup(networkstatus), published);
}
} else {
- if (old_d) {
- digestmap_remove(cached_v2_networkstatus, identity);
- cached_dir_decref(old_d);
- }
+ free_cached_dir(d);
+ digestmap_remove(cached_v2_networkstatus, identity);
}
- /* Now purge old entries. */
trusted_dirs = router_get_trusted_dir_servers();
if (digestmap_size(cached_v2_networkstatus) >
smartlist_len(trusted_dirs) + MAX_UNTRUSTED_NETWORKSTATUSES) {
@@ -1033,7 +993,7 @@ dirserv_set_cached_networkstatus_v2(const char *networkstatus,
tor_assert(oldest);
d = digestmap_remove(cached_v2_networkstatus, oldest);
if (d)
- cached_dir_decref(d);
+ free_cached_dir(d);
}
}
@@ -1045,7 +1005,7 @@ dirserv_set_cached_networkstatus_v2(const char *networkstatus,
static cached_dir_t *
dirserv_pick_cached_dir_obj(cached_dir_t *cache_src,
cached_dir_t *auth_src,
- time_t dirty, cached_dir_t *(*regenerate)(void),
+ time_t dirty, int (*regenerate)(void),
const char *name,
int is_v1_object)
{
@@ -1058,7 +1018,7 @@ dirserv_pick_cached_dir_obj(cached_dir_t *cache_src,
/* We're authoritative. */
if (regenerate != NULL) {
if (dirty && dirty + DIR_REGEN_SLACK_TIME < time(NULL)) {
- if (!(auth_src = regenerate())) {
+ if (regenerate()) {
log_err(LD_BUG, "Couldn't generate %s?", name);
exit(1);
}
@@ -1082,11 +1042,10 @@ dirserv_pick_cached_dir_obj(cached_dir_t *cache_src,
* this kind of object.
**/
static size_t
-dirserv_get_obj(const char **out,
- int compress,
+dirserv_get_obj(const char **out, int compress,
cached_dir_t *cache_src,
cached_dir_t *auth_src,
- time_t dirty, cached_dir_t *(*regenerate)(void),
+ time_t dirty, int (*regenerate)(void),
const char *name,
int is_v1_object)
{
@@ -1105,54 +1064,53 @@ dirserv_get_obj(const char **out,
}
}
-/** Return the most recently generated encoded signed directory, generating a
- * new one as necessary. If not an authoritative directory may return NULL if
- * no directory is yet cached.*/
-cached_dir_t *
-dirserv_get_directory(void)
+/** Set *<b>directory</b> to the most recently generated encoded signed
+ * directory, generating a new one as necessary. If not an authoritative
+ * directory may return 0 if no directory is yet cached.*/
+size_t
+dirserv_get_directory(const char **directory, int compress)
{
- return dirserv_pick_cached_dir_obj(cached_directory, the_directory,
- the_directory_is_dirty,
- dirserv_regenerate_directory,
- "server directory", 1);
+ return dirserv_get_obj(directory, compress,
+ &cached_directory, &the_directory,
+ the_directory_is_dirty,
+ dirserv_regenerate_directory,
+ "server directory", 1);
}
/**
- * Generate a fresh v1 directory (authdirservers only); set the_directory
- * and return a pointer to the new value.
+ * Generate a fresh v1 directory (authdirservers only.)
*/
-static cached_dir_t *
+static int
dirserv_regenerate_directory(void)
{
char *new_directory=NULL;
if (dirserv_dump_directory_to_string(&new_directory,
- get_identity_key(), 0)) {
+ get_identity_key())) {
log_warn(LD_BUG, "Error creating directory.");
tor_free(new_directory);
- return NULL;
+ return -1;
}
- cached_dir_decref(the_directory);
- the_directory = new_cached_dir(new_directory, time(NULL));
+ set_cached_dir(&the_directory, new_directory, time(NULL));
log_info(LD_DIRSERV,"New directory (size %d) has been built.",
- (int)the_directory->dir_len);
+ (int)the_directory.dir_len);
log_debug(LD_DIRSERV,"New directory (size %d):\n%s",
- (int)the_directory->dir_len, the_directory->dir);
+ (int)the_directory.dir_len, the_directory.dir);
the_directory_is_dirty = 0;
/* Save the directory to disk so we re-load it quickly on startup.
*/
- dirserv_set_cached_directory(the_directory->dir, time(NULL), 0);
+ dirserv_set_cached_directory(the_directory.dir, time(NULL), 0);
- return the_directory;
+ return 0;
}
/** For authoritative directories: the current (v1) network status */
-static cached_dir_t the_runningrouters = { NULL, NULL, 0, 0, 0, -1 };
+static cached_dir_t the_runningrouters = { NULL, NULL, 0, 0, 0 };
/** Replace the current running-routers list with a newly generated one. */
-static cached_dir_t *
+static int
generate_runningrouters(void)
{
char *s=NULL;
@@ -1197,11 +1155,11 @@ generate_runningrouters(void)
set_cached_dir(&the_runningrouters, s, time(NULL));
runningrouters_is_dirty = 0;
- return &the_runningrouters;
+ return 0;
err:
tor_free(s);
tor_free(router_status);
- return NULL;
+ return -1;
}
/** Set *<b>rr</b> to the most recently generated encoded signed
@@ -1218,7 +1176,7 @@ dirserv_get_runningrouters(const char **rr, int compress)
}
/** For authoritative directories: the current (v2) network status */
-static cached_dir_t *the_v2_networkstatus = NULL;
+static cached_dir_t the_v2_networkstatus = { NULL, NULL, 0, 0, 0 };
static int
should_generate_v2_networkstatus(void)
@@ -1302,9 +1260,6 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
if (smartlist_len(bandwidths)) {
fast_bandwidth = *(uint32_t*)smartlist_get(bandwidths,
smartlist_len(bandwidths)/8);
- if (fast_bandwidth < ROUTER_REQUIRED_MIN_BANDWIDTH)
- fast_bandwidth = *(uint32_t*)smartlist_get(bandwidths,
- smartlist_len(bandwidths)/4);
guard_bandwidth = *(uint32_t*)smartlist_get(bandwidths,
smartlist_len(bandwidths)/2);
}
@@ -1323,7 +1278,7 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
/** For authoritative directories only: replace the contents of
* <b>the_v2_networkstatus</b> with a newly generated network status
* object. */
-static cached_dir_t *
+static int
generate_v2_networkstatus(void)
{
#define LONGEST_STATUS_FLAG_NAME_LEN 7
@@ -1335,7 +1290,7 @@ generate_v2_networkstatus(void)
/* second line */ \
(LONGEST_STATUS_FLAG_NAME_LEN+1)*N_STATUS_FLAGS + 2)
- cached_dir_t *r = NULL;
+ int r = -1;
size_t len, identity_pkey_len;
char *status = NULL, *client_versions = NULL, *server_versions = NULL,
*identity_pkey = NULL, *hostname = NULL;
@@ -1355,7 +1310,7 @@ generate_v2_networkstatus(void)
int versioning = options->VersioningAuthoritativeDir;
const char *contact;
- if (resolve_my_address(LOG_WARN, options, &addr, &hostname)<0) {
+ if (resolve_my_address(options, &addr, &hostname)<0) {
log_warn(LD_NET, "Couldn't resolve my hostname");
goto done;
}
@@ -1404,9 +1359,9 @@ generate_v2_networkstatus(void)
naming ? " Names" : "",
versioning ? " Versions" : "",
versioning ? "client-versions " : "",
- versioning ? client_versions : "",
+ client_versions,
versioning ? "\nserver-versions " : "",
- versioning ? server_versions : "",
+ server_versions,
versioning ? "\n" : "",
identity_pkey);
outp = status + strlen(status);
@@ -1497,14 +1452,13 @@ generate_v2_networkstatus(void)
goto done;
}
- if (the_v2_networkstatus)
- cached_dir_decref(the_v2_networkstatus);
- the_v2_networkstatus = new_cached_dir(status, time(NULL));
+ set_cached_dir(&the_v2_networkstatus, status, time(NULL));
status = NULL; /* So it doesn't get double-freed. */
the_v2_networkstatus_is_dirty = 0;
- router_set_networkstatus(the_v2_networkstatus->dir,
- time(NULL), NS_GENERATED, NULL);
- r = the_v2_networkstatus;
+ router_set_networkstatus(the_v2_networkstatus.dir, time(NULL), NS_GENERATED,
+ NULL);
+
+ r = 0;
done:
tor_free(client_versions);
tor_free(server_versions);
@@ -1514,45 +1468,6 @@ generate_v2_networkstatus(void)
return r;
}
-/* DOCDOC */
-void
-dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result,
- const char *key)
-{
- tor_assert(result);
-
- if (!cached_v2_networkstatus)
- cached_v2_networkstatus = digestmap_new();
-
- if (should_generate_v2_networkstatus())
- generate_v2_networkstatus();
-
- if (!strcmp(key,"authority")) {
- if (get_options()->AuthoritativeDir) {
- routerinfo_t *me = router_get_my_routerinfo();
- if (me)
- smartlist_add(result,
- tor_memdup(me->cache_info.identity_digest, DIGEST_LEN));
- }
- } else if (!strcmp(key, "all")) {
- digestmap_iter_t *iter;
- iter = digestmap_iter_init(cached_v2_networkstatus);
- while (!digestmap_iter_done(iter)) {
- const char *ident;
- void *val;
- digestmap_iter_get(iter, &ident, &val);
- smartlist_add(result, tor_memdup(ident, DIGEST_LEN));
- iter = digestmap_iter_next(cached_v2_networkstatus, iter);
- }
- smartlist_sort_digests(result);
- if (smartlist_len(result) == 0)
- log_warn(LD_DIRSERV,
- "Client requested 'all' network status objects; we have none.");
- } else if (!strcmpstart(key, "fp/")) {
- dir_split_resource_into_fingerprints(key+3, result, NULL, 1, 1);
- }
-}
-
/** Look for a network status object as specified by <b>key</b>, which should
* be either "authority" (to find a network status generated by us), a hex
* identity digest (to find a network status generated by given directory), or
@@ -1571,7 +1486,7 @@ dirserv_get_networkstatus_v2(smartlist_t *result,
if (get_options()->AuthoritativeDir) {
cached_dir_t *d =
dirserv_pick_cached_dir_obj(NULL,
- the_v2_networkstatus,
+ &the_v2_networkstatus,
the_v2_networkstatus_is_dirty,
generate_v2_networkstatus,
"network status list", 0);
@@ -1598,7 +1513,7 @@ dirserv_get_networkstatus_v2(smartlist_t *result,
"Client requested 'all' network status objects; we have none.");
} else if (!strcmpstart(key, "fp/")) {
smartlist_t *digests = smartlist_create();
- dir_split_resource_into_fingerprints(key+3, digests, NULL, 1, 1);
+ dir_split_resource_into_fingerprints(key+3, digests, NULL, 1);
SMARTLIST_FOREACH(digests, char *, cp,
{
cached_dir_t *cached;
@@ -1619,44 +1534,6 @@ dirserv_get_networkstatus_v2(smartlist_t *result,
}
}
-/** As dirserv_get_routerdescs(), but instead of getting signed_descriptor_t
- * pointers, adds copies of digests to fps_out. For a /tor/server/d/ request,
- * adds descriptor digests; for other requests, adds identity digests.
- */
-int
-dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key,
- const char **msg)
-{
- *msg = NULL;
-
- if (!strcmp(key, "/tor/server/all")) {
- routerlist_t *rl = router_get_routerlist();
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
- smartlist_add(fps_out,
- tor_memdup(r->cache_info.identity_digest, DIGEST_LEN)));
- } else if (!strcmp(key, "/tor/server/authority")) {
- routerinfo_t *ri = router_get_my_routerinfo();
- if (ri)
- smartlist_add(fps_out,
- tor_memdup(ri->cache_info.identity_digest, DIGEST_LEN));
- } else if (!strcmpstart(key, "/tor/server/d/")) {
- key += strlen("/tor/server/d/");
- dir_split_resource_into_fingerprints(key, fps_out, NULL, 1, 1);
- } else if (!strcmpstart(key, "/tor/server/fp/")) {
- key += strlen("/tor/server/fp/");
- dir_split_resource_into_fingerprints(key, fps_out, NULL, 1, 1);
- } else {
- *msg = "Key not recognized";
- return -1;
- }
-
- if (!smartlist_len(fps_out)) {
- *msg = "Servers unavailable";
- return -1;
- }
- return 0;
-}
-
/** Add a signed_descriptor_t to <b>descs_out</b> for each router matching
* <b>key</b>. The key should be either
* - "/tor/server/authority" for our own routerinfo;
@@ -1692,7 +1569,7 @@ dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
} else if (!strcmpstart(key, "/tor/server/d/")) {
smartlist_t *digests = smartlist_create();
key += strlen("/tor/server/d/");
- dir_split_resource_into_fingerprints(key, digests, NULL, 1, 1);
+ dir_split_resource_into_fingerprints(key, digests, NULL, 1);
SMARTLIST_FOREACH(digests, const char *, d,
{
signed_descriptor_t *sd = router_get_by_descriptor_digest(d);
@@ -1705,7 +1582,7 @@ dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
smartlist_t *digests = smartlist_create();
time_t cutoff = time(NULL) - ROUTER_MAX_AGE_TO_PUBLISH;
key += strlen("/tor/server/fp/");
- dir_split_resource_into_fingerprints(key, digests, NULL, 1, 1);
+ dir_split_resource_into_fingerprints(key, digests, NULL, 1);
SMARTLIST_FOREACH(digests, const char *, d,
{
if (router_digest_is_me(d)) {
@@ -1756,7 +1633,6 @@ dirserv_orconn_tls_done(const char *address,
tor_assert(address);
tor_assert(digest_rcvd);
tor_assert(nickname_rcvd);
- (void) as_advertised; // XXXX This should really be implemented. -NM
// XXXXNM We should really have a better solution here than dropping
// XXXXNM whole routers; otherwise, they come back way too easily.
@@ -1795,211 +1671,6 @@ dirserv_orconn_tls_done(const char *address,
}
}
-/** Auth dir server only: if <b>try_all</b> is 1, launch connections to
- * all known routers; else we want to load balance such that we only
- * try a few connections per call.
- *
- * The load balancing is such that if we get called once every ten
- * seconds, we will cycle through all the tests in 1280 seconds (a
- * bit over 20 minutes).
- */
-void
-dirserv_test_reachability(int try_all)
-{
- time_t now = time(NULL);
- routerlist_t *rl = router_get_routerlist();
- static char ctr = 0;
-
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, router, {
- const char *id_digest = router->cache_info.identity_digest;
- if (router_is_me(router))
- continue;
- if (try_all || (((uint8_t)id_digest[0]) % 128) == ctr) {
- log_debug(LD_OR,"Testing reachability of %s at %s:%u.",
- router->nickname, router->address, router->or_port);
- /* Remember when we started trying to determine reachability */
- if (!router->testing_since)
- router->testing_since = now;
- connection_or_connect(router->addr, router->or_port,
- id_digest);
- }
- });
- if (!try_all) /* increment ctr */
- ctr = (ctr + 1) % 128;
-}
-
-/** When we're spooling data onto our outbuf, add more whenever we dip
- * below this threshold. */
-#define DIRSERV_BUFFER_MIN 16384
-
-static int
-connection_dirserv_finish_spooling(dir_connection_t *conn)
-{
- if (conn->zlib_state) {
- connection_write_to_buf_zlib(conn, "", 0, 1);
- tor_zlib_free(conn->zlib_state);
- conn->zlib_state = NULL;
- }
- conn->dir_spool_src = DIR_SPOOL_NONE;
- return 0;
-}
-
-/** DOCDOC */
-static int
-connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn)
-{
- int by_fp = conn->dir_spool_src == DIR_SPOOL_SERVER_BY_FP;
-
- while (smartlist_len(conn->fingerprint_stack) &&
- buf_datalen(conn->_base.outbuf) < DIRSERV_BUFFER_MIN) {
- const char *body;
- char *fp = smartlist_pop_last(conn->fingerprint_stack);
- signed_descriptor_t *sd = NULL;
- if (by_fp) {
- if (router_digest_is_me(fp)) {
- sd = &(router_get_my_routerinfo()->cache_info);
- } else {
- routerinfo_t *ri = router_get_by_digest(fp);
- if (ri &&
- ri->cache_info.published_on > time(NULL)-ROUTER_MAX_AGE_TO_PUBLISH)
- sd = &ri->cache_info;
- }
- } else
- sd = router_get_by_descriptor_digest(fp);
- tor_free(fp);
- if (!sd)
- continue;
- body = signed_descriptor_get_body(sd);
- if (conn->zlib_state) {
- int last = ! smartlist_len(conn->fingerprint_stack);
- connection_write_to_buf_zlib(conn, body,
- sd->signed_descriptor_len, last);
- if (last) {
- tor_zlib_free(conn->zlib_state);
- conn->zlib_state = NULL;
- }
- } else {
- connection_write_to_buf(body,
- sd->signed_descriptor_len,
- TO_CONN(conn));
- }
- }
-
- if (!smartlist_len(conn->fingerprint_stack)) {
- /* We just wrote the last one; finish up. */
- conn->dir_spool_src = DIR_SPOOL_NONE;
- smartlist_free(conn->fingerprint_stack);
- conn->fingerprint_stack = NULL;
- }
- return 0;
-}
-
-/** DOCDOC */
-static int
-connection_dirserv_add_dir_bytes_to_outbuf(dir_connection_t *conn)
-{
- int bytes, remaining;
-
- bytes = DIRSERV_BUFFER_MIN - buf_datalen(conn->_base.outbuf);
- tor_assert(bytes > 0);
- tor_assert(conn->cached_dir);
- if (bytes < 8192)
- bytes = 8192;
- remaining = conn->cached_dir->dir_z_len - conn->cached_dir_offset;
- if (bytes > remaining)
- bytes = remaining;
-
- if (conn->zlib_state) {
- connection_write_to_buf_zlib(conn,
- conn->cached_dir->dir_z + conn->cached_dir_offset,
- bytes, bytes == remaining);
- } else {
- connection_write_to_buf(conn->cached_dir->dir_z + conn->cached_dir_offset,
- bytes, TO_CONN(conn));
- }
- conn->cached_dir_offset += bytes;
- if (conn->cached_dir_offset == (int)conn->cached_dir->dir_z_len) {
- /* We just wrote the last one; finish up. */
- connection_dirserv_finish_spooling(conn);
- cached_dir_decref(conn->cached_dir);
- conn->cached_dir = NULL;
- }
- return 0;
-}
-
-/* DOCDOC */
-static int
-connection_dirserv_add_networkstatus_bytes_to_outbuf(dir_connection_t *conn)
-{
-
- while (buf_datalen(conn->_base.outbuf) < DIRSERV_BUFFER_MIN) {
- if (conn->cached_dir) {
- int uncompressing = (conn->zlib_state != NULL);
- int r = connection_dirserv_add_dir_bytes_to_outbuf(conn);
- if (conn->dir_spool_src == DIR_SPOOL_NONE) {
- /* add_dir_bytes thinks we're done with the cached_dir. But we
- * may have more cached_dirs! */
- conn->dir_spool_src = DIR_SPOOL_NETWORKSTATUS;
- /* This bit is tricky. If we were uncompressing the last
- * networkstatus, we may need to make a new zlib object to
- * uncompress the next one. */
- if (uncompressing && ! conn->zlib_state &&
- conn->fingerprint_stack &&
- smartlist_len(conn->fingerprint_stack)) {
- conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
- }
- }
- if (r) return r;
- } else if (conn->fingerprint_stack &&
- smartlist_len(conn->fingerprint_stack)) {
- /* Add another networkstatus; start serving it. */
- char *fp = smartlist_pop_last(conn->fingerprint_stack);
- cached_dir_t *d;
- if (router_digest_is_me(fp))
- d = the_v2_networkstatus;
- else
- d = digestmap_get(cached_v2_networkstatus, fp);
- tor_free(fp);
- if (d) {
- ++d->refcnt;
- conn->cached_dir = d;
- conn->cached_dir_offset = 0;
- }
- } else {
- connection_dirserv_finish_spooling(conn);
- if (conn->fingerprint_stack)
- smartlist_free(conn->fingerprint_stack);
- conn->fingerprint_stack = NULL;
- return 0;
- }
- }
- return 0;
-}
-
-/** Called whenever we have flushed some directory data in state
- * SERVER_WRITING. */
-int
-connection_dirserv_flushed_some(dir_connection_t *conn)
-{
- tor_assert(conn->_base.state == DIR_CONN_STATE_SERVER_WRITING);
-
- if (buf_datalen(conn->_base.outbuf) >= DIRSERV_BUFFER_MIN)
- return 0;
-
- switch (conn->dir_spool_src) {
- case DIR_SPOOL_SERVER_BY_DIGEST:
- case DIR_SPOOL_SERVER_BY_FP:
- return connection_dirserv_add_servers_to_outbuf(conn);
- case DIR_SPOOL_CACHED_DIR:
- return connection_dirserv_add_dir_bytes_to_outbuf(conn);
- case DIR_SPOOL_NETWORKSTATUS:
- return connection_dirserv_add_networkstatus_bytes_to_outbuf(conn);
- case DIR_SPOOL_NONE:
- default:
- return 0;
- }
-}
-
/** Release all storage used by the directory server. */
void
dirserv_free_all(void)
@@ -2012,13 +1683,13 @@ dirserv_free_all(void)
smartlist_free(fingerprint_list);
fingerprint_list = NULL;
}
- cached_dir_decref(the_directory);
+ clear_cached_dir(&the_directory);
clear_cached_dir(&the_runningrouters);
- cached_dir_decref(the_v2_networkstatus);
- cached_dir_decref(cached_directory);
+ clear_cached_dir(&the_v2_networkstatus);
+ clear_cached_dir(&cached_directory);
clear_cached_dir(&cached_runningrouters);
if (cached_v2_networkstatus) {
- digestmap_free(cached_v2_networkstatus, _free_cached_dir);
+ digestmap_free(cached_v2_networkstatus, free_cached_dir);
cached_v2_networkstatus = NULL;
}
}
diff --git a/src/or/dns.c b/src/or/dns.c
index adfadb6f13..5303ced78a 100644
--- a/src/or/dns.c
+++ b/src/or/dns.c
@@ -7,21 +7,20 @@ const char dns_c_id[] =
/**
* \file dns.c
- * \brief Implements a local cache for DNS results for Tor servers.
- * We provide two asynchronous backend implementations:
- * 1) A farm of 'DNS worker' threads or processes to perform DNS lookups for
- * onion routers and cache the results.
- * 2) A wrapper around Adam Langley's eventdns.c code, to send requests
- * to the nameservers asynchronously.
- * (We can't just use gethostbyname() and friends because we really need to
- * be nonblocking.)
+ * \brief Implements a farm of 'DNS worker' threads or processes to
+ * perform DNS lookups for onion routers and cache the results.
+ * [This needs to be done in the background because of the lack of a
+ * good, ubiquitous asynchronous DNS implementation.]
**/
+/* See
+ * http://elvin.dstc.com/ListArchive/elvin-dev/archive/2001/09/msg00027.html
+ * for some approaches to asynchronous dns. We will want to switch once one of
+ * them becomes more commonly available.
+ */
+
#include "or.h"
#include "../common/ht.h"
-#ifdef USE_EVENTDNS
-#include "eventdns.h"
-#endif
/** Longest hostname we're willing to resolve. */
#define MAX_ADDRESSLEN 256
@@ -34,103 +33,51 @@ const char dns_c_id[] =
/** If more than this many processes are idle, shut down the extras. */
#define MAX_IDLE_DNSWORKERS 10
-/** How long will we wait for an answer from the resolver before we decide
- * that the resolver is wedged? */
-#define RESOLVE_MAX_TIMEOUT 300
-
/** Possible outcomes from hostname lookup: permanent failure,
* transient (retryable) failure, and success. */
#define DNS_RESOLVE_FAILED_TRANSIENT 1
#define DNS_RESOLVE_FAILED_PERMANENT 2
#define DNS_RESOLVE_SUCCEEDED 3
-#ifndef USE_EVENTDNS
/** How many dnsworkers we have running right now. */
static int num_dnsworkers=0;
/** How many of the running dnsworkers have an assigned task right now. */
static int num_dnsworkers_busy=0;
/** When did we last rotate the dnsworkers? */
static time_t last_rotation_time=0;
-#else
-/** Have we currently configured nameservers with eventdns? */
-static int nameservers_configured = 0;
-/** What was the resolv_conf fname we last used when configuring the
- * nameservers? Used to check whether we need to reconfigure. */
-static char *resolv_conf_fname = NULL;
-/** What was the mtime on the resolv.conf file we last used when configuring
- * the nameservers? Used to check whether we need to reconfigure. */
-static time_t resolv_conf_mtime = 0;
-#endif
/** Linked list of connections waiting for a DNS answer. */
typedef struct pending_connection_t {
- edge_connection_t *conn;
+ connection_t *conn;
struct pending_connection_t *next;
} pending_connection_t;
-#define CACHED_RESOLVE_MAGIC 0x1234F00D
-
-/* Possible states for a cached resolve_t */
-/** We are waiting for the resolver system to tell us an answer here.
- * When we get one, or when we time out, the state of this cached_resolve_t
- * will become "DONE" and we'll possibly add a CACHED_VALID or a CACHED_FAILED
- * entry. This cached_resolve_t will be in the hash table so that we will
- * know not to launch more requests for this addr, but rather to add more
- * connections to the pending list for the addr. */
-#define CACHE_STATE_PENDING 0
-/** This used to be a pending cached_resolve_t, and we got an answer for it.
- * Now we're waiting for this cached_resolve_t to expire. This should
- * have no pending connections, and should not appear in the hash table. */
-#define CACHE_STATE_DONE 1
-/** We are caching an answer for this address. This should have no pending
- * connections, and should appear in the hash table. */
-#define CACHE_STATE_CACHED_VALID 2
-/** We are caching a failure for this address. This should have no pending
- * connections, and should appear in the hash table */
-#define CACHE_STATE_CACHED_FAILED 3
-
/** A DNS request: possibly completed, possibly pending; cached_resolve
* structs are stored at the OR side in a hash table, and as a linked
* list from oldest to newest.
*/
typedef struct cached_resolve_t {
HT_ENTRY(cached_resolve_t) node;
- uint32_t magic;
char address[MAX_ADDRESSLEN]; /**< The hostname to be resolved. */
- union {
- uint32_t addr; /**< IPv4 addr for <b>address</b>. */
- char *hostname; /**< Hostname for <b>address</b> (if a reverse lookup) */
- } result;
- uint8_t state; /**< Is this cached entry pending/done/valid/failed? */
- uint8_t is_reverse; /**< Is this a reverse (addr-to-hostname) lookup? */
- time_t expire; /**< Remove items from cache after this time. */
- uint32_t ttl; /**< What TTL did the nameserver tell us? */
- /** Connections that want to know when we get an answer for this resolve. */
+ uint32_t addr; /**< IPv4 addr for <b>address</b>. */
+ char state; /**< 0 is pending; 1 means answer is valid; 2 means resolve
+ * failed. */
+#define CACHE_STATE_PENDING 0
+#define CACHE_STATE_VALID 1
+#define CACHE_STATE_FAILED 2
+ uint32_t expire; /**< Remove items from cache after this time. */
pending_connection_t *pending_connections;
+ struct cached_resolve_t *next;
} cached_resolve_t;
-static void purge_expired_resolves(time_t now);
-static void dns_found_answer(const char *address, int is_reverse,
- uint32_t addr, const char *hostname, char outcome,
- uint32_t ttl);
-static void send_resolved_cell(edge_connection_t *conn, uint8_t answer_type);
-static int launch_resolve(edge_connection_t *exitconn);
-#ifndef USE_EVENTDNS
-static void dnsworkers_rotate(void);
-static void dnsworker_main(void *data);
+static void purge_expired_resolves(uint32_t now);
+static int assign_to_dnsworker(connection_t *exitconn);
+static void dns_purge_resolve(cached_resolve_t *resolve);
+static void dns_found_answer(char *address, uint32_t addr, char outcome);
+static int dnsworker_main(void *data);
static int spawn_dnsworker(void);
static int spawn_enough_dnsworkers(void);
-#else
-static int configure_nameservers(int force);
-static int answer_is_wildcarded(const char *ip);
-#endif
-#ifdef DEBUG_DNS_CACHE
-static void _assert_cache_ok(void);
-#define assert_cache_ok() _assert_cache_ok()
-#else
-#define assert_cache_ok() do {} while (0)
-#endif
-static void assert_resolve_ok(cached_resolve_t *resolve);
+static void send_resolved_cell(connection_t *conn, uint8_t answer_type);
/** Hash table of cached_resolve objects. */
static HT_HEAD(cache_map, cached_resolve_t) cache_root;
@@ -141,11 +88,9 @@ static INLINE int
cached_resolves_eq(cached_resolve_t *a, cached_resolve_t *b)
{
/* make this smarter one day? */
- assert_resolve_ok(a); // Not b; b may be just a search.
return !strncmp(a->address, b->address, MAX_ADDRESSLEN);
}
-/** Hash function for cached_resolve objects */
static INLINE unsigned int
cached_resolve_hash(cached_resolve_t *a)
{
@@ -164,82 +109,12 @@ init_cache_map(void)
HT_INIT(&cache_root);
}
-#ifdef USE_EVENTDNS
-/** Helper: called by eventdns when eventdns wants to log something. */
-static void
-eventdns_log_cb(int warn, const char *msg)
-{
- if (!strcmpstart(msg, "Resolve requested for") &&
- get_options()->SafeLogging) {
- log(LOG_INFO, LD_EXIT, "eventdns: Resolve requested.");
- return;
- } else if (!strcmpstart(msg, "Search: ")) {
- return;
- }
- log(warn?LOG_WARN:LOG_INFO, LD_EXIT, "eventdns: %s", msg);
-}
-#endif
-
/** Initialize the DNS subsystem; called by the OR process. */
-int
+void
dns_init(void)
{
init_cache_map();
-#ifdef USE_EVENTDNS
- if (server_mode(get_options()))
- return configure_nameservers(1);
-#else
- dnsworkers_rotate();
-#endif
- return 0;
-}
-
-/** Called when DNS-related options change (or may have changed) */
-void
-dns_reset(void)
-{
-#ifdef USE_EVENTDNS
- or_options_t *options = get_options();
- if (! server_mode(options)) {
- eventdns_clear_nameservers_and_suspend();
- eventdns_search_clear();
- nameservers_configured = 0;
- tor_free(resolv_conf_fname);
- resolv_conf_mtime = 0;
- } else {
- if (configure_nameservers(0) < 0)
- /* XXXX */
- return;
- }
-#else
dnsworkers_rotate();
-#endif
-}
-
-/** Helper: Given a TTL from a DNS response, determine what TTL to give the
- * OP that asked us to resolve it. */
-uint32_t
-dns_clip_ttl(uint32_t ttl)
-{
- if (ttl < MIN_DNS_TTL)
- return MIN_DNS_TTL;
- else if (ttl > MAX_DNS_TTL)
- return MAX_DNS_TTL;
- else
- return ttl;
-}
-
-/** Helper: Given a TTL from a DNS response, determine how long to hold it in
- * our cache. */
-static uint32_t
-dns_get_expiry_ttl(uint32_t ttl)
-{
- if (ttl < MIN_DNS_TTL)
- return MIN_DNS_TTL;
- else if (ttl > MAX_DNS_ENTRY_AGE)
- return MAX_DNS_ENTRY_AGE;
- else
- return ttl;
}
/** Helper: free storage held by an entry in the DNS cache. */
@@ -251,41 +126,10 @@ _free_cached_resolve(cached_resolve_t *r)
r->pending_connections = victim->next;
tor_free(victim);
}
- if (r->is_reverse)
- tor_free(r->result.hostname);
- r->magic = 0xFF00FF00;
tor_free(r);
}
-/** Compare two cached_resolve_t pointers by expiry time, and return
- * less-than-zero, zero, or greater-than-zero as appropriate. Used for
- * the priority queue implementation. */
-static int
-_compare_cached_resolves_by_expiry(const void *_a, const void *_b)
-{
- const cached_resolve_t *a = _a, *b = _b;
- return a->expire - b->expire;
-}
-
-/** Priority queue of cached_resolve_t objects to let us know when they
- * will expire. */
-static smartlist_t *cached_resolve_pqueue = NULL;
-
-/** Set an expiry time for a cached_resolve_t, and add it to the expiry
- * priority queue */
-static void
-set_expiry(cached_resolve_t *resolve, time_t expires)
-{
- tor_assert(resolve && resolve->expire == 0);
- if (!cached_resolve_pqueue)
- cached_resolve_pqueue = smartlist_create();
- resolve->expire = expires;
- smartlist_pqueue_add(cached_resolve_pqueue,
- _compare_cached_resolves_by_expiry,
- resolve);
-}
-
-/** Free all storage held in the DNS cache and related structures. */
+/** Free all storage held in the DNS cache */
void
dns_free_all(void)
{
@@ -296,112 +140,78 @@ dns_free_all(void)
_free_cached_resolve(item);
}
HT_CLEAR(cache_map, &cache_root);
- if (cached_resolve_pqueue)
- smartlist_free(cached_resolve_pqueue);
- cached_resolve_pqueue = NULL;
-#ifdef USE_EVENTDNS
- tor_free(resolv_conf_fname);
-#endif
}
+/** Linked list of resolved addresses, oldest to newest. */
+static cached_resolve_t *oldest_cached_resolve = NULL;
+static cached_resolve_t *newest_cached_resolve = NULL;
+
/** Remove every cached_resolve whose <b>expire</b> time is before <b>now</b>
* from the cache. */
static void
-purge_expired_resolves(time_t now)
+purge_expired_resolves(uint32_t now)
{
- cached_resolve_t *resolve, *removed;
+ cached_resolve_t *resolve;
pending_connection_t *pend;
- edge_connection_t *pendconn;
-
- assert_cache_ok();
- if (!cached_resolve_pqueue)
- return;
-
- while (smartlist_len(cached_resolve_pqueue)) {
- resolve = smartlist_get(cached_resolve_pqueue, 0);
- if (resolve->expire > now)
- break;
- smartlist_pqueue_pop(cached_resolve_pqueue,
- _compare_cached_resolves_by_expiry);
+ connection_t *pendconn;
+ /* this is fast because the linked list
+ * oldest_cached_resolve is ordered by when they came in.
+ */
+ while (oldest_cached_resolve && (oldest_cached_resolve->expire < now)) {
+ resolve = oldest_cached_resolve;
+ log_debug(LD_EXIT,
+ "Forgetting old cached resolve (address %s, expires %lu)",
+ escaped_safe_str(resolve->address),
+ (unsigned long)resolve->expire);
if (resolve->state == CACHE_STATE_PENDING) {
log_debug(LD_EXIT,
- "Expiring a dns resolve %s that's still pending. Forgot to "
- "cull it? DNS resolve didn't tell us about the timeout?",
- escaped_safe_str(resolve->address));
- } else if (resolve->state == CACHE_STATE_CACHED_VALID ||
- resolve->state == CACHE_STATE_CACHED_FAILED) {
- log_debug(LD_EXIT,
- "Forgetting old cached resolve (address %s, expires %lu)",
- escaped_safe_str(resolve->address),
- (unsigned long)resolve->expire);
- tor_assert(!resolve->pending_connections);
- } else {
- tor_assert(resolve->state == CACHE_STATE_DONE);
- tor_assert(!resolve->pending_connections);
+ "Bug: Expiring a dns resolve %s that's still pending."
+ " Forgot to cull it?", escaped_safe_str(resolve->address));
+ tor_fragile_assert();
}
-
if (resolve->pending_connections) {
log_debug(LD_EXIT,
- "Closing pending connections on timed-out DNS resolve!");
+ "Closing pending connections on expiring DNS resolve!");
tor_fragile_assert();
while (resolve->pending_connections) {
pend = resolve->pending_connections;
resolve->pending_connections = pend->next;
/* Connections should only be pending if they have no socket. */
- tor_assert(pend->conn->_base.s == -1);
+ tor_assert(pend->conn->s == -1);
pendconn = pend->conn;
connection_edge_end(pendconn, END_STREAM_REASON_TIMEOUT,
pendconn->cpath_layer);
circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn);
- connection_free(TO_CONN(pendconn));
+ connection_free(pendconn);
tor_free(pend);
}
}
-
- if (resolve->state == CACHE_STATE_CACHED_VALID ||
- resolve->state == CACHE_STATE_CACHED_FAILED ||
- resolve->state == CACHE_STATE_PENDING) {
- removed = HT_REMOVE(cache_map, &cache_root, resolve);
- if (removed != resolve) {
- log_err(LD_BUG, "The expired resolve we purged didn't match any in"
- " the cache. Tried to purge %s (%p); instead got %s (%p).",
- resolve->address, (void*)resolve,
- removed ? removed->address : "NULL", (void*)remove);
- }
- tor_assert(removed == resolve);
- if (resolve->is_reverse)
- tor_free(resolve->result.hostname);
- resolve->magic = 0xF0BBF0BB;
- tor_free(resolve);
- } else {
- /* This should be in state DONE. Make sure it's not in the cache. */
- cached_resolve_t *tmp = HT_FIND(cache_map, &cache_root, resolve);
- tor_assert(tmp != resolve);
- }
+ oldest_cached_resolve = resolve->next;
+ if (!oldest_cached_resolve) /* if there are no more, */
+ newest_cached_resolve = NULL; /* then make sure the list's tail knows
+ * that too */
+ HT_REMOVE(cache_map, &cache_root, resolve);
+ tor_free(resolve);
}
-
- assert_cache_ok();
}
-/** Send a response to the RESOLVE request of a connection. answer_type must
+/** Send a response to the RESOVLE request of a connection. answer_type must
* be one of RESOLVED_TYPE_(IPV4|ERROR|ERROR_TRANSIENT) */
static void
-send_resolved_cell(edge_connection_t *conn, uint8_t answer_type)
+send_resolved_cell(connection_t *conn, uint8_t answer_type)
{
char buf[RELAY_PAYLOAD_SIZE];
size_t buflen;
- uint32_t ttl;
buf[0] = answer_type;
- ttl = dns_clip_ttl(conn->address_ttl);
switch (answer_type)
{
case RESOLVED_TYPE_IPV4:
buf[1] = 4;
- set_uint32(buf+2, htonl(conn->_base.addr));
- set_uint32(buf+6, htonl(ttl));
+ set_uint32(buf+2, htonl(conn->addr));
+ set_uint32(buf+6, htonl(MAX_DNS_ENTRY_AGE)); /*XXXX send a real TTL*/
buflen = 10;
break;
case RESOLVED_TYPE_ERROR_TRANSIENT:
@@ -409,91 +219,35 @@ send_resolved_cell(edge_connection_t *conn, uint8_t answer_type)
{
const char *errmsg = "Error resolving hostname";
int msglen = strlen(errmsg);
-
+ int ttl = (answer_type == RESOLVED_TYPE_ERROR ? MAX_DNS_ENTRY_AGE : 0);
buf[1] = msglen;
strlcpy(buf+2, errmsg, sizeof(buf)-2);
- set_uint32(buf+2+msglen, htonl(ttl));
+ set_uint32(buf+2+msglen, htonl((uint32_t)ttl));
buflen = 6+msglen;
break;
}
default:
tor_assert(0);
- return;
}
- // log_notice(LD_EXIT, "Sending a regular RESOLVED reply: ");
connection_edge_send_command(conn, circuit_get_by_edge_conn(conn),
RELAY_COMMAND_RESOLVED, buf, buflen,
conn->cpath_layer);
}
-/** Send a response to the RESOLVE request of a connection for an in-addr.arpa
- * address on connection <b>conn</b> which yielded the result <b>hostname</b>.
- * The answer type will be RESOLVED_HOSTNAME.
- */
+/** Link <b>r</b> into the hash table of address-to-result mappings, and add it
+ * to the linked list of resolves-by-age. */
static void
-send_resolved_hostname_cell(edge_connection_t *conn, const char *hostname)
-{
- char buf[RELAY_PAYLOAD_SIZE];
- size_t buflen;
- uint32_t ttl;
- size_t namelen = strlen(hostname);
-
- tor_assert(namelen < 256);
- ttl = dns_clip_ttl(conn->address_ttl);
-
- buf[0] = RESOLVED_TYPE_HOSTNAME;
- buf[1] = (uint8_t)namelen;
- memcpy(buf+2, hostname, namelen);
- set_uint32(buf+2+namelen, htonl(ttl));
- buflen = 2+namelen+4;
-
- // log_notice(LD_EXIT, "Sending a reply RESOLVED reply: %s", hostname);
- connection_edge_send_command(conn, circuit_get_by_edge_conn(conn),
- RELAY_COMMAND_RESOLVED, buf, buflen,
- conn->cpath_layer);
- // log_notice(LD_EXIT, "Sent");
-}
-
-/** Given a lower-case <b>address</b>, check to see whether it's a
- * 1.2.3.4.in-addr.arpa address used for reverse lookups. If so,
- * parse it and place the address in <b>in</b> if present. Return 1 on success;
- * 0 if the address is not in in-addr.arpa format, and -1 if the address is
- * malformed. */
-static int
-parse_inaddr_arpa_address(const char *address, struct in_addr *in)
+insert_resolve(cached_resolve_t *r)
{
- char buf[INET_NTOA_BUF_LEN];
- char *cp;
- size_t len;
- struct in_addr inaddr;
-
- cp = strstr(address, ".in-addr.arpa");
- if (!cp || *(cp+strlen(".in-addr.arpa")))
- return 0; /* not an .in-addr.arpa address */
-
- len = cp - address;
-
- if (len >= INET_NTOA_BUF_LEN)
- return -1; /* Too long. */
-
- memcpy(buf, address, len);
- buf[len] = '\0';
- if (tor_inet_aton(buf, &inaddr) == 0)
- return -1; /* malformed. */
-
- if (in) {
- uint32_t a;
- /* reverse the bytes */
- a = ( ((inaddr.s_addr & 0x000000fful) << 24)
- |((inaddr.s_addr & 0x0000ff00ul) << 8)
- |((inaddr.s_addr & 0x00ff0000ul) >> 8)
- |((inaddr.s_addr & 0xff000000ul) >> 24));
- inaddr.s_addr = a;
-
- memcpy(in, &inaddr, sizeof(inaddr));
+ /* add us to the linked list of resolves */
+ if (!oldest_cached_resolve) {
+ oldest_cached_resolve = r;
+ } else {
+ newest_cached_resolve->next = r;
}
+ newest_cached_resolve = r;
- return 1;
+ HT_INSERT(cache_map, &cache_root, r);
}
/** See if we have a cache entry for <b>exitconn</b>-\>address. if so,
@@ -507,28 +261,22 @@ parse_inaddr_arpa_address(const char *address, struct in_addr *in)
* dns farm, and return 0.
*/
int
-dns_resolve(edge_connection_t *exitconn)
+dns_resolve(connection_t *exitconn)
{
cached_resolve_t *resolve;
cached_resolve_t search;
pending_connection_t *pending_connection;
- circuit_t *circ;
struct in_addr in;
- time_t now = time(NULL);
- int is_reverse = 0, is_resolve, r;
- assert_connection_ok(TO_CONN(exitconn), 0);
- tor_assert(exitconn->_base.s == -1);
-
- assert_cache_ok();
-
- is_resolve = exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE;
+ circuit_t *circ;
+ uint32_t now = time(NULL);
+ assert_connection_ok(exitconn, 0);
+ tor_assert(exitconn->s == -1);
- /* first check if exitconn->_base.address is an IP. If so, we already
+ /* first check if exitconn->address is an IP. If so, we already
* know the answer. */
- if (tor_inet_aton(exitconn->_base.address, &in) != 0) {
- exitconn->_base.addr = ntohl(in.s_addr);
- exitconn->address_ttl = DEFAULT_DNS_TTL;
- if (is_resolve)
+ if (tor_inet_aton(exitconn->address, &in) != 0) {
+ exitconn->addr = ntohl(in.s_addr);
+ if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4);
return 1;
}
@@ -537,51 +285,13 @@ dns_resolve(edge_connection_t *exitconn)
* resolves in the hash table. */
purge_expired_resolves(now);
- /* lower-case exitconn->_base.address, so it's in canonical form */
- tor_strlower(exitconn->_base.address);
-
- /* Check whether this is a reverse lookup. If it's malformed, or it's a
- * .in-addr.arpa address but this isn't a resolve request, kill the
- * connecction.
- */
- if ((r = parse_inaddr_arpa_address(exitconn->_base.address, NULL)) != 0) {
- if (r == 1)
- is_reverse = 1;
-
-#ifdef USE_EVENTDNS
- if (!is_reverse || !is_resolve) {
- if (!is_reverse)
- log_info(LD_EXIT, "Bad .in-addr.arpa address \"%s\"; sending error.",
- escaped_safe_str(exitconn->_base.address));
- else if (!is_resolve)
- log_info(LD_EXIT,
- "Attempt to connect to a .in-addr.arpa address \"%s\"; "
- "sending error.",
- escaped_safe_str(exitconn->_base.address));
-#else
- if (1) {
- log_info(LD_PROTOCOL, "Dnsworker code does not support in-addr.arpa "
- "domain, but received a request for \"%s\"; sending error.",
- escaped_safe_str(exitconn->_base.address));
-#endif
-
- if (exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE)
- send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR);
- circ = circuit_get_by_edge_conn(exitconn);
- if (circ)
- circuit_detach_stream(circ, exitconn);
- if (!exitconn->_base.marked_for_close)
- connection_free(TO_CONN(exitconn));
- return -1;
- }
- //log_notice(LD_EXIT, "Looks like an address %s",
- // exitconn->_base.address);
- }
+ /* lower-case exitconn->address, so it's in canonical form */
+ tor_strlower(exitconn->address);
/* now check the hash table to see if 'address' is already there. */
- strlcpy(search.address, exitconn->_base.address, sizeof(search.address));
+ strlcpy(search.address, exitconn->address, sizeof(search.address));
resolve = HT_FIND(cache_map, &cache_root, &search);
- if (resolve && resolve->expire > now) { /* already there */
+ if (resolve) { /* already there */
switch (resolve->state) {
case CACHE_STATE_PENDING:
/* add us to the pending list */
@@ -591,124 +301,121 @@ dns_resolve(edge_connection_t *exitconn)
pending_connection->next = resolve->pending_connections;
resolve->pending_connections = pending_connection;
log_debug(LD_EXIT,"Connection (fd %d) waiting for pending DNS "
- "resolve of %s", exitconn->_base.s,
- escaped_safe_str(exitconn->_base.address));
- exitconn->_base.state = EXIT_CONN_STATE_RESOLVING;
+ "resolve of %s",
+ exitconn->s, escaped_safe_str(exitconn->address));
+ exitconn->state = EXIT_CONN_STATE_RESOLVING;
return 0;
- case CACHE_STATE_CACHED_VALID:
+ case CACHE_STATE_VALID:
+ exitconn->addr = resolve->addr;
log_debug(LD_EXIT,"Connection (fd %d) found cached answer for %s",
- exitconn->_base.s,
- escaped_safe_str(resolve->address));
- exitconn->address_ttl = resolve->ttl;
- if (resolve->is_reverse) {
- tor_assert(is_resolve);
- send_resolved_hostname_cell(exitconn, resolve->result.hostname);
- } else {
- exitconn->_base.addr = resolve->result.addr;
- if (is_resolve)
- send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4);
- }
+ exitconn->s, escaped_safe_str(exitconn->address));
+ if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
+ send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4);
return 1;
- case CACHE_STATE_CACHED_FAILED:
+ case CACHE_STATE_FAILED:
log_debug(LD_EXIT,"Connection (fd %d) found cached error for %s",
- exitconn->_base.s,
- escaped_safe_str(exitconn->_base.address));
- if (is_resolve)
+ exitconn->s, escaped_safe_str(exitconn->address));
+ if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR);
circ = circuit_get_by_edge_conn(exitconn);
if (circ)
circuit_detach_stream(circ, exitconn);
- if (!exitconn->_base.marked_for_close)
- connection_free(TO_CONN(exitconn));
+ if (!exitconn->marked_for_close)
+ connection_free(exitconn);
return -1;
- case CACHE_STATE_DONE:
- log_err(LD_BUG, "Found a 'DONE' dns resolve still in the cache.");
- tor_fragile_assert();
}
tor_assert(0);
}
/* not there, need to add it */
resolve = tor_malloc_zero(sizeof(cached_resolve_t));
- resolve->magic = CACHED_RESOLVE_MAGIC;
resolve->state = CACHE_STATE_PENDING;
- resolve->is_reverse = is_reverse;
- strlcpy(resolve->address, exitconn->_base.address, sizeof(resolve->address));
+ resolve->expire = now + MAX_DNS_ENTRY_AGE;
+ strlcpy(resolve->address, exitconn->address, sizeof(resolve->address));
- /* add this connection to the pending list */
+ /* add us to the pending list */
pending_connection = tor_malloc_zero(sizeof(pending_connection_t));
pending_connection->conn = exitconn;
resolve->pending_connections = pending_connection;
- exitconn->_base.state = EXIT_CONN_STATE_RESOLVING;
+ exitconn->state = EXIT_CONN_STATE_RESOLVING;
- /* Add this resolve to the cache and priority queue. */
- HT_INSERT(cache_map, &cache_root, resolve);
- set_expiry(resolve, now + RESOLVE_MAX_TIMEOUT);
-
- log_debug(LD_EXIT,"Launching %s.",
- escaped_safe_str(exitconn->_base.address));
- assert_cache_ok();
- return launch_resolve(exitconn);
+ insert_resolve(resolve);
+ return assign_to_dnsworker(exitconn);
}
-/** Log an error and abort if conn is waiting for a DNS resolve.
+/** Find or spawn a dns worker process to handle resolving
+ * <b>exitconn</b>-\>address; tell that dns worker to begin resolving.
*/
-void
-assert_connection_edge_not_dns_pending(edge_connection_t *conn)
+static int
+assign_to_dnsworker(connection_t *exitconn)
{
- pending_connection_t *pend;
- cached_resolve_t **resolve;
+ connection_t *dnsconn;
+ unsigned char len;
- HT_FOREACH(resolve, cache_map, &cache_root) {
- for (pend = (*resolve)->pending_connections;
- pend;
- pend = pend->next) {
- tor_assert(pend->conn != conn);
- }
+ tor_assert(exitconn->state == EXIT_CONN_STATE_RESOLVING);
+ tor_assert(exitconn->s == -1);
+
+ /* respawn here, to be sure there are enough */
+ if (spawn_enough_dnsworkers() < 0) {
+ goto err;
}
-}
-/** Log an error and abort if any connection waiting for a DNS resolve is
- * corrupted. */
-void
-assert_all_pending_dns_resolves_ok(void)
-{
- pending_connection_t *pend;
- cached_resolve_t **resolve;
+ dnsconn = connection_get_by_type_state(CONN_TYPE_DNSWORKER,
+ DNSWORKER_STATE_IDLE);
- HT_FOREACH(resolve, cache_map, &cache_root) {
- for (pend = (*resolve)->pending_connections;
- pend;
- pend = pend->next) {
- assert_connection_ok(TO_CONN(pend->conn), 0);
- tor_assert(pend->conn->_base.s == -1);
- tor_assert(!connection_in_array(TO_CONN(pend->conn)));
- }
+ if (!dnsconn) {
+ log_warn(LD_EXIT,"no idle dns workers. Failing.");
+ if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
+ send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR_TRANSIENT);
+ goto err;
}
+
+ log_debug(LD_EXIT,
+ "Connection (fd %d) needs to resolve %s; assigning "
+ "to DNSWorker (fd %d)", exitconn->s,
+ escaped_safe_str(exitconn->address), dnsconn->s);
+
+ tor_free(dnsconn->address);
+ dnsconn->address = tor_strdup(exitconn->address);
+ dnsconn->state = DNSWORKER_STATE_BUSY;
+ /* touch the lastwritten timestamp, since that's how we check to
+ * see how long it's been since we asked the question, and sometimes
+ * we check before the first call to connection_handle_write(). */
+ dnsconn->timestamp_lastwritten = time(NULL);
+ num_dnsworkers_busy++;
+
+ len = strlen(dnsconn->address);
+ connection_write_to_buf((char*)&len, 1, dnsconn);
+ connection_write_to_buf(dnsconn->address, len, dnsconn);
+
+ return 0;
+err:
+ dns_cancel_pending_resolve(exitconn->address); /* also sends end and frees */
+ return -1;
}
/** Remove <b>conn</b> from the list of connections waiting for conn-\>address.
*/
void
-connection_dns_remove(edge_connection_t *conn)
+connection_dns_remove(connection_t *conn)
{
pending_connection_t *pend, *victim;
cached_resolve_t search;
cached_resolve_t *resolve;
- tor_assert(conn->_base.type == CONN_TYPE_EXIT);
- tor_assert(conn->_base.state == EXIT_CONN_STATE_RESOLVING);
+ tor_assert(conn->type == CONN_TYPE_EXIT);
+ tor_assert(conn->state == EXIT_CONN_STATE_RESOLVING);
- strlcpy(search.address, conn->_base.address, sizeof(search.address));
+ strlcpy(search.address, conn->address, sizeof(search.address));
resolve = HT_FIND(cache_map, &cache_root, &search);
if (!resolve) {
log_notice(LD_BUG, "Address %s is not pending. Dropping.",
- escaped_safe_str(conn->_base.address));
+ escaped_safe_str(conn->address));
return;
}
tor_assert(resolve->pending_connections);
- assert_connection_ok(TO_CONN(conn),0);
+ assert_connection_ok(conn,0);
pend = resolve->pending_connections;
@@ -717,7 +424,7 @@ connection_dns_remove(edge_connection_t *conn)
tor_free(pend);
log_debug(LD_EXIT, "First connection (fd %d) no longer waiting "
"for resolve of %s",
- conn->_base.s, escaped_safe_str(conn->_base.address));
+ conn->s, escaped_safe_str(conn->address));
return;
} else {
for ( ; pend->next; pend = pend->next) {
@@ -727,7 +434,7 @@ connection_dns_remove(edge_connection_t *conn)
tor_free(victim);
log_debug(LD_EXIT,
"Connection (fd %d) no longer waiting for resolve of %s",
- conn->_base.s, escaped_safe_str(conn->_base.address));
+ conn->s, escaped_safe_str(conn->address));
return; /* more are pending */
}
}
@@ -735,23 +442,59 @@ connection_dns_remove(edge_connection_t *conn)
}
}
+/** Log an error and abort if conn is waiting for a DNS resolve.
+ */
+void
+assert_connection_edge_not_dns_pending(connection_t *conn)
+{
+ pending_connection_t *pend;
+ cached_resolve_t **resolve;
+
+ HT_FOREACH(resolve, cache_map, &cache_root) {
+ for (pend = (*resolve)->pending_connections;
+ pend;
+ pend = pend->next) {
+ tor_assert(pend->conn != conn);
+ }
+ }
+}
+
+/** Log an error and abort if any connection waiting for a DNS resolve is
+ * corrupted. */
+void
+assert_all_pending_dns_resolves_ok(void)
+{
+ pending_connection_t *pend;
+ cached_resolve_t **resolve;
+
+ HT_FOREACH(resolve, cache_map, &cache_root) {
+ for (pend = (*resolve)->pending_connections;
+ pend;
+ pend = pend->next) {
+ assert_connection_ok(pend->conn, 0);
+ tor_assert(pend->conn->s == -1);
+ tor_assert(!connection_in_array(pend->conn));
+ }
+ }
+}
+
/** Mark all connections waiting for <b>address</b> for close. Then cancel
* the resolve for <b>address</b> itself, and remove any cached results for
* <b>address</b> from the cache.
*/
void
-dns_cancel_pending_resolve(const char *address)
+dns_cancel_pending_resolve(char *address)
{
pending_connection_t *pend;
cached_resolve_t search;
- cached_resolve_t *resolve, *tmp;
- edge_connection_t *pendconn;
+ cached_resolve_t *resolve;
+ connection_t *pendconn;
circuit_t *circ;
strlcpy(search.address, address, sizeof(search.address));
resolve = HT_FIND(cache_map, &cache_root, &search);
- if (!resolve || resolve->state != CACHE_STATE_PENDING) {
+ if (!resolve) {
log_notice(LD_BUG,"Address %s is not pending. Dropping.",
escaped_safe_str(address));
return;
@@ -773,104 +516,84 @@ dns_cancel_pending_resolve(const char *address)
escaped_safe_str(address));
while (resolve->pending_connections) {
pend = resolve->pending_connections;
- pend->conn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED;
+ pend->conn->state = EXIT_CONN_STATE_RESOLVEFAILED;
pendconn = pend->conn;
- assert_connection_ok(TO_CONN(pendconn), 0);
- tor_assert(pendconn->_base.s == -1);
- if (!pendconn->_base.marked_for_close) {
+ tor_assert(pendconn->s == -1);
+ if (!pendconn->marked_for_close) {
connection_edge_end(pendconn, END_STREAM_REASON_RESOURCELIMIT,
pendconn->cpath_layer);
}
circ = circuit_get_by_edge_conn(pendconn);
if (circ)
circuit_detach_stream(circ, pendconn);
- connection_free(TO_CONN(pendconn));
+ connection_free(pendconn);
resolve->pending_connections = pend->next;
tor_free(pend);
}
- tmp = HT_REMOVE(cache_map, &cache_root, resolve);
- if (tmp != resolve) {
- log_err(LD_BUG, "The cancelled resolve we purged didn't match any in"
- " the cache. Tried to purge %s (%p); instead got %s (%p).",
- resolve->address, (void*)resolve,
- tmp ? tmp->address : "NULL", (void*)tmp);
- }
- tor_assert(tmp == resolve);
-
- resolve->state = CACHE_STATE_DONE;
+ dns_purge_resolve(resolve);
}
-/** Helper: adds an entry to the DNS cache mapping <b>address</b> to the ipv4
- * address <b>addr</b> (if is_reverse is 0) or the hostname <b>hostname</b> if
- * (is_reverse is 1). <b>ttl</b> is a cache ttl; <b>outcome</b> is one of
- * DNS_RESOLVE_{FAILED_TRANSIENT|FAILED_PERMANENT|SUCCEEDED}.
- **/
+/** Remove <b>resolve</b> from the cache.
+ */
static void
-add_answer_to_cache(const char *address, int is_reverse, uint32_t addr,
- const char *hostname, char outcome, uint32_t ttl)
+dns_purge_resolve(cached_resolve_t *resolve)
{
- cached_resolve_t *resolve;
- if (outcome == DNS_RESOLVE_FAILED_TRANSIENT)
- return;
-
- /* XXX This is dumb, but it seems to workaround a bug I can't find. We
- * should nail this so we can cache reverse DNS answers. -NM */
- if (is_reverse)
- return;
+ cached_resolve_t *tmp;
- //log_notice(LD_EXIT, "Adding to cache: %s -> %s (%lx, %s), %d",
- // address, is_reverse?"(reverse)":"", (unsigned long)addr,
- // hostname?hostname:"NULL",(int)outcome);
-
- resolve = tor_malloc_zero(sizeof(cached_resolve_t));
- resolve->magic = CACHED_RESOLVE_MAGIC;
- resolve->state = (outcome == DNS_RESOLVE_SUCCEEDED) ?
- CACHE_STATE_CACHED_VALID : CACHE_STATE_CACHED_FAILED;
- strlcpy(resolve->address, address, sizeof(resolve->address));
- resolve->is_reverse = is_reverse;
- if (is_reverse) {
- tor_assert(hostname);
- resolve->result.hostname = tor_strdup(hostname);
+ /* remove resolve from the linked list */
+ if (resolve == oldest_cached_resolve) {
+ oldest_cached_resolve = resolve->next;
+ if (oldest_cached_resolve == NULL)
+ newest_cached_resolve = NULL;
} else {
- tor_assert(!hostname);
- resolve->result.addr = addr;
+ /* FFFF make it a doubly linked list if this becomes too slow */
+ for (tmp=oldest_cached_resolve; tmp && tmp->next != resolve; tmp=tmp->next)
+ ;
+ tor_assert(tmp); /* it's got to be in the list, or we screwed up somewhere
+ * else */
+ tmp->next = resolve->next; /* unlink it */
+
+ if (newest_cached_resolve == resolve)
+ newest_cached_resolve = tmp;
}
- resolve->ttl = ttl;
- assert_resolve_ok(resolve);
- HT_INSERT(cache_map, &cache_root, resolve);
- set_expiry(resolve, time(NULL) + dns_get_expiry_ttl(ttl));
+
+ /* remove resolve from the map */
+ HT_REMOVE(cache_map, &cache_root, resolve);
+
+ tor_free(resolve);
}
-/** Called on the OR side when a DNS worker or the eventdns library tells us
- * the outcome of a DNS resolve: tell all pending connections about the result
- * of the lookup, and cache the value. (<b>address</b> is a NUL-terminated
- * string containing the address to look up; <b>addr</b> is an IPv4 address in
- * host order; <b>outcome</b> is one of
+/** Called on the OR side when a DNS worker tells us the outcome of a DNS
+ * resolve: tell all pending connections about the result of the lookup, and
+ * cache the value. (<b>address</b> is a NUL-terminated string containing the
+ * address to look up; <b>addr</b> is an IPv4 address in host order;
+ * <b>outcome</b> is one of
* DNS_RESOLVE_{FAILED_TRANSIENT|FAILED_PERMANENT|SUCCEEDED}.
*/
static void
-dns_found_answer(const char *address, int is_reverse, uint32_t addr,
- const char *hostname, char outcome, uint32_t ttl)
+dns_found_answer(char *address, uint32_t addr, char outcome)
{
pending_connection_t *pend;
cached_resolve_t search;
- cached_resolve_t *resolve, *removed;
- edge_connection_t *pendconn;
+ cached_resolve_t *resolve;
+ connection_t *pendconn;
circuit_t *circ;
- assert_cache_ok();
-
strlcpy(search.address, address, sizeof(search.address));
resolve = HT_FIND(cache_map, &cache_root, &search);
if (!resolve) {
log_info(LD_EXIT,"Resolved unasked address %s; caching anyway.",
escaped_safe_str(address));
- add_answer_to_cache(address, is_reverse, addr, hostname, outcome, ttl);
+ resolve = tor_malloc_zero(sizeof(cached_resolve_t));
+ resolve->state = (outcome == DNS_RESOLVE_SUCCEEDED) ?
+ CACHE_STATE_VALID : CACHE_STATE_FAILED;
+ resolve->addr = addr;
+ resolve->expire = time(NULL) + MAX_DNS_ENTRY_AGE;
+ insert_resolve(resolve);
return;
}
- assert_resolve_ok(resolve);
if (resolve->state != CACHE_STATE_PENDING) {
/* XXXX Maybe update addr? or check addr for consistency? Or let
@@ -886,18 +609,23 @@ dns_found_answer(const char *address, int is_reverse, uint32_t addr,
* resolve X.Y.Z. */
/* tor_assert(resolve->state == CACHE_STATE_PENDING); */
+ resolve->addr = addr;
+ if (outcome == DNS_RESOLVE_SUCCEEDED)
+ resolve->state = CACHE_STATE_VALID;
+ else
+ resolve->state = CACHE_STATE_FAILED;
+
while (resolve->pending_connections) {
pend = resolve->pending_connections;
+ assert_connection_ok(pend->conn,time(NULL));
+ pend->conn->addr = resolve->addr;
pendconn = pend->conn; /* don't pass complex things to the
connection_mark_for_close macro */
- assert_connection_ok(TO_CONN(pendconn),time(NULL));
- pendconn->_base.addr = addr;
- pendconn->address_ttl = ttl;
- if (outcome != DNS_RESOLVE_SUCCEEDED) {
+ if (resolve->state == CACHE_STATE_FAILED) {
/* prevent double-remove. */
- pendconn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED;
- if (pendconn->_base.purpose == EXIT_PURPOSE_CONNECT) {
+ pendconn->state = EXIT_CONN_STATE_RESOLVEFAILED;
+ if (pendconn->purpose == EXIT_PURPOSE_CONNECT) {
connection_edge_end(pendconn, END_STREAM_REASON_RESOLVEFAILED,
pendconn->cpath_layer);
/* This detach must happen after we send the end cell. */
@@ -907,109 +635,40 @@ dns_found_answer(const char *address, int is_reverse, uint32_t addr,
/* This detach must happen after we send the resolved cell. */
circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn);
}
- connection_free(TO_CONN(pendconn));
+ connection_free(pendconn);
} else {
- if (pendconn->_base.purpose == EXIT_PURPOSE_CONNECT) {
- tor_assert(!is_reverse);
+ if (pendconn->purpose == EXIT_PURPOSE_CONNECT) {
/* prevent double-remove. */
- pend->conn->_base.state = EXIT_CONN_STATE_CONNECTING;
+ pend->conn->state = EXIT_CONN_STATE_CONNECTING;
circ = circuit_get_by_edge_conn(pend->conn);
tor_assert(circ);
- tor_assert(!CIRCUIT_IS_ORIGIN(circ));
/* unlink pend->conn from resolving_streams, */
circuit_detach_stream(circ, pend->conn);
/* and link it to n_streams */
- pend->conn->next_stream = TO_OR_CIRCUIT(circ)->n_streams;
+ pend->conn->next_stream = circ->n_streams;
pend->conn->on_circuit = circ;
- TO_OR_CIRCUIT(circ)->n_streams = pend->conn;
+ circ->n_streams = pend->conn;
connection_exit_connect(pend->conn);
} else {
/* prevent double-remove. This isn't really an accurate state,
* but it does the right thing. */
- pendconn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED;
- if (is_reverse)
- send_resolved_hostname_cell(pendconn, hostname);
- else
- send_resolved_cell(pendconn, RESOLVED_TYPE_IPV4);
+ pendconn->state = EXIT_CONN_STATE_RESOLVEFAILED;
+ send_resolved_cell(pendconn, RESOLVED_TYPE_IPV4);
circ = circuit_get_by_edge_conn(pendconn);
tor_assert(circ);
circuit_detach_stream(circ, pendconn);
- connection_free(TO_CONN(pendconn));
+ connection_free(pendconn);
}
}
resolve->pending_connections = pend->next;
tor_free(pend);
}
- resolve->state = CACHE_STATE_DONE;
- removed = HT_REMOVE(cache_map, &cache_root, &search);
- if (removed != resolve) {
- log_err(LD_BUG, "The pending resolve we found wasn't removable from"
- " the cache. Tried to purge %s (%p); instead got %s (%p).",
- resolve->address, (void*)resolve,
- removed ? removed->address : "NULL", (void*)removed);
+ if (outcome == DNS_RESOLVE_FAILED_TRANSIENT) { /* remove from cache */
+ dns_purge_resolve(resolve);
}
- assert_resolve_ok(resolve);
- assert_cache_ok();
-
- add_answer_to_cache(address, is_reverse, addr, hostname, outcome, ttl);
- assert_cache_ok();
-}
-
-#ifndef USE_EVENTDNS
-/** Find or spawn a dns worker process to handle resolving
- * <b>exitconn</b>-\>address; tell that dns worker to begin resolving.
- */
-static int
-launch_resolve(edge_connection_t *exitconn)
-{
- connection_t *dnsconn;
- unsigned char len;
-
- tor_assert(exitconn->_base.state == EXIT_CONN_STATE_RESOLVING);
- assert_connection_ok(TO_CONN(exitconn), 0);
- tor_assert(exitconn->_base.s == -1);
-
- /* respawn here, to be sure there are enough */
- if (spawn_enough_dnsworkers() < 0) {
- goto err;
- }
-
- dnsconn = connection_get_by_type_state(CONN_TYPE_DNSWORKER,
- DNSWORKER_STATE_IDLE);
-
- if (!dnsconn) {
- log_warn(LD_EXIT,"no idle dns workers. Failing.");
- if (exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE)
- send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR_TRANSIENT);
- goto err;
- }
-
- log_debug(LD_EXIT,
- "Connection (fd %d) needs to resolve %s; assigning "
- "to DNSWorker (fd %d)", exitconn->_base.s,
- escaped_safe_str(exitconn->_base.address), dnsconn->s);
-
- tor_free(dnsconn->address);
- dnsconn->address = tor_strdup(exitconn->_base.address);
- dnsconn->state = DNSWORKER_STATE_BUSY;
- /* touch the lastwritten timestamp, since that's how we check to
- * see how long it's been since we asked the question, and sometimes
- * we check before the first call to connection_handle_write(). */
- dnsconn->timestamp_lastwritten = time(NULL);
- num_dnsworkers_busy++;
-
- len = strlen(dnsconn->address);
- connection_write_to_buf((char*)&len, 1, dnsconn);
- connection_write_to_buf(dnsconn->address, len, dnsconn);
-
- return 0;
-err:
- /* also sends end and frees */
- dns_cancel_pending_resolve(exitconn->_base.address);
- return -1;
}
/******************************************************************/
@@ -1028,8 +687,6 @@ connection_dns_finished_flushing(connection_t *conn)
return 0;
}
-/** Called when a connection to a dnsworker hits an EOF; this only happens
- * when a dnsworker dies unexpectedly. */
int
connection_dns_reached_eof(connection_t *conn)
{
@@ -1054,7 +711,6 @@ connection_dns_process_inbuf(connection_t *conn)
{
char success;
uint32_t addr;
- int ttl;
tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_DNSWORKER);
@@ -1090,9 +746,7 @@ connection_dns_process_inbuf(connection_t *conn)
tor_assert(success >= DNS_RESOLVE_FAILED_TRANSIENT);
tor_assert(success <= DNS_RESOLVE_SUCCEEDED);
-
- ttl = (success == DNS_RESOLVE_FAILED_TRANSIENT) ? 0 : MAX_DNS_ENTRY_AGE;
- dns_found_answer(conn->address, 0, ntohl(addr), NULL, success, ttl);
+ dns_found_answer(conn->address, ntohl(addr), success);
tor_free(conn->address);
conn->address = tor_strdup("<idle>");
@@ -1109,7 +763,7 @@ connection_dns_process_inbuf(connection_t *conn)
/** Close and re-open all idle dnsworkers; schedule busy ones to be closed
* and re-opened once they're no longer busy.
**/
-static void
+void
dnsworkers_rotate(void)
{
connection_t *dnsconn;
@@ -1140,10 +794,10 @@ dnsworkers_rotate(void)
* The dnsworker runs indefinitely, until its connection is closed or an error
* occurs.
*/
-static void
+static int
dnsworker_main(void *data)
{
- char address[MAX_ADDRESSLEN+1]; /* Plus a byte for a final '.' */
+ char address[MAX_ADDRESSLEN];
unsigned char address_len;
char *log_address;
char answer[5];
@@ -1151,7 +805,6 @@ dnsworker_main(void *data)
int *fdarray = data;
int fd;
int result;
- int search = get_options()->ServerDNSSearchDomains;
/* log_fn(LOG_NOTICE,"After spawn: fdarray @%d has %d:%d", (int)fdarray,
* fdarray[0],fdarray[1]); */
@@ -1189,13 +842,7 @@ dnsworker_main(void *data)
crypto_thread_cleanup();
spawn_exit();
}
- /* Add a period to prevent local domain search, and NUL-terminate. */
- if (address[address_len-1] != '.' && !search) {
- address[address_len] = '.';
- address[address_len+1] = '\0';
- } else {
- address[address_len] = '\0';
- }
+ address[address_len] = 0; /* null terminate it */
log_address = esc_for_log(safe_str(address));
result = tor_lookup_hostname(address, &ip);
@@ -1205,17 +852,17 @@ dnsworker_main(void *data)
switch (result) {
case 1:
/* XXX result can never be 1, because we set it to -1 above on error */
- log_info(LD_NET,"Could not resolve dest addr %s (transient)",
+ log_info(LD_NET,"Could not resolve dest addr %s (transient).",
log_address);
answer[0] = DNS_RESOLVE_FAILED_TRANSIENT;
break;
case -1:
- log_info(LD_NET,"Could not resolve dest addr %s (permanent)",
+ log_info(LD_NET,"Could not resolve dest addr %s (permanent).",
log_address);
answer[0] = DNS_RESOLVE_FAILED_PERMANENT;
break;
case 0:
- log_info(LD_NET,"Resolved address %s", log_address);
+ log_info(LD_NET,"Resolved address %s.", log_address);
answer[0] = DNS_RESOLVE_SUCCEEDED;
break;
}
@@ -1228,6 +875,7 @@ dnsworker_main(void *data)
spawn_exit();
}
}
+ return 0; /* windows wants this function to return an int */
}
/** Launch a new DNS worker; return 0 on success, -1 on failure.
@@ -1248,15 +896,12 @@ spawn_dnsworker(void)
return -1;
}
- tor_assert(fdarray[0] >= 0);
- tor_assert(fdarray[1] >= 0);
-
/* log_fn(LOG_NOTICE,"Before spawn: fdarray @%d has %d:%d",
(int)fdarray, fdarray[0],fdarray[1]); */
fd = fdarray[0]; /* We copy this out here, since dnsworker_main may free
* fdarray */
- spawn_func((void*) dnsworker_main, (void*)fdarray);
+ spawn_func(dnsworker_main, (void*)fdarray);
log_debug(LD_EXIT,"just spawned a dns worker.");
#ifndef TOR_IS_MULTITHREADED
tor_close_socket(fdarray[1]); /* don't need the worker's side of the pipe */
@@ -1347,424 +992,3 @@ spawn_enough_dnsworkers(void)
return 0;
}
-void
-dns_launch_wildcard_checks(void)
-{
-}
-#else /* !USE_EVENTDNS */
-
-/** Eventdns helper: return true iff the eventdns result <b>err</b> is
- * a transient failure. */
-static int
-eventdns_err_is_transient(int err)
-{
- switch (err)
- {
- case DNS_ERR_SERVERFAILED:
- case DNS_ERR_TRUNCATED:
- case DNS_ERR_TIMEOUT:
- return 1;
- default:
- return 0;
- }
-}
-/* Dummy function; never called with eventdns enabled. */
-int
-connection_dns_finished_flushing(connection_t *conn)
-{
- (void)conn;
- tor_assert(0);
- return 0;
-}
-/* Dummy function; never called with eventdns enabled. */
-int
-connection_dns_process_inbuf(connection_t *conn)
-{
- (void)conn;
- tor_assert(0);
- return 0;
-}
-/* Dummy function; never called with eventdns enabled. */
-int
-connection_dns_reached_eof(connection_t *conn)
-{
- (void)conn;
- tor_assert(0);
- return 0;
-}
-
-/** Configure eventdns nameservers if force is true, or if the configuration
- * has changed since the last time we called this function. On Unix, this
- * reads from options->ServerDNSResolvConfFile or /etc/resolv.conf; on
- * Windows, this reads from options->ServerDNSResolvConfFile or the registry.
- * Return 0 on success or -1 on failure. */
-static int
-configure_nameservers(int force)
-{
- or_options_t *options;
- const char *conf_fname;
- struct stat st;
- options = get_options();
- conf_fname = options->ServerDNSResolvConfFile;
-#ifndef MS_WINDOWS
- if (!conf_fname)
- conf_fname = "/etc/resolv.conf";
-#endif
-
- eventdns_set_log_fn(eventdns_log_cb);
- if (conf_fname) {
- if (stat(conf_fname, &st)) {
- log_warn(LD_EXIT, "Unable to stat resolver configuration in '%s'",
- conf_fname);
- return -1;
- }
- if (!force && resolv_conf_fname && !strcmp(conf_fname,resolv_conf_fname)
- && st.st_mtime == resolv_conf_mtime) {
- log_info(LD_EXIT, "No change to '%s'", conf_fname);
- return 0;
- }
- if (nameservers_configured) {
- eventdns_search_clear();
- eventdns_clear_nameservers_and_suspend();
- }
- log_info(LD_EXIT, "Parsing resolver configuration in '%s'", conf_fname);
- if (eventdns_resolv_conf_parse(DNS_OPTIONS_ALL, conf_fname))
- return -1;
- if (eventdns_count_nameservers() == 0) {
- log_warn(LD_EXIT, "Unable to find any nameservers in '%s'.", conf_fname);
- return -1;
- }
- tor_free(resolv_conf_fname);
- resolv_conf_fname = tor_strdup(conf_fname);
- resolv_conf_mtime = st.st_mtime;
- if (nameservers_configured)
- eventdns_resume();
- }
-#ifdef MS_WINDOWS
- else {
- if (nameservers_configured) {
- eventdns_search_clear();
- eventdns_clear_nameservers_and_suspend();
- }
- if (eventdns_config_windows_nameservers()) {
- log_warn(LD_EXIT,"Could not config nameservers.");
- return -1;
- }
- if (eventdns_count_nameservers() == 0) {
- log_warn(LD_EXIT, "Unable to find any platform nameservers in "
- "your Windows configuration. Perhaps you should list a "
- "ServerDNSResolvConfFile file in your torrc?");
- return -1;
- }
- if (nameservers_configured)
- eventdns_resume();
- tor_free(resolv_conf_fname);
- resolv_conf_mtime = 0;
- }
-#endif
-
- nameservers_configured = 1;
- return 0;
-}
-
-/** For eventdns: Called when we get an answer for a request we launched.
- * See eventdns.h for arguments; 'arg' holds the address we tried to resolve.
- */
-static void
-eventdns_callback(int result, char type, int count, int ttl, void *addresses,
- void *arg)
-{
- char *string_address = arg;
- int is_reverse = 0;
- int status = DNS_RESOLVE_FAILED_PERMANENT;
- uint32_t addr = 0;
- const char *hostname = NULL;
-
- if (result == DNS_ERR_NONE) {
- if (type == DNS_IPv4_A && count) {
- char answer_buf[INET_NTOA_BUF_LEN+1];
- struct in_addr in;
- char *escaped_address;
- uint32_t *addrs = addresses;
- in.s_addr = addrs[0];
- addr = ntohl(addrs[0]);
- status = DNS_RESOLVE_SUCCEEDED;
- tor_inet_ntoa(&in, answer_buf, sizeof(answer_buf));
- escaped_address = esc_for_log(string_address);
-
- if (answer_is_wildcarded(answer_buf)) {
- log_debug(LD_EXIT, "eventdns said that %s resolves to ISP-hijacked "
- "address %s; treating as a failure.",
- safe_str(escaped_address),
- escaped_safe_str(answer_buf));
- addr = 0;
- status = DNS_RESOLVE_FAILED_PERMANENT;
- } else {
- log_debug(LD_EXIT, "eventdns said that %s resolves to %s",
- safe_str(escaped_address),
- escaped_safe_str(answer_buf));
- }
- tor_free(escaped_address);
- } else if (type == DNS_PTR && count) {
- char *escaped_address;
- is_reverse = 1;
- hostname = ((char**)addresses)[0];
- status = DNS_RESOLVE_SUCCEEDED;
- escaped_address = esc_for_log(string_address);
- log_debug(LD_EXIT, "eventdns said that %s resolves to %s",
- safe_str(escaped_address),
- escaped_safe_str(hostname));
- tor_free(escaped_address);
- } else if (count) {
- log_warn(LD_EXIT, "eventdns returned only non-IPv4 answers for %s.",
- escaped_safe_str(string_address));
- } else {
- log_warn(LD_BUG, "eventdns returned no addresses or error for %s!",
- escaped_safe_str(string_address));
- }
- } else {
- if (eventdns_err_is_transient(result))
- status = DNS_RESOLVE_FAILED_TRANSIENT;
- }
- dns_found_answer(string_address, is_reverse, addr, hostname, status, ttl);
- tor_free(string_address);
-}
-
-/** For eventdns: start resolving as necessary to find the target for
- * <b>exitconn</b> */
-static int
-launch_resolve(edge_connection_t *exitconn)
-{
- char *addr = tor_strdup(exitconn->_base.address);
- struct in_addr in;
- int r;
- int options = get_options()->ServerDNSSearchDomains ? 0
- : DNS_QUERY_NO_SEARCH;
- /* What? Nameservers not configured? Sounds like a bug. */
- if (!nameservers_configured) {
- log_warn(LD_EXIT, "Harmless bug: nameservers not configured, but resolve "
- "launched. Configuring.");
- if (configure_nameservers(1) < 0)
- return -1;
- }
-
- r = parse_inaddr_arpa_address(exitconn->_base.address, &in);
- if (r == 0) {
- log_info(LD_EXIT, "Launching eventdns request for %s",
- escaped_safe_str(exitconn->_base.address));
- r = eventdns_resolve_ipv4(exitconn->_base.address, options,
- eventdns_callback, addr);
- } else if (r == 1) {
- log_info(LD_EXIT, "Launching eventdns reverse request for %s",
- escaped_safe_str(exitconn->_base.address));
- r = eventdns_resolve_reverse(&in, DNS_QUERY_NO_SEARCH,
- eventdns_callback, addr);
- } else if (r == -1) {
- log_warn(LD_BUG, "Somehow a malformed in-addr.arpa address reached here.");
- }
-
- if (r) {
- log_warn(LD_EXIT, "eventdns rejected address %s: error %d.",
- escaped_safe_str(addr), r);
- if (exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE) {
- if (eventdns_err_is_transient(r))
- send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR_TRANSIENT);
- else {
- exitconn->address_ttl = DEFAULT_DNS_TTL;
- send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR);
- }
- }
- dns_cancel_pending_resolve(addr); /* also sends end and frees */
- tor_free(addr);
- }
- return r ? -1 : 0;
-}
-
-/** How many requests for bogus addresses have we launched so far? */
-static int n_wildcard_requests = 0;
-
-/** Map from dotted-quad IP address in response to an int holding how many
- * times we've seen it for a randomly generated (hopefully bogus) address. It
- * would be easier to use definitely-invalid addresses (as specified by
- * RFC2606), but see comment in dns_launch_wildcard_checks(). */
-static strmap_t *dns_wildcard_response_count = NULL;
-
-/** If present, a list of dotted-quad IP addresses that we are pretty sure our
- * nameserver wants to return in response to requests for nonexistent domains.
- */
-static smartlist_t *dns_wildcard_list = NULL;
-
-/** Called when we see <b>id</b> (a dotted quad) in response to a request for
- * a hopefully bogus address. */
-static void
-wildcard_increment_answer(const char *id)
-{
- int *ip;
- static int notice_given = 0;
- if (!dns_wildcard_response_count)
- dns_wildcard_response_count = strmap_new();
-
- ip = strmap_get(dns_wildcard_response_count, id); // may be null (0)
- if (!ip) {
- ip = tor_malloc_zero(sizeof(int));
- strmap_set(dns_wildcard_response_count, id, ip);
- }
- ++*ip;
-
- if (*ip > 5 && n_wildcard_requests > 10) {
- if (!dns_wildcard_list) dns_wildcard_list = smartlist_create();
- if (!smartlist_string_isin(dns_wildcard_list, id)) {
- log(notice_given ? LOG_INFO : LOG_NOTICE, LD_EXIT,
- "Your DNS provider has given \"%s\" as an answer for %d different "
- "invalid addresses. Apparently they are hijacking DNS failures. "
- "I'll trying to correct for this by treating future occurrences of "
- "\"%s\" as 'not found'.", id, *ip, id);
- smartlist_add(dns_wildcard_list, tor_strdup(id));
- }
- }
-}
-
-/** Callback function when we get an answer (possibly failing) for a request
- * for a (hopefully) nonexistent domain. */
-static void
-eventdns_wildcard_check_callback(int result, char type, int count, int ttl,
- void *addresses, void *arg)
-{
- static int notice_given = 0;
- (void)ttl;
- ++n_wildcard_requests;
- if (result == DNS_ERR_NONE && type == DNS_IPv4_A && count) {
- uint32_t *addrs = addresses;
- int i;
- char *string_address = arg;
- for (i = 0; i < count; ++i) {
- char answer_buf[INET_NTOA_BUF_LEN+1];
- struct in_addr in;
- in.s_addr = addrs[i];
- tor_inet_ntoa(&in, answer_buf, sizeof(answer_buf));
- wildcard_increment_answer(answer_buf);
- }
- log(notice_given ? LOG_INFO : LOG_NOTICE, LD_EXIT,
- "Your DNS provider gave an answer for \"%s\", which "
- "is not supposed to exist. Apparently they are hijacking "
- "DNS failures. Trying to correct for this. We've noticed %d possibly "
- "bad addresses so far.",
- string_address, strmap_size(dns_wildcard_response_count));
- notice_given = 1;
- }
- tor_free(arg);
-}
-
-/** Launch a single request for a nonexistent hostname consisting of between
- * <b>min_len</b> and <b>max_len</b> random (plausible) characters followed by
- * <b>suffix</b> */
-static void
-launch_wildcard_check(int min_len, int max_len, const char *suffix)
-{
- char random_bytes[20], name[64], *addr;
- size_t len;
- int r;
-
- len = min_len + crypto_rand_int(max_len-min_len+1);
- if (crypto_rand(random_bytes, sizeof(random_bytes)) < 0)
- return;
- base32_encode(name, sizeof(name), random_bytes, sizeof(random_bytes));
- name[len] = '\0';
- strlcat(name, suffix, sizeof(name));
-
- addr = tor_strdup(name);
- r = eventdns_resolve_ipv4(name, DNS_QUERY_NO_SEARCH,
- eventdns_wildcard_check_callback, addr);
- if (r)
- tor_free(addr);
-}
-
-#define N_WILDCARD_CHECKS 2
-
-/** Launch DNS requests for a few nonexistent hostnames, and see if we can
- * catch our nameserver trying to hijack them and map them to a stupid "I
- * couldn't find ggoogle.com but maybe you'd like to buy these lovely
- * encyclopedias" page. */
-void
-dns_launch_wildcard_checks(void)
-{
- int i;
- if (!get_options()->ServerDNSDetectHijacking)
- return;
- log_info(LD_EXIT, "Launching checks to see whether our nameservers like "
- "to hijack DNS failures.");
- for (i = 0; i < N_WILDCARD_CHECKS; ++i) {
- /* RFC2606 reserves these. Sadly, some DNS hijackers, in a silly attempt
- * to 'comply' with rfc2606, refrain from giving A records for these.
- * This is the standards-complaince equivalent of making sure that your
- * crackhouse's elevator inspection certificate is up to date.
- */
- launch_wildcard_check(2, 16, "%s.invalid");
- launch_wildcard_check(2, 16, "%s.test");
-
- /* Thy somese will break specs if there are ever any number of
- * 8+-character top-level domains. */
- launch_wildcard_check(8, 16,"");
-
- /* Try some random .com/org/net domains. This will work fine so long as
- * not too many resolve to the same place. */
- launch_wildcard_check(8, 16, "%s.com");
- launch_wildcard_check(8, 16, "%s.org");
- launch_wildcard_check(8, 16, "%s.net");
- }
-}
-
-/** Return true iff we have noticed that the dotted-quad <b>ip</b> has been
- * returned in response to requests for nonexistent hostnames. */
-static int
-answer_is_wildcarded(const char *ip)
-{
- return dns_wildcard_list && smartlist_string_isin(dns_wildcard_list, ip);
-}
-#endif /* USE_EVENTDNS */
-
-/** Exit with an assertion if <b>resolve</b> is corrupt. */
-static void
-assert_resolve_ok(cached_resolve_t *resolve)
-{
- tor_assert(resolve);
- tor_assert(resolve->magic == CACHED_RESOLVE_MAGIC);
- tor_assert(strlen(resolve->address) < MAX_ADDRESSLEN);
- tor_assert(tor_strisnonupper(resolve->address));
- if (resolve->state != CACHE_STATE_PENDING) {
- tor_assert(!resolve->pending_connections);
- }
- if (resolve->state == CACHE_STATE_PENDING ||
- resolve->state == CACHE_STATE_DONE) {
- tor_assert(!resolve->ttl);
- if (resolve->is_reverse)
- tor_assert(!resolve->result.hostname);
- else
- tor_assert(!resolve->result.addr);
- }
-}
-
-#ifdef DEBUG_DNS_CACHE
-/** Exit with an assertion if the DNS cache is corrupt. */
-static void
-_assert_cache_ok(void)
-{
- cached_resolve_t **resolve;
- int bad_rep = _cache_map_HT_REP_IS_BAD(&cache_root);
- if (bad_rep) {
- log_err(LD_BUG, "Bad rep type %d on dns cache hash table", bad_rep);
- tor_assert(!bad_rep);
- }
-
- HT_FOREACH(resolve, cache_map, &cache_root) {
- assert_resolve_ok(*resolve);
- tor_assert((*resolve)->state != CACHE_STATE_DONE);
- }
- if (!cached_resolve_pqueue)
- return;
-
- smartlist_pqueue_assert_ok(cached_resolve_pqueue,
- _compare_cached_resolves_by_expiry);
-}
-#endif
-
diff --git a/src/or/eventdns.c b/src/or/eventdns.c
deleted file mode 100644
index b9c60f0dbe..0000000000
--- a/src/or/eventdns.c
+++ /dev/null
@@ -1,2292 +0,0 @@
-/* $Id$ */
-
-/* The original version of this module was written by Adam Langley; for
- * a history of modifications, check out the subversion logs.
- *
- * When editing this module, try to keep it re-mergeable by Adam. Don't
- * reformat the whitespace, add Tor dependencies, or so on.
- *
- * TODO:
- * - Support AAAA records
- * - Have a way to query for AAAA and A records simultaneously.
- * - Improve request API.
- * - (Can we suppress cnames? Should we?)
- * - Replace all externally visible magic numbers with #defined constants.
- * - Write documentation for APIs of all external functions.
- */
-
-/* Async DNS Library
- * Adam Langley <agl@imperialviolet.org>
- * Public Domain code
- *
- * This software is Public Domain. To view a copy of the public domain dedication,
- * visit http://creativecommons.org/licenses/publicdomain/ or send a letter to
- * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
- *
- * I ask and expect, but do not require, that all derivative works contain an
- * attribution similar to:
- * Parts developed by Adam Langley <agl@imperialviolet.org>
- *
- * You may wish to replace the word "Parts" with something else depending on
- * the amount of original code.
- *
- * (Derivative works does not include programs which link against, run or include
- * the source verbatim in their source distributions)
- *
- * Version: 0.1b
- *
- *
- * Welcome, gentle reader
- *
- * Async DNS lookups are really a whole lot harder than they should be,
- * mostly stemming from the fact that the libc resolver has never been
- * very good at them. Before you use this library you should see if libc
- * can do the job for you with the modern async call getaddrinfo_a
- * (see http://www.imperialviolet.org/page25.html#e498). Otherwise,
- * please continue.
- *
- * This code is based on libevent and you must call event_init before
- * any of the APIs in this file. You must also seed the OpenSSL random
- * source if you are using OpenSSL for ids (see below).
- *
- * This library is designed to be included and shipped with your source
- * code. You statically link with it. You should also test for the
- * existence of strtok_r and define HAVE_STRTOK_R if you have it.
- *
- * The DNS protocol requires a good source of id numbers and these
- * numbers should be unpredictable for spoofing reasons. There are
- * three methods for generating them here and you must define exactly
- * one of them. In increasing order of preference:
- *
- * DNS_USE_GETTIMEOFDAY_FOR_ID:
- * Using the bottom 16 bits of the usec result from gettimeofday. This
- * is a pretty poor solution but should work anywhere.
- * DNS_USE_CPU_CLOCK_FOR_ID:
- * Using the bottom 16 bits of the nsec result from the CPU's time
- * counter. This is better, but may not work everywhere. Requires
- * POSIX realtime support and you'll need to link against -lrt on
- * glibc systems at least.
- * DNS_USE_OPENSSL_FOR_ID:
- * Uses the OpenSSL RAND_bytes call to generate the data. You must
- * have seeded the pool before making any calls to this library.
- *
- * The library keeps track of the state of nameservers and will avoid
- * them when they go down. Otherwise it will round robin between them.
- *
- * Quick start guide:
- * #include "eventdns.h"
- * void callback(int result, char type, int count, int ttl,
- * void *addresses, void *arg);
- * eventdns_resolv_conf_parse(DNS_OPTIONS_ALL, "/etc/resolv.conf");
- * eventdns_resolve("www.hostname.com", 0, callback, NULL);
- *
- * When the lookup is complete the callback function is called. The
- * first argument will be one of the DNS_ERR_* defines in eventdns.h.
- * Hopefully it will be DNS_ERR_NONE, in which case type will be
- * DNS_IPv4_A, count will be the number of IP addresses, ttl is the time
- * which the data can be cached for (in seconds), addresses will point
- * to an array of uint32_t's and arg will be whatever you passed to
- * eventdns_resolve.
- *
- * Searching:
- *
- * In order for this library to be a good replacement for glibc's resolver it
- * supports searching. This involves setting a list of default domains, in
- * which names will be queried for. The number of dots in the query name
- * determines the order in which this list is used.
- *
- * Searching appears to be a single lookup from the point of view of the API,
- * although many DNS queries may be generated from a single call to
- * eventdns_resolve. Searching can also drastically slow down the resolution
- * of names.
- *
- * To disable searching:
- * 1. Never set it up. If you never call eventdns_resolv_conf_parse or
- * eventdns_search_add then no searching will occur.
- *
- * 2. If you do call eventdns_resolv_conf_parse then don't pass
- * DNS_OPTION_SEARCH (or DNS_OPTIONS_ALL, which implies it).
- *
- * 3. When calling eventdns_resolve, pass the DNS_QUERY_NO_SEARCH flag.
- *
- * The order of searches depends on the number of dots in the name. If the
- * number is greater than the ndots setting then the names is first tried
- * globally. Otherwise each search domain is appended in turn.
- *
- * The ndots setting can either be set from a resolv.conf, or by calling
- * eventdns_search_ndots_set.
- *
- * For example, with ndots set to 1 (the default) and a search domain list of
- * ["myhome.net"]:
- * Query: www
- * Order: www.myhome.net, www.
- *
- * Query: www.abc
- * Order: www.abc., www.abc.myhome.net
- *
- * API reference:
- *
- * int eventdns_nameserver_add(unsigned long int address)
- * Add a nameserver. The address should be an IP address in
- * network byte order. The type of address is chosen so that
- * it matches in_addr.s_addr.
- * Returns non-zero on error.
- *
- * int eventdns_nameserver_ip_add(const char *ip_as_string)
- * This wraps the above function by parsing a string as an IP
- * address and adds it as a nameserver.
- * Returns non-zero on error
- *
- * int eventdns_resolve(const char *name, int flags,
- * eventdns_callback_type callback,
- * void *ptr)
- * Resolve a name. The name parameter should be a DNS name.
- * The flags parameter should be 0, or DNS_QUERY_NO_SEARCH
- * which disables searching for this query. (see defn of
- * searching above).
- *
- * The callback argument is a function which is called when
- * this query completes and ptr is an argument which is passed
- * to that callback function.
- *
- * Returns non-zero on error
- *
- * void eventdns_search_clear()
- * Clears the list of search domains
- *
- * void eventdns_search_add(const char *domain)
- * Add a domain to the list of search domains
- *
- * void eventdns_search_ndots_set(int ndots)
- * Set the number of dots which, when found in a name, causes
- * the first query to be without any search domain.
- *
- * int eventdns_count_nameservers(void)
- * Return the number of configured nameservers (not necessarily the
- * number of running nameservers). This is useful for double-checking
- * whether our calls to the various nameserver configuration functions
- * have been successful.
- *
- * int eventdns_clear_nameservers_and_suspend(void)
- * Remove all currently configured nameservers, and suspend all pending
- * resolves. Resolves will not necessarily be re-attempted until
- * eventdns_resume() is called.
- *
- * int eventdns_resume(void)
- * Re-attempt resolves left in limbo after an earlier call to
- * eventdns_clear_nameservers_and_suspend().
- *
- * int eventdns_config_windows_nameservers(void)
- * Attempt to configure a set of nameservers based on platform settings on
- * a win32 host. Preferentially tries to use GetNetworkParams; if that fails,
- * looks in the registry. Returns 0 on success, nonzero on failure.
- *
- * int eventdns_resolv_conf_parse(int flags, const char *filename)
- * Parse a resolv.conf like file from the given filename.
- *
- * See the man page for resolv.conf for the format of this file.
- * The flags argument determines what information is parsed from
- * this file:
- * DNS_OPTION_SEARCH - domain, search and ndots options
- * DNS_OPTION_NAMESERVERS - nameserver lines
- * DNS_OPTION_MISC - timeout and attempts options
- * DNS_OPTIONS_ALL - all of the above
- * The following directives are not parsed from the file:
- * sortlist, rotate, no-check-names, inet6, debug
- *
- * Returns non-zero on error:
- * 0 no errors
- * 1 failed to open file
- * 2 failed to stat file
- * 3 file too large
- * 4 out of memory
- * 5 short read from file
- *
- * Internals:
- *
- * Requests are kept in two queues. The first is the inflight queue. In
- * this queue requests have an allocated transaction id and nameserver.
- * They will soon be transmitted if they haven't already been.
- *
- * The second is the waiting queue. The size of the inflight ring is
- * limited and all other requests wait in waiting queue for space. This
- * bounds the number of concurrent requests so that we don't flood the
- * nameserver. Several algorithms require a full walk of the inflight
- * queue and so bounding its size keeps thing going nicely under huge
- * (many thousands of requests) loads.
- *
- * If a nameserver loses too many requests it is considered down and we
- * try not to use it. After a while we send a probe to that nameserver
- * (a lookup for google.com) and, if it replies, we consider it working
- * again. If the nameserver fails a probe we wait longer to try again
- * with the next probe.
- */
-
-#include "eventdns.h"
-#include "eventdns_tor.h"
-//#define NDEBUG
-
-#ifndef DNS_USE_CPU_CLOCK_FOR_ID
-#ifndef DNS_USE_GETTIMEOFDAY_FOR_ID
-#ifndef DNS_USE_OPENSSL_FOR_ID
-#error Must configure at least one id generation method.
-#error Please see the documentation.
-#endif
-#endif
-#endif
-
-// #define _POSIX_C_SOURCE 200507
-#define _GNU_SOURCE
-
-#ifdef DNS_USE_CPU_CLOCK_FOR_ID
-#ifdef DNS_USE_OPENSSL_FOR_ID
-#error Multiple id options selected
-#endif
-#ifdef DNS_USE_GETTIMEOFDAY_FOR_ID
-#error Multiple id options selected
-#endif
-#include <time.h>
-#endif
-
-#ifdef DNS_USE_OPENSSL_FOR_ID
-#ifdef DNS_USE_GETTIMEOFDAY_FOR_ID
-#error Multiple id options selected
-#endif
-#include <openssl/rand.h>
-#endif
-
-#define _FORTIFY_SOURCE 3
-
-#include <string.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <sys/time.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-#include <unistd.h>
-#include <limits.h>
-#include <sys/stat.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdarg.h>
-
-#ifdef WIN32
-#include <windows.h>
-#include <winsock2.h>
-#include <iphlpapi.h>
-#else
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#endif
-
-#define EVENTDNS_LOG_DEBUG 0
-#define EVENTDNS_LOG_WARN 1
-
-#ifndef HOST_NAME_MAX
-#define HOST_NAME_MAX 255
-#endif
-
-#ifndef NDEBUG
-#include <stdio.h>
-#endif
-
-#undef MIN
-#define MIN(a,b) ((a)<(b)?(a):(b))
-
-#if 0
-#ifdef __USE_ISOC99B
-// libevent doesn't work without this
-typedef uint8_t u_char;
-typedef unsigned int uint;
-#endif
-#endif
-#include <event.h>
-
-#define u64 uint64_t
-#define u32 uint32_t
-#define u16 uint16_t
-#define u8 uint8_t
-
-#include "eventdns.h"
-
-#define MAX_ADDRS 4 // maximum number of addresses from a single packet
-// which we bother recording
-
-#define TYPE_A 1
-#define TYPE_CNAME 5
-#define TYPE_PTR 12
-#define TYPE_AAAA 28
-
-#define CLASS_INET 1
-
-struct request {
- u8 *request; // the dns packet data
- unsigned int request_len;
- u8 reissue_count;
- u8 tx_count; // the number of times that this packet has been sent
- u8 request_type; // TYPE_PTR or TYPE_A
- void *user_pointer; // the pointer given to us for this request
- eventdns_callback_type user_callback;
- struct nameserver *ns; // the server which we last sent it
-
- // elements used by the searching code
- int search_index;
- struct search_state *search_state;
- char *search_origname; // needs to be free()ed
- int search_flags;
-
- // these objects are kept in a circular list
- struct request *next, *prev;
-
- struct event timeout_event;
-
- u16 trans_id; // the transaction id
- char request_appended; // true if the request pointer is data which follows this struct
- char transmit_me; // needs to be transmitted
-};
-
-struct reply {
- u8 type;
- u8 have_answer;
- union {
- struct {
- u32 addrcount;
- u32 addresses[MAX_ADDRS];
- } a;
- struct {
- char name[HOST_NAME_MAX];
- } ptr;
- } data;
-};
-
-struct nameserver {
- int socket; // a connected UDP socket
- u32 address;
- int failed_times; // number of times which we have given this server a chance
- int timedout; // number of times in a row a request has timed out
- struct event event;
- // these objects are kept in a circular list
- struct nameserver *next, *prev;
- struct event timeout_event; // used to keep the timeout for
- // when we next probe this server.
- // Valid if state == 0
- char state; // zero if we think that this server is down
- char choaked; // true if we have an EAGAIN from this server's socket
- char write_waiting; // true if we are waiting for EV_WRITE events
-};
-
-static struct request *req_head = NULL, *req_waiting_head = NULL;
-static struct nameserver *server_head = NULL;
-
-// The number of good nameservers that we have
-static int global_good_nameservers = 0;
-
-// inflight requests are contained in the req_head list
-// and are actually going out across the network
-static int global_requests_inflight = 0;
-// requests which aren't inflight are in the waiting list
-// and are counted here
-static int global_requests_waiting = 0;
-
-static int global_max_requests_inflight = 64;
-
-static struct timeval global_timeout = {3, 0}; // 3 seconds
-static u8 global_max_reissues = 1; // a reissue occurs when we get some errors from the server
-static u8 global_max_retransmits = 3; // number of times we'll retransmit a request which timed out
-// number of timeouts in a row before we consider this server to be down
-static int global_max_nameserver_timeout = 3;
-
-// These are the timeout values for nameservers. If we find a nameserver is down
-// we try to probe it at intervals as given below. Values are in seconds.
-static const struct timeval global_nameserver_timeouts[] = {{10, 0}, {60, 0}, {300, 0}, {900, 0}, {3600, 0}};
-static const int global_nameserver_timeouts_length = sizeof(global_nameserver_timeouts)/sizeof(struct timeval);
-
-const char *const eventdns_error_strings[] = {"no error", "The name server was unable to interpret the query", "The name server suffered an internal error", "The requested domain name does not exist", "The name server refused to reply to the request"};
-
-static struct nameserver *nameserver_pick(void);
-static void eventdns_request_insert(struct request *req, struct request **head);
-static void nameserver_ready_callback(int fd, short events, void *arg);
-static int eventdns_transmit(void);
-static int eventdns_request_transmit(struct request *req);
-static void nameserver_send_probe(struct nameserver *const ns);
-static void search_request_finished(struct request *const);
-static int search_try_next(struct request *const req);
-static int search_request_new(int type, const char *const name, int flags, eventdns_callback_type user_callback, void *user_arg);
-static void eventdns_requests_pump_waiting_queue(void);
-static u16 transaction_id_pick(void);
-static struct request *request_new(int type, const char *name, int flags, eventdns_callback_type, void *ptr);
-static void request_submit(struct request *req);
-
-#ifdef MS_WINDOWS
-static int
-last_error(int sock) {
- int optval, optvallen=sizeof(optval);
- int err = WSAGetLastError();
- if (err == WSAEWOULDBLOCK && sock >= 0) {
- if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&optval,
- &optvallen))
- return err;
- if (optval)
- return optval;
- }
- return err;
-
-}
-static int
-error_is_eagain(int err) {
- return err == EAGAIN || err == WSAEWOULDBLOCK;
-}
-static int
-inet_aton(const char *c, struct in_addr *addr) {
- uint32_t r;
- if (strcmp(c, "255.255.255.255") == 0) {
- addr->s_addr = 0xffffffffu;
- } else {
- r = inet_addr(c);
- if (r == INADDR_NONE)
- return 0;
- addr->s_addr = r;
- }
- return 1;
-}
-#define CLOSE_SOCKET(x) closesocket(x)
-#else
-#define last_error(sock) (errno)
-#define error_is_eagain(err) ((err) == EAGAIN)
-#define CLOSE_SOCKET(x) close(x)
-#endif
-
-#define ISSPACE(c) isspace((int)(unsigned char)(c))
-#define ISDIGIT(c) isdigit((int)(unsigned char)(c))
-
-#ifndef NDEBUG
-static const char *
-debug_ntoa(u32 address) {
- static char buf[32];
- u32 a = ntohl(address);
- sprintf(buf, "%d.%d.%d.%d",
- (int)(u8)((a>>24)&0xff),
- (int)(u8)((a>>16)&0xff),
- (int)(u8)((a>>8 )&0xff),
- (int)(u8)((a )&0xff));
- return buf;
-}
-#endif
-
-static eventdns_debug_log_fn_type eventdns_log_fn = NULL;
-
-void
-eventdns_set_log_fn(eventdns_debug_log_fn_type fn) {
- eventdns_log_fn = fn;
-}
-
-#ifdef __GNUC__
-#define EVENTDNS_LOG_CHECK __attribute__ ((format(printf, 2, 3)))
-#else
-#define EVENTDNS_LOG_CHECK
-#endif
-
-static void _eventdns_log(int warn, const char *fmt, ...) EVENTDNS_LOG_CHECK;
-static void
-_eventdns_log(int warn, const char *fmt, ...) {
- va_list args;
- static char buf[512];
- if (!eventdns_log_fn)
- return;
- va_start(args,fmt);
-#ifdef MS_WINDOWS
- _vsnprintf(buf, sizeof(buf), fmt, args);
-#else
- vsnprintf(buf, sizeof(buf), fmt, args);
-#endif
- buf[sizeof(buf)-1] = '\0';
- eventdns_log_fn(warn, buf);
- va_end(args);
-}
-
-#define log _eventdns_log
-
-// This walks the list of inflight requests to find the
-// one with a matching transaction id. Returns NULL on
-// failure
-static struct request *
-request_find_from_trans_id(u16 trans_id) {
- struct request *req = req_head, *const started_at = req_head;
-
- if (req) {
- do {
- if (req->trans_id == trans_id) return req;
- req = req->next;
- } while (req != started_at);
- }
-
- return NULL;
-}
-
-// a libevent callback function which is called when a nameserver
-// has gone down and we want to test if it has came back to life yet
-static void
-nameserver_prod_callback(int fd, short events, void *arg) {
- struct nameserver *const ns = (struct nameserver *) arg;
- (void)fd;
- (void)events;
-
- nameserver_send_probe(ns);
-}
-
-// a libevent callback which is called when a nameserver probe (to see if
-// it has come back to life) times out. We increment the count of failed_times
-// and wait longer to send the next probe packet.
-static void
-nameserver_probe_failed(struct nameserver *const ns) {
- const struct timeval * timeout;
- (void) evtimer_del(&ns->timeout_event);
- if (ns->state == 1) {
- // This can happen if the nameserver acts in a way which makes us mark
- // it as bad and then starts sending good replies.
- return;
- }
-
- timeout =
- &global_nameserver_timeouts[MIN(ns->failed_times,
- global_nameserver_timeouts_length - 1)];
- ns->failed_times++;
-
- evtimer_set(&ns->timeout_event, nameserver_prod_callback, ns);
- if (evtimer_add(&ns->timeout_event, (struct timeval *) timeout) < 0) {
- log(EVENTDNS_LOG_WARN,
- "Error from libevent when adding timer event for %s",
- debug_ntoa(ns->address));
- // ???? Do more?
- }
-}
-
-// called when a nameserver has been deemed to have failed. For example, too
-// many packets have timed out etc
-static void
-nameserver_failed(struct nameserver *const ns, const char *msg) {
- struct request *req, *started_at;
- // if this nameserver has already been marked as failed
- // then don't do anything
- if (!ns->state) return;
-
- log(EVENTDNS_LOG_WARN, "Nameserver %s has failed: %s",
- debug_ntoa(ns->address), msg);
- global_good_nameservers--;
- assert(global_good_nameservers >= 0);
- if (global_good_nameservers == 0) {
- log(EVENTDNS_LOG_WARN, "All nameservers have failed");
- }
-
- ns->state = 0;
- ns->failed_times = 1;
-
- evtimer_set(&ns->timeout_event, nameserver_prod_callback, ns);
- if (evtimer_add(&ns->timeout_event, (struct timeval *) &global_nameserver_timeouts[0]) < 0) {
- log(EVENTDNS_LOG_WARN,
- "Error from libevent when adding timer event for %s",
- debug_ntoa(ns->address));
- // ???? Do more?
- }
-
- // walk the list of inflight requests to see if any can be reassigned to
- // a different server. Requests in the waiting queue don't have a
- // nameserver assigned yet
-
- // if we don't have *any* good nameservers then there's no point
- // trying to reassign requests to one
- if (!global_good_nameservers) return;
-
- req = req_head;
- started_at = req_head;
- if (req) {
- do {
- if (req->tx_count == 0 && req->ns == ns) {
- // still waiting to go out, can be moved
- // to another server
- req->ns = nameserver_pick();
- }
- req = req->next;
- } while (req != started_at);
- }
-}
-
-static void
-nameserver_up(struct nameserver *const ns) {
- if (ns->state) return;
- log(EVENTDNS_LOG_WARN, "Nameserver %s is back up",
- debug_ntoa(ns->address));
- evtimer_del(&ns->timeout_event);
- ns->state = 1;
- ns->failed_times = 0;
- global_good_nameservers++;
-}
-
-static void
-request_trans_id_set(struct request *const req, const u16 trans_id) {
- req->trans_id = trans_id;
- *((u16 *) req->request) = htons(trans_id);
-}
-
-// Called to remove a request from a list and dealloc it.
-// head is a pointer to the head of the list it should be
-// removed from or NULL if the request isn't in a list.
-static void
-request_finished(struct request *const req, struct request **head) {
- if (head) {
- if (req->next == req) {
- // only item in the list
- *head = NULL;
- } else {
- req->next->prev = req->prev;
- req->prev->next = req->next;
- if (*head == req) *head = req->next;
- }
- }
-
- log(EVENTDNS_LOG_DEBUG, "Removing timeout for request %lx",
- (unsigned long) req);
- evtimer_del(&req->timeout_event);
-
- search_request_finished(req);
- global_requests_inflight--;
-
- if (!req->request_appended) {
- // need to free the request data on it's own
- free(req->request);
- } else {
- // the request data is appended onto the header
- // so everything gets free()ed when we:
- }
-
- free(req);
-
- eventdns_requests_pump_waiting_queue();
-}
-
-// This is called when a server returns a funny error code.
-// We try the request again with another server.
-//
-// return:
-// 0 ok
-// 1 failed/reissue is pointless
-static int
-request_reissue(struct request *req) {
- const struct nameserver *const last_ns = req->ns;
- // the last nameserver should have been marked as failing
- // by the caller of this function, therefore pick will try
- // not to return it
- req->ns = nameserver_pick();
- if (req->ns == last_ns) {
- // ... but pick did return it
- // not a lot of point in trying again with the
- // same server
- return 1;
- }
-
- req->reissue_count++;
- req->tx_count = 0;
- req->transmit_me = 1;
-
- return 0;
-}
-
-// this function looks for space on the inflight queue and promotes
-// requests from the waiting queue if it can.
-static void
-eventdns_requests_pump_waiting_queue(void) {
- while (global_requests_inflight < global_max_requests_inflight &&
- global_requests_waiting) {
- struct request *req;
- // move a request from the waiting queue to the inflight queue
- assert(req_waiting_head);
- if (req_waiting_head->next == req_waiting_head) {
- // only one item in the queue
- req = req_waiting_head;
- req_waiting_head = NULL;
- } else {
- req = req_waiting_head;
- req->next->prev = req->prev;
- req->prev->next = req->next;
- req_waiting_head = req->next;
- }
-
- global_requests_waiting--;
- global_requests_inflight++;
-
- req->ns = nameserver_pick();
- request_trans_id_set(req, transaction_id_pick());
-
- eventdns_request_insert(req, &req_head);
- eventdns_request_transmit(req);
- eventdns_transmit();
- }
-}
-
-static void
-reply_callback(struct request *const req, u32 ttl, u32 err, struct reply *reply) {
- switch (req->request_type) {
- case TYPE_A:
- if (reply)
- req->user_callback(DNS_ERR_NONE, DNS_IPv4_A,
- reply->data.a.addrcount, ttl,
- reply->data.a.addresses,
- req->user_pointer);
- else
- req->user_callback(err, 0, 0, 0, NULL, req->user_pointer);
- return;
- case TYPE_PTR:
- if (reply) {
- char *name = reply->data.ptr.name;
- req->user_callback(DNS_ERR_NONE, DNS_PTR, 1, ttl,
- &name, req->user_pointer);
- } else {
- req->user_callback(err, 0, 0, 0, NULL,
- req->user_pointer);
- }
- return;
- }
- assert(0);
-}
-
-// this processes a parsed reply packet
-static void
-reply_handle(struct request *const req,
- u16 flags, u32 ttl, struct reply *reply) {
- int error;
- static const int error_codes[] = {DNS_ERR_FORMAT, DNS_ERR_SERVERFAILED, DNS_ERR_NOTEXIST, DNS_ERR_NOTIMPL, DNS_ERR_REFUSED};
-
- if (flags & 0x020f || !reply || !reply->have_answer) {
- // there was an error
- if (flags & 0x0200) {
- error = DNS_ERR_TRUNCATED;
- } else {
- u16 error_code = (flags & 0x000f) - 1;
- if (error_code > 4) {
- error = DNS_ERR_UNKNOWN;
- } else {
- error = error_codes[error_code];
- }
- }
-
- switch(error) {
- case DNS_ERR_SERVERFAILED:
- case DNS_ERR_NOTIMPL:
- case DNS_ERR_REFUSED:
- // we regard these errors as marking a bad nameserver
- if (req->reissue_count < global_max_reissues) {
- char msg[64];
- snprintf(msg, sizeof(msg), "Bad response %d",
- error);
- nameserver_failed(req->ns, msg);
- if (!request_reissue(req)) return;
- }
- break;
- default:
- // we got a good reply from the nameserver
- nameserver_up(req->ns);
- }
-
- if (req->search_state && req->request_type != TYPE_PTR) {
- // if we have a list of domains to search in, try the next one
- if (!search_try_next(req)) {
- // a new request was issued so this request is finished and
- // the user callback will be made when that request (or a
- // child of it) finishes.
- request_finished(req, &req_head);
- return;
- }
- }
-
- // all else failed. Pass the failure up
- reply_callback(req, 0, error, NULL);
- request_finished(req, &req_head);
- } else {
- // all ok, tell the user
- reply_callback(req, ttl, 0, reply);
- nameserver_up(req->ns);
- request_finished(req, &req_head);
- }
-}
-
-static inline int
-name_parse(u8 *packet, int length, int *idx, char *name_out, int name_out_len) {
- int name_end = -1;
- int j = *idx;
-#define GET32(x) do { if (j + 4 > length) return -1; memcpy(&_t32, packet + j, 4); j += 4; x = ntohl(_t32); } while(0);
-#define GET16(x) do { if (j + 2 > length) return -1; memcpy(&_t, packet + j, 2); j += 2; x = ntohs(_t); } while(0);
-#define GET8(x) do { if (j >= length) return -1; x = packet[j++]; } while(0);
-
- char *cp = name_out;
- const char *const end = name_out + name_out_len;
-
- // Normally, names are a series of length prefixed strings terminated
- // with a length of 0 (the lengths are u8's < 63).
- // However, the length can start with a pair of 1 bits and that
- // means that the next 14 bits are a pointer within the current
- // packet.
-
- for(;;) {
- u8 label_len;
- if (j >= length) return -1;
- GET8(label_len);
- if (!label_len) break;
- if (label_len & 0xc0) {
- u8 ptr_low;
- GET8(ptr_low);
- if (name_end < 0) name_end = j;
- j = (((int)label_len & 0x3f) << 8) + ptr_low;
- if (j < 0 || j >= length) return -1;
- continue;
- }
- if (label_len > 63) return -1;
- if (cp != name_out) {
- if (cp + 1 >= end) return -1;
- *cp++ = '.';
- }
- if (cp + label_len >= end) return -1;
- memcpy(cp, packet + j, label_len);
- cp += label_len;
- j += label_len;
- }
- if (cp >= end) return -1;
- *cp = '\0';
- if (name_end < 0)
- *idx = j;
- else
- *idx = name_end;
- return 0;
-}
-
-// parses a raw packet from the wire
-static int
-reply_parse(u8 *packet, int length) {
- int j = 0; // index into packet
- u16 _t; // used by the macros
- u32 _t32; // used by the macros
- char tmp_name[256]; // used by the macros
-
- u16 trans_id, flags, questions, answers, authority, additional, datalength;
- u32 ttl, ttl_r = 0xffffffff;
- struct reply reply;
- struct request *req;
- unsigned int i;
-
- GET16(trans_id);
- GET16(flags);
- GET16(questions);
- GET16(answers);
- GET16(authority);
- GET16(additional);
-
- req = request_find_from_trans_id(trans_id);
- if (!req) return -1;
- // XXXX should the other return points also call reply_handle? -NM
- // log("reqparse: trans was %d\n", (int)trans_id);
-
- memset(&reply, 0, sizeof(reply));
-
- if (!(flags & 0x8000)) return -1; // must be an answer
- if (flags & 0x020f) {
- // there was an error
- reply_handle(req, flags, 0, NULL);
- return -1;
- }
- // if (!answers) return; // must have an answer of some form
-
- // This macro skips a name in the DNS reply.
-#define SKIP_NAME \
- do { tmp_name[0] = '\0'; \
- if (name_parse(packet, length, &j, tmp_name, sizeof(tmp_name))<0) \
- return -1; \
- } while(0);
-
- reply.type = req->request_type;
-
- // skip over each question in the reply
- for (i = 0; i < questions; ++i) {
- // the question looks like
- // <label:name><u16:type><u16:class>
- SKIP_NAME;
- j += 4;
- if (j >= length) return -1;
- }
-
- // now we have the answer section which looks like
- // <label:name><u16:type><u16:class><u32:ttl><u16:len><data...>
- for (i = 0; i < answers; ++i) {
- u16 type, class;
- //int pre = j;
-
- // XXX I'd be more comfortable if we actually checked the name
- // here. -NM
- SKIP_NAME;
- GET16(type);
- GET16(class);
- GET32(ttl);
- GET16(datalength);
-
- // log("@%d, Name %s, type %d, class %d, j=%d", pre, tmp_name, (int)type, (int)class, j);
-
- if (type == TYPE_A && class == CLASS_INET) {
- int addrcount, addrtocopy;
- if (req->request_type != TYPE_A) {
- j += datalength; continue;
- }
- // XXXX do something sane with malformed A answers.
- addrcount = datalength >> 2; // each IP address is 4 bytes
- addrtocopy = MIN(MAX_ADDRS - reply.data.a.addrcount, (unsigned)addrcount);
- ttl_r = MIN(ttl_r, ttl);
- // we only bother with the first four addresses.
- if (j + 4*addrtocopy > length) return -1;
- memcpy(&reply.data.a.addresses[reply.data.a.addrcount],
- packet + j, 4*addrtocopy);
- j += 4*addrtocopy;
- reply.data.a.addrcount += addrtocopy;
- reply.have_answer = 1;
- if (reply.data.a.addrcount == MAX_ADDRS) break;
- } else if (type == TYPE_PTR && class == CLASS_INET) {
- if (req->request_type != TYPE_PTR) {
- j += datalength; continue;
- }
- if (name_parse(packet, length, &j, reply.data.ptr.name,
- sizeof(reply.data.ptr.name))<0)
- return -1;
- reply.have_answer = 1;
- break;
- } else if (type == TYPE_AAAA && class == CLASS_INET) {
- if (req->request_type != TYPE_AAAA) {
- j += datalength; continue;
- }
- // XXXX Implement me. -NM
- j += datalength;
- } else {
- // skip over any other type of resource
- j += datalength;
- }
- }
-
- reply_handle(req, flags, ttl_r, &reply);
- return 0;
-#undef SKIP_NAME
-#undef GET32
-#undef GET16
-#undef GET8
-}
-
-// Try to choose a strong transaction id which isn't already in flight
-static u16
-transaction_id_pick(void) {
- for (;;) {
- const struct request *req = req_head, *started_at;
-#ifdef DNS_USE_CPU_CLOCK_FOR_ID
- struct timespec ts;
- const u16 trans_id = ts.tv_nsec & 0xffff;
- if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts)) abort();
-#endif
-
-#ifdef DNS_USE_GETTIMEOFDAY_FOR_ID
- struct timeval tv;
- const u16 trans_id = tv.tv_usec & 0xffff;
- gettimeofday(&tv, NULL);
-#endif
-
-#ifdef DNS_USE_OPENSSL_FOR_ID
- u16 trans_id;
- if (RAND_pseudo_bytes((u8 *) &trans_id, 2) == -1) {
- /* // in the case that the RAND call fails we back
- // down to using gettimeofday.
- struct timeval tv;
- gettimeofday(&tv, NULL);
- trans_id = tv.tv_usec & 0xffff; */
- abort();
- }
-#endif
-
- if (trans_id == 0xffff) continue;
- // now check to see if that id is already inflight
- req = started_at = req_head;
- if (req) {
- do {
- if (req->trans_id == trans_id) break;
- req = req->next;
- } while (req != started_at);
- }
- // we didn't find it, so this is a good id
- if (req == started_at) return trans_id;
- }
-}
-
-// choose a namesever to use. This function will try to ignore
-// nameservers which we think are down and load balance across the rest
-// by updating the server_head global each time.
-static struct nameserver *
-nameserver_pick(void) {
- struct nameserver *started_at = server_head, *picked;
- if (!server_head) return NULL;
-
- // if we don't have any good nameservers then there's no
- // point in trying to find one.
- if (!global_good_nameservers) {
- server_head = server_head->next;
- return server_head;
- }
-
- // remember that nameservers are in a circular list
- for (;;) {
- if (server_head->state) {
- // we think this server is currently good
- picked = server_head;
- server_head = server_head->next;
- return picked;
- }
-
- server_head = server_head->next;
- if (server_head == started_at) {
- // all the nameservers seem to be down
- // so we just return this one and hope for the
- // best
- assert(global_good_nameservers == 0);
- picked = server_head;
- server_head = server_head->next;
- return picked;
- }
- }
-}
-
-// this is called when a namesever socket is ready for reading
-static void
-nameserver_read(struct nameserver *ns) {
- u8 packet[1500];
-
- for (;;) {
- const int r = recv(ns->socket, packet, sizeof(packet), 0);
- if (r < 0) {
- int err = last_error(ns->socket);
- if (error_is_eagain(err)) return;
- nameserver_failed(ns, strerror(err));
- return;
- }
- reply_parse(packet, r);
- }
-}
-
-// set if we are waiting for the ability to write to this server.
-// if waiting is true then we ask libevent for EV_WRITE events, otherwise
-// we stop these events.
-static void
-nameserver_write_waiting(struct nameserver *ns, char waiting) {
- if (ns->write_waiting == waiting) return;
-
- ns->write_waiting = waiting;
- (void) event_del(&ns->event);
- event_set(&ns->event, ns->socket, EV_READ | (waiting ? EV_WRITE : 0) | EV_PERSIST,
- nameserver_ready_callback, ns);
- if (event_add(&ns->event, NULL) < 0) {
- log(EVENTDNS_LOG_WARN, "Error from libevent when adding event for %s",
- debug_ntoa(ns->address));
- // ???? Do more?
- }
-}
-
-// a callback function. Called by libevent when the kernel says that
-// a nameserver socket is ready for writing or reading
-static void
-nameserver_ready_callback(int fd, short events, void *arg) {
- struct nameserver *ns = (struct nameserver *) arg;
- (void)fd;
-
- if (events & EV_WRITE) {
- ns->choaked = 0;
- if (!eventdns_transmit()) {
- nameserver_write_waiting(ns, 0);
- }
- }
- if (events & EV_READ) {
- nameserver_read(ns);
- }
-}
-
-// Converts a string to a length-prefixed set of DNS labels.
-// @buf must be strlen(name)+2 or longer. name and buf must
-// not overlap. name_len should be the length of name
-//
-// Input: abc.def
-// Output: <3>abc<3>def<0>
-//
-// Returns the length of the data. negative on error
-// -1 label was > 63 bytes
-// -2 name was > 255 bytes
-static int
-dnsname_to_labels(u8 *const buf, const char *name, const int name_len) {
- const char *end = name + name_len;
- int j = 0; // current offset into buf
-
- if (name_len > 255) return -2;
-
- for (;;) {
- const char *const start = name;
- name = strchr(name, '.');
- if (!name) {
- const unsigned int label_len = end - start;
- if (label_len > 63) return -1;
- buf[j++] = label_len;
-
- memcpy(buf + j, start, end - start);
- j += end - start;
- break;
- } else {
- // append length of the label.
- const unsigned int label_len = name - start;
- if (label_len > 63) return -1;
- buf[j++] = label_len;
-
- memcpy(buf + j, start, name - start);
- j += name - start;
- // hop over the '.'
- name++;
- }
- }
-
- // the labels must be terminated by a 0.
- // It's possible that the name ended in a .
- // in which case the zero is already there
- if (!j || buf[j-1]) buf[j++] = 0;
- return j;
-}
-
-// Finds the length of a dns request for a DNS name of the given
-// length. The actual request may be smaller than the value returned
-// here
-static int
-eventdns_request_len(const int name_len) {
- return 96 + // length of the DNS standard header
- name_len + 2 +
- 4; // space for the resource type
-}
-
-// build a dns request packet into buf. buf should be at least as long
-// as eventdns_request_len told you it should be.
-//
-// Returns the amount of space used. Negative on error.
-static int
-eventdns_request_data_build(const char *const name, const int name_len, const u16 trans_id,
- const u16 type, const u16 class,
- u8 *const buf) {
- int j = 0; // current offset into buf
- u16 _t; // used by the macros
- u8 *labels;
- int labels_len;
-
-#define APPEND16(x) do { _t = htons(x); memcpy(buf + j, &_t, 2); j += 2; } while(0);
- APPEND16(trans_id);
- APPEND16(0x0100); // standard query, recusion needed
- APPEND16(1); // one question
- APPEND16(0); // no answers
- APPEND16(0); // no authority
- APPEND16(0); // no additional
-
- labels = (u8 *) malloc(name_len + 2);
- if (!labels) return -1;
- labels_len = dnsname_to_labels(labels, name, name_len);
- if (labels_len < 0) {
- free(labels);
- return labels_len;
- }
- memcpy(buf + j, labels, labels_len);
- j += labels_len;
- free(labels);
-
- APPEND16(type);
- APPEND16(class);
-#undef APPEND16
-
- return j;
-}
-
-// this is a libevent callback function which is called when a request
-// has timed out.
-static void
-eventdns_request_timeout_callback(int fd, short events, void *arg) {
- struct request *const req = (struct request *) arg;
- (void) fd;
- (void) events;
-
- log(EVENTDNS_LOG_DEBUG, "Request %lx timed out", (unsigned long) arg);
-
- req->ns->timedout++;
- if (req->ns->timedout > global_max_nameserver_timeout) {
- nameserver_failed(req->ns, "request timed out.");
- }
-
- (void) evtimer_del(&req->timeout_event);
- if (req->tx_count >= global_max_retransmits) {
- // this request has failed
- reply_callback(req, 0, DNS_ERR_TIMEOUT, NULL);
- request_finished(req, &req_head);
- } else {
- // retransmit it
- eventdns_request_transmit(req);
- }
-}
-
-// try to send a request to a given server.
-//
-// return:
-// 0 ok
-// 1 temporary failure
-// 2 other failure
-static int
-eventdns_request_transmit_to(struct request *req, struct nameserver *server) {
- const int r = send(server->socket, req->request, req->request_len, 0);
- if (r < 0) {
- int err = last_error(server->socket);
- if (error_is_eagain(err)) return 1;
- nameserver_failed(req->ns, strerror(err));
- return 2;
- } else if (r != (int)req->request_len) {
- return 1; // short write
- } else {
- return 0;
- }
-}
-
-// try to send a request, updating the fields of the request
-// as needed
-//
-// return:
-// 0 ok
-// 1 failed
-static int
-eventdns_request_transmit(struct request *req) {
- int retcode = 0, r;
-
- // if we fail to send this packet then this flag marks it
- // for eventdns_transmit
- req->transmit_me = 1;
- if (req->trans_id == 0xffff) abort();
-
- if (req->ns->choaked) {
- // don't bother trying to write to a socket
- // which we have had EAGAIN from
- return 1;
- }
-
- r = eventdns_request_transmit_to(req, req->ns);
- switch (r) {
- case 1:
- // temp failure
- req->ns->choaked = 1;
- nameserver_write_waiting(req->ns, 1);
- return 1;
- case 2:
- // failed in some other way
- retcode = 1;
- // fall through
- default:
- // all ok
- log(EVENTDNS_LOG_DEBUG,
- "Setting timeout for request %lx", (unsigned long) req);
- evtimer_set(&req->timeout_event, eventdns_request_timeout_callback, req);
- if (evtimer_add(&req->timeout_event, &global_timeout) < 0) {
- log(EVENTDNS_LOG_WARN,
- "Error from libevent when adding timer for "
- "request %lx", (unsigned long) req);
- // ???? Do more?
- }
- req->tx_count++;
- req->transmit_me = 0;
- return retcode;
- }
-}
-
-static void
-nameserver_probe_callback(int result, char type, int count, int ttl, void *addresses, void *arg) {
- struct nameserver *const ns = (struct nameserver *) arg;
- (void) type;
- (void) count;
- (void) ttl;
- (void) addresses;
-
- if (result == DNS_ERR_NONE || result == DNS_ERR_NOTEXIST) {
- // this is a good reply
- nameserver_up(ns);
- } else nameserver_probe_failed(ns);
-}
-
-static void
-nameserver_send_probe(struct nameserver *const ns) {
- struct request *req;
- // here we need to send a probe to a given nameserver
- // in the hope that it is up now.
-
- log(EVENTDNS_LOG_DEBUG, "Sending probe to %s", debug_ntoa(ns->address));
- req = request_new(TYPE_A, "www.google.com", DNS_QUERY_NO_SEARCH, nameserver_probe_callback, ns);
- if (!req) return;
- // we force this into the inflight queue no matter what
- request_trans_id_set(req, transaction_id_pick());
- req->ns = ns;
- request_submit(req);
-}
-
-// returns:
-// 0 didn't try to transmit anything
-// 1 tried to transmit something
-static int
-eventdns_transmit(void) {
- char did_try_to_transmit = 0;
-
- if (req_head) {
- struct request *const started_at = req_head, *req = req_head;
- // first transmit all the requests which are currently waiting
- do {
- if (req->transmit_me) {
- did_try_to_transmit = 1;
- eventdns_request_transmit(req);
- }
-
- req = req->next;
- } while (req != started_at);
- }
-
- return did_try_to_transmit;
-}
-
-// exported function
-int
-eventdns_count_nameservers(void) {
- const struct nameserver *server = server_head;
- int n = 0;
- if (!server)
- return 0;
- do {
- ++n;
- server = server->next;
- } while (server != server_head);
- return n;
-}
-
-// exported function
-int
-eventdns_clear_nameservers_and_suspend(void) {
- struct nameserver *server = server_head, *started_at = server_head;
- struct request *req = req_head, *req_started_at = req_head;
-
- if (!server)
- return 0;
- while (1) {
- struct nameserver *next = server->next;
- (void) event_del(&server->event);
- (void) evtimer_del(&server->timeout_event);
- if (server->socket >= 0)
- CLOSE_SOCKET(server->socket);
- free(server);
- if (next == started_at)
- break;
- server = next;
- }
- server_head = NULL;
- global_good_nameservers = 0;
-
- while (req) {
- struct request *next = req->next;
- req->tx_count = req->reissue_count = 0;
- req->ns = NULL;
- // ???? What to do about searches?
- (void) evtimer_del(&req->timeout_event);
- req->trans_id = 0;
- req->transmit_me = 0;
-
- global_requests_waiting++;
- eventdns_request_insert(req, &req_waiting_head);
- /* We want to insert these suspended elements at the front of
- * the waiting queue, since they were pending before any of
- * the waiting entries were added. This is a circular list,
- * so we can just shift the start back by one.*/
- req_waiting_head = req_waiting_head->prev;
-
- if (next == req_started_at)
- break;
- req = next;
- }
- req_head = NULL;
- global_requests_inflight = 0;
-
- return 0;
-}
-
-// exported function
-int
-eventdns_resume(void) {
- eventdns_requests_pump_waiting_queue();
- return 0;
-}
-
-// exported function
-int
-eventdns_nameserver_add(unsigned long int address) {
- // first check to see if we already have this nameserver
-
- const struct nameserver *server = server_head, *const started_at = server_head;
- struct nameserver *ns;
- struct sockaddr_in sin;
- int err = 0;
- if (server) {
- do {
- if (server->address == address) return 3;
- server = server->next;
- } while (server != started_at);
- }
-
- ns = (struct nameserver *) malloc(sizeof(struct nameserver));
- if (!ns) return -1;
-
- memset(ns, 0, sizeof(struct nameserver));
-
- ns->socket = socket(PF_INET, SOCK_DGRAM, 0);
- if (ns->socket < 0) { err = 1; goto out1; }
-#ifdef MS_WINDOWS
- {
- u_long nonblocking = 1;
- ioctlsocket(ns->socket, FIONBIO, &nonblocking);
- }
-#else
- fcntl(ns->socket, F_SETFL, O_NONBLOCK);
-#endif
- sin.sin_addr.s_addr = address;
- sin.sin_port = htons(53);
- sin.sin_family = AF_INET;
- if (connect(ns->socket, (struct sockaddr *) &sin, sizeof(sin)) != 0) {
- err = 2;
- goto out2;
- }
-
- ns->address = address;
- ns->state = 1;
- event_set(&ns->event, ns->socket, EV_READ | EV_PERSIST, nameserver_ready_callback, ns);
- if (event_add(&ns->event, NULL) < 0) {
- err = 2;
- goto out2;
- }
-
- log(EVENTDNS_LOG_DEBUG, "Added nameserver %s", debug_ntoa(address));
-
- // insert this nameserver into the list of them
- if (!server_head) {
- ns->next = ns->prev = ns;
- server_head = ns;
- } else {
- ns->next = server_head->next;
- ns->prev = server_head;
- server_head->next = ns;
- if (server_head->prev == server_head) {
- server_head->prev = ns;
- }
- }
-
- global_good_nameservers++;
-
- return 0;
-
- out2:
- CLOSE_SOCKET(ns->socket);
- out1:
- free(ns);
- log(EVENTDNS_LOG_WARN, "Unable to add nameserver %s: error %d",
- debug_ntoa(address), err);
- return err;
-}
-
-// exported function
-int
-eventdns_nameserver_ip_add(const char *ip_as_string) {
- struct in_addr ina;
- if (!inet_aton(ip_as_string, &ina)) return 4;
- return eventdns_nameserver_add(ina.s_addr);
-}
-
-// insert into the tail of the queue
-static void
-eventdns_request_insert(struct request *req, struct request **head) {
- if (!*head) {
- *head = req;
- req->next = req->prev = req;
- return;
- }
-
- req->prev = (*head)->prev;
- req->prev->next = req;
- req->next = *head;
- (*head)->prev = req;
-}
-
-static int
-string_num_dots(const char *s) {
- int count = 0;
- while ((s = strchr(s, '.'))) {
- s++;
- count++;
- }
- return count;
-}
-
-static struct request *
-request_new(int type, const char *name, int flags, eventdns_callback_type callback, void *user_ptr) {
- const char issuing_now = (global_requests_inflight < global_max_requests_inflight) ? 1 : 0;
-
- const int name_len = strlen(name);
- const int request_max_len = eventdns_request_len(name_len);
- const u16 trans_id = issuing_now ? transaction_id_pick() : 0xffff;
- // the request data is alloced in a single block with the header
- struct request *const req = (struct request *) malloc(sizeof(struct request) + request_max_len);
- int rlen;
- (void) flags;
-
- if (!req) return NULL;
- memset(req, 0, sizeof(struct request));
-
- // request data lives just after the header
- req->request = ((u8 *) req) + sizeof(struct request);
- req->request_appended = 1; // denotes that the request data shouldn't be free()ed
- rlen = eventdns_request_data_build(name, name_len, trans_id, type, CLASS_INET, req->request);
- if (rlen < 0) goto err1;
- req->request_len = rlen;
- req->trans_id = trans_id;
- req->tx_count = 0;
- req->request_type = type;
- req->user_pointer = user_ptr;
- req->user_callback = callback;
- req->ns = issuing_now ? nameserver_pick() : NULL;
- req->next = req->prev = NULL;
-
- return req;
- err1:
- free(req);
- return NULL;
-}
-
-static void
-request_submit(struct request *const req) {
- if (req->ns) {
- // if it has a nameserver assigned then this is going
- // straight into the inflight queue
- eventdns_request_insert(req, &req_head);
- global_requests_inflight++;
- eventdns_request_transmit(req);
- } else {
- eventdns_request_insert(req, &req_waiting_head);
- global_requests_waiting++;
- }
-}
-
-// exported function
-int eventdns_resolve_ipv4(const char *name, int flags, eventdns_callback_type callback, void *ptr) {
- log(EVENTDNS_LOG_DEBUG, "Resolve requested for %s", name);
- if (flags & DNS_QUERY_NO_SEARCH) {
- struct request *const req = request_new(TYPE_A, name, flags, callback, ptr);
- if (!req) return 1;
- request_submit(req);
- return 0;
- } else {
- return search_request_new(TYPE_A, name, flags, callback, ptr);
- }
-}
-
-int eventdns_resolve_reverse(struct in_addr *in, int flags, eventdns_callback_type callback, void *ptr) {
- char buf[32];
- struct request *req;
- u32 a;
- assert(in);
- a = ntohl(in->s_addr);
- sprintf(buf, "%d.%d.%d.%d.in-addr.arpa",
- (int)(u8)((a )&0xff),
- (int)(u8)((a>>8 )&0xff),
- (int)(u8)((a>>16)&0xff),
- (int)(u8)((a>>24)&0xff));
- log(EVENTDNS_LOG_DEBUG, "Resolve requested for %s (reverse)", buf);
- req = request_new(TYPE_PTR, buf, flags, callback, ptr);
- if (!req) return 1;
- request_submit(req);
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////
-// Search support
-//
-// the libc resolver has support for searching a number of domains
-// to find a name. If nothing else then it takes the single domain
-// from the gethostname() call.
-//
-// It can also be configured via the domain and search options in a
-// resolv.conf.
-//
-// The ndots option controls how many dots it takes for the resolver
-// to decide that a name is non-local and so try a raw lookup first.
-
-struct search_domain {
- int len;
- struct search_domain *next;
- // the text string is appended to this structure
-};
-
-struct search_state {
- int refcount;
- int ndots;
- int num_domains;
- struct search_domain *head;
-};
-
-static struct search_state *global_search_state = NULL;
-
-static void
-search_state_decref(struct search_state *const state) {
- if (!state) return;
- state->refcount--;
- if (!state->refcount) {
- struct search_domain *next, *dom;
- for (dom = state->head; dom; dom = next) {
- next = dom->next;
- free(dom);
- }
- free(state);
- }
-}
-
-static struct search_state *
-search_state_new(void) {
- struct search_state *state = (struct search_state *) malloc(sizeof(struct search_state));
- if (!state) return NULL;
- memset(state, 0, sizeof(struct search_state));
- state->refcount = 1;
- state->ndots = 1;
-
- return state;
-}
-
-static void
-search_postfix_clear(void) {
- search_state_decref(global_search_state);
-
- global_search_state = search_state_new();
-}
-
-// exported function
-void
-eventdns_search_clear(void) {
- search_postfix_clear();
-}
-
-static void
-search_postfix_add(const char *domain) {
- int domain_len;
- struct search_domain *sdomain;
- while (domain[0] == '.') domain++;
- domain_len = strlen(domain);
-
- if (!global_search_state) global_search_state = search_state_new();
- if (!global_search_state) return;
- global_search_state->num_domains++;
-
- sdomain = (struct search_domain *) malloc(sizeof(struct search_domain) + domain_len);
- if (!sdomain) return;
- memcpy( ((u8 *) sdomain) + sizeof(struct search_domain), domain, domain_len);
- sdomain->next = global_search_state->head;
- sdomain->len = domain_len;
-
- global_search_state->head = sdomain;
-}
-
-// reverse the order of members in the postfix list. This is needed because,
-// when parsing resolv.conf we push elements in the wrong order
-static void
-search_reverse(void) {
- struct search_domain *cur, *prev = NULL, *next;
- cur = global_search_state->head;
- while (cur) {
- next = cur->next;
- cur->next = prev;
- prev = cur;
- cur = next;
- }
-
- global_search_state->head = prev;
-}
-
-// exported function
-void
-eventdns_search_add(const char *domain) {
- search_postfix_add(domain);
-}
-
-// exported function
-void
-eventdns_search_ndots_set(const int ndots) {
- if (!global_search_state) global_search_state = search_state_new();
- if (!global_search_state) return;
- global_search_state->ndots = ndots;
-}
-
-static void
-search_set_from_hostname(void) {
- char hostname[HOST_NAME_MAX + 1], *domainname;
-
- search_postfix_clear();
- if (gethostname(hostname, sizeof(hostname))) return;
- domainname = strchr(hostname, '.');
- if (!domainname) return;
- search_postfix_add(domainname);
-}
-
-// warning: returns malloced string
-static char *
-search_make_new(const struct search_state *const state, int n, const char *const base_name) {
- const int base_len = strlen(base_name);
- const char need_to_append_dot = base_name[base_len - 1] == '.' ? 0 : 1;
- struct search_domain *dom;
-
- for (dom = state->head; dom; dom = dom->next) {
- if (!n--) {
- // this is the postfix we want
- // the actual postfix string is kept at the end of the structure
- const u8 *const postfix = ((u8 *) dom) + sizeof(struct search_domain);
- const int postfix_len = dom->len;
- char *const newname = (char *) malloc(base_len + need_to_append_dot + postfix_len + 1);
- if (!newname) return NULL;
- memcpy(newname, base_name, base_len);
- if (need_to_append_dot) newname[base_len] = '.';
- memcpy(newname + base_len + need_to_append_dot, postfix, postfix_len);
- newname[base_len + need_to_append_dot + postfix_len] = 0;
- return newname;
- }
- }
-
- // we ran off the end of the list and still didn't find the requested string
- abort();
-}
-
-static int
-search_request_new(int type, const char *const name, int flags, eventdns_callback_type user_callback, void *user_arg) {
- assert(type == TYPE_A);
- if ( ((flags & DNS_QUERY_NO_SEARCH) == 0) &&
- global_search_state &&
- global_search_state->num_domains) {
- // we have some domains to search
- struct request *req;
- if (string_num_dots(name) >= global_search_state->ndots) {
- req = request_new(type, name, flags, user_callback, user_arg);
- if (!req) return 1;
- req->search_index = -1;
- } else {
- char *const new_name = search_make_new(global_search_state, 0, name);
- if (!new_name) return 1;
- req = request_new(type, new_name, flags, user_callback, user_arg);
- free(new_name);
- if (!req) return 1;
- req->search_index = 0;
- }
- req->search_origname = strdup(name);
- req->search_state = global_search_state;
- req->search_flags = flags;
- global_search_state->refcount++;
- request_submit(req);
- return 0;
- } else {
- struct request *const req = request_new(type, name, flags, user_callback, user_arg);
- if (!req) return 1;
- request_submit(req);
- return 0;
- }
-}
-
-// this is called when a request has failed to find a name. We need to check
-// if it is part of a search and, if so, try the next name in the list
-// returns:
-// 0 another request has been submitted
-// 1 no more requests needed
-static int
-search_try_next(struct request *const req) {
- if (req->search_state) {
- // it is part of a search
- char *new_name;
- struct request *newreq;
- req->search_index++;
- if (req->search_index >= req->search_state->num_domains) {
- // no more postfixes to try, however we may need to try
- // this name without a postfix
- if (string_num_dots(req->search_origname) < req->search_state->ndots) {
- // yep, we need to try it raw
- struct request *const newreq = request_new(req->request_type, req->search_origname, req->search_flags, req->user_callback, req->user_pointer);
- log(EVENTDNS_LOG_DEBUG, "Search: trying raw query %s", req->search_origname);
- if (newreq) {
- request_submit(newreq);
- return 0;
- }
- }
- return 1;
- }
-
- new_name = search_make_new(req->search_state, req->search_index, req->search_origname);
- if (!new_name) return 1;
- log(EVENTDNS_LOG_DEBUG, "Search: now trying %s (%d)", new_name, req->search_index);
- newreq = request_new(req->request_type, new_name, req->search_flags, req->user_callback, req->user_pointer);
- free(new_name);
- if (!newreq) return 1;
- newreq->search_origname = req->search_origname;
- req->search_origname = NULL;
- newreq->search_state = req->search_state;
- newreq->search_flags = req->search_flags;
- newreq->search_index = req->search_index;
- newreq->search_state->refcount++;
- request_submit(newreq);
- return 0;
- }
- return 1;
-}
-
-static void
-search_request_finished(struct request *const req) {
- if (req->search_state) {
- search_state_decref(req->search_state);
- req->search_state = NULL;
- }
- if (req->search_origname) {
- free(req->search_origname);
- req->search_origname = NULL;
- }
-}
-
-/////////////////////////////////////////////////////////////////////
-// Parsing resolv.conf files
-
-static void
-eventdns_resolv_set_defaults(int flags) {
- // if the file isn't found then we assume a local resolver
- if (flags & DNS_OPTION_SEARCH) search_set_from_hostname();
- if (flags & DNS_OPTION_NAMESERVERS) eventdns_nameserver_ip_add("127.0.0.1");
-}
-
-#ifndef HAVE_STRTOK_R
-static char *
-strtok_r(char *s, const char *delim, char **state) {
- return strtok(s, delim);
-}
-#endif
-
-// helper version of atoi which returns -1 on error
-static int
-strtoint(const char *const str) {
- char *endptr;
- const int r = strtol(str, &endptr, 10);
- if (*endptr) return -1;
- return r;
-}
-
-static void
-resolv_conf_parse_line(char *const start, int flags) {
- char *strtok_state;
- static const char *const delims = " \t";
-#define NEXT_TOKEN strtok_r(NULL, delims, &strtok_state)
-
- char *const first_token = strtok_r(start, delims, &strtok_state);
- if (!first_token) return;
-
- if (!strcmp(first_token, "nameserver")) {
- const char *const nameserver = NEXT_TOKEN;
- struct in_addr ina;
-
- if (inet_aton(nameserver, &ina)) {
- // address is valid
- eventdns_nameserver_add(ina.s_addr);
- }
- } else if (!strcmp(first_token, "domain") && (flags & DNS_OPTION_SEARCH)) {
- const char *const domain = NEXT_TOKEN;
- if (domain) {
- search_postfix_clear();
- search_postfix_add(domain);
- }
- } else if (!strcmp(first_token, "search") && (flags & DNS_OPTION_SEARCH)) {
- const char *domain;
- search_postfix_clear();
-
- while ((domain = NEXT_TOKEN)) {
- search_postfix_add(domain);
- }
- search_reverse();
- } else if (!strcmp(first_token, "options")) {
- const char *option;
-
- while ((option = NEXT_TOKEN)) {
- if (!strncmp(option, "ndots:", 6)) {
- const int ndots = strtoint(&option[6]);
- if (ndots == -1) continue;
- if (!(flags & DNS_OPTION_SEARCH)) continue;
- log(EVENTDNS_LOG_DEBUG,"Setting ndots to %d", ndots);
- if (!global_search_state) global_search_state = search_state_new();
- if (!global_search_state) return;
- global_search_state->ndots = ndots;
- } else if (!strncmp(option, "timeout:", 8)) {
- const int timeout = strtoint(&option[8]);
- if (timeout == -1) continue;
- if (!(flags & DNS_OPTION_MISC)) continue;
- log(EVENTDNS_LOG_DEBUG,"Setting timeout to %d", timeout);
- global_timeout.tv_sec = timeout;
- } else if (!strncmp(option, "attempts:", 9)) {
- int retries = strtoint(&option[9]);
- if (retries == -1) continue;
- if (retries > 255) retries = 255;
- if (!(flags & DNS_OPTION_MISC)) continue;
- log(EVENTDNS_LOG_DEBUG,"Setting retries to %d", retries);
- global_max_retransmits = retries;
- }
- }
- }
-#undef NEXT_TOKEN
-}
-
-// exported function
-// returns:
-// 0 no errors
-// 1 failed to open file
-// 2 failed to stat file
-// 3 file too large
-// 4 out of memory
-// 5 short read from file
-int
-eventdns_resolv_conf_parse(int flags, const char *const filename) {
- struct stat st;
- int fd;
- u8 *resolv;
- char *start;
- int err = 0;
-
- log(EVENTDNS_LOG_DEBUG,"Parsing resolve.conf file %s", filename);
-
- fd = open(filename, O_RDONLY);
- if (fd < 0) {
- eventdns_resolv_set_defaults(flags);
- return 0;
- }
-
- if (fstat(fd, &st)) { err = 2; goto out1; }
- if (!st.st_size) {
- eventdns_resolv_set_defaults(flags);
- err = 0;
- goto out1;
- }
- if (st.st_size > 65535) { err = 3; goto out1; } // no resolv.conf should be any bigger
-
- resolv = (u8 *) malloc(st.st_size + 1);
- if (!resolv) { err = 4; goto out1; }
-
- if (read(fd, resolv, st.st_size) != st.st_size) { err = 5; goto out2; }
- resolv[st.st_size] = 0; // we malloced an extra byte
-
- start = (char *) resolv;
- for (;;) {
- char *const newline = strchr(start, '\n');
- if (!newline) {
- resolv_conf_parse_line(start, flags);
- break;
- } else {
- *newline = 0;
- resolv_conf_parse_line(start, flags);
- start = newline + 1;
- }
- }
-
- if (!server_head && (flags & DNS_OPTION_NAMESERVERS)) {
- // no nameservers were configured.
- eventdns_nameserver_ip_add("127.0.0.1");
- }
- if (flags & DNS_OPTION_SEARCH && (!global_search_state || global_search_state->num_domains == 0)) {
- search_set_from_hostname();
- }
-
-out2:
- free(resolv);
-out1:
- close(fd);
- return err;
-}
-
-#ifdef MS_WINDOWS
-// Add multiple nameservers from a space-or-comma-separated list.
-static int
-eventdns_nameserver_ip_add_line(const char *ips) {
- const char *addr;
- char *buf;
- int r;
- while (*ips) {
- while (ISSPACE(*ips) || *ips == ',' || *ips == '\t')
- ++ips;
- addr = ips;
- while (ISDIGIT(*ips) || *ips == '.')
- ++ips;
- buf = malloc(ips-addr+1);
- if (!buf) return 4;
- memcpy(buf, addr, ips-addr);
- buf[ips-addr] = '\0';
- r = eventdns_nameserver_ip_add(buf);
- free(buf);
- if (r) return r;
- }
- return 0;
-}
-
-typedef DWORD(WINAPI *GetNetworkParams_fn_t)(FIXED_INFO *, DWORD*);
-
-// Use the windows GetNetworkParams interface in iphlpapi.dll to
-// figure out what our nameservers are.
-static int
-load_nameservers_with_getnetworkparams(void) {
- // Based on MSDN examples and inspection of c-ares code.
- FIXED_INFO *fixed;
- HMODULE handle = 0;
- ULONG size = sizeof(FIXED_INFO);
- void *buf = NULL;
- int status = 0, r, added_any;
- IP_ADDR_STRING *ns;
- GetNetworkParams_fn_t fn;
-
- if (!(handle = LoadLibrary("iphlpapi.dll"))) {
- log(EVENTDNS_LOG_WARN,"Could not open iphlpapi.dll");
- //right now status = 0, doesn't that mean "good" - mikec
- status = -1;
- goto done;
- }
-
- if (!(fn =
- (GetNetworkParams_fn_t)
- GetProcAddress(handle, "GetNetworkParams"))) {
- log(EVENTDNS_LOG_WARN,"Could not get address of function.");
- //same as above
- status = -1;
- goto done;
- }
-
- buf = malloc(size);
- if (!buf) {
- status = 4;
- goto done;
- }
- fixed = buf;
- r = fn(fixed, &size);
- if (r != ERROR_SUCCESS && r != ERROR_BUFFER_OVERFLOW) {
- status = -1;
- goto done;
- }
- if (r != ERROR_SUCCESS) {
- free(buf);
- buf = malloc(size);
- if (!buf) { status = 4; goto done; }
- fixed = buf;
- r = fn(fixed, &size);
- if (r != ERROR_SUCCESS) {
- log(EVENTDNS_LOG_DEBUG,"fn() failed.");
- status = -1;
- goto done;
- }
- }
-
- assert(fixed);
- added_any = 0;
- ns = &(fixed->DnsServerList);
- while (ns) {
- r = eventdns_nameserver_ip_add_line(ns->IpAddress.String);
- if (r) {
- log(EVENTDNS_LOG_DEBUG,"Could not add nameserver %s to list,error: %d",
- (ns->IpAddress.String),(int)GetLastError());
- status = r;
- goto done;
- } else {
- log(EVENTDNS_LOG_DEBUG,"Succesfully added %s as nameserver",ns->IpAddress.String);
- }
-
- added_any++;
- ns = ns->Next;
- }
-
- if (!added_any) {
- //should we ever get here? - mikec
- log(EVENTDNS_LOG_DEBUG,"No name servers added.");
- status = -1;
- }
-
- done:
- if (buf)
- free(buf);
- if (handle)
- FreeLibrary(handle);
- return status;
-}
-
-static int
-config_nameserver_from_reg_key(HKEY key, const char *subkey) {
- char *buf;
- DWORD bufsz = 0, type = 0;
- int status = 0;
-
- if (RegQueryValueEx(key, subkey, 0, &type, NULL, &bufsz)
- != ERROR_MORE_DATA)
- return -1;
- if (!(buf = malloc(bufsz)))
- return -1;
-
- if (RegQueryValueEx(key, subkey, 0, &type, (LPBYTE)buf, &bufsz)
- == ERROR_SUCCESS && bufsz > 1) {
- status = eventdns_nameserver_ip_add_line(buf);
- }
-
- free(buf);
- return status;
-}
-
-#define SERVICES_KEY "System\\CurrentControlSet\\Services\\"
-
-#define WIN_NS_9X_KEY SERVICES_KEY "VxD\\MSTCP"
-#define WIN_NS_NT_KEY SERVICES_KEY "Tcpip\\Parameters"
-
-static int
-load_nameservers_from_registry(void) {
- int found = 0;
- int r;
-#define TRY(k, name) \
- if (!found && config_nameserver_from_reg_key(k,name) == 0) { \
- log(EVENTDNS_LOG_DEBUG,"Found nameservers in %s/%s",#k,name); \
- found = 1; \
- } else { \
- if (!found) \
- log(EVENTDNS_LOG_DEBUG,"Didn't find nameservers in %s/%s", \
- #k,#name); \
- }
-
- if (((int)GetVersion()) > 0) { /* NT */
- HKEY nt_key = 0, interfaces_key = 0;
-
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0,
- KEY_READ, &nt_key) != ERROR_SUCCESS) {
- log(EVENTDNS_LOG_DEBUG,"Couldn't open nt key, %d",(int)GetLastError());
- return -1;
- }
-
- r = RegOpenKeyEx(nt_key, "Interfaces", 0,
- KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS,
- &interfaces_key);
-
- if (r != ERROR_SUCCESS ) {
- log(EVENTDNS_LOG_DEBUG,"Couldn't open interfaces key, %d",(int)GetLastError());
- return -1;
- }
-
- TRY(nt_key, "NameServer");
- TRY(nt_key, "DhcpNameServer");
- TRY(interfaces_key, "NameServer");
- TRY(interfaces_key, "DhcpNameServer");
- RegCloseKey(interfaces_key);
- RegCloseKey(nt_key);
- } else {
- HKEY win_key = 0;
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_9X_KEY, 0,
- KEY_READ, &win_key) != ERROR_SUCCESS) {
- log(EVENTDNS_LOG_DEBUG,"Couldn't open registry key, %d",(int)GetLastError());
- return -1;
-
- }
- TRY(win_key, "NameServer");
- RegCloseKey(win_key);
- }
-
- if (found == 0) {
- log(EVENTDNS_LOG_WARN,"Didn't find any nameservers.");
- }
-
- return found ? 0 : -1;
-#undef TRY
-}
-
-int
-eventdns_config_windows_nameservers(void) {
- if (load_nameservers_with_getnetworkparams() == 0) {
- return 0;
- }
-
- return load_nameservers_from_registry();
-}
-#endif
-
-#ifdef EVENTDNS_MAIN
-void
-main_callback(int result, char type, int count, int ttl,
- void *addrs, void *orig) {
- char *n = (char*)orig;
- int i;
- for (i = 0; i < count; ++i) {
- if (type == DNS_IPv4_A) {
- printf("%s: %s\n", n, debug_ntoa(((u32*)addrs)[i]));
- } else if (type == DNS_PTR) {
- printf("%s: %s\n", n, ((char**)addrs)[i]);
- }
- }
- if (!count) {
- printf("%s: No answer (%d)\n", n, result);
- }
- fflush(stdout);
-}
-
-void
-logfn(const char *msg) {
- fprintf(stderr, "%s\n", msg);
-}
-int
-main(int c, char **v) {
- int idx;
- int reverse = 0, verbose = 1;
- if (c<2) {
- fprintf(stderr, "syntax: %s [-x] [-v] hostname\n", v[0]);
- return 1;
- }
- idx = 1;
- while (idx < c && v[idx][0] == '-') {
- if (!strcmp(v[idx], "-x"))
- reverse = 1;
- else if (!strcmp(v[idx], "-v"))
- verbose = 1;
- else
- fprintf(stderr, "Unknown option %s\n", v[idx]);
- ++idx;
- }
- event_init();
- if (verbose)
- eventdns_set_log_fn(logfn);
- eventdns_resolv_conf_parse(DNS_OPTION_NAMESERVERS, "/etc/resolv.conf");
- for (; idx < c; ++idx) {
- if (reverse) {
- struct in_addr addr;
- if (!inet_aton(v[idx], &addr)) {
- fprintf(stderr, "Skipping non-IP %s\n", v[idx]);
- continue;
- }
- fprintf(stderr, "resolving %s...\n",v[idx]);
- eventdns_resolve_reverse(&addr, 0, main_callback, v[idx]);
- } else {
- fprintf(stderr, "resolving (fwd) %s...\n",v[idx]);
- eventdns_resolve_ipv4(v[idx], 0, main_callback, v[idx]);
- }
- }
- fflush(stdout);
- event_dispatch();
- return 0;
-}
-
-#endif
-
-// Local Variables:
-// tab-width: 4
-// c-basic-offset: 4
-// indent-tabs-mode: t
-// End:
-
diff --git a/src/or/eventdns.h b/src/or/eventdns.h
deleted file mode 100644
index 0897b50ca6..0000000000
--- a/src/or/eventdns.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* This software is Public Domain. To view a copy of the public domain dedication,
- * visit http://creativecommons.org/licenses/publicdomain/ or send a letter to
- * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
- *
- * I ask and expect, but do not require, that all derivative works contain an
- * attribution similar to:
- * Parts developed by Adam Langley <agl@imperialviolet.org>
- *
- * You may wish to replace the word "Parts" with something else depending on
- * the amount of original code.
- *
- * (Derivative works does not include programs which link against, run or include
- * the source verbatim in their source distributions)
- */
-
-#ifndef EVENTDNS_H
-#define EVENTDNS_H
-
-/* Error codes 0-5 are as described in RFC 1035. */
-#define DNS_ERR_NONE 0
-/* The name server was unable to interpret the query */
-#define DNS_ERR_FORMAT 1
-/* The name server was unable to process this query due to a problem with the
- * name server */
-#define DNS_ERR_SERVERFAILED 2
-/* The domain name does not exist */
-#define DNS_ERR_NOTEXIST 3
-/* The name server does not support the requested kind of query */
-#define DNS_ERR_NOTIMPL 4
-/* The name server refuses to reform the specified operation for policy
- * reasons */
-#define DNS_ERR_REFUSED 5
-/* The reply was truncated or ill-formated */
-#define DNS_ERR_TRUNCATED 65
-/* An unknown error occurred */
-#define DNS_ERR_UNKNOWN 66
-/* Communication with the server timed out */
-#define DNS_ERR_TIMEOUT 67
-
-#define DNS_IPv4_A 1
-#define DNS_PTR 2 /* XXXX ???? */
-
-#define DNS_QUERY_NO_SEARCH 1
-
-#define DNS_OPTION_SEARCH 1
-#define DNS_OPTION_NAMESERVERS 2
-#define DNS_OPTION_MISC 4
-#define DNS_OPTIONS_ALL 7
-
-typedef void (*eventdns_callback_type) (int result, char type, int count, int ttl, void *addresses, void *arg);
-
-int eventdns_nameserver_add(unsigned long int address);
-int eventdns_count_nameservers(void);
-int eventdns_clear_nameservers_and_suspend(void);
-int eventdns_resume(void);
-int eventdns_nameserver_ip_add(const char *ip_as_string);
-int eventdns_resolve_ipv4(const char *name, int flags, eventdns_callback_type callback, void *ptr);
-struct in_addr;
-int eventdns_resolve_reverse(struct in_addr *addr, int flags, eventdns_callback_type callback, void *ptr);
-int eventdns_resolv_conf_parse(int flags, const char *);
-#ifdef MS_WINDOWS
-int eventdns_config_windows_nameservers(void);
-#endif
-void eventdns_search_clear(void);
-void eventdns_search_add(const char *domain);
-void eventdns_search_ndots_set(const int ndots);
-
-typedef void (*eventdns_debug_log_fn_type)(int warn, const char *msg);
-void eventdns_set_log_fn(eventdns_debug_log_fn_type fn);
-
-#define DNS_NO_SEARCH 1
-
-#endif // !EVENTDNS_H
diff --git a/src/or/eventdns_tor.h b/src/or/eventdns_tor.h
deleted file mode 100644
index a10b3726bb..0000000000
--- a/src/or/eventdns_tor.h
+++ /dev/null
@@ -1,13 +0,0 @@
-
-#include "orconfig.h"
-#define DNS_USE_OPENSSL_FOR_ID
-#ifndef HAVE_UINT
-typedef unsigned int uint;
-#endif
-#ifndef HAVE_U_CHAR
-typedef unsigned char u_char;
-#endif
-#ifdef MS_WINDOWS
-#define inline __inline
-#endif
-
diff --git a/src/or/hibernate.c b/src/or/hibernate.c
index 93c4cbe553..da74e98dd2 100644
--- a/src/or/hibernate.c
+++ b/src/or/hibernate.c
@@ -536,7 +536,7 @@ accounting_set_wakeup_time(void)
#define BW_ACCOUNTING_VERSION 1
/** Save all our bandwidth tracking information to disk. Return 0 on
- * success, -1 on failure. */
+ * success, -1 on failure*/
int
accounting_record_bandwidth_usage(time_t now)
{
@@ -545,18 +545,11 @@ accounting_record_bandwidth_usage(time_t now)
char time1[ISO_TIME_LEN+1];
char time2[ISO_TIME_LEN+1];
char *cp = buf;
- time_t tmp;
/* Format is:
Version\nTime\nTime\nRead\nWrite\nSeconds\nExpected-Rate\n */
format_iso_time(time1, interval_start_time);
format_iso_time(time2, now);
- /* now check to see if they're valid times -- if they're not,
- * and we write them, then tor will refuse to start next time. */
- if (parse_iso_time(time1, &tmp) || parse_iso_time(time2, &tmp)) {
- log_warn(LD_ACCT, "Created a time that we refused to parse.");
- return -1;
- }
tor_snprintf(cp, sizeof(buf),
"%d\n%s\n%s\n"U64_FORMAT"\n"U64_FORMAT"\n%lu\n%lu\n",
BW_ACCOUNTING_VERSION,
@@ -683,8 +676,7 @@ hibernate_hard_limit_reached(void)
static int
hibernate_soft_limit_reached(void)
{
- uint64_t soft_limit = DBL_TO_U64(U64_TO_DBL(get_options()->AccountingMax)
- * .95);
+ uint64_t soft_limit = (uint64_t) ((get_options()->AccountingMax) * .95);
if (!soft_limit)
return 0;
return n_bytes_read_in_interval >= soft_limit
@@ -712,7 +704,6 @@ hibernate_begin(int new_state, time_t now)
/* close listeners. leave control listener(s). */
while ((conn = connection_get_by_type(CONN_TYPE_OR_LISTENER)) ||
(conn = connection_get_by_type(CONN_TYPE_AP_LISTENER)) ||
- (conn = connection_get_by_type(CONN_TYPE_AP_TRANS_LISTENER)) ||
(conn = connection_get_by_type(CONN_TYPE_DIR_LISTENER))) {
log_info(LD_NET,"Closing listener type %d", conn->type);
connection_mark_for_close(conn);
@@ -787,12 +778,11 @@ hibernate_go_dormant(time_t now)
(conn = connection_get_by_type(CONN_TYPE_AP)) ||
(conn = connection_get_by_type(CONN_TYPE_EXIT))) {
if (CONN_IS_EDGE(conn))
- connection_edge_end(TO_EDGE_CONN(conn), END_STREAM_REASON_HIBERNATING,
- TO_EDGE_CONN(conn)->cpath_layer);
+ connection_edge_end(conn, END_STREAM_REASON_HIBERNATING,
+ conn->cpath_layer);
log_info(LD_NET,"Closing conn type %d", conn->type);
if (conn->type == CONN_TYPE_AP) /* send socks failure if needed */
- connection_mark_unattached_ap(TO_EDGE_CONN(conn),
- END_STREAM_REASON_HIBERNATING);
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_HIBERNATING);
else
connection_mark_for_close(conn);
}
diff --git a/src/or/main.c b/src/or/main.c
index b2fd0359d7..336de8b5a7 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -50,12 +50,13 @@ static time_t time_to_fetch_directory = 0;
/** When do we next download a running-routers summary? */
static time_t time_to_fetch_running_routers = 0;
-/** Array of all open connections. The first n_conns elements are valid. */
+/** Array of all open connections; each element corresponds to the element of
+ * poll_array in the same position. The first nfds elements are valid. */
static connection_t *connection_array[MAXCONNECTIONS+1] =
{ NULL };
static smartlist_t *closeable_connection_lst = NULL;
-static int n_conns=0; /**< Number of connections currently active. */
+static int nfds=0; /**< Number of connections currently active. */
/** We set this to 1 when we've opened a circuit, so we can print a log
* entry to inform the user that Tor is working. */
@@ -111,8 +112,8 @@ static char* nt_strerror(uint32_t errnum);
/** How old do we let a connection to an OR get before deciding it's
* obsolete? */
#define TIME_BEFORE_OR_CONN_IS_OBSOLETE (60*60*24*7)
-/** How long do we let OR connections handshake before we decide that
- * they are obsolete? */
+/** How long do we OR connections to handshake before we decide that they
+ * could be obsolete? */
#define TLS_HANDSHAKE_TIMEOUT (60)
/********* END VARIABLES ************/
@@ -120,7 +121,8 @@ static char* nt_strerror(uint32_t errnum);
/****************************************************************************
*
* This section contains accessors and other methods on the connection_array
-* variables (which are global within this file and unavailable outside it).
+* and poll_array variables (which are global within this file and unavailable
+* outside it).
*
****************************************************************************/
@@ -134,15 +136,15 @@ connection_add(connection_t *conn)
tor_assert(conn);
tor_assert(conn->s >= 0);
- if (n_conns >= get_options()->_ConnLimit-1) {
+ if (nfds >= get_options()->_ConnLimit-1) {
log_warn(LD_NET,"Failing because we have %d connections already. Please "
- "raise your ulimit -n.", n_conns);
+ "raise your ulimit -n.", nfds);
return -1;
}
- tor_assert(conn->conn_array_index == -1); /* can only connection_add once */
- conn->conn_array_index = n_conns;
- connection_array[n_conns] = conn;
+ tor_assert(conn->poll_index == -1); /* can only connection_add once */
+ conn->poll_index = nfds;
+ connection_array[nfds] = conn;
conn->read_event = tor_malloc_zero(sizeof(struct event));
conn->write_event = tor_malloc_zero(sizeof(struct event));
@@ -151,10 +153,10 @@ connection_add(connection_t *conn)
event_set(conn->write_event, conn->s, EV_WRITE|EV_PERSIST,
conn_write_callback, conn);
- n_conns++;
+ nfds++;
- log_debug(LD_NET,"new conn type %s, socket %d, n_conns %d.",
- conn_type_to_string(conn->type), conn->s, n_conns);
+ log_debug(LD_NET,"new conn type %s, socket %d, nfds %d.",
+ conn_type_to_string(conn->type), conn->s, nfds);
return 0;
}
@@ -169,24 +171,24 @@ connection_remove(connection_t *conn)
int current_index;
tor_assert(conn);
- tor_assert(n_conns>0);
+ tor_assert(nfds>0);
- log_debug(LD_NET,"removing socket %d (type %s), n_conns now %d",
- conn->s, conn_type_to_string(conn->type), n_conns-1);
+ log_debug(LD_NET,"removing socket %d (type %s), nfds now %d",
+ conn->s, conn_type_to_string(conn->type), nfds-1);
- tor_assert(conn->conn_array_index >= 0);
- current_index = conn->conn_array_index;
- if (current_index == n_conns-1) { /* this is the end */
- n_conns--;
+ tor_assert(conn->poll_index >= 0);
+ current_index = conn->poll_index;
+ if (current_index == nfds-1) { /* this is the end */
+ nfds--;
return 0;
}
connection_unregister(conn);
/* replace this one with the one at the end */
- n_conns--;
- connection_array[current_index] = connection_array[n_conns];
- connection_array[current_index]->conn_array_index = current_index;
+ nfds--;
+ connection_array[current_index] = connection_array[nfds];
+ connection_array[current_index]->poll_index = current_index;
return 0;
}
@@ -210,11 +212,11 @@ connection_unlink(connection_t *conn, int remove)
}
smartlist_remove(closeable_connection_lst, conn);
if (conn->type == CONN_TYPE_EXIT) {
- assert_connection_edge_not_dns_pending(TO_EDGE_CONN(conn));
+ assert_connection_edge_not_dns_pending(conn);
}
- if (conn->type == CONN_TYPE_OR) {
- if (!tor_digest_is_zero(TO_OR_CONN(conn)->identity_digest))
- connection_or_remove_from_identity_map(TO_OR_CONN(conn));
+ if (conn->type == CONN_TYPE_OR &&
+ !tor_digest_is_zero(conn->identity_digest)) {
+ connection_or_remove_from_identity_map(conn);
}
connection_free(conn);
}
@@ -241,7 +243,7 @@ int
connection_in_array(connection_t *conn)
{
int i;
- for (i=0; i<n_conns; ++i) {
+ for (i=0; i<nfds; ++i) {
if (conn==connection_array[i])
return 1;
}
@@ -256,7 +258,7 @@ void
get_connection_array(connection_t ***array, int *n)
{
*array = connection_array;
- *n = n_conns;
+ *n = nfds;
}
/** Set the event mask on <b>conn</b> to <b>events</b>. (The event
@@ -380,10 +382,10 @@ close_closeable_connections(void)
int i;
for (i = 0; i < smartlist_len(closeable_connection_lst); ) {
connection_t *conn = smartlist_get(closeable_connection_lst, i);
- if (conn->conn_array_index < 0) {
+ if (conn->poll_index < 0) {
connection_unlink(conn, 0); /* blow it away right now */
} else {
- if (!conn_close_if_marked(conn->conn_array_index))
+ if (!conn_close_if_marked(conn->poll_index))
++i;
}
}
@@ -395,8 +397,6 @@ static void
conn_read_callback(int fd, short event, void *_conn)
{
connection_t *conn = _conn;
- (void)fd;
- (void)event;
log_debug(LD_NET,"socket %d wants to read.",conn->s);
@@ -411,8 +411,7 @@ conn_read_callback(int fd, short event, void *_conn)
tor_fragile_assert();
#endif
if (CONN_IS_EDGE(conn))
- connection_edge_end_errno(TO_EDGE_CONN(conn),
- TO_EDGE_CONN(conn)->cpath_layer);
+ connection_edge_end_errno(conn, conn->cpath_layer);
connection_mark_for_close(conn);
}
}
@@ -428,8 +427,6 @@ static void
conn_write_callback(int fd, short events, void *_conn)
{
connection_t *conn = _conn;
- (void)fd;
- (void)events;
LOG_FN_CONN(conn, (LOG_DEBUG, LD_NET, "socket %d wants to write.",conn->s));
@@ -442,10 +439,7 @@ conn_write_callback(int fd, short events, void *_conn)
"Bug: unhandled error on write for %s connection (fd %d); removing",
conn_type_to_string(conn->type), conn->s);
tor_fragile_assert();
- if (CONN_IS_EDGE(conn)) {
- /* otherwise we cry wolf about duplicate close */
- conn->edge_has_sent_end = 1;
- }
+ conn->has_sent_end = 1; /* otherwise we cry wolf about duplicate close */
/* XXX do we need a close-immediate here, so we don't try to flush? */
connection_mark_for_close(conn);
}
@@ -491,7 +485,7 @@ conn_close_if_marked(int i)
conn->marked_for_close_file, conn->marked_for_close);
if (connection_speaks_cells(conn)) {
if (conn->state == OR_CONN_STATE_OPEN) {
- retval = flush_buf_tls(TO_OR_CONN(conn)->tls, conn->outbuf, sz,
+ retval = flush_buf_tls(conn->tls, conn->outbuf, sz,
&conn->outbuf_flushlen);
} else
retval = -1; /* never flush non-open broken tls connections */
@@ -540,23 +534,54 @@ void
directory_all_unreachable(time_t now)
{
connection_t *conn;
- (void)now;
stats_n_seconds_working=0; /* reset it */
while ((conn = connection_get_by_type_state(CONN_TYPE_AP,
AP_CONN_STATE_CIRCUIT_WAIT))) {
- edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
log_notice(LD_NET,
"Is your network connection down? "
"Failing connection to '%s:%d'.",
- safe_str(edge_conn->socks_request->address),
- edge_conn->socks_request->port);
- connection_mark_unattached_ap(edge_conn,
- END_STREAM_REASON_NET_UNREACHABLE);
+ safe_str(conn->socks_request->address),
+ conn->socks_request->port);
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_NET_UNREACHABLE);
}
}
+/**
+ * Return the interval to wait between directory downloads, in seconds.
+ */
+static INLINE int
+get_dir_fetch_period(or_options_t *options)
+{
+ if (options->DirFetchPeriod)
+ /* Value from config file. */
+ return options->DirFetchPeriod;
+ else if (options->DirPort)
+ /* Default for directory server */
+ return 60*60;
+ else
+ /* Default for average user. */
+ return 120*60;
+}
+
+/**
+ * Return the interval to wait betweeen router status downloads, in seconds.
+ */
+static INLINE int
+get_status_fetch_period(or_options_t *options)
+{
+ if (options->StatusFetchPeriod)
+ /* Value from config file. */
+ return options->StatusFetchPeriod;
+ else if (options->DirPort)
+ /* Default for directory server */
+ return 15*60;
+ else
+ /* Default for average user. */
+ return 30*60;
+}
+
/** This function is called whenever we successfully pull down some new
* network statuses or server descriptors. */
void
@@ -572,9 +597,14 @@ directory_info_has_arrived(time_t now, int from_cache)
return;
}
- if (server_mode(options) && !we_are_hibernating() && !from_cache &&
- (has_completed_circuit || !any_predicted_circuits(now)))
- consider_testing_reachability(1, 1);
+ if (server_mode(options) &&
+ !we_are_hibernating()) { /* connect to the appropriate routers */
+ if (!authdir_mode(options))
+ router_retry_connections(0, 1);
+ if (!from_cache &&
+ (has_completed_circuit || !any_predicted_circuits(now)))
+ consider_testing_reachability();
+ }
}
/** Perform regular maintenance tasks for a single connection. This
@@ -586,10 +616,9 @@ run_connection_housekeeping(int i, time_t now)
cell_t cell;
connection_t *conn = connection_array[i];
or_options_t *options = get_options();
- or_connection_t *or_conn;
- if (conn->outbuf && !buf_datalen(conn->outbuf) && conn->type == CONN_TYPE_OR)
- TO_OR_CONN(conn)->timestamp_lastempty = now;
+ if (conn->outbuf && !buf_datalen(conn->outbuf))
+ conn->timestamp_lastempty = now;
if (conn->marked_for_close) {
/* nothing to do here */
@@ -611,7 +640,7 @@ run_connection_housekeeping(int i, time_t now)
buf_datalen(conn->inbuf)>=1024) {
log_info(LD_DIR,"Trying to extract information from wedged server desc "
"download.");
- connection_dir_reached_eof(TO_DIR_CONN(conn));
+ connection_dir_reached_eof(conn);
} else {
connection_mark_for_close(conn);
}
@@ -621,19 +650,17 @@ run_connection_housekeeping(int i, time_t now)
if (!connection_speaks_cells(conn))
return; /* we're all done here, the rest is just for OR conns */
- or_conn = TO_OR_CONN(conn);
-
- if (!conn->or_is_obsolete) {
+ if (!conn->is_obsolete) {
if (conn->timestamp_created + TIME_BEFORE_OR_CONN_IS_OBSOLETE < now) {
log_info(LD_OR,
"Marking OR conn to %s:%d obsolete (fd %d, %d secs old).",
conn->address, conn->port, conn->s,
(int)(now - conn->timestamp_created));
- conn->or_is_obsolete = 1;
+ conn->is_obsolete = 1;
} else {
- or_connection_t *best =
- connection_or_get_by_identity_digest(or_conn->identity_digest);
- if (best && best != or_conn &&
+ connection_t *best =
+ connection_or_get_by_identity_digest(conn->identity_digest);
+ if (best && best != conn &&
(conn->state == OR_CONN_STATE_OPEN ||
now > conn->timestamp_created + TLS_HANDSHAKE_TIMEOUT)) {
/* We only mark as obsolete connections that already are in
@@ -648,16 +675,16 @@ run_connection_housekeeping(int i, time_t now)
"(fd %d, %d secs old).",
conn->address, conn->port, conn->s,
(int)(now - conn->timestamp_created));
- conn->or_is_obsolete = 1;
+ conn->is_obsolete = 1;
}
}
}
- if (conn->or_is_obsolete && !or_conn->n_circuits) {
+ if (conn->is_obsolete && !conn->n_circuits) {
/* no unmarked circs -- mark it now */
log_info(LD_OR,
"Expiring non-used OR connection to fd %d (%s:%d) [Obsolete].",
- conn->s, conn->address, conn->port);
+ conn->s,conn->address, conn->port);
connection_mark_for_close(conn);
conn->hold_open_until_flushed = 1;
return;
@@ -666,20 +693,20 @@ run_connection_housekeeping(int i, time_t now)
/* If we haven't written to an OR connection for a while, then either nuke
the connection or send a keepalive, depending. */
if (now >= conn->timestamp_lastwritten + options->KeepalivePeriod) {
- routerinfo_t *router = router_get_by_digest(or_conn->identity_digest);
+ routerinfo_t *router = router_get_by_digest(conn->identity_digest);
if (!connection_state_is_open(conn)) {
log_info(LD_OR,"Expiring non-open OR connection to fd %d (%s:%d).",
conn->s,conn->address, conn->port);
connection_mark_for_close(conn);
conn->hold_open_until_flushed = 1;
- } else if (we_are_hibernating() && !or_conn->n_circuits &&
+ } else if (we_are_hibernating() && !conn->n_circuits &&
!buf_datalen(conn->outbuf)) {
log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) "
"[Hibernating or exiting].",
conn->s,conn->address, conn->port);
connection_mark_for_close(conn);
conn->hold_open_until_flushed = 1;
- } else if (!clique_mode(options) && !or_conn->n_circuits &&
+ } else if (!clique_mode(options) && !conn->n_circuits &&
(!router || !server_mode(options) ||
!router_is_clique_mode(router))) {
log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) "
@@ -688,7 +715,7 @@ run_connection_housekeeping(int i, time_t now)
connection_mark_for_close(conn);
conn->hold_open_until_flushed = 1;
} else if (
- now >= or_conn->timestamp_lastempty + options->KeepalivePeriod*10 &&
+ now >= conn->timestamp_lastempty + options->KeepalivePeriod*10 &&
now >= conn->timestamp_lastwritten + options->KeepalivePeriod*10) {
log_fn(LOG_PROTOCOL_WARN,LD_PROTOCOL,
"Expiring stuck OR connection to fd %d (%s:%d). (%d bytes to "
@@ -703,7 +730,7 @@ run_connection_housekeeping(int i, time_t now)
conn->address, conn->port);
memset(&cell,0,sizeof(cell_t));
cell.command = CELL_PADDING;
- connection_or_write_cell_to_buf(&cell, or_conn);
+ connection_or_write_cell_to_buf(&cell, conn);
}
}
}
@@ -722,7 +749,6 @@ run_scheduled_events(time_t now)
static time_t time_to_try_getting_descriptors = 0;
static time_t time_to_reset_descriptor_failures = 0;
static time_t time_to_add_entropy = 0;
- static time_t time_to_check_for_wildcarded_dns = 0;
or_options_t *options = get_options();
int i;
int have_dir_info;
@@ -743,15 +769,13 @@ run_scheduled_events(time_t now)
rotate_onion_key();
cpuworkers_rotate();
if (router_rebuild_descriptor(1)<0) {
- log_info(LD_CONFIG, "Couldn't rebuild router descriptor");
+ log_warn(LD_BUG, "Couldn't rebuild router descriptor");
}
if (advertised_server_mode())
router_upload_dir_desc_to_dirservers(0);
}
if (time_to_try_getting_descriptors < now) {
- /* XXXX Maybe we should do this every 10sec when not enough info,
- * and every 60sec when we have enough info -NM */
update_router_descriptor_downloads(now);
time_to_try_getting_descriptors = now + DESCRIPTOR_RETRY_INTERVAL;
}
@@ -767,7 +791,7 @@ run_scheduled_events(time_t now)
last_rotated_certificate = now;
if (last_rotated_certificate+MAX_SSL_KEY_LIFETIME < now) {
log_info(LD_GENERAL,"Rotating tls context.");
- if (tor_tls_context_new(get_identity_key(), options->Nickname,
+ if (tor_tls_context_new(get_identity_key(), 1, options->Nickname,
MAX_SSL_KEY_LIFETIME) < 0) {
log_warn(LD_BUG, "Error reinitializing TLS context");
/* XXX is it a bug here, that we just keep going? */
@@ -792,7 +816,7 @@ run_scheduled_events(time_t now)
if (now % 10 == 0 && authdir_mode(options) && !we_are_hibernating()) {
/* try to determine reachability */
- dirserv_test_reachability(0);
+ router_retry_connections(1, 0);
}
/** 2. Periodically, we consider getting a new directory, getting a
@@ -811,8 +835,7 @@ run_scheduled_events(time_t now)
directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR, NULL, 1);
}
-#define V1_DIR_FETCH_PERIOD (60*60)
- time_to_fetch_directory = now + V1_DIR_FETCH_PERIOD;
+ time_to_fetch_directory = now + get_dir_fetch_period(options);
/* Also, take this chance to remove old information from rephist
* and the rend cache. */
@@ -828,8 +851,7 @@ run_scheduled_events(time_t now)
if (!authdir_mode(options) || !options->V1AuthoritativeDir) {
directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST, NULL, 1);
}
-#define V1_RUNNINGROUTERS_FETCH_PERIOD (20*60)
- time_to_fetch_running_routers = now + V1_RUNNINGROUTERS_FETCH_PERIOD;
+ time_to_fetch_running_routers = now + get_status_fetch_period(options);
}
/* 2b. Once per minute, regenerate and upload the descriptor if the old
@@ -843,14 +865,14 @@ run_scheduled_events(time_t now)
}
mark_my_descriptor_dirty_if_older_than(
now - FORCE_REGENERATE_DESCRIPTOR_INTERVAL);
- consider_publishable_server(0);
+ consider_publishable_server(now, 0);
/* also, check religiously for reachability, if it's within the first
* 20 minutes of our uptime. */
if (server_mode(options) &&
(has_completed_circuit || !any_predicted_circuits(now)) &&
stats_n_seconds_working < TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT &&
!we_are_hibernating())
- consider_testing_reachability(1, 1);
+ consider_testing_reachability();
/* If any networkstatus documents are no longer recent, we need to
* update all the descriptors' running status. */
@@ -898,11 +920,11 @@ run_scheduled_events(time_t now)
circuit_build_needed_circs(now);
/** 5. We do housekeeping for each connection... */
- for (i=0;i<n_conns;i++) {
+ for (i=0;i<nfds;i++) {
run_connection_housekeeping(i, now);
}
if (time_to_shrink_buffers < now) {
- for (i=0;i<n_conns;i++) {
+ for (i=0;i<nfds;i++) {
connection_t *conn = connection_array[i];
if (conn->outbuf)
buf_shrink(conn->outbuf);
@@ -924,18 +946,6 @@ run_scheduled_events(time_t now)
* we'll pass it to poll/select and bad things will happen.
*/
close_closeable_connections();
-
- /** 9. and if we're a server, check whether our DNS is telling stories to
- * us. */
- if (server_mode(options) && time_to_check_for_wildcarded_dns < now) {
- if (!time_to_check_for_wildcarded_dns) {
- time_to_check_for_wildcarded_dns = now + 60 + crypto_rand_int(120);
- } else {
- dns_launch_wildcard_checks();
- time_to_check_for_wildcarded_dns = now + 12*3600 +
- crypto_rand_int(12*3600);
- }
- }
}
static struct event *timeout_event = NULL;
@@ -952,9 +962,6 @@ second_elapsed_callback(int fd, short event, void *args)
size_t bytes_read;
int seconds_elapsed;
or_options_t *options = get_options();
- (void)fd;
- (void)event;
- (void)args;
if (!timeout_event) {
timeout_event = tor_malloc_zero(sizeof(struct event));
evtimer_set(timeout_event, second_elapsed_callback, NULL);
@@ -1007,11 +1014,9 @@ second_elapsed_callback(int fd, short event, void *args)
me->address, me->dir_port);
}
-/** If more than this many seconds have elapsed, probably the clock
- * jumped: doesn't count. */
-#define NUM_JUMPED_SECONDS_BEFORE_WARN 10
-/* This used to be 100, but I cranked it down for Mike Chiussi -RD */
- if (seconds_elapsed < NUM_JUMPED_SECONDS_BEFORE_WARN)
+ /* if more than 100s have elapsed, probably the clock jumped: doesn't
+ * count. */
+ if (seconds_elapsed < 100)
stats_n_seconds_working += seconds_elapsed;
else
circuit_note_clock_jumped(seconds_elapsed);
@@ -1051,6 +1056,7 @@ got_libevent_error(void)
static int
do_hup(void)
{
+ char keydir[512];
or_options_t *options = get_options();
log_notice(LD_GENERAL,"Received reload signal (hup). Reloading config.");
@@ -1070,8 +1076,11 @@ do_hup(void)
options = get_options(); /* they have changed now */
if (authdir_mode(options)) {
/* reload the approved-routers file */
- if (dirserv_load_fingerprint_file() < 0) {
- /* warnings are logged from dirserv_load_fingerprint_file() directly */
+ tor_snprintf(keydir, sizeof(keydir),
+ "%s/approved-routers", options->DataDirectory);
+ log_info(LD_GENERAL,
+ "Reloading approved fingerprints from \"%s\"...", keydir);
+ if (dirserv_parse_fingerprint_file(keydir) < 0) {
log_info(LD_GENERAL, "Error reloading fingerprints. "
"Continuing with old list.");
}
@@ -1092,14 +1101,11 @@ do_hup(void)
if (server_mode(options)) {
// const char *descriptor;
- mark_my_descriptor_dirty();
/* Restart cpuworker and dnsworker processes, so they get up-to-date
* configuration options. */
cpuworkers_rotate();
- dns_reset();
+ dnsworkers_rotate();
#if 0
- const char *descriptor;
- char keydir[512];
/* Write out a fresh descriptor, but leave old one on failure. */
router_rebuild_descriptor(1);
descriptor = router_get_my_descriptor();
@@ -1122,11 +1128,7 @@ do_main_loop(void)
{
int loop_result;
- /* initialize dns resolve map, spawn workers if needed */
- if (dns_init() < 0) {
- log_err(LD_GENERAL,"Error initializing dns subsystem; exiting");
- return -1;
- }
+ dns_init(); /* initialize dns resolve map, spawn workers if needed */
handle_signals(1);
@@ -1158,7 +1160,7 @@ do_main_loop(void)
if (authdir_mode(get_options())) {
/* the directory is already here, run startup things */
- dirserv_test_reachability(1);
+ router_retry_connections(1, 1);
}
if (server_mode(get_options())) {
@@ -1217,33 +1219,16 @@ do_main_loop(void)
}
}
-/* DOCDOC */
-int
-control_signal_check(int the_signal)
-{
- switch (the_signal)
- {
- case 1:
- case 2:
- case 10:
- case 12:
- case 15:
- case SIGNEWNYM:
- return 1;
- default:
- return 0;
- }
-}
-
/** Used to implement the SIGNAL control command: if we accept
- * <b>the_signal</b> as a remote pseudo-signal, act on it. */
+ * <b>the_signal</b> as a remote pseudo-signal, then act on it and
+ * return 0. Else return -1. */
/* We don't re-use catch() here because:
* 1. We handle a different set of signals than those allowed in catch.
* 2. Platforms without signal() are unlikely to define SIGfoo.
* 3. The control spec is defined to use fixed numeric signal values
* which just happen to match the unix values.
*/
-void
+int
control_signal_act(int the_signal)
{
switch (the_signal)
@@ -1267,9 +1252,9 @@ control_signal_act(int the_signal)
signal_callback(0,0,(void*)(uintptr_t)SIGNEWNYM);
break;
default:
- log_warn(LD_BUG, "Unrecognized signal number %d.", the_signal);
- break;
+ return -1;
}
+ return 0;
}
/** Libevent callback: invoked when we get a signal.
@@ -1278,8 +1263,6 @@ static void
signal_callback(int fd, short events, void *arg)
{
uintptr_t sig = (uintptr_t)arg;
- (void)fd;
- (void)events;
switch (sig)
{
case SIGTERM:
@@ -1328,21 +1311,21 @@ signal_callback(int fd, short events, void *arg)
}
}
-extern uint64_t buf_total_used;
-extern uint64_t buf_total_alloc;
-extern uint64_t rephist_total_alloc;
-extern uint32_t rephist_total_num;
-
/**
* Write current memory usage information to the log.
*/
static void
dumpmemusage(int severity)
{
+ extern uint64_t buf_total_used;
+ extern uint64_t buf_total_alloc;
+ extern uint64_t rephist_total_alloc;
+ extern uint32_t rephist_total_num;
+
log(severity, LD_GENERAL,
"In buffers: "U64_FORMAT" used/"U64_FORMAT" allocated (%d conns).",
U64_PRINTF_ARG(buf_total_used), U64_PRINTF_ARG(buf_total_alloc),
- n_conns);
+ nfds);
log(severity, LD_GENERAL, "In rephist: "U64_FORMAT" used by %d Tors.",
U64_PRINTF_ARG(rephist_total_alloc), rephist_total_num);
dump_routerlist_mem_usage(severity);
@@ -1360,7 +1343,7 @@ dumpstats(int severity)
log(severity, LD_GENERAL, "Dumping stats:");
- for (i=0;i<n_conns;i++) {
+ for (i=0;i<nfds;i++) {
conn = connection_array[i];
log(severity, LD_GENERAL,
"Conn %d (socket %d) type %d (%s), state %d (%s), created %d secs ago",
@@ -1369,7 +1352,7 @@ dumpstats(int severity)
(int)(now - conn->timestamp_created));
if (!connection_is_listener(conn)) {
log(severity,LD_GENERAL,
- "Conn %d is to %s:%d.", i,
+ "Conn %d is to '%s:%d'.", i,
safe_str(conn->address), conn->port);
log(severity,LD_GENERAL,
"Conn %d: %d bytes waiting on inbuf (len %d, last read %d secs ago)",
@@ -1404,12 +1387,12 @@ dumpstats(int severity)
U64_PRINTF_ARG(stats_n_destroy_cells_processed));
if (stats_n_data_cells_packaged)
log(severity,LD_NET,"Average packaged cell fullness: %2.3f%%",
- 100*(U64_TO_DBL(stats_n_data_bytes_packaged) /
- U64_TO_DBL(stats_n_data_cells_packaged*RELAY_PAYLOAD_SIZE)) );
+ 100*(((double)stats_n_data_bytes_packaged) /
+ (stats_n_data_cells_packaged*RELAY_PAYLOAD_SIZE)) );
if (stats_n_data_cells_received)
log(severity,LD_NET,"Average delivered cell fullness: %2.3f%%",
- 100*(U64_TO_DBL(stats_n_data_bytes_received) /
- U64_TO_DBL(stats_n_data_cells_received*RELAY_PAYLOAD_SIZE)) );
+ 100*(((double)stats_n_data_bytes_received) /
+ (stats_n_data_cells_received*RELAY_PAYLOAD_SIZE)) );
if (now - time_of_process_start >= 0)
elapsed = now - time_of_process_start;
@@ -1521,7 +1504,8 @@ tor_init(int argc, char *argv[])
atexit(exit_function);
if (options_init_from_torrc(argc,argv) < 0) {
- log_err(LD_CONFIG,"Reading config failed--see warnings above.");
+ log_err(LD_CONFIG,"Reading config failed--see warnings above. "
+ "For usage, try -h.");
return -1;
}
@@ -1598,32 +1582,30 @@ tor_cleanup(void)
}
/** Read/create keys as needed, and echo our fingerprint to stdout. */
-static int
+static void
do_list_fingerprint(void)
{
char buf[FINGERPRINT_LEN+1];
crypto_pk_env_t *k;
const char *nickname = get_options()->Nickname;
if (!server_mode(get_options())) {
- log_err(LD_GENERAL,
- "Clients don't have long-term identity keys. Exiting.\n");
- return -1;
+ printf("Clients don't have long-term identity keys. Exiting.\n");
+ return;
}
tor_assert(nickname);
if (init_keys() < 0) {
log_err(LD_BUG,"Error initializing keys; exiting");
- return -1;
+ return;
}
if (!(k = get_identity_key())) {
log_err(LD_GENERAL,"Error: missing identity key.");
- return -1;
+ return;
}
if (crypto_pk_get_fingerprint(k, buf, 1)<0) {
- log_err(LD_BUG, "Error computing fingerprint");
- return -1;
+ log_warn(LD_BUG, "Error computing fingerprint");
+ return;
}
printf("%s %s\n", nickname, buf);
- return 0;
}
/** Entry point for password hashing: take the desired password from
@@ -1791,7 +1773,7 @@ nt_service_main(void)
if (!StartServiceCtrlDispatcher(table)) {
result = GetLastError();
errmsg = nt_strerror(result);
- printf("Service error %d : %s\n", (int) result, errmsg);
+ printf("Service error %d : %s\n", result, errmsg);
LocalFree(errmsg);
if (result == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
if (tor_init(backup_argc, backup_argv) < 0)
@@ -1915,7 +1897,7 @@ nt_service_stop(SC_HANDLE hService)
}
else {
errmsg = nt_strerror(GetLastError());
- printf("Service failed to stop : %s\n",errmsg);
+ printf("Service failed to stop : %s\n");
LocalFree(errmsg);
}
}
@@ -2028,6 +2010,7 @@ nt_service_remove(void)
{
SC_HANDLE hSCManager = NULL;
SC_HANDLE hService = NULL;
+ BOOL result = FALSE;
char *errmsg;
if ((hSCManager = nt_service_open_scm()) == NULL) {
@@ -2131,11 +2114,10 @@ _tor_dmalloc_free(void *p)
int
tor_main(int argc, char *argv[])
{
- int result = 0;
#ifdef USE_DMALLOC
- int r = CRYPTO_set_mem_ex_functions(_tor_malloc, _tor_realloc,
- _tor_dmalloc_free);
- log_notice(LD_CONFIG, "Set up dmalloc; returned %d", r);
+ int r = CRYPTO_set_mem_ex_functions(_tor_malloc, _tor_realloc,
+ _tor_dmalloc_free);
+ log_notice(LD_CONFIG, "Set up damalloc; returned %d", r);
#endif
#ifdef MS_WINDOWS_SERVICE
backup_argv = argv;
@@ -2172,26 +2154,22 @@ tor_main(int argc, char *argv[])
#ifdef MS_WINDOWS_SERVICE
service_status.dwCurrentState = SERVICE_RUNNING;
#endif
- result = do_main_loop();
+ do_main_loop();
break;
case CMD_LIST_FINGERPRINT:
- result = do_list_fingerprint();
+ do_list_fingerprint();
break;
case CMD_HASH_PASSWORD:
do_hash_password();
- result = 0;
break;
case CMD_VERIFY_CONFIG:
printf("Configuration was valid\n");
- result = 0;
break;
- case CMD_RUN_UNITTESTS: /* only set by test.c */
default:
log_warn(LD_BUG,"Illegal command number %d: internal error.",
get_options()->command);
- result = -1;
}
tor_cleanup();
- return result;
+ return -1;
}
diff --git a/src/or/onion.c b/src/or/onion.c
index ba41f21a22..315c5f12dd 100644
--- a/src/or/onion.c
+++ b/src/or/onion.c
@@ -17,7 +17,7 @@ const char onion_c_id[] =
/** Type for a linked list of circuits that are waiting for a free CPU worker
* to process a waiting onion handshake. */
typedef struct onion_queue_t {
- or_circuit_t *circ;
+ circuit_t *circ;
time_t when_added;
struct onion_queue_t *next;
} onion_queue_t;
@@ -35,7 +35,7 @@ static int ol_length=0;
* if ol_list is too long, in which case do nothing and return -1.
*/
int
-onion_pending_add(or_circuit_t *circ)
+onion_pending_add(circuit_t *circ)
{
onion_queue_t *tmp;
time_t now = time(NULL);
@@ -75,7 +75,7 @@ onion_pending_add(or_circuit_t *circ)
onion_pending_remove(ol_list->circ);
log_info(LD_CIRC,
"Circuit create request is too old; cancelling due to overload.");
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_RESOURCELIMIT);
+ circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
}
return 0;
}
@@ -83,10 +83,10 @@ onion_pending_add(or_circuit_t *circ)
/** Remove the first item from ol_list and return it, or return
* NULL if the list is empty.
*/
-or_circuit_t *
+circuit_t *
onion_next_task(void)
{
- or_circuit_t *circ;
+ circuit_t *circ;
if (!ol_list)
return NULL; /* no onions pending, we're done */
@@ -103,7 +103,7 @@ onion_next_task(void)
* circ, remove and free that element. Leave circ itself alone.
*/
void
-onion_pending_remove(or_circuit_t *circ)
+onion_pending_remove(circuit_t *circ)
{
onion_queue_t *tmpo, *victim;
diff --git a/src/or/or.h b/src/or/or.h
index a74a892dd2..b529fcb617 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <limits.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -37,10 +38,30 @@
#ifdef HAVE_CTYPE_H
#include <ctype.h>
#endif
+#include "../common/torint.h"
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h> /* FreeBSD needs this to know what version it is */
#endif
-#include "../common/torint.h"
+#ifdef HAVE_SYS_LIMITS_H
+#include <sys/limits.h>
+#endif
+#ifdef HAVE_MACHINE_LIMITS_H
+#if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
+ /* FreeBSD has a bug where it complains that this file is obsolete,
+ and I should migrate to using sys/limits. It complains even when
+ I include both.
+ __FreeBSD_kernel__ is defined by Debian GNU/kFreeBSD which
+ does the same thing (but doesn't defined __FreeBSD__).
+ */
+#include <machine/limits.h>
+#endif
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h> /* Must be included before sys/stat.h for Ultrix */
+#endif
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
@@ -80,13 +101,7 @@
/** Upper bound on maximum simultaneous connections; can be lowered by
* config file. */
-#ifdef CYGWIN
-/* http://archives.seul.org/or/talk/Aug-2006/msg00210.html */
-#define MAXCONNECTIONS 3200
-#else
-/* very high by default. "nobody should need more than this..." */
#define MAXCONNECTIONS 15000
-#endif
#ifdef MS_WINDOWS
/* No, we don't need to redefine FD_SETSIZE before including winsock:
@@ -155,6 +170,7 @@
#define cell_t tor_cell_t
#endif
+#define DEFAULT_BANDWIDTH_OP (1024 * 1000)
#define MAX_NICKNAME_LEN 19
/* Hex digest plus dollar sign. */
#define MAX_HEX_NICKNAME_LEN (HEX_DIGEST_LEN+1)
@@ -166,14 +182,12 @@
#define MAX_HEADERS_SIZE 50000
#define MAX_BODY_SIZE 500000
-/** How long do we keep DNS cache entries before purging them (regardless of
- * their TTL)? */
+#ifdef TOR_PERF
+/** How long do we keep DNS cache entries before purging them? */
+#define MAX_DNS_ENTRY_AGE (150*60)
+#else
#define MAX_DNS_ENTRY_AGE (30*60)
-#define DEFAULT_DNS_TTL (30*60)
-/** How long can a TTL be before we stop believing it? */
-#define MAX_DNS_TTL (3*60*60)
-/** How small can a TTL be before we stop believing it? */
-#define MIN_DNS_TTL (60)
+#endif
/** How often do we rotate onion keys? */
#define MIN_ONION_KEY_LIFETIME (7*24*60*60)
@@ -221,9 +235,7 @@ typedef enum {
#define CONN_TYPE_CONTROL_LISTENER 12
/** Type for connections from user interface process. */
#define CONN_TYPE_CONTROL 13
-/** Type for sockets listening for transparent proxy connections. */
-#define CONN_TYPE_AP_TRANS_LISTENER 14
-#define _CONN_TYPE_MAX 14
+#define _CONN_TYPE_MAX 13
#define CONN_IS_EDGE(x) \
((x)->type == CONN_TYPE_EXIT || (x)->type == CONN_TYPE_AP)
@@ -291,10 +303,7 @@ typedef enum {
#define AP_CONN_STATE_RESOLVE_WAIT 10
/** State for a SOCKS connection: ready to send and receive. */
#define AP_CONN_STATE_OPEN 11
-/** State for a transparent proxy connection: waiting for original
- * destination. */
-#define AP_CONN_STATE_ORIGDST_WAIT 12
-#define _AP_CONN_STATE_MAX 12
+#define _AP_CONN_STATE_MAX 11
#define _DIR_CONN_STATE_MIN 1
/** State for connection to directory server: waiting for connect(). */
@@ -487,7 +496,6 @@ typedef enum {
#define RESOLVED_TYPE_ERROR_TRANSIENT 0xF0
#define RESOLVED_TYPE_ERROR 0xF1
-/* XXX We should document the meaning of these. */
#define END_CIRC_AT_ORIGIN -1
#define _END_CIRC_REASON_MIN 0
#define END_CIRC_REASON_NONE 0
@@ -589,11 +597,7 @@ typedef struct {
typedef struct buf_t buf_t;
typedef struct socks_request_t socks_request_t;
-#define BASE_CONNECTION_MAGIC 0x7C3C304Eu
-#define OR_CONNECTION_MAGIC 0x7D31FF03u
-#define EDGE_CONNECTION_MAGIC 0xF0374013u
-#define DIR_CONNECTION_MAGIC 0x9988ffeeu
-#define CONTROL_CONNECTION_MAGIC 0x8abc765du
+#define CONNECTION_MAGIC 0x7C3C304Eu
/** Description of a connection to another host or process, and associated
* data.
@@ -613,51 +617,48 @@ typedef struct socks_request_t socks_request_t;
* conn->outbuf. Connections differ primarily in the functions called
* to fill and drain these buffers.
*/
-typedef struct connection_t {
- uint32_t magic; /**< For memory debugging: must equal one of
- * *_CONNECTION_MAGIC. */
+struct connection_t {
+ uint32_t magic; /**< For memory debugging: must equal CONNECTION_MAGIC. */
uint8_t type; /**< What kind of connection is this? */
uint8_t state; /**< Current state of this connection. */
- uint8_t purpose; /**< Only used for DIR and EXIT types currently. */
-
- /* The next fields are all one-bit booleans. Some are only applicable
- * to connection subtypes, but we hold them here anyway, to save space.
- * (Currently, they all fit into a single byte.) */
+ uint8_t purpose; /**< Only used for DIR types currently. */
unsigned wants_to_read:1; /**< Boolean: should we start reading again once
- * the bandwidth throttler allows it? */
+ * the bandwidth throttler allows it?
+ */
unsigned wants_to_write:1; /**< Boolean: should we start writing again once
- * the bandwidth throttler allows reads? */
+ * the bandwidth throttler allows reads?
+ */
unsigned hold_open_until_flushed:1; /**< Despite this connection's being
* marked for close, do we flush it
- * before closing it? */
- unsigned int inbuf_reached_eof:1; /**< Boolean: did read() return 0 on this
- * conn? */
- unsigned edge_has_sent_end:1; /**< For debugging; only used on edge
- * connections. Set once we've set the stream end,
+ * before closing it?
+ */
+ unsigned has_sent_end:1; /**< For debugging; only used on edge connections.
+ * Set once we've set the stream end,
* and check in circuit_about_to_close_connection(). */
/** For control connections only. If set, we send extended info with control
* events as appropriate. */
unsigned int control_events_are_extended:1;
/** Used for OR conns that shouldn't get any new circs attached to them. */
- unsigned int or_is_obsolete:1;
- /** For AP connections only. If 1, and we fail to reach the chosen exit,
- * stop requiring it. */
- unsigned int chosen_exit_optional:1;
+ unsigned int is_obsolete:1;
int s; /**< Our socket; -1 if this connection is closed. */
- int conn_array_index; /**< Index into the global connection array. */
- struct event *read_event; /**< Libevent event structure. */
- struct event *write_event; /**< Libevent event structure. */
+ int poll_index; /* XXXX rename. */
+ struct event *read_event; /**< libevent event structure. */
+ struct event *write_event; /**< libevent event structure. */
buf_t *inbuf; /**< Buffer holding data read over this connection. */
+ int inbuf_reached_eof; /**< Boolean: did read() return 0 on this conn? */
+ time_t timestamp_lastread; /**< When was the last time poll() said we could
+ * read? */
+
buf_t *outbuf; /**< Buffer holding data to write over this connection. */
size_t outbuf_flushlen; /**< How much data should we try to flush from the
* outbuf? */
- time_t timestamp_lastread; /**< When was the last time libevent said we could
- * read? */
- time_t timestamp_lastwritten; /**< When was the last time libevent said we
+ time_t timestamp_lastwritten; /**< When was the last time poll() said we
* could write? */
+
time_t timestamp_created; /**< When was this connection_t created? */
+ time_t timestamp_lastempty; /**< When was the outbuf last completely empty?*/
uint32_t addr; /**< IP of the other side of the connection; used to identify
* routers, along with port. */
@@ -666,166 +667,81 @@ typedef struct connection_t {
uint16_t marked_for_close; /**< Should we close this conn on the next
* iteration of the main loop? (If true, holds
* the line number where this connection was
- * marked.) */
+ * marked.)
+ */
const char *marked_for_close_file; /**< For debugging: in which file were
* we marked for close? */
char *address; /**< FQDN (or IP) of the guy on the other end.
- * strdup into this, because free_connection frees it. */
-
-} connection_t;
-
-/** Subtype of connection_t for an "OR connection" -- that is, one that speaks
- * cells over TLS. */
-typedef struct or_connection_t {
- connection_t _base;
-
- char identity_digest[DIGEST_LEN]; /**< Hash of the public RSA key for
- * the other side's signing key. */
+ * strdup into this, because free_connection frees it.
+ */
+ crypto_pk_env_t *identity_pkey; /**< Public RSA key for the other side's
+ * signing key. */
+ char identity_digest[DIGEST_LEN]; /**< Hash of identity_pkey */
char *nickname; /**< Nickname of OR on other side (if any). */
- tor_tls_t *tls; /**< TLS connection state */
+ /** Nickname of planned exit node -- used with .exit support. */
+ char *chosen_exit_name;
- time_t timestamp_lastempty; /**< When was the outbuf last completely empty?*/
+/* Used only by OR connections: */
+ tor_tls_t *tls; /**< TLS connection state (OR only.) */
- /* bandwidth* and receiver_bucket only used by ORs in OPEN state: */
- int bandwidthrate; /**< Bytes/s added to the bucket. (OPEN ORs only.) */
- int bandwidthburst; /**< Max bucket size for this conn. (OPEN ORs only.) */
+ /* bandwidth and receiver_bucket only used by ORs in OPEN state: */
+ int bandwidth; /**< Connection bandwidth. (OPEN ORs only.) */
int receiver_bucket; /**< When this hits 0, stop receiving. Every second we
- * add 'bandwidthrate' to this, capping it at
- * bandwidthburst. (OPEN ORs only) */
+ * add 'bandwidth' to this, capping it at 10*bandwidth.
+ * (OPEN ORs only)
+ */
circ_id_type_t circ_id_type; /**< When we send CREATE cells along this
* connection, which half of the space should
* we use? */
int n_circuits; /**< How many circuits use this connection as p_conn or
* n_conn ? */
- struct or_connection_t *next_with_same_id; /**< Next connection with same
+ struct connection_t *next_with_same_id; /**< Next connection with same
* identity digest as this one. */
uint16_t next_circ_id; /**< Which circ_id do we try to use next on
* this connection? This is always in the
- * range 0..1<<15-1. */
-} or_connection_t;
-
-/** Subtype of connection_t for an "edge connection" -- that is, a socks (ap)
- * connection, or an exit. */
-typedef struct edge_connection_t {
- connection_t _base;
+ * range 0..1<<15-1. (OR only.)*/
- struct edge_connection_t *next_stream; /**< Points to the next stream at this
- * edge, if any */
+/* Used only by edge connections: */
+ uint16_t stream_id;
+ struct connection_t *next_stream; /**< Points to the next stream at this
+ * edge, if any (Edge only). */
struct crypt_path_t *cpath_layer; /**< A pointer to which node in the circ
- * this conn exits at. */
- int package_window; /**< How many more relay cells can I send into the
- * circuit? */
- int deliver_window; /**< How many more relay cells can end at me? */
+ * this conn exits at. (Edge only.) */
+ int package_window; /**< How many more relay cells can i send into the
+ * circuit? (Edge only.) */
+ int deliver_window; /**< How many more relay cells can end at me? (Edge
+ * only.) */
- /** Nickname of planned exit node -- used with .exit support. */
- char *chosen_exit_name;
+/* Used only by Dir connections */
+ char *requested_resource; /**< Which 'resource' did we ask the directory
+ * for?*/
+/* Used only by AP connections */
socks_request_t *socks_request; /**< SOCKS structure describing request (AP
* only.) */
- struct circuit_t *on_circuit; /**< The circuit (if any) that this edge
- * connection is using. */
-
- uint32_t address_ttl; /**< TTL for address-to-addr mapping on exit
- * connection. Exit connections only. */
-
- uint16_t stream_id; /**< The stream ID used for this edge connection on its
- * circuit */
/** Quasi-global identifier for this connection; used for control.c */
- /* XXXX NM This can get re-used after 2**32 streams */
+ /* XXXX NM This can get re-used after 2**32 circuits. */
uint32_t global_identifier;
- char rend_query[REND_SERVICE_ID_LEN+1]; /**< What rendezvous service are we
- * querying for? (AP only) */
-
- /** Number of times we've reassigned this application connection to
- * a new circuit. We keep track because the timeout is longer if we've
- * already retried several times. */
- uint8_t num_socks_retries;
-
-} edge_connection_t;
-
-/** Subtype of connection_t for an "directory connection" -- that is, an HTTP
- * connection to retrieve or serve directory material. */
-typedef struct dir_connection_t {
- connection_t _base;
-
- char *requested_resource; /**< Which 'resource' did we ask the directory
- * for? */
- unsigned int dirconn_direct:1; /**< Is this dirconn direct, or via Tor? */
-
- /* Used only for server sides of some dir connections, to implement
- * "spooling" of directory material to the outbuf. Otherwise, we'd have
- * to append everything to the outbuf in one enormous chunk. */
- enum {
- DIR_SPOOL_NONE=0, DIR_SPOOL_SERVER_BY_DIGEST, DIR_SPOOL_SERVER_BY_FP,
- DIR_SPOOL_CACHED_DIR, DIR_SPOOL_NETWORKSTATUS
- } dir_spool_src;
- smartlist_t *fingerprint_stack;
- struct cached_dir_t *cached_dir;
- off_t cached_dir_offset;
- tor_zlib_state_t *zlib_state;
-
- char rend_query[REND_SERVICE_ID_LEN+1]; /**< What rendezvous service are we
- * querying for? */
-
- char identity_digest[DIGEST_LEN]; /**< Hash of the public RSA key for
- * the directory server's signing key. */
-} dir_connection_t;
-
-/** Subtype of connection_t for an connection to a controller. */
-typedef struct control_connection_t {
- connection_t _base;
-
- uint32_t event_mask; /**< Bitfield: which events does this controller
- * care about? */
+ /* Used only by control connections */
+ uint32_t event_mask;
uint32_t incoming_cmd_len;
uint32_t incoming_cmd_cur_len;
char *incoming_cmd;
+
+/* Used only by DIR and AP connections: */
+ struct circuit_t *on_circuit; /**< The circuit (if any) that this edge
+ * connection is using. */
+ char rend_query[REND_SERVICE_ID_LEN+1]; /**< What rendezvous service are we
+ * querying for? (DIR/AP only) */
+
/* Used only by control v0 connections */
uint16_t incoming_cmd_type;
-} control_connection_t;
-
-/** Cast a connection_t subtype pointer to a connection_t **/
-#define TO_CONN(c) &(((c)->_base))
-/** Helper macro: Given a pointer to to._base, of type from*, return &to. */
-#define DOWNCAST(to, ptr) \
- (to*) (((char*)(ptr)) - STRUCT_OFFSET(to, _base))
-
-/** Convert a connection_t* to an or_connection_t*; assert if the cast is
- * invalid. */
-static or_connection_t *TO_OR_CONN(connection_t *);
-/** Convert a connection_t* to a dir_connection_t*; assert if the cast is
- * invalid. */
-static dir_connection_t *TO_DIR_CONN(connection_t *);
-/** Convert a connection_t* to an edge_connection_t*; assert if the cast is
- * invalid. */
-static edge_connection_t *TO_EDGE_CONN(connection_t *);
-/** Convert a connection_t* to an control_connection_t*; assert if the cast is
- * invalid. */
-static control_connection_t *TO_CONTROL_CONN(connection_t *);
-
-static INLINE or_connection_t *TO_OR_CONN(connection_t *c)
-{
- tor_assert(c->magic == OR_CONNECTION_MAGIC);
- return DOWNCAST(or_connection_t, c);
-}
-static INLINE dir_connection_t *TO_DIR_CONN(connection_t *c)
-{
- tor_assert(c->magic == DIR_CONNECTION_MAGIC);
- return DOWNCAST(dir_connection_t, c);
-}
-static INLINE edge_connection_t *TO_EDGE_CONN(connection_t *c)
-{
- tor_assert(c->magic == EDGE_CONNECTION_MAGIC);
- return DOWNCAST(edge_connection_t, c);
-}
-static INLINE control_connection_t *TO_CONTROL_CONN(connection_t *c)
-{
- tor_assert(c->magic == CONTROL_CONNECTION_MAGIC);
- return DOWNCAST(control_connection_t, c);
-}
+};
+
+typedef struct connection_t connection_t;
typedef enum {
ADDR_POLICY_ACCEPT=1,
@@ -853,13 +769,8 @@ typedef struct cached_dir_t {
size_t dir_len; /**< Length of <b>dir</b> */
size_t dir_z_len; /**< Length of <b>dir_z</b> */
time_t published; /**< When was this object published */
- int refcnt; /**< Reference count for this cached_dir_t. */
} cached_dir_t;
-typedef enum {
- SAVED_NOWHERE=0, SAVED_IN_CACHE, SAVED_IN_JOURNAL
-} saved_location_t;
-
/** Information need to cache an onion router's descriptor. */
typedef struct signed_descriptor_t {
char *signed_descriptor_body;
@@ -867,8 +778,6 @@ typedef struct signed_descriptor_t {
char signed_descriptor_digest[DIGEST_LEN];
char identity_digest[DIGEST_LEN];
time_t published_on;
- saved_location_t saved_location;
- off_t saved_offset;
} signed_descriptor_t;
/** Information about another onion router in the network. */
@@ -900,8 +809,6 @@ typedef struct {
char *contact_info; /**< Declared contact info for this router. */
unsigned int is_hibernating:1; /**< Whether the router claims to be
* hibernating */
- unsigned int has_old_dnsworkers:1; /**< Whether the router is using
- * dnsworker code. */
/* local info */
unsigned int is_running:1; /**< As far as we know, is this OR currently
@@ -930,10 +837,6 @@ typedef struct {
/** How many times has a descriptor been posted and we believed
* this router to be unreachable? We only actually warn on the third. */
int num_unreachable_notifications;
-
- /** What position is this descriptor within routerlist->routers? -1 for
- * none. */
- int routerlist_index;
} routerinfo_t;
/** Contents of a single router entry in a network status object.
@@ -1037,8 +940,6 @@ typedef struct {
/** List of signed_descriptor_t for older router descriptors we're
* caching. */
smartlist_t *old_routers;
- /** DOCDOC */
- tor_mmap_t *mmap_descriptors;
} routerlist_t;
/** Information on router used when extending a circuit. (We don't need a
@@ -1138,10 +1039,7 @@ typedef struct {
time_t expiry_time;
} cpath_build_state_t;
-#define ORIGIN_CIRCUIT_MAGIC 0x35315243u
-#define OR_CIRCUIT_MAGIC 0x98ABC04Fu
-
-typedef uint16_t circid_t;
+#define CIRCUIT_MAGIC 0x35315243u
/**
* A circuit is a path over the onion routing
@@ -1152,34 +1050,42 @@ typedef uint16_t circid_t;
* OR connections multiplex many circuits at once, and stay standing even
* when there are no circuits running over them.
*
- * A circuit_t structure cann fill one of two roles. First, a or_circuit_t
- * links two connections together: either an edge connection and an OR
- * connection, or two OR connections. (When joined to an OR connection, a
- * circuit_t affects only cells sent to a particular circID on that
- * connection. When joined to an edge connection, a circuit_t affects all
- * data.)
-
- * Second, an origin_circuit_t holds the cipher keys and state for sending data
+ * A circuit_t structure fills two roles. First, a circuit_t links two
+ * connections together: either an edge connection and an OR connection,
+ * or two OR connections. (When joined to an OR connection, a circuit_t
+ * affects only cells sent to a particular circID on that connection. When
+ * joined to an edge connection, a circuit_t affects all data.)
+
+ * Second, a circuit_t holds the cipher keys and state for sending data
* along a given circuit. At the OP, it has a sequence of ciphers, each
* of which is shared with a single OR along the circuit. Separate
* ciphers are used for data going "forward" (away from the OP) and
* "backward" (towards the OP). At the OR, a circuit has only two stream
* ciphers: one for data going forward, and one for data going backward.
*/
-typedef struct circuit_t {
- uint32_t magic; /**< For memory and type debugging: must equal
- * ORIGIN_CIRCUIT_MAGIC or OR_CIRCUIT_MAGIC. */
+struct circuit_t {
+ uint32_t magic; /**< For memory debugging: must equal CIRCUIT_MAGIC. */
+ /** The OR connection that is previous in this circuit. */
+ connection_t *p_conn;
/** The OR connection that is next in this circuit. */
- or_connection_t *n_conn;
+ connection_t *n_conn;
/** The identity hash of n_conn. */
char n_conn_id_digest[DIGEST_LEN];
- /** The circuit_id used in the next (forward) hop of this circuit. */
- uint16_t n_circ_id;
- /** The port for the OR that is next in this circuit. */
- uint16_t n_port;
+ /** Linked list of AP streams associated with this circuit. */
+ connection_t *p_streams;
+ /** Linked list of Exit streams associated with this circuit. */
+ connection_t *n_streams;
+ /** Linked list of Exit streams associated with this circuit that are
+ * still being resolved. */
+ connection_t *resolving_streams;
/** The IPv4 address of the OR that is next in this circuit. */
uint32_t n_addr;
+ /** The port for the OR that is next in this circuit. */
+ uint16_t n_port;
+ /** The next stream_id that will be tried when we're attempting to
+ * construct a new AP stream originating at this circuit. */
+ uint16_t next_stream_id;
/** How many relay data cells can we package (read from edge streams)
* on this circuit before we receive a circuit-level sendme cell asking
* for more? */
@@ -1190,12 +1096,48 @@ typedef struct circuit_t {
* more. */
int deliver_window;
+ /** The circuit_id used in the previous (backward) hop of this circuit. */
+ uint16_t p_circ_id;
+ /** The circuit_id used in the next (forward) hop of this circuit. */
+ uint16_t n_circ_id;
+
+ /** The cipher used by intermediate hops for cells heading toward the
+ * OP. */
+ crypto_cipher_env_t *p_crypto;
+ /** The cipher used by intermediate hops for cells heading away from
+ * the OP. */
+ crypto_cipher_env_t *n_crypto;
+
+ /** The integrity-checking digest used by intermediate hops, for
+ * cells packaged here and heading towards the OP.
+ */
+ crypto_digest_env_t *p_digest;
+ /** The integrity-checking digest used by intermediate hops, for
+ * cells packaged at the OP and arriving here.
+ */
+ crypto_digest_env_t *n_digest;
+
+ /** Build state for this circuit. It includes the intended path
+ * length, the chosen exit router, rendezvous information, etc.
+ */
+ cpath_build_state_t *build_state;
+ /** The doubly-linked list of crypt_path_t entries, one per hop,
+ * for this circuit. This includes ciphers for each hop,
+ * integrity-checking digests for each hop, and package/delivery
+ * windows for each hop.
+ *
+ * The cpath field is defined only when we are the circuit's origin.
+ */
+ crypt_path_t *cpath;
+
/** For storage while passing to cpuworker (state
* CIRCUIT_STATE_ONIONSKIN_PENDING), or while n_conn is pending
* (state CIRCUIT_STATE_OR_WAIT). When defined, it is always
* length ONIONSKIN_CHALLENGE_LEN. */
char *onionskin;
+ char handshake_digest[DIGEST_LEN]; /**< Stores KH for intermediate hops. */
+
time_t timestamp_created; /**< When was this circuit created? */
time_t timestamp_dirty; /**< When the circuit was first used, or 0 if the
* circuit is clean. */
@@ -1209,129 +1151,35 @@ typedef struct circuit_t {
const char *marked_for_close_file; /**< For debugging: in which file was this
* circuit marked for close? */
- struct circuit_t *next; /**< Next circuit in linked list. */
-} circuit_t;
-
-/** An origin_circuit_t holds data necessary to build and use a circuit.
- */
-typedef struct origin_circuit_t {
- circuit_t _base;
-
- /** Linked list of AP streams (or EXIT streams if hidden service)
- * associated with this circuit. */
- edge_connection_t *p_streams;
- /** Build state for this circuit. It includes the intended path
- * length, the chosen exit router, rendezvous information, etc.
- */
- cpath_build_state_t *build_state;
- /** The doubly-linked list of crypt_path_t entries, one per hop,
- * for this circuit. This includes ciphers for each hop,
- * integrity-checking digests for each hop, and package/delivery
- * windows for each hop.
- *
- * The cpath field is defined only when we are the circuit's origin.
+ /**
+ * The rend_query field holds the y portion of y.onion (nul-terminated)
+ * if purpose is C_INTRODUCING or C_ESTABLISH_REND, or is a C_GENERAL
+ * for a hidden service, or is S_*.
*/
- crypt_path_t *cpath;
+ char rend_query[REND_SERVICE_ID_LEN+1];
/** The rend_pk_digest field holds a hash of location-hidden service's
- * PK if purpose is S_ESTABLISH_INTRO or S_RENDEZVOUSING.
+ * PK if purpose is INTRO_POINT or S_ESTABLISH_INTRO or S_RENDEZVOUSING.
*/
char rend_pk_digest[DIGEST_LEN];
- /** Holds rendezvous cookie if purpose is C_ESTABLISH_REND. Filled with
- * zeroes otherwise.
+ /** Holds rendezvous cookie if purpose is REND_POINT_WAITING or
+ * C_ESTABLISH_REND. Filled with zeroes otherwise.
*/
char rend_cookie[REND_COOKIE_LEN];
- /**
- * The rend_query field holds the y portion of y.onion (nul-terminated)
- * if purpose is C_INTRODUCING or C_ESTABLISH_REND, or is a C_GENERAL
- * for a hidden service, or is S_*.
- */
- char rend_query[REND_SERVICE_ID_LEN+1];
-
- /** The next stream_id that will be tried when we're attempting to
- * construct a new AP stream originating at this circuit. */
- uint16_t next_stream_id;
+ /** Points to spliced circuit if purpose is REND_ESTABLISHED, and circuit
+ * is not marked for close. */
+ struct circuit_t *rend_splice;
/** Quasi-global identifier for this circuit; used for control.c */
/* XXXX NM This can get re-used after 2**32 circuits. */
uint32_t global_identifier;
-} origin_circuit_t;
-
-/** An or_circuit_t holds information needed to implement a circuit at an
- * OR. */
-typedef struct or_circuit_t {
- circuit_t _base;
-
- /** The circuit_id used in the previous (backward) hop of this circuit. */
- circid_t p_circ_id;
- /** The OR connection that is previous in this circuit. */
- or_connection_t *p_conn;
- /** Linked list of Exit streams associated with this circuit. */
- edge_connection_t *n_streams;
- /** Linked list of Exit streams associated with this circuit that are
- * still being resolved. */
- edge_connection_t *resolving_streams;
- /** The cipher used by intermediate hops for cells heading toward the
- * OP. */
- crypto_cipher_env_t *p_crypto;
- /** The cipher used by intermediate hops for cells heading away from
- * the OP. */
- crypto_cipher_env_t *n_crypto;
-
- /** The integrity-checking digest used by intermediate hops, for
- * cells packaged here and heading towards the OP.
- */
- crypto_digest_env_t *p_digest;
- /** The integrity-checking digest used by intermediate hops, for
- * cells packaged at the OP and arriving here.
- */
- crypto_digest_env_t *n_digest;
-
- /** Points to spliced circuit if purpose is REND_ESTABLISHED, and circuit
- * is not marked for close. */
- struct or_circuit_t *rend_splice;
-
-#if REND_COOKIE_LEN >= DIGEST_LEN
-#define REND_TOKEN_LEN REND_COOKIE_LEN
-#else
-#define REND_TOKEN_LEN DIGEST_LEN
-#endif
+ struct circuit_t *next; /**< Next circuit in linked list. */
+};
- /** A hash of location-hidden service's PK if purpose is INTRO_POINT, or a
- * rendezvous cookie if purpose is REND_POINT_WAITING. Filled with zeroes
- * otherwise.
- */
- char rend_token[REND_TOKEN_LEN];
-
- char handshake_digest[DIGEST_LEN]; /**< Stores KH for the handshake. */
-} or_circuit_t;
-
-/** Convert a circuit subtype to a circuit_t.*/
-#define TO_CIRCUIT(x) (&((x)->_base))
-
-/** Convert a circuit_t* to a pointer to the enclosing or_circuit_t. Asserts
- * if the cast is impossible. */
-static or_circuit_t *TO_OR_CIRCUIT(circuit_t *);
-/** Convert a circuit_t* to a pointer to the enclosing origin_circuit_t.
- * Asserts if the cast is impossible. */
-static origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *);
-
-static INLINE or_circuit_t *TO_OR_CIRCUIT(circuit_t *x)
-{
- tor_assert(x->magic == OR_CIRCUIT_MAGIC);
- //return (or_circuit_t*) (((char*)x) - STRUCT_OFFSET(or_circuit_t, _base));
- return DOWNCAST(or_circuit_t, x);
-}
-static INLINE origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *x)
-{
- tor_assert(x->magic == ORIGIN_CIRCUIT_MAGIC);
- //return (origin_circuit_t*)
- // (((char*)x) - STRUCT_OFFSET(origin_circuit_t, _base));
- return DOWNCAST(origin_circuit_t, x);
-}
+typedef struct circuit_t circuit_t;
#define ALLOW_INVALID_ENTRY 1
#define ALLOW_INVALID_EXIT 2
@@ -1406,8 +1254,6 @@ typedef struct {
config_line_t *DirPolicy; /**< Lists of dir policy components */
/** Addresses to bind for listening for SOCKS connections. */
config_line_t *SocksListenAddress;
- /** Addresses to bind for listening for transparent connections. */
- config_line_t *TransListenAddress;
/** Addresses to bind for listening for OR connections. */
config_line_t *ORListenAddress;
/** Addresses to bind for listening for directory connections. */
@@ -1429,7 +1275,6 @@ typedef struct {
* length (alpha in geometric distribution). */
int ORPort; /**< Port to listen on for OR connections. */
int SocksPort; /**< Port to listen on for SOCKS connections. */
- int TransPort; /**< Port to listen on for transparent connections. */
int ControlPort; /**< Port to listen on for control connections. */
int DirPort; /**< Port to listen on for directory connections. */
int AssumeReachable; /**< Whether to publish our descriptor regardless. */
@@ -1441,8 +1286,6 @@ typedef struct {
int VersioningAuthoritativeDir; /**< Boolean: is this an authoritative
* directory that's willing to recommend
* versions? */
- int AvoidDiskWrites; /**< Boolean: should we never cache things to disk?
- * Not used yet. */
int ClientOnly; /**< Boolean: should we never evolve into a server role? */
int NoPublish; /**< Boolean: should we never publish a descriptor? */
int PublishServerDescriptor; /**< Do we publish our descriptor as normal? */
@@ -1471,8 +1314,12 @@ typedef struct {
int TrackHostExitsExpire; /**< Number of seconds until we expire an
* addressmap */
config_line_t *AddressMap; /**< List of address map directives. */
+ int DirFetchPeriod; /**< How often do we fetch new directories? */
+ int DirPostPeriod; /**< How often do we post our server descriptor to the
+ * authoritative directory servers? */
int RendPostPeriod; /**< How often do we post each rendezvous service
* descriptor? Remember to publish them independently. */
+ int StatusFetchPeriod; /**< How often do we fetch running-routers lists? */
int KeepalivePeriod; /**< How often do we send padding cells to keep
* connections alive? */
int SocksTimeout; /**< How long do we let a socks connection wait
@@ -1494,10 +1341,6 @@ typedef struct {
* to use in a second? */
uint64_t MaxAdvertisedBandwidth; /**< How much bandwidth are we willing to
* tell people we have? */
- uint64_t RelayBandwidthRate; /**< How much bandwidth, on average, are we
- * willing to use for all relayed conns? */
- uint64_t RelayBandwidthBurst; /**< How much bandwidth, at maximum, will we
- * use in a second for all relayed conns? */
int NumCpus; /**< How many CPUs should we try to use? */
int RunTesting; /**< If true, create testing circuits to measure how well the
* other ORs are running. */
@@ -1571,14 +1414,6 @@ typedef struct {
char *VirtualAddrNetwork; /**< Address and mask to hand out for virtual
* MAPADDRESS requests. */
- int ServerDNSSearchDomains; /**< Boolean: If set, we don't force exit
- * addresses to be FQDNs, but rather search for them in
- * the local domains. */
- int ServerDNSDetectHijacking; /**< Boolean: If true, check for DNS failure
- * hijacking */
- char *ServerDNSResolvConfFile; /**< If provided, we configure our internal
- * resolver from the file here rather than from
- * /etc/resolv.conf (unix) or the registry (windows) */
} or_options_t;
/** Persistent state for an onion router, as saved to disk. */
@@ -1612,7 +1447,6 @@ typedef struct {
#define MAX_SOCKS_ADDR_LEN 256
#define SOCKS_COMMAND_CONNECT 0x01
#define SOCKS_COMMAND_RESOLVE 0xF0
-#define SOCKS_COMMAND_RESOLVE_PTR 0xF1
/** State of a SOCKS request from a user to an OP */
struct socks_request_t {
char socks_version; /**< Which version of SOCKS did the client use? */
@@ -1651,8 +1485,6 @@ int flush_buf(int s, buf_t *buf, size_t sz, size_t *buf_flushlen);
int flush_buf_tls(tor_tls_t *tls, buf_t *buf, size_t sz, size_t *buf_flushlen);
int write_to_buf(const char *string, size_t string_len, buf_t *buf);
-int write_to_buf_zlib(buf_t *buf, tor_zlib_state_t *state,
- const char *data, size_t data_len, int done);
int fetch_from_buf(char *string, size_t string_len, buf_t *buf);
int fetch_from_buf_http(buf_t *buf,
char **headers_out, size_t max_headerlen,
@@ -1668,34 +1500,32 @@ void assert_buf_ok(buf_t *buf);
/********************************* circuitbuild.c **********************/
-char *circuit_list_path(origin_circuit_t *circ, int verbose);
-void circuit_log_path(int severity, unsigned int domain,
- origin_circuit_t *circ);
-void circuit_rep_hist_note_result(origin_circuit_t *circ);
-origin_circuit_t *origin_circuit_init(uint8_t purpose, int need_uptime,
- int need_capacity, int internal);
-origin_circuit_t *circuit_establish_circuit(uint8_t purpose,
- extend_info_t *exit,
+char *circuit_list_path(circuit_t *circ, int verbose);
+void circuit_log_path(int severity, unsigned int domain, circuit_t *circ);
+void circuit_rep_hist_note_result(circuit_t *circ);
+void circuit_dump_by_conn(connection_t *conn, int severity);
+circuit_t *circuit_init(uint8_t purpose, int need_uptime,
+ int need_capacity, int internal);
+circuit_t *circuit_establish_circuit(uint8_t purpose, extend_info_t *exit,
int need_uptime, int need_capacity,
int internal);
-int circuit_handle_first_hop(origin_circuit_t *circ);
-void circuit_n_conn_done(or_connection_t *or_conn, int status);
+int circuit_handle_first_hop(circuit_t *circ);
+void circuit_n_conn_done(connection_t *or_conn, int status);
int inform_testing_reachability(void);
-int circuit_send_next_onion_skin(origin_circuit_t *circ);
+int circuit_send_next_onion_skin(circuit_t *circ);
void circuit_note_clock_jumped(int seconds_elapsed);
int circuit_extend(cell_t *cell, circuit_t *circ);
int circuit_init_cpath_crypto(crypt_path_t *cpath, char *key_data,
int reverse);
-int circuit_finish_handshake(origin_circuit_t *circ, uint8_t cell_type,
- char *reply);
-int circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer);
-int onionskin_answer(or_circuit_t *circ, uint8_t cell_type, char *payload,
+int circuit_finish_handshake(circuit_t *circ, uint8_t cell_type, char *reply);
+int circuit_truncated(circuit_t *circ, crypt_path_t *layer);
+int onionskin_answer(circuit_t *circ, uint8_t cell_type, char *payload,
char *keys);
int circuit_all_predicted_ports_handled(time_t now, int *need_uptime,
int *need_capacity);
-int circuit_append_new_exit(origin_circuit_t *circ, extend_info_t *info);
-int circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *info);
+int circuit_append_new_exit(circuit_t *circ, extend_info_t *info);
+int circuit_extend_to_new_exit(circuit_t *circ, extend_info_t *info);
void onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop);
extend_info_t *extend_info_from_router(routerinfo_t *r);
extend_info_t *extend_info_dup(extend_info_t *info);
@@ -1716,29 +1546,24 @@ void entry_guards_free_all(void);
circuit_t * _circuit_get_global_list(void);
const char *circuit_state_to_string(int state);
-void circuit_dump_by_conn(connection_t *conn, int severity);
-void circuit_set_p_circid_orconn(or_circuit_t *circ, uint16_t id,
- or_connection_t *conn);
-void circuit_set_n_circid_orconn(circuit_t *circ, uint16_t id,
- or_connection_t *conn);
+enum which_conn_changed_t { P_CONN_CHANGED=1, N_CONN_CHANGED=0 };
+void circuit_set_circid_orconn(circuit_t *circ, uint16_t id,
+ connection_t *conn,
+ enum which_conn_changed_t which);
void circuit_set_state(circuit_t *circ, int state);
void circuit_close_all_marked(void);
-origin_circuit_t *origin_circuit_new(void);
-or_circuit_t *or_circuit_new(uint16_t p_circ_id, or_connection_t *p_conn);
-circuit_t *circuit_get_by_circid_orconn(uint16_t circ_id,
- or_connection_t *conn);
-int circuit_id_used_on_conn(uint16_t circ_id, or_connection_t *conn);
-circuit_t *circuit_get_by_edge_conn(edge_connection_t *conn);
-void circuit_unlink_all_from_or_conn(or_connection_t *conn, int reason);
-origin_circuit_t *circuit_get_by_global_id(uint32_t id);
-origin_circuit_t *circuit_get_by_rend_query_and_purpose(const char *rend_query,
- uint8_t purpose);
-origin_circuit_t *circuit_get_next_by_pk_and_purpose(origin_circuit_t *start,
+circuit_t *circuit_new(uint16_t p_circ_id, connection_t *p_conn);
+circuit_t *circuit_get_by_circid_orconn(uint16_t circ_id, connection_t *conn);
+int circuit_id_used_on_conn(uint16_t circ_id, connection_t *conn);
+circuit_t *circuit_get_by_edge_conn(connection_t *conn);
+void circuit_unlink_all_from_or_conn(connection_t *conn, int reason);
+circuit_t *circuit_get_by_global_id(uint32_t id);
+circuit_t *circuit_get_by_rend_query_and_purpose(const char *rend_query,
+ uint8_t purpose);
+circuit_t *circuit_get_next_by_pk_and_purpose(circuit_t *start,
const char *digest, uint8_t purpose);
-or_circuit_t *circuit_get_rendezvous(const char *cookie);
-or_circuit_t *circuit_get_intro_point(const char *digest);
-origin_circuit_t *circuit_find_to_cannibalize(uint8_t purpose,
- extend_info_t *info,
+circuit_t *circuit_get_rendezvous(const char *cookie);
+circuit_t *circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
int need_uptime,
int need_capacity, int internal);
void circuit_mark_all_unused_circs(void);
@@ -1757,36 +1582,32 @@ void circuit_free_all(void);
void circuit_expire_building(time_t now);
void circuit_remove_handled_ports(smartlist_t *needed_ports);
-int circuit_stream_is_being_handled(edge_connection_t *conn, uint16_t port,
+int circuit_stream_is_being_handled(connection_t *conn, uint16_t port,
int min);
void circuit_build_needed_circs(time_t now);
-void circuit_detach_stream(circuit_t *circ, edge_connection_t *conn);
+void circuit_detach_stream(circuit_t *circ, connection_t *conn);
void circuit_about_to_close_connection(connection_t *conn);
-
-void reset_bandwidth_test(void);
-int circuit_enough_testing_circs(void);
-
-void circuit_has_opened(origin_circuit_t *circ);
-void circuit_build_failed(origin_circuit_t *circ);
-origin_circuit_t *circuit_launch_by_nickname(uint8_t purpose,
+void circuit_has_opened(circuit_t *circ);
+void circuit_build_failed(circuit_t *circ);
+circuit_t *circuit_launch_by_nickname(uint8_t purpose,
const char *exit_nickname,
int need_uptime, int need_capacity,
int is_internal);
-origin_circuit_t *circuit_launch_by_extend_info(uint8_t purpose,
+circuit_t *circuit_launch_by_extend_info(uint8_t purpose,
extend_info_t *info,
int need_uptime, int need_capacity,
int is_internal);
-origin_circuit_t *circuit_launch_by_router(uint8_t purpose, routerinfo_t *exit,
+circuit_t *circuit_launch_by_router(uint8_t purpose, routerinfo_t *exit,
int need_uptime, int need_capacity,
int is_internal);
void circuit_reset_failure_count(int timeout);
-int connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn,
- origin_circuit_t *circ);
-int connection_ap_handshake_attach_circuit(edge_connection_t *conn);
+int connection_ap_handshake_attach_chosen_circuit(connection_t *conn,
+ circuit_t *circ);
+int connection_ap_handshake_attach_circuit(connection_t *conn);
/********************************* command.c ***************************/
-void command_process_cell(cell_t *cell, or_connection_t *conn);
+void command_process_cell(cell_t *cell, connection_t *conn);
extern uint64_t stats_n_padding_cells_processed;
extern uint64_t stats_n_create_cells_processed;
@@ -1806,8 +1627,8 @@ int config_get_lines(char *string, config_line_t **result);
void config_free_lines(config_line_t *front);
int options_trial_assign(config_line_t *list, int use_defaults,
int clear_first, char **msg);
-int resolve_my_address(int warn_severity, or_options_t *options,
- uint32_t *addr, char **hostname_out);
+int resolve_my_address(or_options_t *options, uint32_t *addr,
+ char **hostname_out);
void options_init(or_options_t *options);
int options_init_from_torrc(int argc, char **argv);
int options_init_logs(or_options_t *options, int validate_only);
@@ -1860,16 +1681,13 @@ int connection_fetch_from_buf(char *string, size_t len, connection_t *conn);
int connection_wants_to_flush(connection_t *conn);
int connection_outbuf_too_full(connection_t *conn);
int connection_handle_write(connection_t *conn);
-void _connection_controller_force_write(control_connection_t *conn);
+void _connection_controller_force_write(connection_t *conn);
void connection_write_to_buf(const char *string, size_t len,
connection_t *conn);
-void connection_write_to_buf_zlib(dir_connection_t *conn,
- const char *data, size_t data_len,
- int done);
-or_connection_t *connection_or_exact_get_by_addr_port(uint32_t addr,
+connection_t *connection_or_exact_get_by_addr_port(uint32_t addr,
uint16_t port);
-edge_connection_t *connection_get_by_global_id(uint32_t id);
+connection_t *connection_get_by_global_id(uint32_t id);
connection_t *connection_get_by_type(int type);
connection_t *connection_get_by_type_purpose(int type, int purpose);
@@ -1888,50 +1706,46 @@ int connection_state_is_connecting(connection_t *conn);
char *alloc_http_authenticator(const char *authenticator);
void assert_connection_ok(connection_t *conn, time_t now);
-int connection_or_nonopen_was_started_here(or_connection_t *conn);
+int connection_or_nonopen_was_started_here(connection_t *conn);
/********************************* connection_edge.c *************************/
#define connection_mark_unattached_ap(conn, endreason) \
_connection_mark_unattached_ap((conn), (endreason), __LINE__, _SHORT_FILE_)
-void _connection_mark_unattached_ap(edge_connection_t *conn, int endreason,
+void _connection_mark_unattached_ap(connection_t *conn, int endreason,
int line, const char *file);
-int connection_edge_reached_eof(edge_connection_t *conn);
-int connection_edge_process_inbuf(edge_connection_t *conn,
- int package_partial);
-int connection_edge_destroy(uint16_t circ_id, edge_connection_t *conn);
-int connection_edge_end(edge_connection_t *conn, char reason,
+int connection_edge_reached_eof(connection_t *conn);
+int connection_edge_process_inbuf(connection_t *conn, int package_partial);
+int connection_edge_destroy(uint16_t circ_id, connection_t *conn);
+int connection_edge_end(connection_t *conn, char reason,
crypt_path_t *cpath_layer);
-int connection_edge_end_errno(edge_connection_t *conn,
- crypt_path_t *cpath_layer);
-int connection_edge_finished_flushing(edge_connection_t *conn);
-int connection_edge_finished_connecting(edge_connection_t *conn);
+int connection_edge_end_errno(connection_t *conn, crypt_path_t *cpath_layer);
+int connection_edge_finished_flushing(connection_t *conn);
+int connection_edge_finished_connecting(connection_t *conn);
-int connection_ap_handshake_send_begin(edge_connection_t *ap_conn,
- origin_circuit_t *circ);
-int connection_ap_handshake_send_resolve(edge_connection_t *ap_conn,
- origin_circuit_t *circ);
+int connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ);
+int connection_ap_handshake_send_resolve(connection_t *ap_conn,
+ circuit_t *circ);
int connection_ap_make_bridge(char *address, uint16_t port);
-void connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
+void connection_ap_handshake_socks_reply(connection_t *conn, char *reply,
size_t replylen,
socks5_reply_status_t status);
-void connection_ap_handshake_socks_resolved(edge_connection_t *conn,
+void connection_ap_handshake_socks_resolved(connection_t *conn,
int answer_type,
size_t answer_len,
const char *answer,
int ttl);
int connection_exit_begin_conn(cell_t *cell, circuit_t *circ);
-int connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ);
-void connection_exit_connect(edge_connection_t *conn);
-int connection_edge_is_rendezvous_stream(edge_connection_t *conn);
-int connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit);
+int connection_exit_begin_resolve(cell_t *cell, circuit_t *circ);
+void connection_exit_connect(connection_t *conn);
+int connection_edge_is_rendezvous_stream(connection_t *conn);
+int connection_ap_can_use_exit(connection_t *conn, routerinfo_t *exit);
void connection_ap_expire_beginning(void);
void connection_ap_attach_pending(void);
-int connection_ap_detach_retriable(edge_connection_t *conn,
- origin_circuit_t *circ);
+int connection_ap_detach_retriable(connection_t *conn, circuit_t *circ);
void addressmap_init(void);
void addressmap_clean(time_t now);
@@ -1939,7 +1753,7 @@ void addressmap_clear_configured(void);
void addressmap_clear_transient(void);
void addressmap_free_all(void);
void addressmap_rewrite(char *address, size_t maxlen);
-int addressmap_have_mapping(const char *address);
+int addressmap_already_mapped(const char *address);
void addressmap_register(const char *address, char *new_address,
time_t expires);
int parse_virtual_addr_network(const char *val, int validate_only,
@@ -1952,8 +1766,8 @@ int address_is_in_virtual_range(const char *addr);
const char *addressmap_register_virtual_address(int type, char *new_address);
void addressmap_get_mappings(smartlist_t *sl, time_t min_expires,
time_t max_expires);
-int connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
- origin_circuit_t *circ);
+int connection_ap_handshake_rewrite_and_attach(connection_t *conn,
+ circuit_t *circ);
void set_exit_redirects(smartlist_t *lst);
typedef enum hostname_type_t {
@@ -1963,24 +1777,23 @@ hostname_type_t parse_extended_hostname(char *address);
/********************************* connection_or.c ***************************/
-void connection_or_remove_from_identity_map(or_connection_t *conn);
+void connection_or_remove_from_identity_map(connection_t *conn);
void connection_or_clear_identity_map(void);
-or_connection_t *connection_or_get_by_identity_digest(const char *digest);
+connection_t *connection_or_get_by_identity_digest(const char *digest);
-int connection_or_reached_eof(or_connection_t *conn);
-int connection_or_process_inbuf(or_connection_t *conn);
-int connection_or_finished_flushing(or_connection_t *conn);
-int connection_or_finished_connecting(or_connection_t *conn);
+int connection_or_reached_eof(connection_t *conn);
+int connection_or_process_inbuf(connection_t *conn);
+int connection_or_finished_flushing(connection_t *conn);
+int connection_or_finished_connecting(connection_t *conn);
-or_connection_t *connection_or_connect(uint32_t addr, uint16_t port,
+connection_t *connection_or_connect(uint32_t addr, uint16_t port,
const char *id_digest);
-int connection_tls_start_handshake(or_connection_t *conn, int receiving);
-int connection_tls_continue_handshake(or_connection_t *conn);
+int connection_tls_start_handshake(connection_t *conn, int receiving);
+int connection_tls_continue_handshake(connection_t *conn);
-void connection_or_write_cell_to_buf(const cell_t *cell,
- or_connection_t *conn);
-int connection_or_send_destroy(uint16_t circ_id, or_connection_t *conn,
+void connection_or_write_cell_to_buf(const cell_t *cell, connection_t *conn);
+int connection_or_send_destroy(uint16_t circ_id, connection_t *conn,
int reason);
/********************************* control.c ***************************/
@@ -2039,16 +1852,13 @@ void control_adjust_event_log_severity(void);
#define LOG_FN_CONN(conn, args) \
CONN_LOG_PROTECT(conn, log_fn args)
-int connection_control_finished_flushing(control_connection_t *conn);
-int connection_control_reached_eof(control_connection_t *conn);
-int connection_control_process_inbuf(control_connection_t *conn);
+int connection_control_finished_flushing(connection_t *conn);
+int connection_control_reached_eof(connection_t *conn);
+int connection_control_process_inbuf(connection_t *conn);
-int control_event_circuit_status(origin_circuit_t *circ,
- circuit_status_event_t e);
-int control_event_stream_status(edge_connection_t *conn,
- stream_status_event_t e);
-int control_event_or_conn_status(or_connection_t *conn,
- or_conn_status_event_t e);
+int control_event_circuit_status(circuit_t *circ, circuit_status_event_t e);
+int control_event_stream_status(connection_t *conn, stream_status_event_t e);
+int control_event_or_conn_status(connection_t *conn, or_conn_status_event_t e);
int control_event_bandwidth_used(uint32_t n_read, uint32_t n_written);
void control_event_logmsg(int severity, unsigned int domain, const char *msg);
int control_event_descriptors_changed(smartlist_t *routers);
@@ -2094,21 +1904,20 @@ void directory_initiate_command_routerstatus(routerstatus_t *status,
int parse_http_response(const char *headers, int *code, time_t *date,
int *compression, char **response);
-int connection_dir_reached_eof(dir_connection_t *conn);
-int connection_dir_process_inbuf(dir_connection_t *conn);
-int connection_dir_finished_flushing(dir_connection_t *conn);
-int connection_dir_finished_connecting(dir_connection_t *conn);
-void connection_dir_request_failed(dir_connection_t *conn);
+int connection_dir_reached_eof(connection_t *conn);
+int connection_dir_process_inbuf(connection_t *conn);
+int connection_dir_finished_flushing(connection_t *conn);
+int connection_dir_finished_connecting(connection_t *conn);
+void connection_dir_request_failed(connection_t *conn);
int dir_split_resource_into_fingerprints(const char *resource,
smartlist_t *fp_out, int *compresseed_out,
- int decode_hex, int sort_uniq);
+ int decode_hex);
char *directory_dump_request_log(void);
/********************************* dirserv.c ***************************/
-int connection_dirserv_flushed_some(dir_connection_t *conn);
int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk);
-int dirserv_load_fingerprint_file(void);
+int dirserv_parse_fingerprint_file(const char *fname);
void dirserv_free_fingerprint_list(void);
const char *dirserv_get_nickname_by_digest(const char *digest);
int dirserv_add_descriptor(const char *desc, const char **msg);
@@ -2118,10 +1927,9 @@ int dirserv_thinks_router_is_blatantly_unreachable(routerinfo_t *router,
time_t now);
int list_server_status(smartlist_t *routers, char **router_status_out);
int dirserv_dump_directory_to_string(char **dir_out,
- crypto_pk_env_t *private_key,
- int complete);
+ crypto_pk_env_t *private_key);
void directory_set_dirty(void);
-cached_dir_t *dirserv_get_directory(void);
+size_t dirserv_get_directory(const char **cp, int compress);
size_t dirserv_get_runningrouters(const char **rr, int compress);
void dirserv_set_cached_directory(const char *directory, time_t when,
int is_running_routers);
@@ -2129,10 +1937,6 @@ void dirserv_set_cached_networkstatus_v2(const char *directory,
const char *identity,
time_t published);
void dirserv_get_networkstatus_v2(smartlist_t *result, const char *key);
-void dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result,
- const char *key);
-int dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key,
- const char **msg);
int dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
const char **msg);
void dirserv_orconn_tls_done(const char *address,
@@ -2140,28 +1944,24 @@ void dirserv_orconn_tls_done(const char *address,
const char *digest_rcvd,
const char *nickname,
int as_advertised);
-void dirserv_test_reachability(int try_all);
int authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
int complain);
int dirserv_would_reject_router(routerstatus_t *rs);
void dirserv_free_all(void);
-void cached_dir_decref(cached_dir_t *d);
/********************************* dns.c ***************************/
-int dns_init(void);
+void dns_init(void);
void dns_free_all(void);
-uint32_t dns_clip_ttl(uint32_t ttl);
int connection_dns_finished_flushing(connection_t *conn);
int connection_dns_reached_eof(connection_t *conn);
int connection_dns_process_inbuf(connection_t *conn);
-void dns_reset(void);
-void connection_dns_remove(edge_connection_t *conn);
-void assert_connection_edge_not_dns_pending(edge_connection_t *conn);
+void dnsworkers_rotate(void);
+void connection_dns_remove(connection_t *conn);
+void assert_connection_edge_not_dns_pending(connection_t *conn);
void assert_all_pending_dns_resolves_ok(void);
-void dns_cancel_pending_resolve(const char *question);
-int dns_resolve(edge_connection_t *exitconn);
-void dns_launch_wildcard_checks(void);
+void dns_cancel_pending_resolve(char *question);
+int dns_resolve(connection_t *exitconn);
/********************************* hibernate.c **********************/
@@ -2179,8 +1979,6 @@ void accounting_set_bandwidth_usage_from_state(or_state_t *state);
/********************************* main.c ***************************/
-extern int has_completed_circuit;
-
int connection_add(connection_t *conn);
int connection_remove(connection_t *conn);
int connection_in_array(connection_t *conn);
@@ -2201,8 +1999,7 @@ void connection_start_writing(connection_t *conn);
void directory_all_unreachable(time_t now);
void directory_info_has_arrived(time_t now, int from_cache);
-int control_signal_check(int the_signal);
-void control_signal_act(int the_signal);
+int control_signal_act(int the_signal);
void handle_signals(int is_parent);
void tor_cleanup(void);
void tor_free_all(int postfork);
@@ -2211,9 +2008,9 @@ int tor_main(int argc, char *argv[]);
/********************************* onion.c ***************************/
-int onion_pending_add(or_circuit_t *circ);
-or_circuit_t *onion_next_task(void);
-void onion_pending_remove(or_circuit_t *circ);
+int onion_pending_add(circuit_t *circ);
+circuit_t *onion_next_task(void);
+void onion_pending_remove(circuit_t *circ);
int onion_skin_create(crypto_pk_env_t *router_key,
crypto_dh_env_t **handshake_state_out,
@@ -2270,8 +2067,6 @@ int policies_parse_exit_policy(config_line_t *cfg,
addr_policy_t **dest,
int rejectprivate);
int exit_policy_is_general_exit(addr_policy_t *policy);
-int policy_is_reject_star(addr_policy_t *policy);
-int policies_getinfo_helper(const char *question, char **answer);
void addr_policy_free(addr_policy_t *p);
void policies_free_all(void);
@@ -2286,13 +2081,12 @@ int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ,
void relay_header_pack(char *dest, const relay_header_t *src);
void relay_header_unpack(relay_header_t *dest, const char *src);
-int connection_edge_send_command(edge_connection_t *fromconn, circuit_t *circ,
+int connection_edge_send_command(connection_t *fromconn, circuit_t *circ,
int relay_command, const char *payload,
size_t payload_len,
crypt_path_t *cpath_layer);
-int connection_edge_package_raw_inbuf(edge_connection_t *conn,
- int package_partial);
-void connection_edge_consider_sending_sendme(edge_connection_t *conn);
+int connection_edge_package_raw_inbuf(connection_t *conn, int package_partial);
+void connection_edge_consider_sending_sendme(connection_t *conn);
socks5_reply_status_t connection_edge_end_reason_socks5_response(int reason);
int errno_to_end_reason(int e);
@@ -2316,8 +2110,6 @@ void rep_hist_note_bytes_read(int num_bytes, time_t when);
void rep_hist_note_bytes_written(int num_bytes, time_t when);
int rep_hist_bandwidth_assess(void);
char *rep_hist_get_bandwidth_lines(void);
-void rep_hist_update_state(or_state_t *state);
-int rep_hist_load_state(or_state_t *state, char **err);
void rep_history_clean(time_t before);
void rep_hist_note_used_port(uint16_t port, time_t now);
@@ -2328,8 +2120,8 @@ void rep_hist_note_used_internal(time_t now, int need_uptime,
int rep_hist_get_predicted_internal(time_t now, int *need_uptime,
int *need_capacity);
-int any_predicted_circuits(time_t now);
-int rep_hist_circbuilding_dormant(time_t now);
+void rep_hist_update_state(or_state_t *state);
+int rep_hist_load_state(or_state_t *state, char **err);
int any_predicted_circuits(time_t now);
@@ -2337,23 +2129,22 @@ void rep_hist_free_all(void);
/********************************* rendclient.c ***************************/
-void rend_client_introcirc_has_opened(origin_circuit_t *circ);
-void rend_client_rendcirc_has_opened(origin_circuit_t *circ);
-int rend_client_introduction_acked(origin_circuit_t *circ, const char *request,
+void rend_client_introcirc_has_opened(circuit_t *circ);
+void rend_client_rendcirc_has_opened(circuit_t *circ);
+int rend_client_introduction_acked(circuit_t *circ, const char *request,
size_t request_len);
void rend_client_refetch_renddesc(const char *query);
int rend_client_remove_intro_point(extend_info_t *failed_intro,
const char *query);
-int rend_client_rendezvous_acked(origin_circuit_t *circ, const char *request,
+int rend_client_rendezvous_acked(circuit_t *circ, const char *request,
size_t request_len);
-int rend_client_receive_rendezvous(origin_circuit_t *circ, const char *request,
+int rend_client_receive_rendezvous(circuit_t *circ, const char *request,
size_t request_len);
void rend_client_desc_here(const char *query);
extend_info_t *rend_client_get_random_intro(const char *query);
-int rend_client_send_introduction(origin_circuit_t *introcirc,
- origin_circuit_t *rendcirc);
+int rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc);
/********************************* rendcommon.c ***************************/
@@ -2418,27 +2209,25 @@ void rend_services_init(void);
void rend_services_introduce(void);
void rend_consider_services_upload(time_t now);
-void rend_service_intro_has_opened(origin_circuit_t *circuit);
-int rend_service_intro_established(origin_circuit_t *circuit,
- const char *request,
+void rend_service_intro_has_opened(circuit_t *circuit);
+int rend_service_intro_established(circuit_t *circuit, const char *request,
size_t request_len);
-void rend_service_rendezvous_has_opened(origin_circuit_t *circuit);
-int rend_service_introduce(origin_circuit_t *circuit, const char *request,
+void rend_service_rendezvous_has_opened(circuit_t *circuit);
+int rend_service_introduce(circuit_t *circuit, const char *request,
size_t request_len);
-void rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc);
-int rend_service_set_connection_addr_port(edge_connection_t *conn,
- origin_circuit_t *circ);
+void rend_service_relaunch_rendezvous(circuit_t *oldcirc);
+int rend_service_set_connection_addr_port(connection_t *conn, circuit_t *circ);
void rend_service_dump_stats(int severity);
void rend_service_free_all(void);
/********************************* rendmid.c *******************************/
-int rend_mid_establish_intro(or_circuit_t *circ, const char *request,
+int rend_mid_establish_intro(circuit_t *circ, const char *request,
size_t request_len);
-int rend_mid_introduce(or_circuit_t *circ, const char *request,
+int rend_mid_introduce(circuit_t *circ, const char *request,
size_t request_len);
-int rend_mid_establish_rendezvous(or_circuit_t *circ, const char *request,
+int rend_mid_establish_rendezvous(circuit_t *circ, const char *request,
size_t request_len);
-int rend_mid_rendezvous(or_circuit_t *circ, const char *request,
+int rend_mid_rendezvous(circuit_t *circ, const char *request,
size_t request_len);
/********************************* router.c ***************************/
@@ -2456,33 +2245,31 @@ int init_keys(void);
int check_whether_orport_reachable(void);
int check_whether_dirport_reachable(void);
-void consider_testing_reachability(int test_or, int test_dir);
+void consider_testing_reachability(void);
void router_orport_found_reachable(void);
void router_dirport_found_reachable(void);
void server_has_changed_ip(void);
-void router_perform_bandwidth_test(int num_circs, time_t now);
+void consider_publishable_server(time_t now, int force);
int authdir_mode(or_options_t *options);
int clique_mode(or_options_t *options);
int server_mode(or_options_t *options);
int advertised_server_mode(void);
int proxy_mode(or_options_t *options);
-void consider_publishable_server(int force);
+void router_retry_connections(int testing_reachability, int try_all);
int router_is_clique_mode(routerinfo_t *router);
void router_upload_dir_desc_to_dirservers(int force);
void mark_my_descriptor_dirty_if_older_than(time_t when);
void mark_my_descriptor_dirty(void);
void check_descriptor_bandwidth_changed(time_t now);
void check_descriptor_ipaddress_changed(time_t now);
-void router_new_address_suggestion(const char *suggestion);
-int router_compare_to_my_exit_policy(edge_connection_t *conn);
+int router_compare_to_my_exit_policy(connection_t *conn);
routerinfo_t *router_get_my_routerinfo(void);
const char *router_get_my_descriptor(void);
int router_digest_is_me(const char *digest);
int router_is_me(routerinfo_t *router);
int router_fingerprint_is_me(const char *fp);
-int router_pick_published_address(or_options_t *options, uint32_t *addr);
int router_rebuild_descriptor(int force);
int router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
crypto_pk_env_t *ident_key);
@@ -2573,11 +2360,10 @@ int router_add_to_routerlist(routerinfo_t *router, const char **msg,
int from_cache, int from_fetch);
int router_load_single_router(const char *s, uint8_t purpose,
const char **msg);
-void router_load_routers_from_string(const char *s,
- saved_location_t saved_location,
+void router_load_routers_from_string(const char *s, int from_cache,
smartlist_t *requested_fingerprints);
typedef enum {
- NS_FROM_CACHE, NS_FROM_DIR_BY_FP, NS_FROM_DIR_ALL, NS_GENERATED
+ NS_FROM_CACHE, NS_FROM_DIR, NS_GENERATED
} networkstatus_source_t;
int router_set_networkstatus(const char *s, time_t arrived_at,
networkstatus_source_t source,
@@ -2623,6 +2409,9 @@ typedef struct tor_version_t {
* VER_RELEASE. */
enum { VER_PRE=0, VER_RC=1, VER_RELEASE=2, } status;
int patchlevel;
+ /** CVS status. For version in the post-0.1 format, this is always
+ * IS_NOT_CVS */
+ enum { IS_CVS=0, IS_NOT_CVS=1} cvs;
char status_tag[MAX_STATUS_TAG_LEN];
} tor_version_t;
@@ -2643,8 +2432,7 @@ int router_append_dirobj_signature(char *buf, size_t buf_len,
const char *digest,
crypto_pk_env_t *private_key);
int router_parse_list_from_string(const char **s,
- smartlist_t *dest,
- saved_location_t saved_location);
+ smartlist_t *dest);
int router_parse_routerlist_from_directory(const char *s,
routerlist_t **dest,
crypto_pk_env_t *pkey,
@@ -2652,8 +2440,7 @@ int router_parse_routerlist_from_directory(const char *s,
int write_to_cache);
int router_parse_runningrouters(const char *str);
int router_parse_directory(const char *str);
-routerinfo_t *router_parse_entry_from_string(const char *s, const char *end,
- int cache_copy);
+routerinfo_t *router_parse_entry_from_string(const char *s, const char *end);
addr_policy_t *router_parse_addr_policy_from_string(const char *s,
int assume_action);
version_status_t tor_version_is_obsolete(const char *myversion,
diff --git a/src/or/policies.c b/src/or/policies.c
index 327af18d62..b7946f9204 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -128,7 +128,7 @@ parse_reachable_addresses(void)
int
firewall_is_fascist_or(void)
{
- return reachable_or_addr_policy != NULL;
+ return !!reachable_or_addr_policy;
}
/** Return true iff <b>policy</b> (possibly NULL) will allow a
@@ -603,7 +603,7 @@ policies_parse_exit_policy(config_line_t *cfg, addr_policy_t **dest,
/** Return true iff <b>ri</b> is "useful as an exit node", meaning
* it allows exit to at least one /8 address space for at least
- * two of ports 80, 443, and 6667. */
+ * one of ports 80, 443, and 6667. */
int
exit_policy_is_general_exit(addr_policy_t *policy)
{
@@ -619,40 +619,10 @@ exit_policy_is_general_exit(addr_policy_t *policy)
if ((p->addr & 0xff000000ul) == 0x7f000000ul)
continue; /* 127.x */
/* We have a match that is at least a /8. */
- if (p->policy_type == ADDR_POLICY_ACCEPT) {
- ++n_allowed;
- break; /* stop considering this port */
- }
+ if (p->policy_type == ADDR_POLICY_ACCEPT)
+ return 1;
}
}
- return n_allowed >= 2;
-}
-
-/** Return false if <b>policy</b> might permit access to some addr:port;
- * otherwise if we are certain it rejects everything, return true. */
-int
-policy_is_reject_star(addr_policy_t *p)
-{
- for ( ; p; p = p->next) {
- if (p->policy_type == ADDR_POLICY_ACCEPT)
- return 0;
- else if (p->policy_type == ADDR_POLICY_REJECT &&
- p->prt_min <= 1 && p->prt_max == 65535 &&
- p->msk == 0)
- return 1;
- }
- return 1;
-}
-
-int
-policies_getinfo_helper(const char *question, char **answer)
-{
- if (!strcmp(question, "exit-policy/default")) {
- *answer = tor_strdup(DEFAULT_EXIT_POLICY);
-// } else if (!strcmp(question, "exit-policy/prepend")) {
- } else {
- *answer = NULL;
- }
return 0;
}
diff --git a/src/or/relay.c b/src/or/relay.c
index 8d9ce04fb1..8dbe4acc12 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -16,19 +16,19 @@ const char relay_c_id[] =
static int relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
crypt_path_t **layer_hint, char *recognized);
-static edge_connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell,
+static connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell,
int cell_direction);
static int
connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
- edge_connection_t *conn,
+ connection_t *conn,
crypt_path_t *layer_hint);
static void
circuit_consider_sending_sendme(circuit_t *circ, crypt_path_t *layer_hint);
static void
circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint);
static int
-circuit_resume_edge_reading_helper(edge_connection_t *conn,
+circuit_resume_edge_reading_helper(connection_t *conn,
circuit_t *circ,
crypt_path_t *layer_hint);
static int
@@ -144,7 +144,7 @@ relay_crypt_one_payload(crypto_cipher_env_t *cipher, char *in,
int
circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction)
{
- or_connection_t *or_conn=NULL;
+ connection_t *conn=NULL;
crypt_path_t *layer_hint=NULL;
char recognized=0;
int reason;
@@ -162,7 +162,7 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction)
}
if (recognized) {
- edge_connection_t *conn = relay_lookup_conn(circ, cell, cell_direction);
+ conn = relay_lookup_conn(circ, cell, cell_direction);
if (cell_direction == CELL_DIRECTION_OUT) {
++stats_n_relay_cells_delivered;
log_debug(LD_OR,"Sending away from origin.");
@@ -190,25 +190,19 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction)
/* not recognized. pass it on. */
if (cell_direction == CELL_DIRECTION_OUT) {
cell->circ_id = circ->n_circ_id; /* switch it */
- or_conn = circ->n_conn;
- } else if (! CIRCUIT_IS_ORIGIN(circ)) {
- cell->circ_id = TO_OR_CIRCUIT(circ)->p_circ_id; /* switch it */
- or_conn = TO_OR_CIRCUIT(circ)->p_conn;
+ conn = circ->n_conn;
} else {
- // XXXX NM WARN.
- return 0;
+ cell->circ_id = circ->p_circ_id; /* switch it */
+ conn = circ->p_conn;
}
- if (!or_conn) {
- // XXXX Can this splice stuff be done more cleanly?
- if (! CIRCUIT_IS_ORIGIN(circ) &&
- TO_OR_CIRCUIT(circ)->rend_splice &&
- cell_direction == CELL_DIRECTION_OUT) {
- or_circuit_t *splice = TO_OR_CIRCUIT(circ)->rend_splice;
+ if (!conn) {
+ if (circ->rend_splice && cell_direction == CELL_DIRECTION_OUT) {
tor_assert(circ->purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED);
- tor_assert(splice->_base.purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED);
- cell->circ_id = splice->p_circ_id;
- if ((reason = circuit_receive_relay_cell(cell, TO_CIRCUIT(splice),
+ tor_assert(circ->rend_splice->purpose ==
+ CIRCUIT_PURPOSE_REND_ESTABLISHED);
+ cell->circ_id = circ->rend_splice->p_circ_id;
+ if ((reason = circuit_receive_relay_cell(cell, circ->rend_splice,
CELL_DIRECTION_IN)) < 0) {
log_warn(LD_REND, "Error relaying cell across rendezvous; closing "
"circuits");
@@ -225,7 +219,7 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction)
log_debug(LD_OR,"Passing on unrecognized cell.");
++stats_n_relay_cells_relayed;
- connection_or_write_cell_to_buf(cell, or_conn);
+ connection_or_write_cell_to_buf(cell, conn);
return 0;
}
@@ -246,10 +240,12 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction)
* Return -1 to indicate that we should mark the circuit for close,
* else return 0.
*/
+/* wrap this into receive_relay_cell one day */
static int
relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
crypt_path_t **layer_hint, char *recognized)
{
+ crypt_path_t *thishop;
relay_header_t rh;
tor_assert(circ);
@@ -261,8 +257,8 @@ relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
if (cell_direction == CELL_DIRECTION_IN) {
if (CIRCUIT_IS_ORIGIN(circ)) { /* We're at the beginning of the circuit.
* We'll want to do layered decrypts. */
- crypt_path_t *thishop, *cpath = TO_ORIGIN_CIRCUIT(circ)->cpath;
- thishop = cpath;
+ tor_assert(circ->cpath);
+ thishop = circ->cpath;
if (thishop->state != CPATH_STATE_OPEN) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Relay cell before first created cell? Closing.");
@@ -285,27 +281,25 @@ relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
}
thishop = thishop->next;
- } while (thishop != cpath && thishop->state == CPATH_STATE_OPEN);
- log_warn(LD_OR,"in-cell at client not recognized. Closing.");
+ } while (thishop != circ->cpath && thishop->state == CPATH_STATE_OPEN);
+ log_warn(LD_OR,"in-cell at OP not recognized. Closing.");
return -1;
} else { /* we're in the middle. Just one crypt. */
- if (relay_crypt_one_payload(TO_OR_CIRCUIT(circ)->p_crypto,
- cell->payload, 1) < 0)
+ if (relay_crypt_one_payload(circ->p_crypto, cell->payload, 1) < 0)
return -1;
// log_fn(LOG_DEBUG,"Skipping recognized check, because we're not "
-// "the client.");
+// "the OP.");
}
} else /* cell_direction == CELL_DIRECTION_OUT */ {
/* we're in the middle. Just one crypt. */
- if (relay_crypt_one_payload(TO_OR_CIRCUIT(circ)->n_crypto,
- cell->payload, 0) < 0)
+ if (relay_crypt_one_payload(circ->n_crypto, cell->payload, 0) < 0)
return -1;
relay_header_unpack(&rh, cell->payload);
if (rh.recognized == 0) {
/* it's possibly recognized. have to check digest to be sure. */
- if (relay_digest_matches(TO_OR_CIRCUIT(circ)->n_digest, cell)) {
+ if (relay_digest_matches(circ->n_digest, cell)) {
*recognized = 1;
return 0;
}
@@ -314,7 +308,7 @@ relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
return 0;
}
-/** Package a relay cell from an edge:
+/** Package a relay cell:
* - Encrypt it to the right layer
* - connection_or_write_cell_to_buf to the right conn
*/
@@ -323,12 +317,12 @@ circuit_package_relay_cell(cell_t *cell, circuit_t *circ,
int cell_direction,
crypt_path_t *layer_hint)
{
- or_connection_t *conn; /* where to send the cell */
+ connection_t *conn; /* where to send the cell */
+ crypt_path_t *thishop; /* counter for repeated crypts */
if (cell_direction == CELL_DIRECTION_OUT) {
- crypt_path_t *thishop; /* counter for repeated crypts */
conn = circ->n_conn;
- if (!CIRCUIT_IS_ORIGIN(circ) || !conn) {
+ if (!conn) {
log_warn(LD_BUG,"outgoing relay cell has n_conn==NULL. Dropping.");
return 0; /* just drop it */
}
@@ -345,20 +339,18 @@ circuit_package_relay_cell(cell_t *cell, circuit_t *circ,
}
thishop = thishop->prev;
- } while (thishop != TO_ORIGIN_CIRCUIT(circ)->cpath->prev);
+ } while (thishop != circ->cpath->prev);
} else { /* incoming cell */
- or_circuit_t *or_circ;
- if (CIRCUIT_IS_ORIGIN(circ)) {
+ conn = circ->p_conn;
+ if (!conn) {
/* XXXX RD This is a bug, right? */
- log_warn(LD_BUG,"incoming relay cell at origin circuit. Dropping.");
+ log_warn(LD_BUG,"incoming relay cell has p_conn==NULL. Dropping.");
assert_circuit_ok(circ);
return 0; /* just drop it */
}
- or_circ = TO_OR_CIRCUIT(circ);
- conn = or_circ->p_conn;
- relay_set_digest(or_circ->p_digest, cell);
- if (relay_crypt_one_payload(or_circ->p_crypto, cell->payload, 1) < 0)
+ relay_set_digest(circ->p_digest, cell);
+ if (relay_crypt_one_payload(circ->p_crypto, cell->payload, 1) < 0)
return -1;
}
++stats_n_relay_cells_relayed;
@@ -369,10 +361,10 @@ circuit_package_relay_cell(cell_t *cell, circuit_t *circ,
/** If cell's stream_id matches the stream_id of any conn that's
* attached to circ, return that conn, else return NULL.
*/
-static edge_connection_t *
+static connection_t *
relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction)
{
- edge_connection_t *tmpconn;
+ connection_t *tmpconn;
relay_header_t rh;
relay_header_unpack(&rh, cell->payload);
@@ -384,33 +376,25 @@ relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction)
* that we allow rendezvous *to* an OP.
*/
- if (CIRCUIT_IS_ORIGIN(circ)) {
- for (tmpconn = TO_ORIGIN_CIRCUIT(circ)->p_streams; tmpconn;
- tmpconn=tmpconn->next_stream) {
- if (rh.stream_id == tmpconn->stream_id &&
- !tmpconn->_base.marked_for_close) {
- log_debug(LD_APP,"found conn for stream %d.", rh.stream_id);
+ for (tmpconn = circ->n_streams; tmpconn; tmpconn=tmpconn->next_stream) {
+ if (rh.stream_id == tmpconn->stream_id && !tmpconn->marked_for_close) {
+ log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id);
+ if (cell_direction == CELL_DIRECTION_OUT ||
+ connection_edge_is_rendezvous_stream(tmpconn))
return tmpconn;
- }
}
- } else {
- for (tmpconn = TO_OR_CIRCUIT(circ)->n_streams; tmpconn;
- tmpconn=tmpconn->next_stream) {
- if (rh.stream_id == tmpconn->stream_id &&
- !tmpconn->_base.marked_for_close) {
- log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id);
- if (cell_direction == CELL_DIRECTION_OUT ||
- connection_edge_is_rendezvous_stream(tmpconn))
- return tmpconn;
- }
+ }
+ for (tmpconn = circ->p_streams; tmpconn; tmpconn=tmpconn->next_stream) {
+ if (rh.stream_id == tmpconn->stream_id && !tmpconn->marked_for_close) {
+ log_debug(LD_APP,"found conn for stream %d.", rh.stream_id);
+ return tmpconn;
}
- for (tmpconn = TO_OR_CIRCUIT(circ)->resolving_streams; tmpconn;
- tmpconn=tmpconn->next_stream) {
- if (rh.stream_id == tmpconn->stream_id &&
- !tmpconn->_base.marked_for_close) {
- log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id);
- return tmpconn;
- }
+ }
+ for (tmpconn = circ->resolving_streams; tmpconn;
+ tmpconn=tmpconn->next_stream) {
+ if (rh.stream_id == tmpconn->stream_id && !tmpconn->marked_for_close) {
+ log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id);
+ return tmpconn;
}
}
return NULL; /* probably a begin relay cell */
@@ -455,32 +439,30 @@ relay_header_unpack(relay_header_t *dest, const char *src)
* return -1. Else return 0.
*/
int
-connection_edge_send_command(edge_connection_t *fromconn, circuit_t *circ,
+connection_edge_send_command(connection_t *fromconn, circuit_t *circ,
int relay_command, const char *payload,
size_t payload_len, crypt_path_t *cpath_layer)
{
cell_t cell;
relay_header_t rh;
int cell_direction;
- /* XXXX NM Split this function into a separate versions per circuit type? */
- if (fromconn && fromconn->_base.marked_for_close) {
+ if (fromconn && fromconn->marked_for_close) {
log_warn(LD_BUG,
"Bug: called on conn that's already marked for close at %s:%d.",
- fromconn->_base.marked_for_close_file,
- fromconn->_base.marked_for_close);
+ fromconn->marked_for_close_file, fromconn->marked_for_close);
return 0;
}
if (!circ) {
tor_assert(fromconn);
- if (fromconn->_base.type == CONN_TYPE_AP) {
+ if (fromconn->type == CONN_TYPE_AP) {
log_info(LD_APP,"no circ. Closing conn.");
connection_mark_unattached_ap(fromconn, END_STREAM_REASON_INTERNAL);
} else {
log_info(LD_EXIT,"no circ. Closing conn.");
- fromconn->_base.edge_has_sent_end = 1; /* no circ to send to */
- connection_mark_for_close(TO_CONN(fromconn));
+ fromconn->has_sent_end = 1; /* no circ to send to */
+ connection_mark_for_close(fromconn);
}
return -1;
}
@@ -490,11 +472,9 @@ connection_edge_send_command(edge_connection_t *fromconn, circuit_t *circ,
if (cpath_layer) {
cell.circ_id = circ->n_circ_id;
cell_direction = CELL_DIRECTION_OUT;
- } else if (! CIRCUIT_IS_ORIGIN(circ)) {
- cell.circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
- cell_direction = CELL_DIRECTION_IN;
} else {
- return -1;
+ cell.circ_id = circ->p_circ_id;
+ cell_direction = CELL_DIRECTION_IN;
}
memset(&rh, 0, sizeof(rh));
@@ -639,8 +619,8 @@ errno_to_end_reason(int e)
E_CASE(EMFILE):
return END_STREAM_REASON_RESOURCELIMIT;
default:
- log_info(LD_EXIT, "Didn't recognize errno %d (%s); telling the client "
- "that we are ending a stream for 'misc' reason.",
+ log_info(LD_EXIT, "Didn't recognize errno %d (%s); telling the OP that "
+ "we are ending a stream for 'misc' reason.",
e, tor_socket_strerror(e));
return END_STREAM_REASON_MISC;
}
@@ -668,16 +648,15 @@ edge_reason_is_retriable(int reason)
*/
static int
connection_edge_process_end_not_open(
- relay_header_t *rh, cell_t *cell, origin_circuit_t *circ,
- edge_connection_t *conn, crypt_path_t *layer_hint)
+ relay_header_t *rh, cell_t *cell, circuit_t *circ,
+ connection_t *conn, crypt_path_t *layer_hint)
{
struct in_addr in;
routerinfo_t *exitrouter;
int reason = *(cell->payload+RELAY_HEADER_SIZE);
- (void) layer_hint; /* unused */
if (rh->length > 0 && edge_reason_is_retriable(reason) &&
- conn->_base.type == CONN_TYPE_AP) {
+ conn->type == CONN_TYPE_AP) {
log_info(LD_APP,"Address '%s' refused due to '%s'. Considering retrying.",
safe_str(conn->socks_request->address),
connection_edge_end_reason_str(reason));
@@ -717,35 +696,19 @@ connection_edge_process_end_not_open(
/* rewrite it to an IP if we learned one. */
addressmap_rewrite(conn->socks_request->address,
sizeof(conn->socks_request->address));
- if (conn->_base.chosen_exit_optional) {
- /* stop wanting a specific exit */
- conn->_base.chosen_exit_optional = 0;
- tor_free(conn->chosen_exit_name);
- }
if (connection_ap_detach_retriable(conn, circ) >= 0)
return 0;
/* else, conn will get closed below */
break;
- case END_STREAM_REASON_CONNECTREFUSED:
- if (!conn->_base.chosen_exit_optional)
- break; /* break means it'll close, below */
- /* Else fall through: expire this circuit, clear the
- * chosen_exit_name field, and try again. */
case END_STREAM_REASON_RESOLVEFAILED:
- case END_STREAM_REASON_TIMEOUT:
case END_STREAM_REASON_MISC:
if (client_dns_incr_failures(conn->socks_request->address)
< MAX_RESOLVE_FAILURES) {
/* We haven't retried too many times; reattach the connection. */
circuit_log_path(LOG_INFO,LD_APP,circ);
- tor_assert(circ->_base.timestamp_dirty);
- circ->_base.timestamp_dirty -= get_options()->MaxCircuitDirtiness;
+ tor_assert(circ->timestamp_dirty);
+ circ->timestamp_dirty -= get_options()->MaxCircuitDirtiness;
- if (conn->_base.chosen_exit_optional) {
- /* stop wanting a specific exit */
- conn->_base.chosen_exit_optional = 0;
- tor_free(conn->chosen_exit_name);
- }
if (connection_ap_detach_retriable(conn, circ) >= 0)
return 0;
/* else, conn will get closed below */
@@ -766,11 +729,6 @@ connection_edge_process_end_not_open(
exitrouter->exit_policy =
router_parse_addr_policy_from_string("reject *:*", -1);
}
- if (conn->_base.chosen_exit_optional) {
- /* stop wanting a specific exit */
- conn->_base.chosen_exit_optional = 0;
- tor_free(conn->chosen_exit_name);
- }
if (connection_ap_detach_retriable(conn, circ) >= 0)
return 0;
/* else, will close below */
@@ -782,13 +740,12 @@ connection_edge_process_end_not_open(
log_info(LD_APP,
"Edge got end (%s) before we're connected. Marking for close.",
connection_edge_end_reason_str(rh->length > 0 ? reason : -1));
- if (conn->_base.type == CONN_TYPE_AP) {
+ if (conn->type == CONN_TYPE_AP) {
circuit_log_path(LOG_INFO,LD_APP,circ);
connection_mark_unattached_ap(conn, reason);
} else {
- /* we just got an 'end', don't need to send one */
- conn->_base.edge_has_sent_end = 1;
- connection_mark_for_close(TO_CONN(conn));
+ conn->has_sent_end = 1; /* we just got an 'end', don't need to send one */
+ connection_mark_for_close(conn);
}
return 0;
}
@@ -803,29 +760,22 @@ connection_edge_process_end_not_open(
static int
connection_edge_process_relay_cell_not_open(
relay_header_t *rh, cell_t *cell, circuit_t *circ,
- edge_connection_t *conn, crypt_path_t *layer_hint)
+ connection_t *conn, crypt_path_t *layer_hint)
{
- if (rh->command == RELAY_COMMAND_END) {
- if (CIRCUIT_IS_ORIGIN(circ))
- return connection_edge_process_end_not_open(rh, cell,
- TO_ORIGIN_CIRCUIT(circ), conn,
- layer_hint);
- else
- return 0;
- }
+ if (rh->command == RELAY_COMMAND_END)
+ return connection_edge_process_end_not_open(rh, cell, circ, conn,
+ layer_hint);
- if (conn->_base.type == CONN_TYPE_AP &&
- rh->command == RELAY_COMMAND_CONNECTED) {
- tor_assert(CIRCUIT_IS_ORIGIN(circ));
- if (conn->_base.state != AP_CONN_STATE_CONNECT_WAIT) {
+ if (conn->type == CONN_TYPE_AP && rh->command == RELAY_COMMAND_CONNECTED) {
+ if (conn->state != AP_CONN_STATE_CONNECT_WAIT) {
log_warn(LD_APP,"Got 'connected' while not in state connect_wait. "
"Dropping.");
return 0;
}
// log_fn(LOG_INFO,"Connected! Notifying application.");
- conn->_base.state = AP_CONN_STATE_OPEN;
+ conn->state = AP_CONN_STATE_OPEN;
log_info(LD_APP,"'connected' received after %d seconds.",
- (int)(time(NULL) - conn->_base.timestamp_lastread));
+ (int)(time(NULL) - conn->timestamp_lastread));
if (rh->length >= 4) {
uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE));
int ttl;
@@ -844,29 +794,25 @@ connection_edge_process_relay_cell_not_open(
client_dns_set_addressmap(conn->socks_request->address, addr,
conn->chosen_exit_name, ttl);
}
- circuit_log_path(LOG_INFO,LD_APP,TO_ORIGIN_CIRCUIT(circ));
- /* don't send a socks reply to transparent conns */
- if (!conn->socks_request->has_finished)
- connection_ap_handshake_socks_reply(conn, NULL, 0, SOCKS5_SUCCEEDED);
+ circuit_log_path(LOG_INFO,LD_APP,circ);
+ connection_ap_handshake_socks_reply(conn, NULL, 0, SOCKS5_SUCCEEDED);
/* handle anything that might have queued */
if (connection_edge_package_raw_inbuf(conn, 1) < 0) {
/* (We already sent an end cell if possible) */
- connection_mark_for_close(TO_CONN(conn));
+ connection_mark_for_close(conn);
return 0;
}
return 0;
}
- if (conn->_base.type == CONN_TYPE_AP &&
- rh->command == RELAY_COMMAND_RESOLVED) {
+ if (conn->type == CONN_TYPE_AP && rh->command == RELAY_COMMAND_RESOLVED) {
int ttl;
int answer_len;
- if (conn->_base.state != AP_CONN_STATE_RESOLVE_WAIT) {
+ if (conn->state != AP_CONN_STATE_RESOLVE_WAIT) {
log_warn(LD_APP,"Got a 'resolved' cell while not in state resolve_wait. "
"Dropping.");
return 0;
}
- tor_assert(conn->socks_request->command == SOCKS_COMMAND_RESOLVE ||
- conn->socks_request->command == SOCKS_COMMAND_RESOLVE_PTR);
+ tor_assert(conn->socks_request->command == SOCKS_COMMAND_RESOLVE);
answer_len = cell->payload[RELAY_HEADER_SIZE+1];
if (rh->length < 2 || answer_len+2>rh->length) {
log_warn(LD_PROTOCOL, "Dropping malformed 'resolved' cell");
@@ -890,8 +836,8 @@ connection_edge_process_relay_cell_not_open(
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Got an unexpected relay command %d, in state %d (%s). Dropping.",
- rh->command, conn->_base.state,
- conn_state_to_string(conn->_base.type, conn->_base.state));
+ rh->command, conn->state,
+ conn_state_to_string(conn->type, conn->state));
return 0; /* for forward compatibility, don't kill the circuit */
// connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL,
// conn->cpath_layer);
@@ -910,7 +856,7 @@ connection_edge_process_relay_cell_not_open(
*/
static int
connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
- edge_connection_t *conn,
+ connection_t *conn,
crypt_path_t *layer_hint)
{
static int num_seen=0;
@@ -935,13 +881,13 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
/* either conn is NULL, in which case we've got a control cell, or else
* conn points to the recognized stream. */
- if (conn && !connection_state_is_open(TO_CONN(conn)))
+ if (conn && !connection_state_is_open(conn))
return connection_edge_process_relay_cell_not_open(
&rh, cell, circ, conn, layer_hint);
switch (rh.command) {
case RELAY_COMMAND_DROP:
-// log_info(domain,"Got a relay-level padding cell. Dropping.");
+ log_info(domain,"Got a relay-level padding cell. Dropping.");
return 0;
case RELAY_COMMAND_BEGIN:
if (layer_hint &&
@@ -963,7 +909,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
"(relay data) circ deliver_window below 0. Killing.");
connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL,
conn->cpath_layer);
- connection_mark_for_close(TO_CONN(conn));
+ connection_mark_for_close(conn);
return -END_CIRC_REASON_TORPROTOCOL;
}
log_debug(domain,"circ deliver_window now %d.", layer_hint ?
@@ -984,7 +930,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
stats_n_data_bytes_received += rh.length;
connection_write_to_buf(cell->payload + RELAY_HEADER_SIZE,
- rh.length, TO_CONN(conn));
+ rh.length, conn);
connection_edge_consider_sending_sendme(conn);
return 0;
case RELAY_COMMAND_END:
@@ -996,21 +942,32 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
}
/* XXX add to this log_fn the exit node's nickname? */
log_info(domain,"%d: end cell (%s) for stream %d. Removing stream.",
- conn->_base.s,
+ conn->s,
connection_edge_end_reason_str(rh.length > 0 ?
*(char *)(cell->payload+RELAY_HEADER_SIZE) : -1),
conn->stream_id);
if (conn->socks_request && !conn->socks_request->has_finished)
log_warn(LD_BUG,
"Bug: open stream hasn't sent socks answer yet? Closing.");
+#ifdef HALF_OPEN
+ conn->done_sending = 1;
+ shutdown(conn->s, 1); /* XXX check return; refactor NM */
+ if (conn->done_receiving) {
+ /* We just *got* an end; no reason to send one. */
+ conn->has_sent_end = 1;
+ connection_mark_for_close(conn);
+ conn->hold_open_until_flushed = 1;
+ }
+#else
/* We just *got* an end; no reason to send one. */
- conn->_base.edge_has_sent_end = 1;
- if (!conn->_base.marked_for_close) {
+ conn->has_sent_end = 1;
+ if (!conn->marked_for_close) {
/* only mark it if not already marked. it's possible to
* get the 'end' right around when the client hangs up on us. */
- connection_mark_for_close(TO_CONN(conn));
- conn->_base.hold_open_until_flushed = 1;
+ connection_mark_for_close(conn);
+ conn->hold_open_until_flushed = 1;
}
+#endif
return 0;
case RELAY_COMMAND_EXTEND:
if (conn) {
@@ -1025,13 +982,12 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
return 0;
}
log_debug(domain,"Got an extended cell! Yay.");
- if ((reason = circuit_finish_handshake(TO_ORIGIN_CIRCUIT(circ),
- CELL_CREATED,
+ if ((reason = circuit_finish_handshake(circ, CELL_CREATED,
cell->payload+RELAY_HEADER_SIZE)) < 0) {
log_warn(domain,"circuit_finish_handshake failed.");
return reason;
}
- if ((reason=circuit_send_next_onion_skin(TO_ORIGIN_CIRCUIT(circ)))<0) {
+ if ((reason=circuit_send_next_onion_skin(circ))<0) {
log_info(domain,"circuit_send_next_onion_skin() failed.");
return reason;
}
@@ -1044,7 +1000,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
if (circ->n_conn) {
uint8_t reason = *(uint8_t*)(cell->payload + RELAY_HEADER_SIZE);
connection_or_send_destroy(circ->n_circ_id, circ->n_conn, reason);
- circuit_set_n_circid_orconn(circ, 0, NULL);
+ circuit_set_circid_orconn(circ, 0, NULL, N_CONN_CHANGED);
}
log_debug(LD_EXIT, "Processed 'truncate', replying.");
{
@@ -1059,7 +1015,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
log_warn(LD_EXIT,"'truncated' unsupported at non-origin. Dropping.");
return 0;
}
- circuit_truncated(TO_ORIGIN_CIRCUIT(circ), layer_hint);
+ circuit_truncated(circ, layer_hint);
return 0;
case RELAY_COMMAND_CONNECTED:
if (conn) {
@@ -1089,11 +1045,11 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
conn->package_window += STREAMWINDOW_INCREMENT;
log_debug(domain,"stream-level sendme, packagewindow now %d.",
conn->package_window);
- connection_start_reading(TO_CONN(conn));
+ connection_start_reading(conn);
/* handle whatever might still be on the inbuf */
if (connection_edge_package_raw_inbuf(conn, 1) < 0) {
/* (We already sent an end cell if possible) */
- connection_mark_for_close(TO_CONN(conn));
+ connection_mark_for_close(conn);
return 0;
}
return 0;
@@ -1109,7 +1065,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
circ->purpose);
return 0;
}
- connection_exit_begin_resolve(cell, TO_OR_CIRCUIT(circ));
+ connection_exit_begin_resolve(cell, circ);
return 0;
case RELAY_COMMAND_RESOLVED:
if (conn) {
@@ -1152,7 +1108,7 @@ uint64_t stats_n_data_bytes_received = 0;
* be marked for close, else return 0.
*/
int
-connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial)
+connection_edge_package_raw_inbuf(connection_t *conn, int package_partial)
{
size_t amount_to_process, length;
char payload[CELL_PAYLOAD_SIZE];
@@ -1160,11 +1116,11 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial)
unsigned domain = conn->cpath_layer ? LD_APP : LD_EXIT;
tor_assert(conn);
-
- if (conn->_base.marked_for_close) {
+ tor_assert(!connection_speaks_cells(conn));
+ if (conn->marked_for_close) {
log_warn(LD_BUG,
"Bug: called on conn that's already marked for close at %s:%d.",
- conn->_base.marked_for_close_file, conn->_base.marked_for_close);
+ conn->marked_for_close_file, conn->marked_for_close);
return 0;
}
@@ -1182,11 +1138,11 @@ repeat_connection_edge_package_raw_inbuf:
if (conn->package_window <= 0) {
log_info(domain,"called with package_window %d. Skipping.",
conn->package_window);
- connection_stop_reading(TO_CONN(conn));
+ connection_stop_reading(conn);
return 0;
}
- amount_to_process = buf_datalen(conn->_base.inbuf);
+ amount_to_process = buf_datalen(conn->inbuf);
if (!amount_to_process)
return 0;
@@ -1202,10 +1158,10 @@ repeat_connection_edge_package_raw_inbuf:
stats_n_data_bytes_packaged += length;
stats_n_data_cells_packaged += 1;
- connection_fetch_from_buf(payload, length, TO_CONN(conn));
+ connection_fetch_from_buf(payload, length, conn);
- log_debug(domain,"(%d) Packaging %d bytes (%d waiting).", conn->_base.s,
- (int)length, (int)buf_datalen(conn->_base.inbuf));
+ log_debug(domain,"(%d) Packaging %d bytes (%d waiting).", conn->s,
+ (int)length, (int)buf_datalen(conn->inbuf));
if (connection_edge_send_command(conn, circ, RELAY_COMMAND_DATA,
payload, length, conn->cpath_layer) < 0)
@@ -1221,7 +1177,7 @@ repeat_connection_edge_package_raw_inbuf:
}
if (--conn->package_window <= 0) { /* is it 0 after decrement? */
- connection_stop_reading(TO_CONN(conn));
+ connection_stop_reading(conn);
log_debug(domain,"conn->package_window reached 0.");
circuit_consider_stop_edge_reading(circ, conn->cpath_layer);
return 0; /* don't process the inbuf any more */
@@ -1239,11 +1195,11 @@ repeat_connection_edge_package_raw_inbuf:
* low, send back a suitable number of stream-level sendme cells.
*/
void
-connection_edge_consider_sending_sendme(edge_connection_t *conn)
+connection_edge_consider_sending_sendme(connection_t *conn)
{
circuit_t *circ;
- if (connection_outbuf_too_full(TO_CONN(conn)))
+ if (connection_outbuf_too_full(conn))
return;
circ = circuit_get_by_edge_conn(conn);
@@ -1257,7 +1213,7 @@ connection_edge_consider_sending_sendme(edge_connection_t *conn)
while (conn->deliver_window < STREAMWINDOW_START - STREAMWINDOW_INCREMENT) {
log_debug(conn->cpath_layer?LD_APP:LD_EXIT,
"Outbuf %d, Queueing stream sendme.",
- (int)conn->_base.outbuf_flushlen);
+ (int)conn->outbuf_flushlen);
conn->deliver_window += STREAMWINDOW_INCREMENT;
if (connection_edge_send_command(conn, circ, RELAY_COMMAND_SENDME,
NULL, 0, conn->cpath_layer) < 0) {
@@ -1278,12 +1234,10 @@ circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
log_debug(layer_hint?LD_APP:LD_EXIT,"resuming");
- if (CIRCUIT_IS_ORIGIN(circ))
- circuit_resume_edge_reading_helper(TO_ORIGIN_CIRCUIT(circ)->p_streams,
- circ, layer_hint);
- else
- circuit_resume_edge_reading_helper(TO_OR_CIRCUIT(circ)->n_streams,
- circ, layer_hint);
+ /* have to check both n_streams and p_streams, to handle rendezvous */
+ if (circuit_resume_edge_reading_helper(circ->n_streams, circ, layer_hint)
+ >= 0)
+ circuit_resume_edge_reading_helper(circ->p_streams, circ, layer_hint);
}
/** A helper function for circuit_resume_edge_reading() above.
@@ -1291,21 +1245,21 @@ circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
* of a linked list of edge streams that should each be considered.
*/
static int
-circuit_resume_edge_reading_helper(edge_connection_t *conn,
+circuit_resume_edge_reading_helper(connection_t *conn,
circuit_t *circ,
crypt_path_t *layer_hint)
{
for ( ; conn; conn=conn->next_stream) {
- if (conn->_base.marked_for_close)
+ if (conn->marked_for_close)
continue;
if ((!layer_hint && conn->package_window > 0) ||
(layer_hint && conn->package_window > 0 &&
conn->cpath_layer == layer_hint)) {
- connection_start_reading(TO_CONN(conn));
+ connection_start_reading(conn);
/* handle whatever might still be on the inbuf */
if (connection_edge_package_raw_inbuf(conn, 1)<0) {
/* (We already sent an end cell if possible) */
- connection_mark_for_close(TO_CONN(conn));
+ connection_mark_for_close(conn);
continue;
}
@@ -1328,17 +1282,16 @@ circuit_resume_edge_reading_helper(edge_connection_t *conn,
static int
circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
{
- edge_connection_t *conn = NULL;
+ connection_t *conn = NULL;
unsigned domain = layer_hint ? LD_APP : LD_EXIT;
if (!layer_hint) {
- or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
log_debug(domain,"considering circ->package_window %d",
circ->package_window);
if (circ->package_window <= 0) {
log_debug(domain,"yes, not-at-origin. stopped.");
- for (conn = or_circ->n_streams; conn; conn=conn->next_stream)
- connection_stop_reading(TO_CONN(conn));
+ for (conn = circ->n_streams; conn; conn=conn->next_stream)
+ connection_stop_reading(conn);
return 1;
}
return 0;
@@ -1348,16 +1301,12 @@ circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
layer_hint->package_window);
if (layer_hint->package_window <= 0) {
log_debug(domain,"yes, at-origin. stopped.");
-#if 0
- // XXXX NM DEAD CODE.
for (conn = circ->n_streams; conn; conn=conn->next_stream)
if (conn->cpath_layer == layer_hint)
connection_stop_reading(conn);
-#endif
- for (conn = TO_ORIGIN_CIRCUIT(circ)->p_streams; conn;
- conn=conn->next_stream)
+ for (conn = circ->p_streams; conn; conn=conn->next_stream)
if (conn->cpath_layer == layer_hint)
- connection_stop_reading(TO_CONN(conn));
+ connection_stop_reading(conn);
return 1;
}
return 0;
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index 0b61004d0a..ec6f299165 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -14,9 +14,10 @@ const char rendclient_c_id[] =
/** Called when we've established a circuit to an introduction point:
* send the introduction request. */
void
-rend_client_introcirc_has_opened(origin_circuit_t *circ)
+rend_client_introcirc_has_opened(circuit_t *circ)
{
- tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
+ tor_assert(circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
+ tor_assert(CIRCUIT_IS_ORIGIN(circ));
tor_assert(circ->cpath);
log_info(LD_REND,"introcirc is open");
@@ -27,17 +28,17 @@ rend_client_introcirc_has_opened(origin_circuit_t *circ)
* it fails, mark the circ for close and return -1. else return 0.
*/
static int
-rend_client_send_establish_rendezvous(origin_circuit_t *circ)
+rend_client_send_establish_rendezvous(circuit_t *circ)
{
- tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND);
+ tor_assert(circ->purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND);
log_info(LD_REND, "Sending an ESTABLISH_RENDEZVOUS cell");
if (crypto_rand(circ->rend_cookie, REND_COOKIE_LEN) < 0) {
log_warn(LD_BUG, "Internal error: Couldn't produce random cookie.");
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return -1;
}
- if (connection_edge_send_command(NULL,TO_CIRCUIT(circ),
+ if (connection_edge_send_command(NULL,circ,
RELAY_COMMAND_ESTABLISH_RENDEZVOUS,
circ->rend_cookie, REND_COOKIE_LEN,
circ->cpath->prev)<0) {
@@ -53,8 +54,7 @@ rend_client_send_establish_rendezvous(origin_circuit_t *circ)
* down introcirc if possible.
*/
int
-rend_client_send_introduction(origin_circuit_t *introcirc,
- origin_circuit_t *rendcirc)
+rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc)
{
size_t payload_len;
int r;
@@ -64,8 +64,8 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
crypt_path_t *cpath;
off_t dh_offset;
- tor_assert(introcirc->_base.purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
- tor_assert(rendcirc->_base.purpose == CIRCUIT_PURPOSE_C_REND_READY);
+ tor_assert(introcirc->purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
+ tor_assert(rendcirc->purpose == CIRCUIT_PURPOSE_C_REND_READY);
tor_assert(!rend_cmp_service_ids(introcirc->rend_query,
rendcirc->rend_query));
@@ -111,15 +111,13 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
klen = crypto_pk_asn1_encode(extend_info->onion_key, tmp+7+DIGEST_LEN+2,
sizeof(tmp)-(7+DIGEST_LEN+2));
set_uint16(tmp+7+DIGEST_LEN, htons(klen));
- memcpy(tmp+7+DIGEST_LEN+2+klen, rendcirc->rend_cookie,
- REND_COOKIE_LEN);
+ memcpy(tmp+7+DIGEST_LEN+2+klen, rendcirc->rend_cookie, REND_COOKIE_LEN);
dh_offset = 7+DIGEST_LEN+2+klen+REND_COOKIE_LEN;
} else {
/* Version 0. */
strncpy(tmp, rendcirc->build_state->chosen_exit->nickname,
(MAX_NICKNAME_LEN+1)); /* nul pads */
- memcpy(tmp+MAX_NICKNAME_LEN+1, rendcirc->rend_cookie,
- REND_COOKIE_LEN);
+ memcpy(tmp+MAX_NICKNAME_LEN+1, rendcirc->rend_cookie, REND_COOKIE_LEN);
dh_offset = MAX_NICKNAME_LEN+1+REND_COOKIE_LEN;
}
@@ -143,7 +141,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
tor_assert(DIGEST_LEN + r <= RELAY_PAYLOAD_SIZE); /* we overran something */
payload_len = DIGEST_LEN + r;
- if (connection_edge_send_command(NULL, TO_CIRCUIT(introcirc),
+ if (connection_edge_send_command(NULL, introcirc,
RELAY_COMMAND_INTRODUCE1,
payload, payload_len,
introcirc->cpath->prev)<0) {
@@ -153,21 +151,22 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
}
/* Now, we wait for an ACK or NAK on this circuit. */
- introcirc->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT;
+ introcirc->purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT;
return 0;
err:
- circuit_mark_for_close(TO_CIRCUIT(introcirc), END_CIRC_AT_ORIGIN);
- circuit_mark_for_close(TO_CIRCUIT(rendcirc), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(introcirc, END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(rendcirc, END_CIRC_AT_ORIGIN);
return -1;
}
/** Called when a rendezvous circuit is open; sends a establish
* rendezvous circuit as appropriate. */
void
-rend_client_rendcirc_has_opened(origin_circuit_t *circ)
+rend_client_rendcirc_has_opened(circuit_t *circ)
{
- tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND);
+ tor_assert(circ->purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND);
+ tor_assert(CIRCUIT_IS_ORIGIN(circ));
log_info(LD_REND,"rendcirc is open");
@@ -180,21 +179,21 @@ rend_client_rendcirc_has_opened(origin_circuit_t *circ)
/** Called when get an ACK or a NAK for a REND_INTRODUCE1 cell.
*/
int
-rend_client_introduction_acked(origin_circuit_t *circ,
+rend_client_introduction_acked(circuit_t *circ,
const char *request, size_t request_len)
{
- origin_circuit_t *rendcirc;
- (void) request; // XXXX Use this.
+ circuit_t *rendcirc;
- if (circ->_base.purpose != CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
+ if (circ->purpose != CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
log_warn(LD_PROTOCOL,
"Received REND_INTRODUCE_ACK on unexpected circuit %d.",
- circ->_base.n_circ_id);
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circ->n_circ_id);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return -1;
}
tor_assert(circ->build_state->chosen_exit);
+ tor_assert(circ->build_state->chosen_exit->nickname);
if (request_len == 0) {
/* It's an ACK; the introduction point relayed our introduction request. */
@@ -205,16 +204,16 @@ rend_client_introduction_acked(origin_circuit_t *circ,
rendcirc = circuit_get_by_rend_query_and_purpose(
circ->rend_query, CIRCUIT_PURPOSE_C_REND_READY);
if (rendcirc) { /* remember the ack */
- rendcirc->_base.purpose = CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED;
+ rendcirc->purpose = CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED;
} else {
log_info(LD_REND,"...Found no rend circ. Dropping on the floor.");
}
/* close the circuit: we won't need it anymore. */
- circ->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACKED;
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACKED;
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
} else {
/* It's a NAK; the introduction point didn't relay our request. */
- circ->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCING;
+ circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCING;
/* Remove this intro point from the set of viable introduction
* points. If any remain, extend to a new one and try again.
* If none remain, refetch the service descriptor.
@@ -229,14 +228,14 @@ rend_client_introduction_acked(origin_circuit_t *circ,
if (!extend_info) {
log_warn(LD_REND, "No introduction points left for %s. Closing.",
escaped_safe_str(circ->rend_query));
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return -1;
}
log_info(LD_REND,
"Got nack for %s from %s. Re-extending circ %d, "
"this time to %s.",
escaped_safe_str(circ->rend_query),
- circ->build_state->chosen_exit->nickname, circ->_base.n_circ_id,
+ circ->build_state->chosen_exit->nickname, circ->n_circ_id,
extend_info->nickname);
result = circuit_extend_to_new_exit(circ, extend_info);
extend_info_free(extend_info);
@@ -340,38 +339,36 @@ rend_client_remove_intro_point(extend_info_t *failed_intro, const char *query)
* the circuit to C_REND_READY.
*/
int
-rend_client_rendezvous_acked(origin_circuit_t *circ, const char *request,
+rend_client_rendezvous_acked(circuit_t *circ, const char *request,
size_t request_len)
{
- (void) request;
- (void) request_len;
/* we just got an ack for our establish-rendezvous. switch purposes. */
- if (circ->_base.purpose != CIRCUIT_PURPOSE_C_ESTABLISH_REND) {
+ if (circ->purpose != CIRCUIT_PURPOSE_C_ESTABLISH_REND) {
log_warn(LD_PROTOCOL,"Got a rendezvous ack when we weren't expecting one. "
"Closing circ.");
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return -1;
}
log_info(LD_REND,"Got rendezvous ack. This circuit is now ready for "
"rendezvous.");
- circ->_base.purpose = CIRCUIT_PURPOSE_C_REND_READY;
+ circ->purpose = CIRCUIT_PURPOSE_C_REND_READY;
return 0;
}
/** Bob sent us a rendezvous cell; join the circuits. */
int
-rend_client_receive_rendezvous(origin_circuit_t *circ, const char *request,
+rend_client_receive_rendezvous(circuit_t *circ, const char *request,
size_t request_len)
{
crypt_path_t *hop;
char keys[DIGEST_LEN+CPATH_KEY_MATERIAL_LEN];
- if ((circ->_base.purpose != CIRCUIT_PURPOSE_C_REND_READY &&
- circ->_base.purpose != CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED)
+ if ((circ->purpose != CIRCUIT_PURPOSE_C_REND_READY &&
+ circ->purpose != CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED)
|| !circ->build_state->pending_final_cpath) {
log_warn(LD_PROTOCOL,"Got rendezvous2 cell from hidden service, but not "
"expecting it. Closing.");
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return -1;
}
@@ -405,7 +402,7 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const char *request,
hop->dh_handshake_state = NULL;
/* All is well. Extend the circuit. */
- circ->_base.purpose = CIRCUIT_PURPOSE_C_REND_JOINED;
+ circ->purpose = CIRCUIT_PURPOSE_C_REND_JOINED;
hop->state = CPATH_STATE_OPEN;
/* set the windows to default. these are the windows
* that alice thinks bob has.
@@ -417,7 +414,7 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const char *request,
circ->build_state->pending_final_cpath = NULL; /* prevent double-free */
return 0;
err:
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return -1;
}
@@ -429,7 +426,7 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const char *request,
void
rend_client_desc_here(const char *query)
{
- edge_connection_t *conn;
+ connection_t *conn;
rend_cache_entry_t *entry;
time_t now = time(NULL);
int i, n_conns;
@@ -438,26 +435,25 @@ rend_client_desc_here(const char *query)
get_connection_array(&carray, &n_conns);
for (i = 0; i < n_conns; ++i) {
- if (carray[i]->type != CONN_TYPE_AP ||
- carray[i]->state != AP_CONN_STATE_RENDDESC_WAIT ||
- carray[i]->marked_for_close)
- continue;
- conn = TO_EDGE_CONN(carray[i]);
- if (rend_cmp_service_ids(query, conn->rend_query))
+ conn = carray[i];
+ if (conn->type != CONN_TYPE_AP ||
+ conn->state != AP_CONN_STATE_RENDDESC_WAIT ||
+ conn->marked_for_close ||
+ rend_cmp_service_ids(query, conn->rend_query))
continue;
- assert_connection_ok(TO_CONN(conn), now);
+ assert_connection_ok(conn, now);
if (rend_cache_lookup_entry(conn->rend_query, -1, &entry) == 1 &&
entry->parsed->n_intro_points > 0) {
/* either this fetch worked, or it failed but there was a
* valid entry from before which we should reuse */
log_info(LD_REND,"Rend desc is usable. Launching circuits.");
- conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
+ conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
/* restart their timeout values, so they get a fair shake at
* connecting to the hidden service. */
- conn->_base.timestamp_created = now;
- conn->_base.timestamp_lastread = now;
- conn->_base.timestamp_lastwritten = now;
+ conn->timestamp_created = now;
+ conn->timestamp_lastread = now;
+ conn->timestamp_lastwritten = now;
if (connection_ap_handshake_attach_circuit(conn) < 0) {
/* it will never work */
diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c
index ab38e9f3a6..4c60bac803 100644
--- a/src/or/rendcommon.c
+++ b/src/or/rendcommon.c
@@ -234,7 +234,7 @@ rend_get_service_id(crypto_pk_env_t *pk, char *out)
/** How old do we let hidden service descriptors get discarding them as too
* old? */
#define REND_CACHE_MAX_AGE (2*24*60*60)
-/** How wrong do we assume our clock may be when checking whether hidden
+/** How wrong to we assume our clock may be when checking whether hidden
* services are too old or too new? */
#define REND_CACHE_MAX_SKEW (24*60*60)
@@ -432,41 +432,34 @@ void
rend_process_relay_cell(circuit_t *circ, int command, size_t length,
const char *payload)
{
- or_circuit_t *or_circ = NULL;
- origin_circuit_t *origin_circ = NULL;
int r;
- if (CIRCUIT_IS_ORIGIN(circ))
- origin_circ = TO_ORIGIN_CIRCUIT(circ);
- else
- or_circ = TO_OR_CIRCUIT(circ);
-
switch (command) {
case RELAY_COMMAND_ESTABLISH_INTRO:
- r = rend_mid_establish_intro(or_circ,payload,length);
+ r = rend_mid_establish_intro(circ,payload,length);
break;
case RELAY_COMMAND_ESTABLISH_RENDEZVOUS:
- r = rend_mid_establish_rendezvous(or_circ,payload,length);
+ r = rend_mid_establish_rendezvous(circ,payload,length);
break;
case RELAY_COMMAND_INTRODUCE1:
- r = rend_mid_introduce(or_circ,payload,length);
+ r = rend_mid_introduce(circ,payload,length);
break;
case RELAY_COMMAND_INTRODUCE2:
- r = rend_service_introduce(origin_circ,payload,length);
+ r = rend_service_introduce(circ,payload,length);
break;
case RELAY_COMMAND_INTRODUCE_ACK:
- r = rend_client_introduction_acked(origin_circ,payload,length);
+ r = rend_client_introduction_acked(circ,payload,length);
break;
case RELAY_COMMAND_RENDEZVOUS1:
- r = rend_mid_rendezvous(or_circ,payload,length);
+ r = rend_mid_rendezvous(circ,payload,length);
break;
case RELAY_COMMAND_RENDEZVOUS2:
- r = rend_client_receive_rendezvous(origin_circ,payload,length);
+ r = rend_client_receive_rendezvous(circ,payload,length);
break;
case RELAY_COMMAND_INTRO_ESTABLISHED:
- r = rend_service_intro_established(origin_circ,payload,length);
+ r = rend_service_intro_established(circ,payload,length);
break;
case RELAY_COMMAND_RENDEZVOUS_ESTABLISHED:
- r = rend_client_rendezvous_acked(origin_circ,payload,length);
+ r = rend_client_rendezvous_acked(circ,payload,length);
break;
default:
tor_assert(0);
diff --git a/src/or/rendmid.c b/src/or/rendmid.c
index e96d608d59..c1252289bc 100644
--- a/src/or/rendmid.c
+++ b/src/or/rendmid.c
@@ -15,7 +15,7 @@ const char rendmid_c_id[] =
* setting the circuit's purpose and service pk digest.
*/
int
-rend_mid_establish_intro(or_circuit_t *circ, const char *request,
+rend_mid_establish_intro(circuit_t *circ, const char *request,
size_t request_len)
{
crypto_pk_env_t *pk = NULL;
@@ -23,7 +23,7 @@ rend_mid_establish_intro(or_circuit_t *circ, const char *request,
char expected_digest[DIGEST_LEN];
char pk_digest[DIGEST_LEN];
size_t asn1len;
- or_circuit_t *c;
+ circuit_t *c;
char serviceid[REND_SERVICE_ID_LEN+1];
int reason = END_CIRC_REASON_INTERNAL;
@@ -31,7 +31,7 @@ rend_mid_establish_intro(or_circuit_t *circ, const char *request,
"Received an ESTABLISH_INTRO request on circuit %d",
circ->p_circ_id);
- if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) {
+ if (circ->purpose != CIRCUIT_PURPOSE_OR || circ->n_conn) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Rejecting ESTABLISH_INTRO on non-OR or non-edge circuit.");
reason = END_CIRC_REASON_TORPROTOCOL;
@@ -87,15 +87,15 @@ rend_mid_establish_intro(or_circuit_t *circ, const char *request,
/* Close any other intro circuits with the same pk. */
c = NULL;
- while ((c = circuit_get_intro_point(pk_digest))) {
- log_info(LD_REND, "Replacing old circuit for service %s",
- safe_str(serviceid));
- circuit_mark_for_close(TO_CIRCUIT(c), END_CIRC_REASON_REQUESTED);
- /* Now it's marked, and it won't be returned next time. */
+ while ((c = circuit_get_next_by_pk_and_purpose(
+ c,pk_digest,CIRCUIT_PURPOSE_INTRO_POINT))) {
+ log_info(LD_REND, "Replacing old circuit %d for service %s",
+ c->p_circ_id, safe_str(serviceid));
+ circuit_mark_for_close(c, END_CIRC_REASON_REQUESTED);
}
/* Acknowledge the request. */
- if (connection_edge_send_command(NULL,TO_CIRCUIT(circ),
+ if (connection_edge_send_command(NULL,circ,
RELAY_COMMAND_INTRO_ESTABLISHED,
"", 0, NULL)<0) {
log_info(LD_GENERAL, "Couldn't send INTRO_ESTABLISHED cell.");
@@ -103,8 +103,8 @@ rend_mid_establish_intro(or_circuit_t *circ, const char *request,
}
/* Now, set up this circuit. */
- circ->_base.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
- memcpy(circ->rend_token, pk_digest, DIGEST_LEN);
+ circ->purpose = CIRCUIT_PURPOSE_INTRO_POINT;
+ memcpy(circ->rend_pk_digest, pk_digest, DIGEST_LEN);
log_info(LD_REND,
"Established introduction point on circuit %d for service %s",
@@ -116,7 +116,7 @@ rend_mid_establish_intro(or_circuit_t *circ, const char *request,
reason = END_CIRC_REASON_TORPROTOCOL;
err:
if (pk) crypto_free_pk_env(pk);
- circuit_mark_for_close(TO_CIRCUIT(circ), reason);
+ circuit_mark_for_close(circ, reason);
return -1;
}
@@ -125,23 +125,20 @@ rend_mid_establish_intro(or_circuit_t *circ, const char *request,
* INTRODUCE2 cell.
*/
int
-rend_mid_introduce(or_circuit_t *circ, const char *request, size_t request_len)
+rend_mid_introduce(circuit_t *circ, const char *request, size_t request_len)
{
- or_circuit_t *intro_circ;
+ circuit_t *intro_circ;
char serviceid[REND_SERVICE_ID_LEN+1];
char nak_body[1];
- if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) {
+ if (circ->purpose != CIRCUIT_PURPOSE_OR || circ->n_conn) {
log_warn(LD_PROTOCOL,
"Rejecting INTRODUCE1 on non-OR or non-edge circuit %d.",
circ->p_circ_id);
goto err;
}
- /* We could change this to MAX_HEX_NICKNAME_LEN now that 0.0.9.x is
- * obsolete; however, there isn't much reason to do so, and we're going
- * to revise this protocol anyway.
- */
+ /* change to MAX_HEX_NICKNAME_LEN once 0.0.9.x is obsolete */
if (request_len < (DIGEST_LEN+(MAX_NICKNAME_LEN+1)+REND_COOKIE_LEN+
DH_KEY_LEN+CIPHER_KEY_LEN+PKCS1_OAEP_PADDING_OVERHEAD)) {
log_warn(LD_PROTOCOL, "Impossibly short INTRODUCE1 cell on circuit %d; "
@@ -153,7 +150,8 @@ rend_mid_introduce(or_circuit_t *circ, const char *request, size_t request_len)
base32_encode(serviceid, REND_SERVICE_ID_LEN+1, request,10);
/* The first 20 bytes are all we look at: they have a hash of Bob's PK. */
- intro_circ = circuit_get_intro_point(request);
+ intro_circ = circuit_get_next_by_pk_and_purpose(
+ NULL, request, CIRCUIT_PURPOSE_INTRO_POINT);
if (!intro_circ) {
log_info(LD_REND,
"No intro circ found for INTRODUCE1 cell (%s) from circuit %d; "
@@ -165,11 +163,10 @@ rend_mid_introduce(or_circuit_t *circ, const char *request, size_t request_len)
log_info(LD_REND,
"Sending introduction request for service %s "
"from circ %d to circ %d",
- safe_str(serviceid), circ->p_circ_id,
- intro_circ->p_circ_id);
+ safe_str(serviceid), circ->p_circ_id, intro_circ->p_circ_id);
/* Great. Now we just relay the cell down the circuit. */
- if (connection_edge_send_command(NULL, TO_CIRCUIT(intro_circ),
+ if (connection_edge_send_command(NULL, intro_circ,
RELAY_COMMAND_INTRODUCE2,
request, request_len, NULL)) {
log_warn(LD_GENERAL,
@@ -177,11 +174,10 @@ rend_mid_introduce(or_circuit_t *circ, const char *request, size_t request_len)
goto err;
}
/* And sent an ack down Alice's circuit. Empty body means succeeded. */
- if (connection_edge_send_command(NULL,TO_CIRCUIT(circ),
- RELAY_COMMAND_INTRODUCE_ACK,
+ if (connection_edge_send_command(NULL,circ,RELAY_COMMAND_INTRODUCE_ACK,
NULL,0,NULL)) {
log_warn(LD_GENERAL, "Unable to send INTRODUCE_ACK cell to Tor client.");
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
+ circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
return -1;
}
@@ -189,12 +185,11 @@ rend_mid_introduce(or_circuit_t *circ, const char *request, size_t request_len)
err:
/* Send the client an NACK */
nak_body[0] = 1;
- if (connection_edge_send_command(NULL,TO_CIRCUIT(circ),
- RELAY_COMMAND_INTRODUCE_ACK,
+ if (connection_edge_send_command(NULL,circ,RELAY_COMMAND_INTRODUCE_ACK,
nak_body, 1, NULL)) {
log_warn(LD_GENERAL, "Unable to send NAK to Tor client.");
/* Is this right? */
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
+ circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
}
return -1;
}
@@ -203,13 +198,13 @@ rend_mid_introduce(or_circuit_t *circ, const char *request, size_t request_len)
* rendezvous cookie.
*/
int
-rend_mid_establish_rendezvous(or_circuit_t *circ, const char *request,
+rend_mid_establish_rendezvous(circuit_t *circ, const char *request,
size_t request_len)
{
char hexid[9];
int reason = END_CIRC_REASON_TORPROTOCOL;
- if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) {
+ if (circ->purpose != CIRCUIT_PURPOSE_OR || circ->n_conn) {
log_warn(LD_PROTOCOL,
"Tried to establish rendezvous on non-OR or non-edge circuit.");
goto err;
@@ -227,7 +222,7 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const char *request,
}
/* Acknowledge the request. */
- if (connection_edge_send_command(NULL,TO_CIRCUIT(circ),
+ if (connection_edge_send_command(NULL,circ,
RELAY_COMMAND_RENDEZVOUS_ESTABLISHED,
"", 0, NULL)<0) {
log_warn(LD_PROTOCOL, "Couldn't send RENDEZVOUS_ESTABLISHED cell.");
@@ -235,8 +230,8 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const char *request,
goto err;
}
- circ->_base.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
- memcpy(circ->rend_token, request, REND_COOKIE_LEN);
+ circ->purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
+ memcpy(circ->rend_cookie, request, REND_COOKIE_LEN);
base16_encode(hexid,9,request,4);
@@ -246,7 +241,7 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const char *request,
return 0;
err:
- circuit_mark_for_close(TO_CIRCUIT(circ), reason);
+ circuit_mark_for_close(circ, reason);
return -1;
}
@@ -255,10 +250,9 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const char *request,
* connecting the two circuits.
*/
int
-rend_mid_rendezvous(or_circuit_t *circ, const char *request,
- size_t request_len)
+rend_mid_rendezvous(circuit_t *circ, const char *request, size_t request_len)
{
- or_circuit_t *rend_circ;
+ circuit_t *rend_circ;
char hexid[9];
int reason = END_CIRC_REASON_INTERNAL;
base16_encode(hexid,9,request,request_len<4?request_len:4);
@@ -269,7 +263,7 @@ rend_mid_rendezvous(or_circuit_t *circ, const char *request,
circ->p_circ_id, hexid);
}
- if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) {
+ if (circ->purpose != CIRCUIT_PURPOSE_OR || circ->n_conn) {
log_info(LD_REND,
"Tried to complete rendezvous on non-OR or non-edge circuit %d.",
circ->p_circ_id);
@@ -295,12 +289,12 @@ rend_mid_rendezvous(or_circuit_t *circ, const char *request,
}
/* Send the RENDEZVOUS2 cell to Alice. */
- if (connection_edge_send_command(NULL, TO_CIRCUIT(rend_circ),
+ if (connection_edge_send_command(NULL, rend_circ,
RELAY_COMMAND_RENDEZVOUS2,
request+REND_COOKIE_LEN,
request_len-REND_COOKIE_LEN, NULL)) {
log_warn(LD_GENERAL,
- "Unable to send RENDEZVOUS2 cell to client on circuit %d.",
+ "Unable to send RENDEZVOUS2 cell to OP on circuit %d.",
rend_circ->p_circ_id);
goto err;
}
@@ -310,16 +304,16 @@ rend_mid_rendezvous(or_circuit_t *circ, const char *request,
"Completing rendezvous: circuit %d joins circuit %d (cookie %s)",
circ->p_circ_id, rend_circ->p_circ_id, hexid);
- circ->_base.purpose = CIRCUIT_PURPOSE_REND_ESTABLISHED;
- rend_circ->_base.purpose = CIRCUIT_PURPOSE_REND_ESTABLISHED;
- memset(circ->rend_token, 0, REND_COOKIE_LEN);
+ circ->purpose = CIRCUIT_PURPOSE_REND_ESTABLISHED;
+ rend_circ->purpose = CIRCUIT_PURPOSE_REND_ESTABLISHED;
+ memset(circ->rend_cookie, 0, REND_COOKIE_LEN);
rend_circ->rend_splice = circ;
circ->rend_splice = rend_circ;
return 0;
err:
- circuit_mark_for_close(TO_CIRCUIT(circ), reason);
+ circuit_mark_for_close(circ, reason);
return -1;
}
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 0cda1d95c0..45454985ed 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -11,8 +11,8 @@ const char rendservice_c_id[] =
#include "or.h"
-static origin_circuit_t *find_intro_circuit(routerinfo_t *router,
- const char *pk_digest);
+static circuit_t *find_intro_circuit(routerinfo_t *router,
+ const char *pk_digest);
/** Represents the mapping from a virtual port of a rendezvous service to
* a real port on some IP.
@@ -179,7 +179,7 @@ parse_port_config(const char *string)
} else {
addrport = smartlist_get(sl,1);
if (strchr(addrport, ':') || strchr(addrport, '.')) {
- if (parse_addr_port(LOG_WARN, addrport, NULL, &addr, &p)<0) {
+ if (parse_addr_port(addrport, NULL, &addr, &p)<0) {
log_warn(LD_CONFIG,"Unparseable address in hidden service port "
"configuration.");
goto err;
@@ -285,7 +285,7 @@ static void
rend_service_update_descriptor(rend_service_t *service)
{
rend_service_descriptor_t *d;
- origin_circuit_t *circ;
+ circuit_t *circ;
int i,n;
routerinfo_t *router;
@@ -310,7 +310,7 @@ rend_service_update_descriptor(rend_service_t *service)
continue;
}
circ = find_intro_circuit(router, service->pk_digest);
- if (circ && circ->_base.purpose == CIRCUIT_PURPOSE_S_INTRO) {
+ if (circ && circ->purpose == CIRCUIT_PURPOSE_S_INTRO) {
/* We have an entirely established intro circuit. */
d->intro_points[d->n_intro_points] = tor_strdup(router->nickname);
d->intro_point_extend_info[d->n_intro_points] =
@@ -410,7 +410,7 @@ rend_service_requires_uptime(rend_service_t *service)
* rendezvous point.
*/
int
-rend_service_introduce(origin_circuit_t *circuit, const char *request,
+rend_service_introduce(circuit_t *circuit, const char *request,
size_t request_len)
{
char *ptr, *r_cookie;
@@ -421,7 +421,7 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request,
int r, i;
size_t len, keylen;
crypto_dh_env_t *dh = NULL;
- origin_circuit_t *launched = NULL;
+ circuit_t *launched = NULL;
crypt_path_t *cpath = NULL;
char serviceid[REND_SERVICE_ID_LEN+1];
char hexcookie[9];
@@ -430,12 +430,12 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request,
base32_encode(serviceid, REND_SERVICE_ID_LEN+1,
circuit->rend_pk_digest,10);
log_info(LD_REND, "Received INTRODUCE2 cell for service %s on circ %d.",
- escaped(serviceid), circuit->_base.n_circ_id);
+ escaped(serviceid), circuit->n_circ_id);
- if (circuit->_base.purpose != CIRCUIT_PURPOSE_S_INTRO) {
+ if (circuit->purpose != CIRCUIT_PURPOSE_S_INTRO) {
log_warn(LD_PROTOCOL,
"Got an INTRODUCE2 over a non-introduction circuit %d.",
- circuit->_base.n_circ_id);
+ circuit->n_circ_id);
return -1;
}
@@ -443,7 +443,7 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request,
if (request_len < DIGEST_LEN+REND_COOKIE_LEN+(MAX_NICKNAME_LEN+1)+
DH_KEY_LEN+42) {
log_warn(LD_PROTOCOL, "Got a truncated INTRODUCE2 cell on circ %d.",
- circuit->_base.n_circ_id);
+ circuit->n_circ_id);
return -1;
}
@@ -518,7 +518,7 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request,
ptr=memchr(rp_nickname,0,nickname_field_len);
if (!ptr || ptr == rp_nickname) {
log_warn(LD_PROTOCOL,
- "Couldn't find a nul-padded nickname in INTRODUCE2 cell.");
+ "Couldn't find a null-padded nickname in INTRODUCE2 cell.");
return -1;
}
if ((version == 0 && !is_legal_nickname(rp_nickname)) ||
@@ -609,8 +609,7 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request,
return 0;
err:
if (dh) crypto_dh_free(dh);
- if (launched)
- circuit_mark_for_close(TO_CIRCUIT(launched), END_CIRC_AT_ORIGIN);
+ if (launched) circuit_mark_for_close(launched, END_CIRC_AT_ORIGIN);
if (extend_info) extend_info_free(extend_info);
return -1;
}
@@ -619,12 +618,12 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request,
* than the last hop: launches a new circuit to the same rendezvous point.
*/
void
-rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc)
+rend_service_relaunch_rendezvous(circuit_t *oldcirc)
{
- origin_circuit_t *newcirc;
+ circuit_t *newcirc;
cpath_build_state_t *newstate, *oldstate;
- tor_assert(oldcirc->_base.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
+ tor_assert(oldcirc->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
if (!oldcirc->build_state ||
oldcirc->build_state->failure_count > MAX_REND_FAILURES ||
@@ -664,10 +663,8 @@ rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc)
oldstate->pending_final_cpath = NULL;
memcpy(newcirc->rend_query, oldcirc->rend_query, REND_SERVICE_ID_LEN+1);
- memcpy(newcirc->rend_pk_digest, oldcirc->rend_pk_digest,
- DIGEST_LEN);
- memcpy(newcirc->rend_cookie, oldcirc->rend_cookie,
- REND_COOKIE_LEN);
+ memcpy(newcirc->rend_pk_digest, oldcirc->rend_pk_digest, DIGEST_LEN);
+ memcpy(newcirc->rend_cookie, oldcirc->rend_cookie, REND_COOKIE_LEN);
}
/** Launch a circuit to serve as an introduction point for the service
@@ -677,7 +674,7 @@ static int
rend_service_launch_establish_intro(rend_service_t *service,
const char *nickname)
{
- origin_circuit_t *launched;
+ circuit_t *launched;
log_info(LD_REND,
"Launching circuit to introduction point %s for service %s",
@@ -698,7 +695,7 @@ rend_service_launch_establish_intro(rend_service_t *service,
sizeof(launched->rend_query));
memcpy(launched->rend_pk_digest, service->pk_digest, DIGEST_LEN);
- if (launched->_base.state == CIRCUIT_STATE_OPEN)
+ if (launched->state == CIRCUIT_STATE_OPEN)
rend_service_intro_has_opened(launched);
return 0;
}
@@ -707,7 +704,7 @@ rend_service_launch_establish_intro(rend_service_t *service,
* sends a RELAY_ESTABLISH_INTRO cell.
*/
void
-rend_service_intro_has_opened(origin_circuit_t *circuit)
+rend_service_intro_has_opened(circuit_t *circuit)
{
rend_service_t *service;
size_t len;
@@ -716,7 +713,8 @@ rend_service_intro_has_opened(origin_circuit_t *circuit)
char auth[DIGEST_LEN + 9];
char serviceid[REND_SERVICE_ID_LEN+1];
- tor_assert(circuit->_base.purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
+ tor_assert(circuit->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
+ tor_assert(CIRCUIT_IS_ORIGIN(circuit));
tor_assert(circuit->cpath);
base32_encode(serviceid, REND_SERVICE_ID_LEN+1,
@@ -725,13 +723,13 @@ rend_service_intro_has_opened(origin_circuit_t *circuit)
service = rend_service_get_by_pk_digest(circuit->rend_pk_digest);
if (!service) {
log_warn(LD_REND, "Unrecognized service ID %s on introduction circuit %d.",
- serviceid, circuit->_base.n_circ_id);
+ serviceid, circuit->n_circ_id);
goto err;
}
log_info(LD_REND,
"Established circuit %d as introduction point for service %s",
- circuit->_base.n_circ_id, serviceid);
+ circuit->n_circ_id, serviceid);
/* Build the payload for a RELAY_ESTABLISH_INTRO cell. */
len = crypto_pk_asn1_encode(service->private_key, buf+2,
@@ -750,32 +748,29 @@ rend_service_intro_has_opened(origin_circuit_t *circuit)
}
len += r;
- if (connection_edge_send_command(NULL, TO_CIRCUIT(circuit),
- RELAY_COMMAND_ESTABLISH_INTRO,
+ if (connection_edge_send_command(NULL, circuit,RELAY_COMMAND_ESTABLISH_INTRO,
buf, len, circuit->cpath->prev)<0) {
log_info(LD_GENERAL,
"Couldn't send introduction request for service %s on circuit %d",
- serviceid, circuit->_base.n_circ_id);
+ serviceid, circuit->n_circ_id);
goto err;
}
return;
err:
- circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(circuit, END_CIRC_AT_ORIGIN);
}
/** Called when we get an INTRO_ESTABLISHED cell; mark the circuit as a
* live introduction point, and note that the service descriptor is
* now out-of-date.*/
int
-rend_service_intro_established(origin_circuit_t *circuit, const char *request,
+rend_service_intro_established(circuit_t *circuit, const char *request,
size_t request_len)
{
rend_service_t *service;
- (void) request;
- (void) request_len;
- if (circuit->_base.purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) {
+ if (circuit->purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) {
log_warn(LD_PROTOCOL,
"received INTRO_ESTABLISHED cell on non-intro circuit.");
goto err;
@@ -783,15 +778,15 @@ rend_service_intro_established(origin_circuit_t *circuit, const char *request,
service = rend_service_get_by_pk_digest(circuit->rend_pk_digest);
if (!service) {
log_warn(LD_REND, "Unknown service on introduction circuit %d.",
- circuit->_base.n_circ_id);
+ circuit->n_circ_id);
goto err;
}
service->desc_is_dirty = time(NULL);
- circuit->_base.purpose = CIRCUIT_PURPOSE_S_INTRO;
+ circuit->purpose = CIRCUIT_PURPOSE_S_INTRO;
return 0;
err:
- circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(circuit, END_CIRC_AT_ORIGIN);
return -1;
}
@@ -799,7 +794,7 @@ rend_service_intro_established(origin_circuit_t *circuit, const char *request,
* RELAY_COMMAND_RENDEZVOUS1 cell.
*/
void
-rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
+rend_service_rendezvous_has_opened(circuit_t *circuit)
{
rend_service_t *service;
char buf[RELAY_PAYLOAD_SIZE];
@@ -807,7 +802,7 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
char serviceid[REND_SERVICE_ID_LEN+1];
char hexcookie[9];
- tor_assert(circuit->_base.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
+ tor_assert(circuit->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
tor_assert(circuit->cpath);
tor_assert(circuit->build_state);
hop = circuit->build_state->pending_final_cpath;
@@ -820,7 +815,7 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
log_info(LD_REND,
"Done building circuit %d to rendezvous with "
"cookie %s for service %s",
- circuit->_base.n_circ_id, hexcookie, serviceid);
+ circuit->n_circ_id, hexcookie, serviceid);
service = rend_service_get_by_pk_digest(circuit->rend_pk_digest);
if (!service) {
@@ -840,8 +835,7 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
DIGEST_LEN);
/* Send the cell */
- if (connection_edge_send_command(NULL, TO_CIRCUIT(circuit),
- RELAY_COMMAND_RENDEZVOUS1,
+ if (connection_edge_send_command(NULL, circuit, RELAY_COMMAND_RENDEZVOUS1,
buf, REND_COOKIE_LEN+DH_KEY_LEN+DIGEST_LEN,
circuit->cpath->prev)<0) {
log_warn(LD_GENERAL, "Couldn't send RENDEZVOUS1 cell.");
@@ -863,11 +857,11 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
circuit->build_state->pending_final_cpath = NULL; /* prevent double-free */
/* Change the circuit purpose. */
- circuit->_base.purpose = CIRCUIT_PURPOSE_S_REND_JOINED;
+ circuit->purpose = CIRCUIT_PURPOSE_S_REND_JOINED;
return;
err:
- circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(circuit, END_CIRC_AT_ORIGIN);
}
/*
@@ -878,14 +872,15 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
* <b>router</b> for the service whose public key is <b>pk_digest</b>. Return
* NULL if no such service is found.
*/
-static origin_circuit_t *
+static circuit_t *
find_intro_circuit(routerinfo_t *router, const char *pk_digest)
{
- origin_circuit_t *circ = NULL;
+ circuit_t *circ = NULL;
tor_assert(router);
while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
CIRCUIT_PURPOSE_S_INTRO))) {
+ tor_assert(circ->cpath);
if (!strcasecmp(circ->build_state->chosen_exit->nickname,
router->nickname)) {
return circ;
@@ -895,6 +890,7 @@ find_intro_circuit(routerinfo_t *router, const char *pk_digest)
circ = NULL;
while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
CIRCUIT_PURPOSE_S_ESTABLISH_INTRO))) {
+ tor_assert(circ->cpath);
if (!strcasecmp(circ->build_state->chosen_exit->nickname,
router->nickname)) {
return circ;
@@ -1090,7 +1086,7 @@ rend_service_dump_stats(int severity)
routerinfo_t *router;
rend_service_t *service;
char *nickname;
- origin_circuit_t *circ;
+ circuit_t *circ;
for (i=0; i < smartlist_len(rend_service_list); ++i) {
service = smartlist_get(rend_service_list, i);
@@ -1110,7 +1106,7 @@ rend_service_dump_stats(int severity)
continue;
}
log(severity, LD_GENERAL, " Intro point at %s: circuit is %s",nickname,
- circuit_state_to_string(circ->_base.state));
+ circuit_state_to_string(circ->state));
}
}
}
@@ -1121,15 +1117,14 @@ rend_service_dump_stats(int severity)
* or 0 for success.
*/
int
-rend_service_set_connection_addr_port(edge_connection_t *conn,
- origin_circuit_t *circ)
+rend_service_set_connection_addr_port(connection_t *conn, circuit_t *circ)
{
rend_service_t *service;
int i;
rend_service_port_config_t *p;
char serviceid[REND_SERVICE_ID_LEN+1];
- tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_S_REND_JOINED);
+ tor_assert(circ->purpose == CIRCUIT_PURPOSE_S_REND_JOINED);
log_debug(LD_REND,"beginning to hunt for addr/port");
base32_encode(serviceid, REND_SERVICE_ID_LEN+1,
circ->rend_pk_digest,10);
@@ -1137,19 +1132,19 @@ rend_service_set_connection_addr_port(edge_connection_t *conn,
if (!service) {
log_warn(LD_REND, "Couldn't find any service associated with pk %s on "
"rendezvous circuit %d; closing.",
- serviceid, circ->_base.n_circ_id);
+ serviceid, circ->n_circ_id);
return -1;
}
for (i = 0; i < smartlist_len(service->ports); ++i) {
p = smartlist_get(service->ports, i);
- if (conn->_base.port == p->virtual_port) {
- conn->_base.addr = p->real_addr;
- conn->_base.port = p->real_port;
+ if (conn->port == p->virtual_port) {
+ conn->addr = p->real_addr;
+ conn->port = p->real_port;
return 0;
}
}
log_info(LD_REND, "No virtual port mapping exists for port %d on service %s",
- conn->_base.port,serviceid);
+ conn->port,serviceid);
return -1;
}
diff --git a/src/or/rephist.c b/src/or/rephist.c
index 2dceb143b1..8caad25ce4 100644
--- a/src/or/rephist.c
+++ b/src/or/rephist.c
@@ -59,13 +59,14 @@ typedef struct or_history_t {
/** Map from hex OR identity digest to or_history_t. */
static digestmap_t *history_map = NULL;
-/** Return the or_history_t for the named OR, creating it if necessary. */
+/** Return the or_history_t for the named OR, creating it if necessary.
+ */
static or_history_t *
get_or_history(const char* id)
{
or_history_t *hist;
- if (tor_mem_is_zero(id, DIGEST_LEN))
+ if (!memcmp(id, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", DIGEST_LEN))
return NULL;
hist = digestmap_get(history_map, id);
@@ -82,7 +83,7 @@ get_or_history(const char* id)
/** Return the link_history_t for the link from the first named OR to
* the second, creating it if necessary. (ORs are identified by
- * identity digest.)
+ * identity digest)
*/
static link_history_t *
get_link_history(const char *from_id, const char *to_id)
@@ -92,7 +93,7 @@ get_link_history(const char *from_id, const char *to_id)
orhist = get_or_history(from_id);
if (!orhist)
return NULL;
- if (tor_mem_is_zero(to_id, DIGEST_LEN))
+ if (!memcmp(to_id, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", DIGEST_LEN))
return NULL;
lhist = (link_history_t*) digestmap_get(orhist->link_history_map, to_id);
if (!lhist) {
@@ -104,7 +105,7 @@ get_link_history(const char *from_id, const char *to_id)
return lhist;
}
-/** Helper: free storage held by a single link history entry. */
+/** Helper: free storage held by a single link history entry */
static void
_free_link_history(void *val)
{
@@ -112,7 +113,7 @@ _free_link_history(void *val)
tor_free(val);
}
-/** Helper: free storage held by a single OR history entry. */
+/** Helper: free storage held by a single OR history entry */
static void
free_or_history(void *_hist)
{
@@ -140,7 +141,8 @@ update_or_history(or_history_t *hist, time_t when)
}
}
-/** Initialize the static data structures for tracking history. */
+/** Initialize the static data structures for tracking history.
+ */
void
rep_hist_init(void)
{
@@ -234,7 +236,7 @@ rep_hist_note_connection_died(const char* id, time_t when)
/** Remember that we successfully extended from the OR with identity
* digest <b>from_id</b> to the OR with identity digest
- * <b>to_name</b>.
+ * <b>to_name</b>.
*/
void
rep_hist_note_extend_succeeded(const char *from_id, const char *to_id)
@@ -342,8 +344,7 @@ rep_hist_dump_stats(time_t now, int severity)
}
/** Remove history info for routers/links that haven't changed since
- * <b>before</b>.
- */
+ * <b>before</b> */
void
rep_history_clean(time_t before)
{
@@ -386,10 +387,11 @@ rep_history_clean(time_t before)
#define NUM_SECS_BW_SUM_INTERVAL (15*60)
/** How far in the past do we remember and publish bandwidth use? */
#define NUM_SECS_BW_SUM_IS_VALID (24*60*60)
-/** How many bandwidth usage intervals do we remember? (derived) */
+/** How many bandwidth usage intervals do we remember? (derived.) */
#define NUM_TOTALS (NUM_SECS_BW_SUM_IS_VALID/NUM_SECS_BW_SUM_INTERVAL)
-/** Structure to track bandwidth use, and remember the maxima for a given
+/**
+ * Structure to track bandwidth use, and remember the maxima for a given
* time period.
*/
typedef struct bw_array_t {
@@ -421,7 +423,8 @@ typedef struct bw_array_t {
uint64_t totals[NUM_TOTALS];
} bw_array_t;
-/** Shift the current period of b forward by one. */
+/** Shift the current period of b forward by one.
+ */
static void
commit_max(bw_array_t *b)
{
@@ -441,7 +444,8 @@ commit_max(bw_array_t *b)
b->total_in_period = 0;
}
-/** Shift the current observation time of 'b' forward by one second. */
+/** Shift the current observation time of 'b' forward by one second.
+ */
static INLINE void
advance_obs(bw_array_t *b)
{
@@ -466,7 +470,8 @@ advance_obs(bw_array_t *b)
commit_max(b);
}
-/** Add 'n' bytes to the number of bytes in b for second 'when'. */
+/** Add 'n' bytes to the number of bytes in b for second 'when'.
+ */
static INLINE void
add_obs(bw_array_t *b, time_t when, uint64_t n)
{
@@ -483,7 +488,8 @@ add_obs(bw_array_t *b, time_t when, uint64_t n)
b->total_in_period += n;
}
-/** Allocate, initialize, and return a new bw_array. */
+/** Allocate, initialize, and return a new bw_array.
+ */
static bw_array_t *
bw_array_new(void)
{
@@ -500,7 +506,8 @@ bw_array_new(void)
static bw_array_t *read_array = NULL;
static bw_array_t *write_array = NULL;
-/** Set up read_array and write_array. */
+/** Set up read_array and write_array
+ */
static void
bw_arrays_init(void)
{
@@ -556,7 +563,8 @@ find_largest_max(bw_array_t *b)
return max;
}
-/** Find the largest sums in the past NUM_SECS_BW_SUM_IS_VALID (roughly)
+/**
+ * Find the largest sums in the past NUM_SECS_BW_SUM_IS_VALID (roughly)
* seconds. Find one sum for reading and one for writing. They don't have
* to be at the same time).
*
@@ -569,12 +577,15 @@ rep_hist_bandwidth_assess(void)
r = find_largest_max(read_array);
w = find_largest_max(write_array);
if (r>w)
- return (int)(U64_TO_DBL(w)/NUM_SECS_ROLLING_MEASURE);
+ return (int)(w/(double)NUM_SECS_ROLLING_MEASURE);
else
- return (int)(U64_TO_DBL(r)/NUM_SECS_ROLLING_MEASURE);
+ return (int)(r/(double)NUM_SECS_ROLLING_MEASURE);
+
+ return 0;
}
-/** Print the bandwidth history of b (either read_array or write_array)
+/**
+ * Print the bandwidth history of b (either read_array or write_array)
* into the buffer pointed to by buf. The format is simply comma
* separated numbers, from oldest to newest.
*
@@ -608,7 +619,8 @@ rep_hist_fill_bandwidth_history(char *buf, size_t len, bw_array_t *b)
return cp-buf;
}
-/** Allocate and return lines for representing this server's bandwidth
+/**
+ * Allocate and return lines for representing this server's bandwidth
* history in its descriptor.
*/
char *
@@ -677,7 +689,8 @@ rep_hist_update_state(or_state_t *state)
state->dirty = 1;
}
-/** Set bandwidth history from our saved state. */
+/** Set bandwidth history from our saved state.
+ */
int
rep_hist_load_state(or_state_t *state, char **err)
{
@@ -738,17 +751,12 @@ rep_hist_load_state(or_state_t *state, char **err)
return 0;
}
-/*********************************************************************/
-
/** A list of port numbers that have been used recently. */
static smartlist_t *predicted_ports_list=NULL;
/** The corresponding most recently used time for each port. */
static smartlist_t *predicted_ports_times=NULL;
-/** We just got an application request for a connection with
- * port <b>port</b>. Remember it for the future, so we can keep
- * some circuits open that will exit to this port.
- */
+/** DOCDOC */
static void
add_predicted_port(uint16_t port, time_t now)
{
@@ -762,10 +770,7 @@ add_predicted_port(uint16_t port, time_t now)
smartlist_add(predicted_ports_times, tmp_time);
}
-/** Initialize whatever memory and structs are needed for predicting
- * which ports will be used. Also seed it with port 80, so we'll build
- * circuits on start-up.
- */
+/** DOCDOC */
static void
predicted_ports_init(void)
{
@@ -774,9 +779,7 @@ predicted_ports_init(void)
add_predicted_port(80, time(NULL)); /* add one to kickstart us */
}
-/** Free whatever memory is needed for predicting which ports will
- * be used.
- */
+/** DOCDOC */
static void
predicted_ports_free(void)
{
@@ -918,22 +921,6 @@ any_predicted_circuits(time_t now)
predicted_internal_time + PREDICTED_CIRCS_RELEVANCE_TIME >= now;
}
-/** Return 1 if we have no need for circuits currently, else return 0. */
-int
-rep_hist_circbuilding_dormant(time_t now)
-{
- if (any_predicted_circuits(now))
- return 0;
-
- /* see if we'll still need to build testing circuits */
- if (server_mode(get_options()) && !check_whether_orport_reachable())
- return 0;
- if (!check_whether_dirport_reachable())
- return 0;
-
- return 1;
-}
-
/** Free all storage held by the OR/link history caches, by the
* bandwidth history arrays, or by the port history. */
void
diff --git a/src/or/router.c b/src/or/router.c
index a5f8db09ae..dd9bde6ff3 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -232,8 +232,7 @@ init_key_from_file(const char *fname)
}
/** Initialize all OR private keys, and the TLS context, as necessary.
- * On OPs, this only initializes the tls context. Return 0 on success,
- * or -1 if Tor should die.
+ * On OPs, this only initializes the tls context.
*/
int
init_keys(void)
@@ -261,10 +260,10 @@ init_keys(void)
return -1;
set_identity_key(prkey);
/* Create a TLS context; default the client nickname to "client". */
- if (tor_tls_context_new(get_identity_key(),
+ if (tor_tls_context_new(get_identity_key(), 1,
options->Nickname ? options->Nickname : "client",
MAX_SSL_KEY_LIFETIME) < 0) {
- log_err(LD_GENERAL,"Error creating TLS context for Tor client.");
+ log_err(LD_GENERAL,"Error creating TLS context for OP.");
return -1;
}
return 0;
@@ -303,7 +302,7 @@ init_keys(void)
}
/* 3. Initialize link key and TLS context. */
- if (tor_tls_context_new(get_identity_key(), options->Nickname,
+ if (tor_tls_context_new(get_identity_key(), 1, options->Nickname,
MAX_SSL_KEY_LIFETIME) < 0) {
log_err(LD_GENERAL,"Error initializing TLS context");
return -1;
@@ -311,6 +310,10 @@ init_keys(void)
/* 4. Build our router descriptor. */
/* Must be called after keys are initialized. */
mydesc = router_get_my_descriptor();
+ if (!mydesc) {
+ log_err(LD_GENERAL,"Error initializing descriptor.");
+ return -1;
+ }
if (authdir_mode(options)) {
const char *m;
/* We need to add our own fingerprint so it gets recognized. */
@@ -318,10 +321,6 @@ init_keys(void)
log_err(LD_GENERAL,"Error adding own fingerprint to approved set");
return -1;
}
- if (!mydesc) {
- log_err(LD_GENERAL,"Error initializing descriptor.");
- return -1;
- }
if (dirserv_add_descriptor(mydesc, &m) < 0) {
log_err(LD_GENERAL,"Unable to add own descriptor to directory: %s",
m?m:"<unknown error>");
@@ -329,6 +328,13 @@ init_keys(void)
}
}
+#if 0
+ tor_snprintf(keydir,sizeof(keydir),"%s/router.desc", datadir);
+ log_info(LD_GENERAL,"Dumping descriptor to \"%s\"...",keydir);
+ if (write_str_to_file(keydir, mydesc,0)) {
+ return -1;
+ }
+#endif
/* 5. Dump fingerprint to 'fingerprint' */
tor_snprintf(keydir,sizeof(keydir),"%s/fingerprint", datadir);
log_info(LD_GENERAL,"Dumping fingerprint to \"%s\"...",keydir);
@@ -353,7 +359,9 @@ init_keys(void)
if (!authdir_mode(options))
return 0;
/* 6. [authdirserver only] load approved-routers file */
- if (dirserv_load_fingerprint_file() < 0) {
+ tor_snprintf(keydir,sizeof(keydir),"%s/approved-routers", datadir);
+ log_info(LD_DIRSERV,"Loading approved fingerprints from \"%s\"...",keydir);
+ if (dirserv_parse_fingerprint_file(keydir) < 0) {
log_err(LD_GENERAL,"Error loading fingerprints");
return -1;
}
@@ -364,7 +372,8 @@ init_keys(void)
(uint16_t)options->DirPort, digest,
options->V1AuthoritativeDir);
}
- return 0; /* success */
+ /* success */
+ return 0;
}
/* Keep track of whether we should upload our server descriptor,
@@ -376,12 +385,13 @@ static int can_reach_or_port = 0;
/** Whether we can reach our DirPort from the outside. */
static int can_reach_dir_port = 0;
-/** Return 1 if ORPort is known reachable; else return 0. */
+/** Return 1 if or port is known reachable; else return 0. */
int
check_whether_orport_reachable(void)
{
or_options_t *options = get_options();
- return options->AssumeReachable ||
+ return clique_mode(options) ||
+ options->AssumeReachable ||
can_reach_or_port;
}
@@ -436,23 +446,22 @@ decide_to_advertise_dirport(or_options_t *options, routerinfo_t *router)
* Success is noticed in connection_dir_client_reached_eof().
*/
void
-consider_testing_reachability(int test_or, int test_dir)
+consider_testing_reachability(void)
{
routerinfo_t *me = router_get_my_routerinfo();
- int orport_reachable = check_whether_orport_reachable();
- if (!me)
+ if (!me) {
+ log_warn(LD_BUG,
+ "Bug: router_get_my_routerinfo() did not find my routerinfo?");
return;
+ }
- if (test_or && (!orport_reachable || !circuit_enough_testing_circs())) {
- log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.",
- !orport_reachable ? "reachability" : "bandwidth",
- me->address, me->or_port);
+ if (!check_whether_orport_reachable()) {
log_info(LD_CIRC, "Testing reachability of my ORPort: %s:%d.",
me->address, me->or_port);
circuit_launch_by_router(CIRCUIT_PURPOSE_TESTING, me, 0, 1, 1);
}
- if (test_dir && !check_whether_dirport_reachable()) {
+ if (!check_whether_dirport_reachable()) {
/* ask myself, via tor, for my server descriptor. */
directory_initiate_command_router(me, DIR_PURPOSE_FETCH_SERVERDESC,
1, "authority", NULL, 0);
@@ -464,12 +473,14 @@ void
router_orport_found_reachable(void)
{
if (!can_reach_or_port) {
- log_notice(LD_OR,"Self-testing indicates your ORPort is reachable from "
- "the outside. Excellent.%s",
- get_options()->PublishServerDescriptor ?
- " Publishing server descriptor." : "");
+ if (!clique_mode(get_options()))
+ log_notice(LD_OR,"Self-testing indicates your ORPort is reachable from "
+ "the outside. Excellent.%s",
+ get_options()->PublishServerDescriptor ?
+ " Publishing server descriptor." : "");
can_reach_or_port = 1;
mark_my_descriptor_dirty();
+ consider_publishable_server(time(NULL), 1);
}
}
@@ -481,53 +492,19 @@ router_dirport_found_reachable(void)
log_notice(LD_DIRSERV,"Self-testing indicates your DirPort is reachable "
"from the outside. Excellent.");
can_reach_dir_port = 1;
- mark_my_descriptor_dirty();
}
}
-#define UPTIME_CUTOFF_FOR_NEW_BANDWIDTH_TEST (6*60*60)
-
/** Our router has just moved to a new IP. Reset stats. */
void
server_has_changed_ip(void)
{
- if (stats_n_seconds_working > UPTIME_CUTOFF_FOR_NEW_BANDWIDTH_TEST)
- reset_bandwidth_test();
stats_n_seconds_working = 0;
can_reach_or_port = 0;
can_reach_dir_port = 0;
mark_my_descriptor_dirty();
}
-/** We have enough testing circuit open. Send a bunch of "drop"
- * cells down each of them, to exercise our bandwidth. */
-void
-router_perform_bandwidth_test(int num_circs, time_t now)
-{
- int num_cells = get_options()->BandwidthRate * 10 / CELL_NETWORK_SIZE;
- int max_cells = num_cells < CIRCWINDOW_START ?
- num_cells : CIRCWINDOW_START;
- int cells_per_circuit = max_cells / num_circs;
- origin_circuit_t *circ = NULL;
-
- log_notice(LD_OR,"Performing bandwidth self-test.");
- while ((circ = circuit_get_next_by_pk_and_purpose(circ, NULL,
- CIRCUIT_PURPOSE_TESTING))) {
- /* dump cells_per_circuit drop cells onto this circ */
- int i = cells_per_circuit;
- if (circ->_base.state != CIRCUIT_STATE_OPEN)
- continue;
- circ->_base.timestamp_dirty = now;
- while (i-- > 0) {
- if (connection_edge_send_command(NULL, TO_CIRCUIT(circ),
- RELAY_COMMAND_DROP,
- NULL, 0, circ->cpath->prev)<0) {
- return; /* stop if error */
- }
- }
- }
-}
-
/** Return true iff we believe ourselves to be an authoritative
* directory server.
*/
@@ -592,7 +569,7 @@ proxy_mode(or_options_t *options)
* - We have the AuthoritativeDirectory option set.
*/
static int
-decide_if_publishable_server(void)
+decide_if_publishable_server(time_t now)
{
or_options_t *options = get_options();
@@ -616,7 +593,7 @@ decide_if_publishable_server(void)
* determine what IP address and ports to test.
*/
void
-consider_publishable_server(int force)
+consider_publishable_server(time_t now, int force)
{
int rebuilt;
@@ -624,7 +601,7 @@ consider_publishable_server(int force)
return;
rebuilt = router_rebuild_descriptor(0);
- if (decide_if_publishable_server()) {
+ if (decide_if_publishable_server(now)) {
set_server_advertised(1);
if (rebuilt == 0)
router_upload_dir_desc_to_dirservers(force);
@@ -634,9 +611,58 @@ consider_publishable_server(int force)
}
/*
- * Clique maintenance -- to be phased out.
+ * Clique maintenance
*/
+/** OR only: if in clique mode, try to open connections to all of the
+ * other ORs we know about. Otherwise, open connections to those we
+ * think are in clique mode.
+ *
+ * If <b>testing_reachability</b> is 0, try to open the connections
+ * but only if we don't already have one. If it's 1, then we're an
+ * auth dir server, and we should try to connect regardless of
+ * whether we already have a connection open -- but if <b>try_all</b>
+ * is 0, we want to load balance such that we only try a few connections
+ * per call.
+ *
+ * The load balancing is such that if we get called once every ten
+ * seconds, we will cycle through all the tests in 1280 seconds (a
+ * bit over 20 minutes).
+ */
+void
+router_retry_connections(int testing_reachability, int try_all)
+{
+ time_t now = time(NULL);
+ routerlist_t *rl = router_get_routerlist();
+ or_options_t *options = get_options();
+ static char ctr = 0;
+
+ tor_assert(server_mode(options));
+
+ SMARTLIST_FOREACH(rl->routers, routerinfo_t *, router, {
+ const char *id_digest = router->cache_info.identity_digest;
+ if (router_is_me(router))
+ continue;
+ if (!clique_mode(options) && !router_is_clique_mode(router))
+ continue;
+ if ((testing_reachability &&
+ (try_all || (((uint8_t)id_digest[0]) % 128) == ctr)) ||
+ (!testing_reachability &&
+ !connection_or_get_by_identity_digest(id_digest))) {
+ log_debug(LD_OR,"%sconnecting to %s at %s:%u.",
+ clique_mode(options) ? "(forced) " : "",
+ router->nickname, router->address, router->or_port);
+ /* Remember when we started trying to determine reachability */
+ if (!router->testing_since)
+ router->testing_since = now;
+ connection_or_connect(router->addr, router->or_port,
+ id_digest);
+ }
+ });
+ if (testing_reachability && !try_all) /* increment ctr */
+ ctr = (ctr + 1) % 128;
+}
+
/** Return true iff this OR should try to keep connections open to all
* other ORs. */
int
@@ -670,7 +696,7 @@ router_upload_dir_desc_to_dirservers(int force)
s = router_get_my_descriptor();
if (!s) {
- log_info(LD_GENERAL, "No descriptor; skipping upload");
+ log_warn(LD_GENERAL, "No descriptor; skipping upload");
return;
}
if (!get_options()->PublishServerDescriptor)
@@ -685,16 +711,16 @@ router_upload_dir_desc_to_dirservers(int force)
* conn. Return 0 if we accept; non-0 if we reject.
*/
int
-router_compare_to_my_exit_policy(edge_connection_t *conn)
+router_compare_to_my_exit_policy(connection_t *conn)
{
tor_assert(desc_routerinfo);
/* make sure it's resolved to something. this way we can't get a
'maybe' below. */
- if (!conn->_base.addr)
+ if (!conn->addr)
return -1;
- return compare_addr_to_addr_policy(conn->_base.addr, conn->_base.port,
+ return compare_addr_to_addr_policy(conn->addr, conn->port,
desc_routerinfo->exit_policy) != ADDR_POLICY_ACCEPTED;
}
@@ -751,10 +777,7 @@ router_get_my_descriptor(void)
const char *body;
if (!router_get_my_routerinfo())
return NULL;
- /* Make sure this is nul-terminated. */
- tor_assert(desc_routerinfo->cache_info.saved_location == SAVED_NOWHERE);
body = signed_descriptor_get_body(&desc_routerinfo->cache_info);
- tor_assert(!body[desc_routerinfo->cache_info.signed_descriptor_len]);
log_debug(LD_GENERAL,"my desc is '%s'", body);
return body;
}
@@ -762,29 +785,9 @@ router_get_my_descriptor(void)
/*DOCDOC*/
static smartlist_t *warned_nonexistent_family = NULL;
-static int router_guess_address_from_dir_headers(uint32_t *guess);
-
-/** Return our current best guess at our address, either because
- * it's configured in torrc, or because we've learned it from
- * dirserver headers. */
-int
-router_pick_published_address(or_options_t *options, uint32_t *addr)
-{
- if (resolve_my_address(LOG_INFO, options, addr, NULL) < 0) {
- log_info(LD_CONFIG, "Could not determine our address locally. "
- "Checking if directory headers provide any hints.");
- if (router_guess_address_from_dir_headers(addr) < 0) {
- log_info(LD_CONFIG, "No hints from directory headers either. "
- "Will try again later.");
- return -1;
- }
- }
- return 0;
-}
-
/** If <b>force</b> is true, or our descriptor is out-of-date, rebuild
* a fresh routerinfo and signed server descriptor for this OR.
- * Return 0 on success, -1 on temporary error.
+ * Return 0 on success, -1 on error.
*/
int
router_rebuild_descriptor(int force)
@@ -798,16 +801,12 @@ router_rebuild_descriptor(int force)
if (desc_clean_since && !force)
return 0;
- if (router_pick_published_address(options, &addr) < 0) {
- /* Stop trying to rebuild our descriptor every second. We'll
- * learn that it's time to try again when server_has_changed_ip()
- * marks it dirty. */
- desc_clean_since = time(NULL);
+ if (resolve_my_address(options, &addr, NULL) < 0) {
+ log_warn(LD_CONFIG,"options->Address didn't resolve into an IP.");
return -1;
}
ri = tor_malloc_zero(sizeof(routerinfo_t));
- ri->routerlist_index = -1;
ri->address = tor_dup_addr(addr);
ri->nickname = tor_strdup(options->Nickname);
ri->addr = addr;
@@ -878,11 +877,6 @@ router_rebuild_descriptor(int force)
}
tor_free(name);
});
-
- /* remove duplicates from the list */
- smartlist_sort_strings(ri->declared_family);
- smartlist_uniq_strings(ri->declared_family);
-
smartlist_free(family);
}
ri->cache_info.signed_descriptor_body = tor_malloc(8192);
@@ -949,31 +943,6 @@ check_descriptor_bandwidth_changed(time_t now)
}
}
-static void
-log_addr_has_changed(int severity, uint32_t prev, uint32_t cur)
-{
- char addrbuf_prev[INET_NTOA_BUF_LEN];
- char addrbuf_cur[INET_NTOA_BUF_LEN];
- struct in_addr in_prev;
- struct in_addr in_cur;
-
- in_prev.s_addr = htonl(prev);
- tor_inet_ntoa(&in_prev, addrbuf_prev, sizeof(addrbuf_prev));
-
- in_cur.s_addr = htonl(cur);
- tor_inet_ntoa(&in_cur, addrbuf_cur, sizeof(addrbuf_cur));
-
- if (prev)
- log_fn(severity, LD_GENERAL,
- "Our IP Address has changed from %s to %s; "
- "rebuilding descriptor.",
- addrbuf_prev, addrbuf_cur);
- else
- log_notice(LD_GENERAL,
- "Guessed our IP address as %s.",
- addrbuf_cur);
-}
-
/** Check whether our own address as defined by the Address configuration
* has changed. This is for routers that get their address from a service
* like dyndns. If our address has changed, mark our descriptor dirty. */
@@ -982,72 +951,34 @@ check_descriptor_ipaddress_changed(time_t now)
{
uint32_t prev, cur;
or_options_t *options = get_options();
- (void) now;
if (!desc_routerinfo)
return;
prev = desc_routerinfo->addr;
- if (resolve_my_address(LOG_INFO, options, &cur, NULL) < 0) {
- log_info(LD_CONFIG,"options->Address didn't resolve into an IP.");
+ if (resolve_my_address(options, &cur, NULL) < 0) {
+ log_warn(LD_CONFIG,"options->Address didn't resolve into an IP.");
return;
}
if (prev != cur) {
- log_addr_has_changed(LOG_INFO, prev, cur);
- mark_my_descriptor_dirty();
- /* the above call is probably redundant, since resolve_my_address()
- * probably already noticed and marked it dirty. */
- }
-}
-
-static uint32_t last_guessed_ip = 0;
-
-/** A directory authority told us our IP address is <b>suggestion</b>.
- * If this address is different from the one we think we are now, and
- * if our computer doesn't actually know its IP address, then switch. */
-void
-router_new_address_suggestion(const char *suggestion)
-{
- uint32_t addr, cur;
- struct in_addr in;
- or_options_t *options = get_options();
+ char addrbuf_prev[INET_NTOA_BUF_LEN];
+ char addrbuf_cur[INET_NTOA_BUF_LEN];
+ struct in_addr in_prev;
+ struct in_addr in_cur;
- /* first, learn what the IP address actually is */
- if (!tor_inet_aton(suggestion, &in)) {
- log_debug(LD_DIR, "Malformed X-Your-Address-Is header. Ignoring.");
- return;
- }
- addr = ntohl(in.s_addr);
-
- log_debug(LD_DIR, "Got X-Your-Address-Is: %s.", suggestion);
-
- if (!server_mode(options) ||
- resolve_my_address(LOG_INFO, options, &cur, NULL) >= 0) {
- /* We're all set -- we already know our address. Great. */
- last_guessed_ip = cur; /* store it in case we need it later */
- return;
- }
+ in_prev.s_addr = htonl(prev);
+ tor_inet_ntoa(&in_prev, addrbuf_prev, sizeof(addrbuf_prev));
- if (last_guessed_ip != addr) {
- log_addr_has_changed(LOG_NOTICE, last_guessed_ip, addr);
- server_has_changed_ip();
- last_guessed_ip = addr; /* router_rebuild_descriptor() will fetch it */
- }
-}
+ in_cur.s_addr = htonl(cur);
+ tor_inet_ntoa(&in_cur, addrbuf_cur, sizeof(addrbuf_cur));
-/** We failed to resolve our address locally, but we'd like to build
- * a descriptor and publish / test reachability. If we have a guess
- * about our address based on directory headers, answer it and return
- * 0; else return -1. */
-static int
-router_guess_address_from_dir_headers(uint32_t *guess)
-{
- if (last_guessed_ip) {
- *guess = last_guessed_ip;
- return 0;
+ log_info(LD_GENERAL,
+ "Our IP Address has changed from %s to %s; "
+ "rebuilding descriptor.",
+ addrbuf_prev, addrbuf_cur);
+ mark_my_descriptor_dirty();
}
- return -1;
}
/** Set <b>platform</b> (max length <b>len</b>) to a NUL-terminated short
@@ -1151,13 +1082,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
"uptime %ld\n"
"bandwidth %d %d %d\n"
"onion-key\n%s"
- "signing-key\n%s"
-#ifdef USE_EVENTDNS
- "opt eventdns 1\n"
-#else
- "opt eventdns 0\n"
-#endif
- "%s%s%s",
+ "signing-key\n%s%s%s%s",
router->nickname,
router->address,
router->or_port,
@@ -1236,7 +1161,6 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
written += result;
}
} /* end for */
-
if (written+256 > maxlen) /* Not enough room for signature. */
return -1;
@@ -1262,7 +1186,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
#ifdef DEBUG_ROUTER_DUMP_ROUTER_TO_STRING
cp = s_tmp = s_dup = tor_strdup(s);
- ri_tmp = router_parse_entry_from_string(cp, NULL, 1);
+ ri_tmp = router_parse_entry_from_string(cp, NULL);
if (!ri_tmp) {
log_err(LD_BUG,
"We just generated a router descriptor we can't parse: <<%s>>",
@@ -1305,10 +1229,10 @@ is_legal_hexdigest(const char *s)
{
size_t len;
tor_assert(s);
- if (s[0] == '$') s++;
len = strlen(s);
- return (len == HEX_DIGEST_LEN &&
- strspn(s,HEX_CHARACTERS)==len);
+ return (len == HEX_DIGEST_LEN+1 &&
+ s[0] == '$' &&
+ strspn(s+1,HEX_CHARACTERS)==len-1);
}
/** Forget that we have issued any router-related warnings, so that we'll
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 71cc367af1..a68ed86e6c 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -55,13 +55,9 @@ static routerlist_t *routerlist = NULL;
* about. This list is kept sorted by published_on. */
static smartlist_t *networkstatus_list = NULL;
-/** Global list of local_routerstatus_t for each router, known or unknown.
- * Kept sorted by digest. */
+/** Global list of local_routerstatus_t for each router, known or unknown. */
static smartlist_t *routerstatus_list = NULL;
-/** Map from lowercase nickname to digest of named server, if any. */
-static strmap_t *named_server_map = NULL;
-
/** True iff any member of networkstatus_list has changed since the last time
* we called routerstatus_list_update_from_networkstatus(). */
static int networkstatus_list_has_changed = 0;
@@ -187,33 +183,17 @@ router_append_to_journal(signed_descriptor_t *desc)
tor_assert(len == strlen(body));
- if (append_bytes_to_file(fname, body, len, 1)) {
+ if (append_bytes_to_file(fname, body, len, 0)) {
log_warn(LD_FS, "Unable to store router descriptor");
tor_free(fname);
return -1;
}
- desc->saved_location = SAVED_IN_JOURNAL;
- desc->saved_offset = router_journal_len;
tor_free(fname);
router_journal_len += len;
return 0;
}
-static int
-_compare_old_routers_by_age(const void **_a, const void **_b)
-{
- const signed_descriptor_t *r1 = *_a, *r2 = *_b;
- return r1->published_on - r2->published_on;
-}
-
-static int
-_compare_routers_by_age(const void **_a, const void **_b)
-{
- const routerinfo_t *r1 = *_a, *r2 = *_b;
- return r1->cache_info.published_on - r2->cache_info.published_on;
-}
-
/** If the journal is too long, or if <b>force</b> is true, then atomically
* replace the router store with the routers currently in our routerlist, and
* clear the journal. Return 0 on success, -1 on failure.
@@ -227,8 +207,6 @@ router_rebuild_store(int force)
smartlist_t *chunk_list = NULL;
char *fname = NULL;
int r = -1, i;
- off_t offset = 0;
- smartlist_t *old_routers, *routers;
if (!force && !router_should_rebuild_store())
return 0;
@@ -238,28 +216,15 @@ router_rebuild_store(int force)
/* Don't save deadweight. */
routerlist_remove_old_routers();
- log_info(LD_DIR, "Rebuilding router descriptor cache");
-
options = get_options();
fname_len = strlen(options->DataDirectory)+32;
fname = tor_malloc(fname_len);
tor_snprintf(fname, fname_len, "%s/cached-routers", options->DataDirectory);
chunk_list = smartlist_create();
- old_routers = smartlist_create();
- smartlist_add_all(old_routers, routerlist->old_routers);
- smartlist_sort(old_routers, _compare_old_routers_by_age);
- routers = smartlist_create();
- smartlist_add_all(routers, routerlist->routers);
- smartlist_sort(routers, _compare_routers_by_age);
for (i = 0; i < 2; ++i) {
- smartlist_t *lst = smartlist_create();
- /* We sort the routers by age to enhance locality on disk. */
- if (i==0)
- lst = old_routers;
- else
- lst = routers;
- /* Now, add the appropriate members to chunk_list */
+ smartlist_t *lst = (i == 0) ? routerlist->old_routers :
+ routerlist->routers;
SMARTLIST_FOREACH(lst, void *, ptr,
{
signed_descriptor_t *sd = (i==0) ?
@@ -268,7 +233,6 @@ router_rebuild_store(int force)
const char *body = signed_descriptor_get_body(sd);
if (!body) {
log_warn(LD_BUG, "Bug! No descriptor available for router.");
- smartlist_free(lst);
goto done;
}
c = tor_malloc(sizeof(sized_chunk_t));
@@ -277,42 +241,15 @@ router_rebuild_store(int force)
smartlist_add(chunk_list, c);
});
}
- if (write_chunks_to_file(fname, chunk_list, 1)<0) {
+ if (write_chunks_to_file(fname, chunk_list, 0)<0) {
log_warn(LD_FS, "Error writing router store to disk.");
goto done;
}
- /* Our mmap is now invalid. */
- if (routerlist->mmap_descriptors) {
- tor_munmap_file(routerlist->mmap_descriptors);
- routerlist->mmap_descriptors = tor_mmap_file(fname);
- if (! routerlist->mmap_descriptors)
- log_warn(LD_FS, "Unable to mmap new descriptor file at '%s'.",fname);
- }
-
- offset = 0;
- for (i = 0; i < 2; ++i) {
- smartlist_t *lst = (i == 0) ? old_routers : routers;
- SMARTLIST_FOREACH(lst, void *, ptr,
- {
- signed_descriptor_t *sd = (i==0) ?
- ((signed_descriptor_t*)ptr): &((routerinfo_t*)ptr)->cache_info;
-
- sd->saved_location = SAVED_IN_CACHE;
- if (routerlist->mmap_descriptors) {
- tor_free(sd->signed_descriptor_body); // sets it to null
- sd->saved_offset = offset;
- }
- offset += sd->signed_descriptor_len;
- signed_descriptor_get_body(sd);
- });
- }
- smartlist_free(old_routers);
- smartlist_free(routers);
tor_snprintf(fname, fname_len, "%s/cached-routers.new",
options->DataDirectory);
- write_str_to_file(fname, "", 1);
+ write_str_to_file(fname, "", 0);
r = 0;
router_store_len = len;
@@ -335,36 +272,31 @@ router_reload_router_list(void)
{
or_options_t *options = get_options();
size_t fname_len = strlen(options->DataDirectory)+32;
- char *fname = tor_malloc(fname_len), *contents;
+ char *fname = tor_malloc(fname_len);
struct stat st;
+ int j;
if (!routerlist)
router_get_routerlist(); /* mallocs and inits it in place */
router_journal_len = router_store_len = 0;
- tor_snprintf(fname, fname_len, "%s/cached-routers", options->DataDirectory);
-
- if (routerlist->mmap_descriptors) /* get rid of it first */
- tor_munmap_file(routerlist->mmap_descriptors);
-
- routerlist->mmap_descriptors = tor_mmap_file(fname);
- if (routerlist->mmap_descriptors) {
- router_store_len = routerlist->mmap_descriptors->size;
- router_load_routers_from_string(routerlist->mmap_descriptors->data,
- SAVED_IN_CACHE, NULL);
- }
-
- tor_snprintf(fname, fname_len, "%s/cached-routers.new",
- options->DataDirectory);
- contents = read_file_to_str(fname, 1);
- if (contents) {
- stat(fname, &st);
- router_load_routers_from_string(contents,
- SAVED_IN_JOURNAL, NULL);
- tor_free(contents);
+ for (j = 0; j < 2; ++j) {
+ char *contents;
+ tor_snprintf(fname, fname_len,
+ (j==0)?"%s/cached-routers":"%s/cached-routers.new",
+ options->DataDirectory);
+ contents = read_file_to_str(fname, 0);
+ if (contents) {
+ stat(fname, &st);
+ if (j==0)
+ router_store_len = st.st_size;
+ else
+ router_journal_len = st.st_size;
+ router_load_routers_from_string(contents, 1, NULL);
+ tor_free(contents);
+ }
}
-
tor_free(fname);
if (router_journal_len) {
@@ -606,21 +538,6 @@ router_reset_status_download_failures(void)
mark_all_trusteddirservers_up();
}
-/** Look through the routerlist and identify routers that
- * advertise the same /16 network address as <b>router</b>.
- * Add each of them to <b>sl</b>.
- */
-static void
-routerlist_add_network_family(smartlist_t *sl, routerinfo_t *router)
-{
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, r,
- {
- if (router != r &&
- (router->addr & 0xffff0000) == (r->addr & 0xffff0000))
- smartlist_add(sl, r);
- });
-}
-
/** Add all the family of <b>router</b> to the smartlist <b>sl</b>.
* This is used to make sure we don't pick siblings in a single path.
*/
@@ -630,10 +547,6 @@ routerlist_add_family(smartlist_t *sl, routerinfo_t *router)
routerinfo_t *r;
config_line_t *cl;
- /* First, add any routers with similar network addresses.
- * XXX It's possible this will be really expensive; we'll see. */
- routerlist_add_network_family(sl, router);
-
if (!router->declared_family)
return;
@@ -1018,7 +931,6 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
char digest[DIGEST_LEN];
routerinfo_t *best_match=NULL;
int n_matches = 0;
- char *named_digest = NULL;
tor_assert(nickname);
if (!routerlist)
@@ -1032,17 +944,16 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
maybedigest = (strlen(nickname) == HEX_DIGEST_LEN) &&
(base16_decode(digest,DIGEST_LEN,nickname,HEX_DIGEST_LEN) == 0);
- if (named_server_map &&
- (named_digest = strmap_get_lc(named_server_map, nickname))) {
- return digestmap_get(routerlist->identity_map, named_digest);
- }
-
SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
{
if (!strcasecmp(router->nickname, nickname)) {
- ++n_matches;
- if (n_matches <= 1 || router->is_running)
- best_match = router;
+ if (router->is_named)
+ return router;
+ else {
+ ++n_matches;
+ if (n_matches <= 1 || router->is_running)
+ best_match = router;
+ }
} else if (maybedigest &&
!memcmp(digest, router->cache_info.identity_digest, DIGEST_LEN)
) {
@@ -1080,7 +991,7 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
char *alternatives = smartlist_join_strings(fps, "; ",0,NULL);
log_warn(LD_CONFIG,
"There are multiple matches for the nickname \"%s\","
- " but none is listed as named by the directory authorities. "
+ " but none is listed as named by the directory authories. "
"Choosing one arbitrarily. If you meant one in particular, "
"you should say %s.", nickname, alternatives);
tor_free(alternatives);
@@ -1095,7 +1006,7 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
base16_encode(fp, sizeof(fp),
best_match->cache_info.identity_digest, DIGEST_LEN);
log_warn(LD_CONFIG, "You specified a server \"%s\" by name, but the "
- "directory authorities do not have a binding for this nickname. "
+ "directory authorities do not have a listing for this name. "
"To make sure you get the same server in the future, refer to "
"it by key, as \"$%s\".", nickname, fp);
rs->name_lookup_warned = 1;
@@ -1179,28 +1090,10 @@ router_get_by_descriptor_digest(const char *digest)
return digestmap_get(routerlist->desc_digest_map, digest);
}
-/* DOCDOC Not always nul-terminated. */
const char *
signed_descriptor_get_body(signed_descriptor_t *desc)
{
- const char *r;
- size_t len = desc->signed_descriptor_len;
- tor_assert(len > 32);
- if (desc->saved_location == SAVED_IN_CACHE && routerlist &&
- routerlist->mmap_descriptors) {
- tor_assert(desc->saved_offset + len <= routerlist->mmap_descriptors->size);
- r = routerlist->mmap_descriptors->data + desc->saved_offset;
- } else {
- r = desc->signed_descriptor_body;
- }
- tor_assert(r);
- tor_assert(!memcmp("router ", r, 7));
-#if 0
- tor_assert(!memcmp("\n-----END SIGNATURE-----\n",
- r + len - 25, 25));
-#endif
-
- return r;
+ return desc->signed_descriptor_body;
}
/** Return the current list of all known routers. */
@@ -1274,10 +1167,7 @@ routerlist_free(routerlist_t *rl)
signed_descriptor_free(sd));
smartlist_free(rl->routers);
smartlist_free(rl->old_routers);
- if (routerlist->mmap_descriptors)
- tor_munmap_file(routerlist->mmap_descriptors);
tor_free(rl);
-
router_dir_info_changed();
}
@@ -1349,7 +1239,6 @@ routerlist_insert(routerlist_t *rl, routerinfo_t *ri)
digestmap_set(rl->desc_digest_map, ri->cache_info.signed_descriptor_digest,
&(ri->cache_info));
smartlist_add(rl->routers, ri);
- ri->routerlist_index = smartlist_len(rl->routers) - 1;
router_dir_info_changed();
// routerlist_assert_ok(rl);
}
@@ -1363,7 +1252,6 @@ routerlist_insert_old(routerlist_t *rl, routerinfo_t *ri)
signed_descriptor_t *sd = signed_descriptor_from_routerinfo(ri);
digestmap_set(rl->desc_digest_map, sd->signed_descriptor_digest, sd);
smartlist_add(rl->old_routers, sd);
- ri->routerlist_index = -1;
} else {
routerinfo_free(ri);
}
@@ -1382,13 +1270,7 @@ routerlist_remove(routerlist_t *rl, routerinfo_t *ri, int idx, int make_old)
idx = _routerlist_find_elt(rl->routers, ri, idx);
if (idx < 0)
return;
- ri->routerlist_index = -1;
smartlist_del(rl->routers, idx);
- if (idx < smartlist_len(rl->routers)) {
- routerinfo_t *r = smartlist_get(rl->routers, idx);
- r->routerlist_index = idx;
- }
-
ri_tmp = digestmap_remove(rl->identity_map, ri->cache_info.identity_digest);
router_dir_info_changed();
tor_assert(ri_tmp == ri);
@@ -1437,8 +1319,6 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old,
router_dir_info_changed();
if (idx >= 0) {
smartlist_set(rl->routers, idx, ri_new);
- ri_old->routerlist_index = -1;
- ri_new->routerlist_index = idx;
} else {
log_warn(LD_BUG, "Appending entry from routerlist_replace.");
routerlist_insert(rl, ri_new);
@@ -1622,10 +1502,10 @@ int
router_add_to_routerlist(routerinfo_t *router, const char **msg,
int from_cache, int from_fetch)
{
+ int i;
const char *id_digest;
int authdir = get_options()->AuthoritativeDir;
int authdir_believes_valid = 0;
- routerinfo_t *old_router;
tor_assert(msg);
@@ -1681,91 +1561,68 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
rs->need_to_mirror = 0;
});
- /* If we have a router with the same identity key, choose the newer one. */
- old_router = digestmap_get(routerlist->identity_map,
- router->cache_info.identity_digest);
- if (old_router) {
- int pos = old_router->routerlist_index;
- tor_assert(smartlist_get(routerlist->routers, pos) == old_router);
-
- if (router->cache_info.published_on <=
- old_router->cache_info.published_on) {
- /* Same key, but old */
- log_debug(LD_DIR, "Skipping not-new descriptor for router '%s'",
- router->nickname);
- /* Only journal this desc if we'll be serving it. */
- if (!from_cache && get_options()->DirPort)
- router_append_to_journal(&router->cache_info);
- routerlist_insert_old(routerlist, router);
- *msg = "Router descriptor was not new.";
- return -1;
- } else {
- /* Same key, new. */
- int unreachable = 0;
- log_debug(LD_DIR, "Replacing entry for router '%s/%s' [%s]",
- router->nickname, old_router->nickname,
- hex_str(id_digest,DIGEST_LEN));
- if (router->addr == old_router->addr &&
- router->or_port == old_router->or_port) {
- /* these carry over when the address and orport are unchanged.*/
- router->last_reachable = old_router->last_reachable;
- router->testing_since = old_router->testing_since;
- router->num_unreachable_notifications =
- old_router->num_unreachable_notifications;
- }
- if (authdir && !from_cache && !from_fetch &&
- router_have_minimum_dir_info() &&
- dirserv_thinks_router_is_blatantly_unreachable(router,
- time(NULL))) {
- if (router->num_unreachable_notifications >= 3) {
- unreachable = 1;
- log_notice(LD_DIR, "Notifying server '%s' that it's unreachable. "
- "(ContactInfo '%s', platform '%s').",
- router->nickname,
- router->contact_info ? router->contact_info : "",
- router->platform ? router->platform : "");
- } else {
- log_info(LD_DIR,"'%s' may be unreachable -- the %d previous "
- "descriptors were thought to be unreachable.",
- router->nickname, router->num_unreachable_notifications);
- router->num_unreachable_notifications++;
- }
- }
- routerlist_replace(routerlist, old_router, router, pos, 1);
- if (!from_cache) {
- router_append_to_journal(&router->cache_info);
- }
- directory_set_dirty();
- *msg = unreachable ? "Dirserver believes your ORPort is unreachable" :
- authdir_believes_valid ? "Valid server updated" :
- ("Invalid server updated. (This dirserver is marking your "
- "server as unapproved.)");
- return unreachable ? 1 : 0;
- }
- }
-
-#if 0
- /* XXXX This block is slow, and could be smarter. All it does is ensure
- * that if we have a named server called "Foo", we will never have another
- * server called "Foo." router_get_by_nickname() already knows to prefer
- * named routers, so the problem only arises when there is a named router
- * called 'foo', but we don't have it. If, instead, we kept a
- * name-to-identity-key mapping for each named router in the networkstatus
- * list, we could eliminate this block.
- *
- * Hm. perhaps we should; I don't see how this code is non-broken wrt named
- * routers. -NM
- */
-
- /* If the identity key has changed, and one of the
+ /* If we have a router with this name, and the identity key is the same,
+ * choose the newer one. If the identity key has changed, and one of the
* routers is named, drop the unnamed ones. (If more than one are named,
* drop the old ones.)
*/
for (i = 0; i < smartlist_len(routerlist->routers); ++i) {
routerinfo_t *old_router = smartlist_get(routerlist->routers, i);
- if (!memcmp(router->cache_info.identity_digest,
- old_router->cache_info.identity_digest, DIGEST_LEN)) {
-
+ if (!crypto_pk_cmp_keys(router->identity_pkey,old_router->identity_pkey)) {
+ if (router->cache_info.published_on <=
+ old_router->cache_info.published_on) {
+ /* Same key, but old */
+ log_debug(LD_DIR, "Skipping not-new descriptor for router '%s'",
+ router->nickname);
+ /* Only journal this desc if we'll be serving it. */
+ if (!from_cache && get_options()->DirPort)
+ router_append_to_journal(&router->cache_info);
+ routerlist_insert_old(routerlist, router);
+ *msg = "Router descriptor was not new.";
+ return -1;
+ } else {
+ /* Same key, new. */
+ int unreachable = 0;
+ log_debug(LD_DIR, "Replacing entry for router '%s/%s' [%s]",
+ router->nickname, old_router->nickname,
+ hex_str(id_digest,DIGEST_LEN));
+ if (router->addr == old_router->addr &&
+ router->or_port == old_router->or_port) {
+ /* these carry over when the address and orport are unchanged.*/
+ router->last_reachable = old_router->last_reachable;
+ router->testing_since = old_router->testing_since;
+ router->num_unreachable_notifications =
+ old_router->num_unreachable_notifications;
+ }
+ if (authdir && !from_cache && !from_fetch &&
+ router_have_minimum_dir_info() &&
+ dirserv_thinks_router_is_blatantly_unreachable(router,
+ time(NULL))) {
+ if (router->num_unreachable_notifications >= 3) {
+ unreachable = 1;
+ log_notice(LD_DIR, "Notifying server '%s' that it's unreachable. "
+ "(ContactInfo '%s', platform '%s').",
+ router->nickname,
+ router->contact_info ? router->contact_info : "",
+ router->platform ? router->platform : "");
+ } else {
+ log_info(LD_DIR,"'%s' may be unreachable -- the %d previous "
+ "descriptors were thought to be unreachable.",
+ router->nickname, router->num_unreachable_notifications);
+ router->num_unreachable_notifications++;
+ }
+ }
+ routerlist_replace(routerlist, old_router, router, i, 1);
+ if (!from_cache) {
+ router_append_to_journal(&router->cache_info);
+ }
+ directory_set_dirty();
+ *msg = unreachable ? "Dirserver believes your ORPort is unreachable" :
+ authdir_believes_valid ? "Valid server updated" :
+ ("Invalid server updated. (This dirserver is marking your "
+ "server as unapproved.)");
+ return unreachable ? 1 : 0;
+ }
} else if (!strcasecmp(router->nickname, old_router->nickname)) {
/* nicknames match, keys don't. */
if (router->is_named) {
@@ -1776,13 +1633,13 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
/* mark-for-close connections using the old key, so we can
* make new ones with the new key.
*/
- or_connection_t *conn;
+ connection_t *conn;
while ((conn = connection_or_get_by_identity_digest(
old_router->cache_info.identity_digest))) {
log_info(LD_DIR,"Closing conn to router '%s'; there is now a named "
"router with that name.",
old_router->nickname);
- connection_mark_for_close(TO_CONN(conn));
+ connection_mark_for_close(conn);
}
routerlist_remove(routerlist, old_router, i--, 0);
} else if (old_router->is_named) {
@@ -1796,8 +1653,6 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
}
}
}
-#endif
-
/* We haven't seen a router with this name before. Add it to the end of
* the list. */
routerlist_insert(routerlist, router);
@@ -1935,7 +1790,7 @@ routerlist_remove_old_routers(void)
retain = digestmap_new();
cutoff = now - OLD_ROUTER_DESC_MAX_AGE;
- if (options->DirPort) {
+ if (server_mode(options) && options->DirPort) {
SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
{
SMARTLIST_FOREACH(ns->entries, routerstatus_t *, rs,
@@ -2024,7 +1879,7 @@ router_load_single_router(const char *s, uint8_t purpose, const char **msg)
tor_assert(msg);
*msg = NULL;
- if (!(ri = router_parse_entry_from_string(s, NULL, 1))) {
+ if (!(ri = router_parse_entry_from_string(s, NULL))) {
log_warn(LD_DIR, "Error parsing router descriptor; dropping.");
*msg = "Couldn't parse router descriptor.";
return -1;
@@ -2064,18 +1919,16 @@ router_load_single_router(const char *s, uint8_t purpose, const char **msg)
* uppercased identity fingerprints. Do not update any router whose
* fingerprint is not on the list; after updating a router, remove its
* fingerprint from the list.
- * DOCDOC saved_location
*/
void
-router_load_routers_from_string(const char *s, saved_location_t saved_location,
+router_load_routers_from_string(const char *s, int from_cache,
smartlist_t *requested_fingerprints)
{
smartlist_t *routers = smartlist_create(), *changed = smartlist_create();
char fp[HEX_DIGEST_LEN+1];
const char *msg;
- int from_cache = (saved_location != SAVED_NOWHERE);
- router_parse_list_from_string(&s, routers, saved_location);
+ router_parse_list_from_string(&s, routers);
routers_update_status_from_networkstatus(routers, !from_cache);
@@ -2170,13 +2023,12 @@ add_networkstatus_to_cache(const char *s,
/** How far in the future do we allow a network-status to get before removing
* it? (seconds) */
#define NETWORKSTATUS_ALLOW_SKEW (24*60*60)
-
/** Given a string <b>s</b> containing a network status that we received at
* <b>arrived_at</b> from <b>source</b>, try to parse it, see if we want to
* store it, and put it into our cache as necessary.
*
* If <b>source</b> is NS_FROM_DIR or NS_FROM_CACHE, do not replace our
- * own networkstatus_t (if we're an authoritative directory server).
+ * own networkstatus_t (if we're a directory server).
*
* If <b>source</b> is NS_FROM_CACHE, do not write our networkstatus_t to the
* cache.
@@ -2241,8 +2093,7 @@ router_set_networkstatus(const char *s, time_t arrived_at,
if (!networkstatus_list)
networkstatus_list = smartlist_create();
- if ( (source == NS_FROM_DIR_BY_FP || source == NS_FROM_DIR_ALL) &&
- router_digest_is_me(ns->identity_digest)) {
+ if (source == NS_FROM_DIR && router_digest_is_me(ns->identity_digest)) {
/* Don't replace our own networkstatus when we get it from somebody else.*/
networkstatus_free(ns);
return 0;
@@ -2254,14 +2105,12 @@ router_set_networkstatus(const char *s, time_t arrived_at,
} else {
char *requested =
smartlist_join_strings(requested_fingerprints," ",0,NULL);
- if (source != NS_FROM_DIR_ALL) {
- log_warn(LD_DIR,
+ log_warn(LD_DIR,
"We received a network status with a fingerprint (%s) that we "
"never requested. (We asked for: %s.) Dropping.",
fp, requested);
- tor_free(requested);
- return 0;
- }
+ tor_free(requested);
+ return 0;
}
}
@@ -2270,9 +2119,6 @@ router_set_networkstatus(const char *s, time_t arrived_at,
/* We got a non-trusted networkstatus, and we're a directory cache.
* This means that we asked an authority, and it told us about another
* authority we didn't recognize. */
- log_info(LD_DIR,
- "We do not recognize authority (%s) but we are willing "
- "to cache it", fp);
add_networkstatus_to_cache(s, source, ns);
networkstatus_free(ns);
}
@@ -2335,8 +2181,7 @@ router_set_networkstatus(const char *s, time_t arrived_at,
log_info(LD_DIR, "Setting networkstatus %s %s (published %s)",
source == NS_FROM_CACHE?"cached from":
- ((source == NS_FROM_DIR_BY_FP || source == NS_FROM_DIR_ALL) ?
- "downloaded from":"generated for"),
+ (source==NS_FROM_DIR?"downloaded from":"generated for"),
trusted_dir->description, published);
networkstatus_list_has_changed = 1;
router_dir_info_changed();
@@ -2656,7 +2501,6 @@ update_networkstatus_client_downloads(time_t now)
resource = tor_malloc(resource_len);
memcpy(resource, "fp/", 3);
cp = resource+3;
- smartlist_sort_digests(missing);
needed = smartlist_len(missing);
SMARTLIST_FOREACH(missing, const char *, d,
{
@@ -2677,10 +2521,10 @@ void
update_networkstatus_downloads(time_t now)
{
or_options_t *options = get_options();
- if (options->DirPort)
- update_networkstatus_cache_downloads(now);
- else
- update_networkstatus_client_downloads(now);
+ if (server_mode(options) && options->DirPort)
+ update_networkstatus_cache_downloads(time(NULL));
+ else
+ update_networkstatus_client_downloads(time(NULL));
}
/** Return 1 if all running sufficiently-stable routers will reject
@@ -2728,7 +2572,7 @@ add_trusted_dir_server(const char *nickname, const char *address,
trusted_dir_servers = smartlist_create();
if (!address) { /* The address is us; we should guess. */
- if (resolve_my_address(LOG_WARN, get_options(), &a, &hostname) < 0) {
+ if (resolve_my_address(get_options(), &a, &hostname) < 0) {
log_warn(LD_CONFIG,
"Couldn't find a suitable address when adding ourself as a "
"trusted directory server.");
@@ -2837,7 +2681,6 @@ compute_recommended_versions(time_t now, int client)
smartlist_t *combined, *recommended;
int n_versioning;
char *result;
- (void) now; /* right now, we consider *all* ors. */
if (!networkstatus_list)
return tor_strdup("<none>");
@@ -2932,12 +2775,12 @@ routers_update_all_from_networkstatus(void)
++n_named;
});
- if (n_listing) {
- if (n_valid <= n_listing/2) {
+ if (n_recent && n_listing) {
+ if (n_valid <= n_recent/2) {
log_info(LD_GENERAL,
"%d/%d recent statements from directory authorities list us "
"as unapproved. Are you misconfigured?",
- n_listing-n_valid, n_listing);
+ n_recent-n_valid, n_recent);
have_warned_about_invalid_status = 1;
} else if (n_naming && !n_named) {
log_info(LD_GENERAL, "0/%d name-binding directory authorities "
@@ -3138,10 +2981,6 @@ routerstatus_list_update_from_networkstatus(time_t now)
* is a conflict on that nickname, map the lc nickname to conflict.
*/
name_map = strmap_new();
- /* Clear the global map... */
- if (named_server_map)
- strmap_free(named_server_map, _tor_free);
- named_server_map = strmap_new();
memset(conflict, 0xff, sizeof(conflict));
for (i = 0; i < n_statuses; ++i) {
if (!networkstatus[i]->binds_names)
@@ -3155,14 +2994,11 @@ routerstatus_list_update_from_networkstatus(time_t now)
warned = smartlist_string_isin(warned_conflicts, rs->nickname);
if (!other_digest) {
strmap_set_lc(name_map, rs->nickname, rs->identity_digest);
- strmap_set_lc(named_server_map, rs->nickname,
- tor_memdup(rs->identity_digest, DIGEST_LEN));
if (warned)
smartlist_string_remove(warned_conflicts, rs->nickname);
} else if (memcmp(other_digest, rs->identity_digest, DIGEST_LEN) &&
other_digest != conflict) {
if (!warned) {
- char *d;
int should_warn = options->DirPort && options->AuthoritativeDir;
char fp1[HEX_DIGEST_LEN+1];
char fp2[HEX_DIGEST_LEN+1];
@@ -3173,8 +3009,6 @@ routerstatus_list_update_from_networkstatus(time_t now)
"($%s vs $%s)",
rs->nickname, fp1, fp2);
strmap_set_lc(name_map, rs->nickname, conflict);
- d = strmap_remove_lc(named_server_map, rs->nickname);
- tor_free(d);
smartlist_add(warned_conflicts, tor_strdup(rs->nickname));
}
} else {
@@ -3337,7 +3171,6 @@ routerstatus_list_update_from_networkstatus(time_t now)
}
SMARTLIST_FOREACH(routerstatus_list, local_routerstatus_t *, rs,
local_routerstatus_free(rs));
-
smartlist_free(routerstatus_list);
routerstatus_list = result;
@@ -3418,10 +3251,9 @@ list_pending_descriptor_downloads(digestmap_t *result)
if (conn->type == CONN_TYPE_DIR &&
conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC &&
!conn->marked_for_close) {
- const char *resource = TO_DIR_CONN(conn)->requested_resource;
- if (!strcmpstart(resource, prefix))
- dir_split_resource_into_fingerprints(resource + p_len,
- tmp, NULL, 1, 0);
+ if (!strcmpstart(conn->requested_resource, prefix))
+ dir_split_resource_into_fingerprints(conn->requested_resource+p_len,
+ tmp, NULL, 1);
}
}
SMARTLIST_FOREACH(tmp, char *, d,
@@ -3485,18 +3317,18 @@ initiate_descriptor_downloads(routerstatus_t *source,
/** Return 0 if this routerstatus is obsolete, too new, isn't
* running, or otherwise not a descriptor that we would make any
* use of even if we had it. Else return 1. */
-static INLINE int
+static int
client_would_use_router(routerstatus_t *rs, time_t now, or_options_t *options)
{
+ if (rs->published_on + ROUTER_MAX_AGE < now) {
+ /* This one is too old to consider. */
+ return 0;
+ }
if (!rs->is_running && !options->FetchUselessDescriptors) {
/* If we had this router descriptor, we wouldn't even bother using it.
* But, if we want to have a complete list, fetch it anyway. */
return 0;
}
- if (rs->published_on + ROUTER_MAX_AGE < now) {
- /* This one is too old to consider. */
- return 0;
- }
if (rs->published_on + ESTIMATED_PROPAGATION_TIME > now) {
/* Most caches probably don't have this descriptor yet. */
return 0;
@@ -3528,15 +3360,15 @@ router_list_client_downloadable(void)
SMARTLIST_FOREACH(routerstatus_list, local_routerstatus_t *, rs,
{
routerinfo_t *ri;
- if (router_get_by_descriptor_digest(rs->status.descriptor_digest)) {
- /* We have the 'best' descriptor for this router. */
- ++n_uptodate;
- } else if (!client_would_use_router(&rs->status, now, options)) {
+ if (!client_would_use_router(&rs->status, now, options)) {
/* We wouldn't want this descriptor even if we got it. */
++n_wouldnt_use;
} else if (digestmap_get(downloading, rs->status.descriptor_digest)) {
/* We're downloading this one now. */
++n_in_progress;
+ } else if (router_get_by_descriptor_digest(rs->status.descriptor_digest)) {
+ /* We have the 'best' descriptor for this router. */
+ ++n_uptodate;
} else if ((ri = router_get_by_digest(rs->status.identity_digest)) &&
ri->cache_info.published_on > rs->status.published_on) {
/* Oddly, we have a descriptor more recent than the 'best' one, but it
@@ -3601,19 +3433,15 @@ update_router_descriptor_client_downloads(time_t now)
int should_delay, n_downloadable;
or_options_t *options = get_options();
- if (options->DirPort) {
+ if (server_mode(options) && options->DirPort) {
log_warn(LD_BUG,
- "Called router_descriptor_client_downloads() on a dir mirror?");
+ "Called router_descriptor_client_downloads() on a mirror?");
}
- if (rep_hist_circbuilding_dormant(now)) {
- log_info(LD_CIRC, "Skipping descriptor downloads: we haven't needed "
- "any circuits lately.");
- return;
- }
-
- if (networkstatus_list && smartlist_len(networkstatus_list) <=
- smartlist_len(trusted_dir_servers)/2) {
+ /* XXX here's another magic 2 that probably should be replaced
+ * by <= smartlist_len(trusted_dir_servers)/2
+ * or by a function returning same. -- weasel */
+ if (networkstatus_list && smartlist_len(networkstatus_list) < 2) {
log_info(LD_DIR,
"Not enough networkstatus documents to launch requests.");
}
@@ -3638,8 +3466,8 @@ update_router_descriptor_client_downloads(time_t now)
(int)(now-last_routerdesc_download_attempted));
} else {
log_info(LD_DIR,
- "There are not many downloadable routerdescs, but we haven't "
- "tried downloading descriptors recently. Downloading.");
+ "There are not many downloadable routerdescs, but we've "
+ "never downloaded descriptors before. Downloading.");
}
}
}
@@ -3657,7 +3485,6 @@ update_router_descriptor_client_downloads(time_t now)
(n_downloadable+n_per_request-1)/n_per_request,
n_downloadable>n_per_request?"s":"",
n_downloadable, n_downloadable>1?"s":"", n_per_request);
- smartlist_sort_digests(downloadable);
for (i=0; i < n_downloadable; i += n_per_request) {
initiate_descriptor_downloads(NULL, downloadable, i, i+n_per_request);
}
@@ -3678,11 +3505,10 @@ update_router_descriptor_cache_downloads(time_t now)
int i, j, n;
int n_download;
or_options_t *options = get_options();
- (void) now;
- if (!options->DirPort) {
+ if (!(server_mode(options) && options->DirPort)) {
log_warn(LD_BUG, "Called update_router_descriptor_cache_downloads() "
- "on a non-dir-mirror?");
+ "on a non-mirror?");
}
if (!networkstatus_list || !smartlist_len(networkstatus_list))
@@ -3796,7 +3622,7 @@ void
update_router_descriptor_downloads(time_t now)
{
or_options_t *options = get_options();
- if (options->DirPort) {
+ if (server_mode(options) && options->DirPort) {
update_router_descriptor_cache_downloads(now);
} else {
update_router_descriptor_client_downloads(now);
@@ -3833,7 +3659,7 @@ router_have_minimum_dir_info(void)
/** DOCDOC
* Must change when authorities change, networkstatuses change, or list of
- * routerdescs changes, or number of running routers changes.
+ * routerdescs changes.
*/
static void
router_dir_info_changed(void)
@@ -3933,9 +3759,6 @@ router_reset_descriptor_download_failures(void)
* automatically non-cosmetic. */
#define ROUTER_MAX_COSMETIC_TIME_DIFFERENCE (12*60*60)
-/** We allow uptime to vary from how much it ought to be by this much. */
-#define ROUTER_ALLOW_UPTIME_DRIFT (30*60)
-
/** Return true iff the only differences between r1 and r2 are such that
* would not cause a recent (post 0.1.1.6) dirserver to republish.
*/
@@ -3965,7 +3788,6 @@ router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2)
(r1->contact_info && r2->contact_info &&
strcasecmp(r1->contact_info, r2->contact_info)) ||
r1->is_hibernating != r2->is_hibernating ||
- r1->has_old_dnsworkers != r2->has_old_dnsworkers ||
cmp_addr_policies(r1->exit_policy, r2->exit_policy))
return 0;
if ((r1->declared_family == NULL) != (r2->declared_family == NULL))
@@ -3996,8 +3818,7 @@ router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2)
* give or take 30 minutes? */
r1pub = r1->cache_info.published_on;
r2pub = r2->cache_info.published_on;
- if (abs(r2->uptime - (r1->uptime + (r2pub - r1pub)))
- > ROUTER_ALLOW_UPTIME_DRIFT)
+ if (abs(r2->uptime - (r1->uptime + (r2pub - r1pub))) > 30*60)
return 0;
/* Otherwise, the difference is cosmetic. */
@@ -4019,7 +3840,6 @@ routerlist_assert_ok(routerlist_t *rl)
sd2 = digestmap_get(rl->desc_digest_map,
r->cache_info.signed_descriptor_digest);
tor_assert(&(r->cache_info) == sd2);
- tor_assert(r->routerlist_index == r_sl_idx);
});
SMARTLIST_FOREACH(rl->old_routers, signed_descriptor_t *, sd,
{
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 2f214a1ef4..10f5512ae3 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -54,7 +54,6 @@ typedef enum {
K_SERVER_VERSIONS,
K_R,
K_S,
- K_EVENTDNS,
_UNRECOGNIZED,
_ERR,
_EOF,
@@ -146,7 +145,6 @@ static struct {
{ "dir-options", K_DIR_OPTIONS, ARGS, NO_OBJ, NETSTATUS },
{ "client-versions", K_CLIENT_VERSIONS, ARGS, NO_OBJ, NETSTATUS },
{ "server-versions", K_SERVER_VERSIONS, ARGS, NO_OBJ, NETSTATUS },
- { "eventdns", K_EVENTDNS, ARGS, NO_OBJ, RTR },
{ NULL, -1, NO_ARGS, NO_OBJ, ANY }
};
@@ -542,6 +540,14 @@ find_dir_signing_key(const char *str)
if (tok->key) {
key = tok->key;
tok->key = NULL; /* steal reference. */
+ } else if (tok->n_args >= 1) {
+ /** XXXX Once all the directories are running 0.1.0.6-rc or later, we
+ * can remove this logic. */
+ key = crypto_pk_DER64_decode_public_key(tok->args[0]);
+ if (!key) {
+ log_warn(LD_DIR, "Unparseable dir-signing-key argument");
+ return NULL;
+ }
} else {
log_warn(LD_DIR, "Dir-signing-key token contained no key");
return NULL;
@@ -637,20 +643,17 @@ check_directory_signature(const char *digest,
* are marked running and valid. Advances *s to a point immediately
* following the last router entry. Ignore any trailing router entries that
* are not complete. Returns 0 on success and -1 on failure.
- * DOCDOC saved_location
*/
int
-router_parse_list_from_string(const char **s, smartlist_t *dest,
- saved_location_t saved_location)
+router_parse_list_from_string(const char **s, smartlist_t *dest)
{
routerinfo_t *router;
- const char *end, *cp, *start;
+ const char *end, *cp;
tor_assert(s);
tor_assert(*s);
tor_assert(dest);
- start = *s;
while (1) {
*s = eat_whitespace(*s);
/* Don't start parsing the rest of *s unless it contains a router. */
@@ -681,19 +684,13 @@ router_parse_list_from_string(const char **s, smartlist_t *dest,
continue;
}
- router = router_parse_entry_from_string(*s, end,
- saved_location != SAVED_IN_CACHE);
+ router = router_parse_entry_from_string(*s, end);
+ *s = end;
if (!router) {
log_warn(LD_DIR, "Error reading router; skipping");
- *s = end;
continue;
}
- if (saved_location != SAVED_NOWHERE) {
- router->cache_info.saved_location = saved_location;
- router->cache_info.saved_offset = *s - start;
- }
- *s = end;
smartlist_add(dest, router);
}
@@ -703,11 +700,9 @@ router_parse_list_from_string(const char **s, smartlist_t *dest,
/** Helper function: reads a single router entry from *<b>s</b> ...
* *<b>end</b>. Mallocs a new router and returns it if all goes well, else
* returns NULL.
- * DOCDOC cache_copy
*/
routerinfo_t *
-router_parse_entry_from_string(const char *s, const char *end,
- int cache_copy)
+router_parse_entry_from_string(const char *s, const char *end)
{
routerinfo_t *router = NULL;
char signed_digest[128];
@@ -754,9 +749,7 @@ router_parse_entry_from_string(const char *s, const char *end,
}
router = tor_malloc_zero(sizeof(routerinfo_t));
- router->routerlist_index = -1;
- if (cache_copy)
- router->cache_info.signed_descriptor_body = tor_strndup(s, end-s);
+ router->cache_info.signed_descriptor_body = tor_strndup(s, end-s);
router->cache_info.signed_descriptor_len = end-s;
memcpy(router->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
@@ -878,13 +871,6 @@ router_parse_entry_from_string(const char *s, const char *end,
router->contact_info = tor_strdup(tok->args[0]);
}
- if ((tok = find_first_by_keyword(tokens, K_EVENTDNS))) {
- router->has_old_dnsworkers = tok->n_args && !strcmp(tok->args[0], "0");
- } else if (router->platform) {
- if (! tor_version_as_new_as(router->platform, "0.1.2.2-alpha"))
- router->has_old_dnsworkers = 1;
- }
-
exit_policy_tokens = find_all_exitpolicy(tokens);
SMARTLIST_FOREACH(exit_policy_tokens, directory_token_t *, t,
if (router_add_exit_policy(router,t)<0) {
@@ -1085,15 +1071,6 @@ _compare_routerstatus_entries(const void **_a, const void **_b)
return memcmp(a->identity_digest, b->identity_digest, DIGEST_LEN);
}
-static void
-_free_duplicate_routerstatus_entry(void *e)
-{
- log_warn(LD_DIR,
- "Network-status has two entries for the same router. "
- "Dropping one.");
- routerstatus_free(e);
-}
-
/** Given a versioned (v2 or later) network-status object in <b>s</b>, try to
* parse it and return the result. Return NULL on failure. Check the
* signature of the network status, but do not (yet) check the signing key for
@@ -1236,8 +1213,20 @@ networkstatus_parse_from_string(const char *s)
smartlist_add(ns->entries, rs);
}
smartlist_sort(ns->entries, _compare_routerstatus_entries);
- smartlist_uniq(ns->entries, _compare_routerstatus_entries,
- _free_duplicate_routerstatus_entry);
+
+ /* Kill duplicate entries. */
+ for (i=0; i < smartlist_len(ns->entries)-1; ++i) {
+ routerstatus_t *rs1 = smartlist_get(ns->entries, i);
+ routerstatus_t *rs2 = smartlist_get(ns->entries, i+1);
+ if (!memcmp(rs1->identity_digest,
+ rs2->identity_digest, DIGEST_LEN)) {
+ log_warn(LD_DIR,
+ "Network-status has two entries for the same router. "
+ "Dropping one.");
+ smartlist_del_keeporder(ns->entries, i--);
+ routerstatus_free(rs1);
+ }
+ }
if (tokenize_string(s, NULL, tokens, NETSTATUS)) {
log_warn(LD_DIR, "Error tokenizing network-status footer.");
@@ -1810,7 +1799,7 @@ tor_version_parse(const char *s, tor_version_t *out)
{
char *eos=NULL, *cp=NULL;
/* Format is:
- * "Tor " ? NUM dot NUM dot NUM [ ( pre | rc | dot ) NUM [ - tag ] ]
+ * "Tor " ? NUM dot NUM dot NUM [ ( pre | rc | dot ) NUM [ -cvs ] ]
*/
tor_assert(s);
tor_assert(out);
@@ -1836,6 +1825,7 @@ tor_version_parse(const char *s, tor_version_t *out)
if (!*eos) {
out->status = VER_RELEASE;
out->patchlevel = 0;
+ out->cvs = IS_NOT_CVS;
return 0;
}
cp = eos;
@@ -1859,10 +1849,15 @@ tor_version_parse(const char *s, tor_version_t *out)
if (!eos || eos==cp) return -1;
cp = eos;
- /* Get status tag. */
+ /* Get cvs status and status tag. */
if (*cp == '-' || *cp == '.')
++cp;
strlcpy(out->status_tag, cp, sizeof(out->status_tag));
+ if (0==strcmp(cp, "cvs")) {
+ out->cvs = IS_CVS;
+ } else {
+ out->cvs = IS_NOT_CVS;
+ }
return 0;
}
@@ -1886,7 +1881,11 @@ tor_version_compare(tor_version_t *a, tor_version_t *b)
else if ((i = a->patchlevel - b->patchlevel))
return i;
- return strcmp(a->status_tag, b->status_tag);
+ if (a->major > 0 || a->minor > 0) {
+ return strcmp(a->status_tag, b->status_tag);
+ } else {
+ return (a->cvs - b->cvs);
+ }
}
/** Return true iff versions <b>a</b> and <b>b</b> belong to the same series.
@@ -1929,9 +1928,22 @@ _compare_tor_version_str_ptr(const void **_a, const void **_b)
void
sort_version_list(smartlist_t *versions, int remove_duplicates)
{
- smartlist_sort(versions, _compare_tor_version_str_ptr);
+ int i;
- if (remove_duplicates)
- smartlist_uniq(versions, _compare_tor_version_str_ptr, NULL);
+ smartlist_sort(versions, _compare_tor_version_str_ptr);
+ if (!remove_duplicates)
+ return;
+
+ for (i = 1; i < smartlist_len(versions); ++i) {
+ const void *a, *b;
+ a = smartlist_get(versions, i-1);
+ b = smartlist_get(versions, i);
+ /* use version_cmp so we catch multiple representations of the same
+ * version */
+ if (_compare_tor_version_str_ptr(&a,&b) == 0) {
+ tor_free(smartlist_get(versions, i));
+ smartlist_del_keeporder(versions, i--);
+ }
+ }
}
diff --git a/src/or/test.c b/src/or/test.c
index 4f9d79ccf5..7a413f525b 100644
--- a/src/or/test.c
+++ b/src/or/test.c
@@ -416,6 +416,19 @@ test_crypto(void)
test_eq(0, crypto_pk_cmp_keys(pk1, pk2));
tor_free(cp);
+ /* Check DER encoding */
+ i=crypto_pk_DER64_encode_public_key(pk1, &cp);
+ test_assert(i>0);
+ test_assert(cp);
+ test_assert(!strchr(cp, ' '));
+ test_assert(!strchr(cp, '\n'));
+ test_eq(0, crypto_pk_cmp_keys(pk1, pk1));
+ crypto_free_pk_env(pk2);
+ pk2 = crypto_pk_DER64_decode_public_key(cp);
+ test_assert(pk2);
+ test_eq(0, crypto_pk_cmp_keys(pk1, pk2));
+ tor_free(cp);
+
test_eq(128, crypto_pk_keysize(pk1));
test_eq(128, crypto_pk_keysize(pk2));
@@ -773,16 +786,6 @@ test_util(void)
test_streq("and", smartlist_bsearch(sl, " AND", _compare_without_first_ch));
test_eq_ptr(NULL, smartlist_bsearch(sl, " ANz", _compare_without_first_ch));
- /* Test reverse() and pop_last() */
- smartlist_reverse(sl);
- cp = smartlist_join_strings(sl, ",", 0, NULL);
- test_streq(cp,"the,router,onion,nickm,by,arma,and");
- tor_free(cp);
- cp = smartlist_pop_last(sl);
- test_streq(cp, "and");
- tor_free(cp);
- test_eq(smartlist_len(sl), 6);
-
/* Test tor_strstrip() */
strcpy(buf, "Testing 1 2 3");
test_eq(0, tor_strstrip(buf, ",!"));
@@ -807,28 +810,27 @@ test_util(void)
/* Test parse_addr_port */
cp = NULL; u32 = 3; u16 = 3;
- test_assert(!parse_addr_port(LOG_WARN, "1.2.3.4", &cp, &u32, &u16));
+ test_assert(!parse_addr_port("1.2.3.4", &cp, &u32, &u16));
test_streq(cp, "1.2.3.4");
test_eq(u32, 0x01020304u);
test_eq(u16, 0);
tor_free(cp);
- test_assert(!parse_addr_port(LOG_WARN, "4.3.2.1:99", &cp, &u32, &u16));
+ test_assert(!parse_addr_port("4.3.2.1:99", &cp, &u32, &u16));
test_streq(cp, "4.3.2.1");
test_eq(u32, 0x04030201u);
test_eq(u16, 99);
tor_free(cp);
- test_assert(!parse_addr_port(LOG_WARN, "nonexistent.address:4040",
- &cp, NULL, &u16));
+ test_assert(!parse_addr_port("nonexistent.address:4040", &cp, NULL, &u16));
test_streq(cp, "nonexistent.address");
test_eq(u16, 4040);
tor_free(cp);
- test_assert(!parse_addr_port(LOG_WARN, "localhost:9999", &cp, &u32, &u16));
+ test_assert(!parse_addr_port("localhost:9999", &cp, &u32, &u16));
test_streq(cp, "localhost");
test_eq(u32, 0x7f000001u);
test_eq(u16, 9999);
tor_free(cp);
u32 = 3;
- test_assert(!parse_addr_port(LOG_WARN, "localhost", NULL, &u32, &u16));
+ test_assert(!parse_addr_port("localhost", NULL, &u32, &u16));
test_eq(cp, NULL);
test_eq(u32, 0x7f000001u);
test_eq(u16, 0);
@@ -921,73 +923,11 @@ test_util(void)
smartlist_free(sl);
}
-static int
-_compare_strings_for_pqueue(const void *s1, const void *s2)
-{
- return strcmp((const char*)s1, (const char*)s2);
-}
-
-static void
-test_pqueue(void)
-{
- smartlist_t *sl;
- int (*cmp)(const void *, const void*);
-#define OK() smartlist_pqueue_assert_ok(sl, cmp)
-
- cmp = _compare_strings_for_pqueue;
-
- sl = smartlist_create();
- smartlist_pqueue_add(sl, cmp, (char*)"cows");
- smartlist_pqueue_add(sl, cmp, (char*)"zebras");
- smartlist_pqueue_add(sl, cmp, (char*)"fish");
- smartlist_pqueue_add(sl, cmp, (char*)"frogs");
- smartlist_pqueue_add(sl, cmp, (char*)"apples");
- smartlist_pqueue_add(sl, cmp, (char*)"squid");
- smartlist_pqueue_add(sl, cmp, (char*)"daschunds");
- smartlist_pqueue_add(sl, cmp, (char*)"eggplants");
- smartlist_pqueue_add(sl, cmp, (char*)"weissbier");
- smartlist_pqueue_add(sl, cmp, (char*)"lobsters");
- smartlist_pqueue_add(sl, cmp, (char*)"roquefort");
-
- OK();
-
- test_eq(smartlist_len(sl), 11);
- test_streq(smartlist_get(sl, 0), "apples");
- test_streq(smartlist_pqueue_pop(sl, cmp), "apples");
- test_eq(smartlist_len(sl), 10);
- OK();
- test_streq(smartlist_pqueue_pop(sl, cmp), "cows");
- test_streq(smartlist_pqueue_pop(sl, cmp), "daschunds");
- smartlist_pqueue_add(sl, cmp, (char*)"chinchillas");
- OK();
- smartlist_pqueue_add(sl, cmp, (char*)"fireflies");
- OK();
- test_streq(smartlist_pqueue_pop(sl, cmp), "chinchillas");
- test_streq(smartlist_pqueue_pop(sl, cmp), "eggplants");
- test_streq(smartlist_pqueue_pop(sl, cmp), "fireflies");
- OK();
- test_streq(smartlist_pqueue_pop(sl, cmp), "fish");
- test_streq(smartlist_pqueue_pop(sl, cmp), "frogs");
- test_streq(smartlist_pqueue_pop(sl, cmp), "lobsters");
- test_streq(smartlist_pqueue_pop(sl, cmp), "roquefort");
- OK();
- test_eq(smartlist_len(sl), 3);
- test_streq(smartlist_pqueue_pop(sl, cmp), "squid");
- test_streq(smartlist_pqueue_pop(sl, cmp), "weissbier");
- test_streq(smartlist_pqueue_pop(sl, cmp), "zebras");
- test_eq(smartlist_len(sl), 0);
- OK();
-#undef OK
- smartlist_free(sl);
-}
-
static void
test_gzip(void)
{
- char *buf1, *buf2=NULL, *buf3=NULL, *cp1, *cp2;
- const char *ccp2;
+ char *buf1, *buf2=NULL, *buf3=NULL;
size_t len1, len2;
- tor_zlib_state_t *state;
buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ");
test_eq(detect_compression_method(buf1, strlen(buf1)), 0);
@@ -1053,35 +993,6 @@ test_gzip(void)
ZLIB_METHOD, 1, LOG_INFO));
tor_assert(!buf3);
- /* Now, try streaming compression. */
- tor_free(buf1);
- tor_free(buf2);
- tor_free(buf3);
- state = tor_zlib_new(1, ZLIB_METHOD);
- tor_assert(state);
- cp1 = buf1 = tor_malloc(1024);
- len1 = 1024;
- ccp2 = "ABCDEFGHIJABCDEFGHIJ";
- len2 = 21;
- test_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 0)
- == TOR_ZLIB_OK);
- test_eq(len2, 0); /* Make sure we compressed it all. */
- test_assert(cp1 > buf1);
-
- len2 = 0;
- cp2 = cp1;
- test_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 1)
- == TOR_ZLIB_DONE);
- test_eq(len2, 0);
- test_assert(cp1 > cp2); /* Make sure we really added something. */
-
- tor_assert(!tor_gzip_uncompress(&buf3, &len2, buf1, 1024-len1,
- ZLIB_METHOD, 1, LOG_WARN));
- test_streq(buf3, "ABCDEFGHIJABCDEFGHIJ"); /*Make sure it compressed right.*/
- tor_free(buf3);
-
- tor_zlib_free(state);
-
tor_free(buf2);
tor_free(buf3);
tor_free(buf1);
@@ -1105,10 +1016,8 @@ test_strmap(void)
test_eq_ptr(strmap_get(map,"K1"), (void*)100);
test_eq_ptr(strmap_get(map,"K2"), (void*)101);
test_eq_ptr(strmap_get(map,"K-not-there"), NULL);
- strmap_assert_ok(map);
v = strmap_remove(map,"K2");
- strmap_assert_ok(map);
test_eq_ptr(v, (void*)101);
test_eq_ptr(strmap_get(map,"K2"), NULL);
test_eq_ptr(strmap_remove(map,"K2"), NULL);
@@ -1116,10 +1025,8 @@ test_strmap(void)
strmap_set(map, "K2", (void*)101);
strmap_set(map, "K3", (void*)102);
strmap_set(map, "K4", (void*)103);
- strmap_assert_ok(map);
strmap_set(map, "K5", (void*)104);
strmap_set(map, "K6", (void*)105);
- strmap_assert_ok(map);
#if 0
iter = strmap_iter_init(map);
@@ -1146,7 +1053,6 @@ test_strmap(void)
test_eq_ptr(strmap_get(map, "K5"), (void*)10816);
#endif
- strmap_assert_ok(map);
/* Clean up after ourselves. */
strmap_free(map, NULL);
@@ -1154,11 +1060,9 @@ test_strmap(void)
map = strmap_new();
strmap_set_lc(map,"Ab.C", (void*)1);
test_eq_ptr(strmap_get(map,"ab.c"), (void*)1);
- strmap_assert_ok(map);
test_eq_ptr(strmap_get_lc(map,"AB.C"), (void*)1);
test_eq_ptr(strmap_get(map,"AB.C"), NULL);
test_eq_ptr(strmap_remove_lc(map,"aB.C"), (void*)1);
- strmap_assert_ok(map);
test_eq_ptr(strmap_get_lc(map,"AB.C"), NULL);
strmap_free(map,NULL);
}
@@ -1241,8 +1145,6 @@ test_onion_handshake(void)
crypto_free_pk_env(pk);
}
-extern smartlist_t *fingerprint_list;
-
static void
test_dir_format(void)
{
@@ -1357,11 +1259,6 @@ test_dir_format(void)
strcat(buf2, pk1_str);
strcat(buf2, "signing-key\n");
strcat(buf2, pk2_str);
-#ifdef USE_EVENTDNS
- strcat(buf2, "opt eventdns 1\n");
-#else
- strcat(buf2, "opt eventdns 0\n");
-#endif
strcat(buf2, bw_lines);
strcat(buf2, "router-signature\n");
buf[strlen(buf2)] = '\0'; /* Don't compare the sig; it's never the same
@@ -1372,7 +1269,7 @@ test_dir_format(void)
test_assert(router_dump_router_to_string(buf, 2048, &r1, pk2)>0);
cp = buf;
- rp1 = router_parse_entry_from_string((const char*)cp,NULL,1);
+ rp1 = router_parse_entry_from_string((const char*)cp,NULL);
test_assert(rp1);
test_streq(rp1->address, r1.address);
test_eq(rp1->or_port, r1.or_port);
@@ -1395,7 +1292,7 @@ test_dir_format(void)
test_streq(buf, buf2);
cp = buf;
- rp2 = router_parse_entry_from_string(&cp,1);
+ rp2 = router_parse_entry_from_string(&cp);
test_assert(rp2);
test_streq(rp2->address, r2.address);
test_eq(rp2->or_port, r2.or_port);
@@ -1416,6 +1313,7 @@ test_dir_format(void)
/* Okay, now for the directories. */
{
+ extern smartlist_t *fingerprint_list;
fingerprint_list = smartlist_create();
crypto_pk_get_fingerprint(pk2, buf, 1);
add_fingerprint_to_dir("Magri", buf, fingerprint_list);
@@ -1435,7 +1333,7 @@ test_dir_format(void)
test_assert(router_dump_router_to_string(buf, 2048, &r2, pk1)>0);
test_eq(dirserv_add_descriptor(buf,&m), 2);
get_options()->Nickname = tor_strdup("DirServer");
- test_assert(!dirserv_dump_directory_to_string(&cp,pk3, 0));
+ test_assert(!dirserv_dump_directory_to_string(&cp,pk3));
crypto_pk_get_digest(pk3, d);
test_assert(!router_parse_directory(cp));
test_eq(2, smartlist_len(dir1->routers));
@@ -1460,30 +1358,35 @@ test_dir_format(void)
test_eq(4, ver1.micro);
test_eq(VER_PRE, ver1.status);
test_eq(2, ver1.patchlevel);
+ test_eq(IS_CVS, ver1.cvs);
test_eq(0, tor_version_parse("0.3.4rc1", &ver1));
test_eq(0, ver1.major);
test_eq(3, ver1.minor);
test_eq(4, ver1.micro);
test_eq(VER_RC, ver1.status);
test_eq(1, ver1.patchlevel);
+ test_eq(IS_NOT_CVS, ver1.cvs);
test_eq(0, tor_version_parse("1.3.4", &ver1));
test_eq(1, ver1.major);
test_eq(3, ver1.minor);
test_eq(4, ver1.micro);
test_eq(VER_RELEASE, ver1.status);
test_eq(0, ver1.patchlevel);
+ test_eq(IS_NOT_CVS, ver1.cvs);
test_eq(0, tor_version_parse("1.3.4.999", &ver1));
test_eq(1, ver1.major);
test_eq(3, ver1.minor);
test_eq(4, ver1.micro);
test_eq(VER_RELEASE, ver1.status);
test_eq(999, ver1.patchlevel);
+ test_eq(IS_NOT_CVS, ver1.cvs);
test_eq(0, tor_version_parse("0.1.2.4-alpha", &ver1));
test_eq(0, ver1.major);
test_eq(1, ver1.minor);
test_eq(2, ver1.micro);
test_eq(4, ver1.patchlevel);
test_eq(VER_RELEASE, ver1.status);
+ test_eq(IS_NOT_CVS, ver1.cvs);
test_streq("alpha", ver1.status_tag);
test_eq(0, tor_version_parse("0.1.2.4", &ver1));
test_eq(0, ver1.major);
@@ -1491,6 +1394,7 @@ test_dir_format(void)
test_eq(2, ver1.micro);
test_eq(4, ver1.patchlevel);
test_eq(VER_RELEASE, ver1.status);
+ test_eq(IS_NOT_CVS, ver1.cvs);
test_streq("", ver1.status_tag);
#define test_eq_vs(vs1, vs2) test_eq_type(version_status_t, "%d", (vs1), (vs2))
@@ -1711,8 +1615,6 @@ main(int c, char**v)
{
or_options_t *options = options_new();
char *errmsg = NULL;
- (void) c;
- (void) v;
options->command = CMD_RUN_UNITTESTS;
network_init();
setup_directory();
@@ -1748,7 +1650,6 @@ main(int c, char**v)
test_util();
test_strmap();
test_control_formats();
- test_pqueue();
puts("\n========================= Onion Skins =====================");
test_onion();
test_onion_handshake();
diff --git a/src/tools/tor-resolve.c b/src/tools/tor-resolve.c
index 6e1b59ecfd..052526698e 100644
--- a/src/tools/tor-resolve.c
+++ b/src/tools/tor-resolve.c
@@ -217,7 +217,7 @@ main(int argc, char **argv)
sockshost = 0x7f000001u; /* localhost */
socksport = 9050; /* 9050 */
} else if (n_args == 2) {
- if (parse_addr_port(LOG_WARN, arg[1], NULL, &sockshost, &socksport)<0) {
+ if (parse_addr_port(arg[1], NULL, &sockshost, &socksport)<0) {
fprintf(stderr, "Couldn't parse/resolve address %s", arg[1]);
return 1;
}
diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h
index 0836d59605..629d5c82a8 100644
--- a/src/win32/orconfig.h
+++ b/src/win32/orconfig.h
@@ -221,5 +221,5 @@
#define HAVE_EVENT_H
/* Version number of package */
-#define VERSION "0.1.2.1-alpha-dev"
+#define VERSION "0.1.1.23"
diff --git a/tor.spec.in b/tor.spec.in
index 405088c18e..9482b0529f 100644
--- a/tor.spec.in
+++ b/tor.spec.in
@@ -84,9 +84,9 @@
# Using the build date ensures that every build really does get
# a different release number. We use this trick for CVS versions.
# For release versions, we don't want or need it.
-%define is_dev_version %(echo %{native_version} | grep 'dev' > /dev/null && echo 1 || echo 0)
+%define is_cvs_version %(echo %{native_version} | grep 'cvs' > /dev/null && echo 1 || echo 0)
-%if %{is_dev_version}
+%if %{is_cvs_version}
%define blddate %(date -u +"%Y%m%d%H%M")
%define release %{pkgspec}.%{specver}.%{ostag}.%{blddate}
%else
@@ -122,7 +122,7 @@ Group: System Environment/Daemons
License: BSD-like
Vendor: R. Dingledine <arma@seul.org>
-Packager: Andrew Lewman <phobos@interloper.org>
+Packager: Nick Mathewson <nickm@seul.org>
%if %{is_suse}
Requires: openssl >= 0.9.6