summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml15
-rw-r--r--ChangeLog1847
-rw-r--r--Doxyfile.in2597
-rw-r--r--Makefile.am127
-rw-r--r--ReleaseNotes1747
-rw-r--r--changes/bug298198
-rw-r--r--changes/bug303444
-rw-r--r--changes/bug313353
-rw-r--r--changes/bug316525
-rw-r--r--changes/bug316694
-rw-r--r--changes/bug317343
-rw-r--r--changes/bug318104
-rw-r--r--changes/bug318375
-rw-r--r--changes/bug319224
-rw-r--r--changes/bug319393
-rw-r--r--changes/bug319953
-rw-r--r--changes/bug321065
-rw-r--r--changes/bug321088
-rw-r--r--changes/bug321247
-rw-r--r--changes/bug322953
-rw-r--r--changes/bug324023
-rw-r--r--changes/bug32402_git_scripts3
-rw-r--r--changes/bug324495
-rw-r--r--changes/bug325884
-rw-r--r--changes/bug327533
-rw-r--r--changes/bug327714
-rw-r--r--changes/bug327783
-rw-r--r--changes/bug328414
-rw-r--r--changes/bug328845
-rw-r--r--changes/bug330873
-rw-r--r--changes/bug33093_logging5
-rw-r--r--changes/bug33095_0415
-rw-r--r--changes/bug331044
-rw-r--r--changes/bug333745
-rw-r--r--changes/bug335454
-rw-r--r--changes/bug336085
-rw-r--r--changes/bug336684
-rw-r--r--changes/bug336744
-rw-r--r--changes/bug337827
-rw-r--r--changes/bug339183
-rw-r--r--changes/bug341304
-rw-r--r--changes/bug341314
-rw-r--r--changes/bug342334
-rw-r--r--changes/bug342993
-rw-r--r--changes/doc329713
-rw-r--r--changes/geoip-2019-11-064
-rw-r--r--changes/geoip-2019-12-034
-rw-r--r--changes/ticket289706
-rw-r--r--changes/ticket296693
-rw-r--r--changes/ticket308603
-rw-r--r--changes/ticket310913
-rw-r--r--changes/ticket311893
-rw-r--r--changes/ticket315487
-rw-r--r--changes/ticket316823
-rw-r--r--changes/ticket318415
-rw-r--r--changes/ticket318593
-rw-r--r--changes/ticket31919_bionic5
-rw-r--r--changes/ticket319585
-rw-r--r--changes/ticket320585
-rw-r--r--changes/ticket320633
-rw-r--r--changes/ticket320863
-rw-r--r--changes/ticket321913
-rw-r--r--changes/ticket322404
-rw-r--r--changes/ticket322412
-rw-r--r--changes/ticket322422
-rw-r--r--changes/ticket324074
-rw-r--r--changes/ticket325005
-rw-r--r--changes/ticket326294
-rw-r--r--changes/ticket326724
-rw-r--r--changes/ticket32705_disable7
-rw-r--r--changes/ticket327654
-rw-r--r--changes/ticket330754
-rw-r--r--changes/ticket331885
-rw-r--r--changes/ticket332124
-rw-r--r--changes/ticket332133
-rw-r--r--changes/ticket334584
-rw-r--r--changes/ticket334604
-rw-r--r--changes/ticket336464
-rw-r--r--changes/ticket33678_0433
-rw-r--r--changes/ticket338047
-rw-r--r--changes/ticket34255_0433
-rw-r--r--changes/ticket400307
-rw-r--r--configure.ac211
-rwxr-xr-xcontrib/client-tools/tor-resolve.py15
-rw-r--r--contrib/win32build/tor-mingw.nsi.in2
-rw-r--r--doc/HACKING/CircuitPaddingDevelopment.md1234
-rw-r--r--doc/HACKING/CircuitPaddingQuickStart.md263
-rw-r--r--doc/HACKING/CodingStandards.md57
-rw-r--r--doc/HACKING/HelpfulTools.md32
-rw-r--r--doc/HACKING/Module.md35
-rw-r--r--doc/HACKING/ReleasingTor.md2
-rw-r--r--doc/HACKING/design/00-overview.md124
-rw-r--r--doc/HACKING/design/01-common-utils.md121
-rw-r--r--doc/HACKING/design/01a-memory.md93
-rw-r--r--doc/HACKING/design/01e-os-compat.md50
-rw-r--r--doc/HACKING/design/03-modules.md247
-rw-r--r--doc/HACKING/design/Makefile34
-rw-r--r--doc/HACKING/design/this-not-that.md51
-rw-r--r--doc/include.am1
-rw-r--r--doc/tor-doxygen.css10
-rw-r--r--doc/tor.1.txt3168
-rw-r--r--m4/pprint.m4228
-rwxr-xr-xscripts/coccinelle/apply.sh9
-rwxr-xr-xscripts/coccinelle/check_cocci_parse.sh98
-rw-r--r--scripts/coccinelle/exceptions.txt24
-rwxr-xr-xscripts/coccinelle/test-operator-cleanup13
-rw-r--r--scripts/coccinelle/tor-coccinelle.h60
-rwxr-xr-xscripts/coccinelle/try_parse.sh46
-rwxr-xr-xscripts/codegen/fuzzing_include_am.py5
-rwxr-xr-xscripts/codegen/gen_server_ciphers.py19
-rwxr-xr-xscripts/codegen/get_mozilla_ciphers.py13
-rw-r--r--scripts/codegen/makedesc.py25
-rwxr-xr-xscripts/git/git-merge-forward.sh62
-rwxr-xr-xscripts/git/git-pull-all.sh17
-rwxr-xr-xscripts/git/git-push-all.sh104
-rwxr-xr-xscripts/git/git-setup-dirs.sh550
-rwxr-xr-xscripts/git/pre-commit.git-hook90
-rwxr-xr-xscripts/git/pre-push.git-hook152
-rwxr-xr-xscripts/maint/add_c_file.py212
-rwxr-xr-xscripts/maint/annotate_ifdef_directives.py5
-rwxr-xr-xscripts/maint/checkIncludes.py5
-rwxr-xr-xscripts/maint/checkSpace.pl54
-rwxr-xr-xscripts/maint/checkSpaceTest.sh36
-rw-r--r--scripts/maint/checkspace_tests/dubious.c83
-rw-r--r--scripts/maint/checkspace_tests/dubious.h4
-rw-r--r--scripts/maint/checkspace_tests/expected.txt31
-rw-r--r--scripts/maint/checkspace_tests/good_guard.h6
-rw-r--r--scripts/maint/checkspace_tests/same_guard.h6
-rw-r--r--scripts/maint/checkspace_tests/subdir/dubious.c1
-rwxr-xr-xscripts/maint/format_changelog.py47
-rwxr-xr-xscripts/maint/lintChanges.py5
-rwxr-xr-xscripts/maint/locatemissingdoxygen.py11
-rw-r--r--scripts/maint/practracker/exceptions.txt107
-rwxr-xr-xscripts/maint/practracker/includes.py16
-rw-r--r--scripts/maint/practracker/metrics.py5
-rwxr-xr-xscripts/maint/practracker/practracker.py45
-rwxr-xr-xscripts/maint/practracker/practracker_tests.py5
-rw-r--r--scripts/maint/practracker/problem.py24
-rwxr-xr-xscripts/maint/practracker/test_practracker.sh44
-rw-r--r--scripts/maint/practracker/testdata/.may_include1
-rw-r--r--scripts/maint/practracker/testdata/a.c3
-rw-r--r--scripts/maint/practracker/testdata/ex0-expected.txt8
-rw-r--r--scripts/maint/practracker/testdata/ex1-expected.txt2
-rw-r--r--scripts/maint/practracker/testdata/ex1-overbroad-expected.txt4
-rw-r--r--scripts/maint/practracker/testdata/ex1-regen-expected.txt46
-rw-r--r--scripts/maint/practracker/testdata/ex1-regen-overbroad-expected.txt45
-rw-r--r--scripts/maint/practracker/testdata/ex1.txt6
-rw-r--r--scripts/maint/practracker/util.py11
-rwxr-xr-xscripts/maint/rectify_include_paths.py5
-rwxr-xr-xscripts/maint/redox.py28
-rwxr-xr-xscripts/maint/rename_c_identifier.py266
-rwxr-xr-xscripts/maint/sortChanges.py15
-rwxr-xr-xscripts/maint/update_versions.py5
-rw-r--r--scripts/test/appveyor-irc-notify.py4
-rw-r--r--src/app/app.md6
-rw-r--r--src/app/config/.may_include2
-rw-r--r--src/app/config/app_config.md6
-rw-r--r--src/app/config/config.c3103
-rw-r--r--src/app/config/config.h111
-rw-r--r--src/app/config/include.am21
-rw-r--r--src/app/config/or_options_st.h149
-rw-r--r--src/app/config/or_state_st.h11
-rw-r--r--src/app/config/quiet_level.c38
-rw-r--r--src/app/config/quiet_level.h30
-rw-r--r--src/app/config/statefile.c79
-rw-r--r--src/app/config/statefile.h4
-rw-r--r--src/app/config/testnet.inc1
-rw-r--r--src/app/config/tor_cmdline_mode.h34
-rw-r--r--src/app/main/.may_include1
-rw-r--r--src/app/main/app_main.md2
-rw-r--r--src/app/main/include.am18
-rw-r--r--src/app/main/main.c86
-rw-r--r--src/app/main/main.h2
-rw-r--r--src/app/main/ntmain.c5
-rw-r--r--src/app/main/ntmain.h5
-rw-r--r--src/app/main/shutdown.c5
-rw-r--r--src/app/main/shutdown.h2
-rw-r--r--src/app/main/subsysmgr.c236
-rw-r--r--src/app/main/subsysmgr.h24
-rw-r--r--src/app/main/subsystem_list.c11
-rw-r--r--src/app/main/tor_main.c2
-rw-r--r--src/arch_goals.md31
-rw-r--r--src/config/mmdb-convert.py5
-rw-r--r--src/core/core.md18
-rw-r--r--src/core/crypto/core_crypto.md6
-rw-r--r--src/core/crypto/hs_ntor.c2
-rw-r--r--src/core/crypto/hs_ntor.h11
-rw-r--r--src/core/crypto/include.am18
-rw-r--r--src/core/crypto/onion_crypto.c2
-rw-r--r--src/core/crypto/onion_crypto.h2
-rw-r--r--src/core/crypto/onion_fast.c2
-rw-r--r--src/core/crypto/onion_fast.h2
-rw-r--r--src/core/crypto/onion_ntor.c2
-rw-r--r--src/core/crypto/onion_ntor.h7
-rw-r--r--src/core/crypto/onion_tap.c2
-rw-r--r--src/core/crypto/onion_tap.h2
-rw-r--r--src/core/crypto/relay_crypto.c7
-rw-r--r--src/core/crypto/relay_crypto.h2
-rw-r--r--src/core/include.am425
-rw-r--r--src/core/mainloop/.may_include6
-rw-r--r--src/core/mainloop/connection.c370
-rw-r--r--src/core/mainloop/connection.h201
-rw-r--r--src/core/mainloop/core_mainloop.md10
-rw-r--r--src/core/mainloop/cpuworker.c6
-rw-r--r--src/core/mainloop/cpuworker.h6
-rw-r--r--src/core/mainloop/include.am22
-rw-r--r--src/core/mainloop/mainloop.c50
-rw-r--r--src/core/mainloop/mainloop.h5
-rw-r--r--src/core/mainloop/mainloop_pubsub.c11
-rw-r--r--src/core/mainloop/mainloop_pubsub.h39
-rw-r--r--src/core/mainloop/mainloop_state.inc19
-rw-r--r--src/core/mainloop/mainloop_state_st.h23
-rw-r--r--src/core/mainloop/mainloop_sys.c59
-rw-r--r--src/core/mainloop/mainloop_sys.h7
-rw-r--r--src/core/mainloop/netstatus.c12
-rw-r--r--src/core/mainloop/netstatus.h14
-rw-r--r--src/core/mainloop/periodic.c5
-rw-r--r--src/core/mainloop/periodic.h9
-rw-r--r--src/core/or/.may_include4
-rw-r--r--src/core/or/addr_policy_st.h7
-rw-r--r--src/core/or/address_set.c4
-rw-r--r--src/core/or/address_set.h2
-rw-r--r--src/core/or/cell_queue_st.h9
-rw-r--r--src/core/or/cell_st.h8
-rw-r--r--src/core/or/channel.c53
-rw-r--r--src/core/or/channel.h77
-rw-r--r--src/core/or/channelpadding.c11
-rw-r--r--src/core/or/channelpadding.h2
-rw-r--r--src/core/or/channeltls.c7
-rw-r--r--src/core/or/channeltls.h8
-rw-r--r--src/core/or/circuit_st.h13
-rw-r--r--src/core/or/circuitbuild.c4
-rw-r--r--src/core/or/circuitbuild.h2
-rw-r--r--src/core/or/circuitlist.c50
-rw-r--r--src/core/or/circuitlist.h8
-rw-r--r--src/core/or/circuitmux.c62
-rw-r--r--src/core/or/circuitmux.h70
-rw-r--r--src/core/or/circuitmux_ewma.c115
-rw-r--r--src/core/or/circuitmux_ewma.h114
-rw-r--r--src/core/or/circuitpadding.c18
-rw-r--r--src/core/or/circuitpadding.h6
-rw-r--r--src/core/or/circuitpadding_machines.c2
-rw-r--r--src/core/or/circuitstats.c4
-rw-r--r--src/core/or/circuitstats.h4
-rw-r--r--src/core/or/circuituse.c90
-rw-r--r--src/core/or/circuituse.h11
-rw-r--r--src/core/or/command.c22
-rw-r--r--src/core/or/command.h3
-rw-r--r--src/core/or/connection_edge.c183
-rw-r--r--src/core/or/connection_edge.h20
-rw-r--r--src/core/or/connection_or.c31
-rw-r--r--src/core/or/connection_or.h11
-rw-r--r--src/core/or/connection_st.h7
-rw-r--r--src/core/or/core_or.md62
-rw-r--r--src/core/or/cpath_build_state_st.h8
-rw-r--r--src/core/or/crypt_path.c2
-rw-r--r--src/core/or/crypt_path_reference_st.h8
-rw-r--r--src/core/or/crypt_path_st.h7
-rw-r--r--src/core/or/dataflow.md (renamed from doc/HACKING/design/02-dataflow.md)12
-rw-r--r--src/core/or/destroy_cell_queue_st.h12
-rw-r--r--src/core/or/dos.c15
-rw-r--r--src/core/or/dos.h2
-rw-r--r--src/core/or/edge_connection_st.h8
-rw-r--r--src/core/or/entry_connection_st.h8
-rw-r--r--src/core/or/entry_port_cfg_st.h11
-rw-r--r--src/core/or/extend_info_st.h7
-rw-r--r--src/core/or/half_edge_st.h8
-rw-r--r--src/core/or/include.am98
-rw-r--r--src/core/or/listener_connection_st.h8
-rw-r--r--src/core/or/ocirc_event.c2
-rw-r--r--src/core/or/ocirc_event.h2
-rw-r--r--src/core/or/ocirc_event_sys.h2
-rw-r--r--src/core/or/onion.c2
-rw-r--r--src/core/or/onion.h2
-rw-r--r--src/core/or/or.h24
-rw-r--r--src/core/or/or_circuit_st.h4
-rw-r--r--src/core/or/or_connection_st.h9
-rw-r--r--src/core/or/or_handshake_certs_st.h7
-rw-r--r--src/core/or/or_handshake_state_st.h8
-rw-r--r--src/core/or/or_periodic.c4
-rw-r--r--src/core/or/or_periodic.h2
-rw-r--r--src/core/or/or_sys.c2
-rw-r--r--src/core/or/or_sys.h2
-rw-r--r--src/core/or/orconn_event.c2
-rw-r--r--src/core/or/orconn_event.h2
-rw-r--r--src/core/or/orconn_event_sys.h2
-rw-r--r--src/core/or/origin_circuit_st.h7
-rw-r--r--src/core/or/policies.c58
-rw-r--r--src/core/or/policies.h2
-rw-r--r--src/core/or/port_cfg_st.h8
-rw-r--r--src/core/or/protover.c2
-rw-r--r--src/core/or/protover.h2
-rw-r--r--src/core/or/protover_rust.c2
-rw-r--r--src/core/or/reasons.c2
-rw-r--r--src/core/or/reasons.h2
-rw-r--r--src/core/or/relay.c2
-rw-r--r--src/core/or/relay.h4
-rw-r--r--src/core/or/relay_crypto_st.h9
-rw-r--r--src/core/or/scheduler.c7
-rw-r--r--src/core/or/scheduler.h17
-rw-r--r--src/core/or/scheduler_kist.c25
-rw-r--r--src/core/or/scheduler_vanilla.c12
-rw-r--r--src/core/or/sendme.c2
-rw-r--r--src/core/or/sendme.h2
-rw-r--r--src/core/or/server_port_cfg_st.h8
-rw-r--r--src/core/or/socks_request_st.h14
-rw-r--r--src/core/or/status.c2
-rw-r--r--src/core/or/status.h8
-rw-r--r--src/core/or/tor_version_st.h8
-rw-r--r--src/core/or/var_cell_st.h8
-rw-r--r--src/core/or/versions.c2
-rw-r--r--src/core/or/versions.h2
-rw-r--r--src/core/proto/.may_include6
-rw-r--r--src/core/proto/core_proto.md6
-rw-r--r--src/core/proto/include.am18
-rw-r--r--src/core/proto/proto_cell.c10
-rw-r--r--src/core/proto/proto_cell.h8
-rw-r--r--src/core/proto/proto_control0.c8
-rw-r--r--src/core/proto/proto_control0.h8
-rw-r--r--src/core/proto/proto_ext_or.c8
-rw-r--r--src/core/proto/proto_ext_or.h7
-rw-r--r--src/core/proto/proto_haproxy.c45
-rw-r--r--src/core/proto/proto_haproxy.h12
-rw-r--r--src/core/proto/proto_http.c8
-rw-r--r--src/core/proto/proto_http.h8
-rw-r--r--src/core/proto/proto_socks.c15
-rw-r--r--src/core/proto/proto_socks.h7
-rw-r--r--src/ext/ed25519/ref10/base.py19
-rw-r--r--src/ext/ed25519/ref10/base2.py15
-rw-r--r--src/ext/ed25519/ref10/d.py7
-rw-r--r--src/ext/ed25519/ref10/d2.py7
-rw-r--r--src/ext/ed25519/ref10/sqrtm1.py7
-rw-r--r--src/ext/ht.h9
-rw-r--r--src/ext/siphash.h2
-rw-r--r--src/ext/timeouts/timeout.h6
-rw-r--r--src/ext/tinytest_macros.h4
-rw-r--r--src/feature/api/.may_include1
-rw-r--r--src/feature/api/feature_api.md2
-rw-r--r--src/feature/api/include.am11
-rw-r--r--src/feature/api/tor_api.c2
-rw-r--r--src/feature/api/tor_api.h2
-rw-r--r--src/feature/api/tor_api_internal.h7
-rw-r--r--src/feature/client/.may_include1
-rw-r--r--src/feature/client/addressmap.c2
-rw-r--r--src/feature/client/addressmap.h8
-rw-r--r--src/feature/client/bridges.c2
-rw-r--r--src/feature/client/bridges.h2
-rw-r--r--src/feature/client/circpathbias.c2
-rw-r--r--src/feature/client/circpathbias.h2
-rw-r--r--src/feature/client/dnsserv.c2
-rw-r--r--src/feature/client/dnsserv.h2
-rw-r--r--src/feature/client/entrynodes.c6
-rw-r--r--src/feature/client/entrynodes.h8
-rw-r--r--src/feature/client/feature_client.md5
-rw-r--r--src/feature/client/include.am20
-rw-r--r--src/feature/client/proxymode.c32
-rw-r--r--src/feature/client/proxymode.h17
-rw-r--r--src/feature/client/transports.c13
-rw-r--r--src/feature/client/transports.h2
-rw-r--r--src/feature/control/.may_include1
-rw-r--r--src/feature/control/btrack.c2
-rw-r--r--src/feature/control/btrack_circuit.c2
-rw-r--r--src/feature/control/btrack_circuit.h2
-rw-r--r--src/feature/control/btrack_orconn.c2
-rw-r--r--src/feature/control/btrack_orconn.h2
-rw-r--r--src/feature/control/btrack_orconn_cevent.c3
-rw-r--r--src/feature/control/btrack_orconn_cevent.h2
-rw-r--r--src/feature/control/btrack_orconn_maps.c2
-rw-r--r--src/feature/control/btrack_orconn_maps.h2
-rw-r--r--src/feature/control/btrack_sys.h2
-rw-r--r--src/feature/control/control.c2
-rw-r--r--src/feature/control/control.h2
-rw-r--r--src/feature/control/control_auth.c2
-rw-r--r--src/feature/control/control_auth.h2
-rw-r--r--src/feature/control/control_bootstrap.c2
-rw-r--r--src/feature/control/control_cmd.c161
-rw-r--r--src/feature/control/control_cmd.h2
-rw-r--r--src/feature/control/control_cmd_args_st.h2
-rw-r--r--src/feature/control/control_connection_st.h7
-rw-r--r--src/feature/control/control_events.c56
-rw-r--r--src/feature/control/control_events.h9
-rw-r--r--src/feature/control/control_fmt.c95
-rw-r--r--src/feature/control/control_fmt.h4
-rw-r--r--src/feature/control/control_getinfo.c195
-rw-r--r--src/feature/control/control_getinfo.h6
-rw-r--r--src/feature/control/control_hs.c342
-rw-r--r--src/feature/control/control_hs.h34
-rw-r--r--src/feature/control/control_proto.c159
-rw-r--r--src/feature/control/control_proto.h74
-rw-r--r--src/feature/control/feature_control.md8
-rw-r--r--src/feature/control/fmt_serverstatus.c7
-rw-r--r--src/feature/control/fmt_serverstatus.h2
-rw-r--r--src/feature/control/getinfo_geoip.c9
-rw-r--r--src/feature/control/getinfo_geoip.h7
-rw-r--r--src/feature/control/include.am39
-rw-r--r--src/feature/dirauth/.may_include2
-rw-r--r--src/feature/dirauth/authmode.c11
-rw-r--r--src/feature/dirauth/authmode.h12
-rw-r--r--src/feature/dirauth/bridgeauth.c7
-rw-r--r--src/feature/dirauth/bridgeauth.h7
-rw-r--r--src/feature/dirauth/bwauth.c8
-rw-r--r--src/feature/dirauth/bwauth.h2
-rw-r--r--src/feature/dirauth/dirauth_config.c470
-rw-r--r--src/feature/dirauth/dirauth_config.h91
-rw-r--r--src/feature/dirauth/dirauth_options.inc105
-rw-r--r--src/feature/dirauth/dirauth_options_st.h24
-rw-r--r--src/feature/dirauth/dirauth_periodic.c9
-rw-r--r--src/feature/dirauth/dirauth_periodic.h7
-rw-r--r--src/feature/dirauth/dirauth_stub.c33
-rw-r--r--src/feature/dirauth/dirauth_sys.c34
-rw-r--r--src/feature/dirauth/dirauth_sys.h22
-rw-r--r--src/feature/dirauth/dircollate.c10
-rw-r--r--src/feature/dirauth/dircollate.h10
-rw-r--r--src/feature/dirauth/dirvote.c64
-rw-r--r--src/feature/dirauth/dirvote.h30
-rw-r--r--src/feature/dirauth/dsigs_parse.c2
-rw-r--r--src/feature/dirauth/dsigs_parse.h2
-rw-r--r--src/feature/dirauth/feature_dirauth.md9
-rw-r--r--src/feature/dirauth/guardfraction.c2
-rw-r--r--src/feature/dirauth/guardfraction.h4
-rw-r--r--src/feature/dirauth/include.am52
-rw-r--r--src/feature/dirauth/keypin.c4
-rw-r--r--src/feature/dirauth/keypin.h9
-rw-r--r--src/feature/dirauth/ns_detached_signatures_st.h8
-rw-r--r--src/feature/dirauth/process_descs.c298
-rw-r--r--src/feature/dirauth/process_descs.h68
-rw-r--r--src/feature/dirauth/reachability.c12
-rw-r--r--src/feature/dirauth/reachability.h33
-rw-r--r--src/feature/dirauth/recommend_pkg.c2
-rw-r--r--src/feature/dirauth/recommend_pkg.h2
-rw-r--r--src/feature/dirauth/shared_random.c87
-rw-r--r--src/feature/dirauth/shared_random.h61
-rw-r--r--src/feature/dirauth/shared_random_state.c171
-rw-r--r--src/feature/dirauth/shared_random_state.h64
-rw-r--r--src/feature/dirauth/vote_microdesc_hash_st.h8
-rw-r--r--src/feature/dirauth/voteflags.c48
-rw-r--r--src/feature/dirauth/voteflags.h2
-rw-r--r--src/feature/dircache/.may_include1
-rw-r--r--src/feature/dircache/cached_dir_st.h8
-rw-r--r--src/feature/dircache/conscache.c11
-rw-r--r--src/feature/dircache/conscache.h13
-rw-r--r--src/feature/dircache/consdiffmgr.c8
-rw-r--r--src/feature/dircache/consdiffmgr.h21
-rw-r--r--src/feature/dircache/dircache.c16
-rw-r--r--src/feature/dircache/dircache.h2
-rw-r--r--src/feature/dircache/dircache_stub.c78
-rw-r--r--src/feature/dircache/dirserv.c182
-rw-r--r--src/feature/dircache/dirserv.h43
-rw-r--r--src/feature/dircache/feature_dircache.md6
-rw-r--r--src/feature/dircache/include.am21
-rw-r--r--src/feature/dirclient/.may_include1
-rw-r--r--src/feature/dirclient/dir_server_st.h7
-rw-r--r--src/feature/dirclient/dirclient.c87
-rw-r--r--src/feature/dirclient/dirclient.h4
-rw-r--r--src/feature/dirclient/dirclient_modes.c95
-rw-r--r--src/feature/dirclient/dirclient_modes.h24
-rw-r--r--src/feature/dirclient/dlstatus.c7
-rw-r--r--src/feature/dirclient/dlstatus.h2
-rw-r--r--src/feature/dirclient/download_status_st.h8
-rw-r--r--src/feature/dirclient/feature_dirclient.md7
-rw-r--r--src/feature/dirclient/include.am14
-rw-r--r--src/feature/dircommon/.may_include1
-rw-r--r--src/feature/dircommon/consdiff.c8
-rw-r--r--src/feature/dircommon/consdiff.h7
-rw-r--r--src/feature/dircommon/dir_connection_st.h11
-rw-r--r--src/feature/dircommon/directory.c33
-rw-r--r--src/feature/dircommon/directory.h8
-rw-r--r--src/feature/dircommon/feature_dircommon.md7
-rw-r--r--src/feature/dircommon/fp_pair.c14
-rw-r--r--src/feature/dircommon/fp_pair.h6
-rw-r--r--src/feature/dircommon/include.am16
-rw-r--r--src/feature/dircommon/vote_timing_st.h8
-rw-r--r--src/feature/dircommon/voting_schedule.c3
-rw-r--r--src/feature/dircommon/voting_schedule.h13
-rw-r--r--src/feature/dirparse/.may_include1
-rw-r--r--src/feature/dirparse/authcert_members.h29
-rw-r--r--src/feature/dirparse/authcert_members.i13
-rw-r--r--src/feature/dirparse/authcert_parse.c10
-rw-r--r--src/feature/dirparse/authcert_parse.h2
-rw-r--r--src/feature/dirparse/feature_dirparse.md8
-rw-r--r--src/feature/dirparse/include.am25
-rw-r--r--src/feature/dirparse/microdesc_parse.c4
-rw-r--r--src/feature/dirparse/microdesc_parse.h2
-rw-r--r--src/feature/dirparse/ns_parse.c5
-rw-r--r--src/feature/dirparse/ns_parse.h2
-rw-r--r--src/feature/dirparse/parsecommon.c2
-rw-r--r--src/feature/dirparse/parsecommon.h2
-rw-r--r--src/feature/dirparse/policy_parse.c4
-rw-r--r--src/feature/dirparse/policy_parse.h2
-rw-r--r--src/feature/dirparse/routerparse.c4
-rw-r--r--src/feature/dirparse/routerparse.h5
-rw-r--r--src/feature/dirparse/sigcommon.c2
-rw-r--r--src/feature/dirparse/sigcommon.h2
-rw-r--r--src/feature/dirparse/signing.c2
-rw-r--r--src/feature/dirparse/signing.h2
-rw-r--r--src/feature/dirparse/unparseable.c7
-rw-r--r--src/feature/dirparse/unparseable.h2
-rw-r--r--src/feature/feature.md7
-rw-r--r--src/feature/hibernate/.may_include1
-rw-r--r--src/feature/hibernate/feature_hibernate.md14
-rw-r--r--src/feature/hibernate/hibernate.c2
-rw-r--r--src/feature/hibernate/hibernate.h2
-rw-r--r--src/feature/hibernate/include.am8
-rw-r--r--src/feature/hs/.may_include1
-rw-r--r--src/feature/hs/feature_hs.md8
-rw-r--r--src/feature/hs/hs_cache.c285
-rw-r--r--src/feature/hs/hs_cache.h45
-rw-r--r--src/feature/hs/hs_cell.c52
-rw-r--r--src/feature/hs/hs_cell.h47
-rw-r--r--src/feature/hs/hs_circuit.c228
-rw-r--r--src/feature/hs/hs_circuit.h17
-rw-r--r--src/feature/hs/hs_circuitmap.c65
-rw-r--r--src/feature/hs/hs_circuitmap.h13
-rw-r--r--src/feature/hs/hs_client.c911
-rw-r--r--src/feature/hs/hs_client.h84
-rw-r--r--src/feature/hs/hs_common.c107
-rw-r--r--src/feature/hs/hs_common.h72
-rw-r--r--src/feature/hs/hs_config.c26
-rw-r--r--src/feature/hs/hs_config.h2
-rw-r--r--src/feature/hs/hs_control.c20
-rw-r--r--src/feature/hs/hs_control.h2
-rw-r--r--src/feature/hs/hs_descriptor.c239
-rw-r--r--src/feature/hs/hs_descriptor.h131
-rw-r--r--src/feature/hs/hs_dos.c53
-rw-r--r--src/feature/hs/hs_dos.h5
-rw-r--r--src/feature/hs/hs_ident.c21
-rw-r--r--src/feature/hs/hs_ident.h42
-rw-r--r--src/feature/hs/hs_intropoint.c32
-rw-r--r--src/feature/hs/hs_intropoint.h11
-rw-r--r--src/feature/hs/hs_service.c307
-rw-r--r--src/feature/hs/hs_service.h149
-rw-r--r--src/feature/hs/hs_stats.c2
-rw-r--r--src/feature/hs/hs_stats.h2
-rw-r--r--src/feature/hs/hsdir_index_st.h15
-rw-r--r--src/feature/hs/include.am35
-rw-r--r--src/feature/hs_common/.may_include1
-rw-r--r--src/feature/hs_common/feature_hs_common.md3
-rw-r--r--src/feature/hs_common/include.am10
-rw-r--r--src/feature/hs_common/replaycache.c2
-rw-r--r--src/feature/hs_common/replaycache.h15
-rw-r--r--src/feature/hs_common/shared_random_client.c22
-rw-r--r--src/feature/hs_common/shared_random_client.h2
-rw-r--r--src/feature/keymgt/.may_include1
-rw-r--r--src/feature/keymgt/feature_keymgt.md3
-rw-r--r--src/feature/keymgt/include.am8
-rw-r--r--src/feature/keymgt/loadkey.c4
-rw-r--r--src/feature/keymgt/loadkey.h2
-rw-r--r--src/feature/nodelist/.may_include1
-rw-r--r--src/feature/nodelist/authcert.c2
-rw-r--r--src/feature/nodelist/authcert.h2
-rw-r--r--src/feature/nodelist/authority_cert_st.h8
-rw-r--r--src/feature/nodelist/desc_store_st.h7
-rw-r--r--src/feature/nodelist/describe.c2
-rw-r--r--src/feature/nodelist/describe.h2
-rw-r--r--src/feature/nodelist/dirlist.c2
-rw-r--r--src/feature/nodelist/dirlist.h2
-rw-r--r--src/feature/nodelist/document_signature_st.h8
-rw-r--r--src/feature/nodelist/extrainfo_st.h8
-rw-r--r--src/feature/nodelist/feature_nodelist.md2
-rw-r--r--src/feature/nodelist/fmt_routerstatus.c15
-rw-r--r--src/feature/nodelist/fmt_routerstatus.h3
-rw-r--r--src/feature/nodelist/include.am49
-rw-r--r--src/feature/nodelist/microdesc.c5
-rw-r--r--src/feature/nodelist/microdesc.h2
-rw-r--r--src/feature/nodelist/microdesc_st.h9
-rw-r--r--src/feature/nodelist/networkstatus.c72
-rw-r--r--src/feature/nodelist/networkstatus.h8
-rw-r--r--src/feature/nodelist/networkstatus_sr_info_st.h8
-rw-r--r--src/feature/nodelist/networkstatus_st.h7
-rw-r--r--src/feature/nodelist/networkstatus_voter_info_st.h7
-rw-r--r--src/feature/nodelist/nickname.c2
-rw-r--r--src/feature/nodelist/nickname.h2
-rw-r--r--src/feature/nodelist/node_select.c63
-rw-r--r--src/feature/nodelist/node_select.h2
-rw-r--r--src/feature/nodelist/node_st.h8
-rw-r--r--src/feature/nodelist/nodefamily.c2
-rw-r--r--src/feature/nodelist/nodefamily.h2
-rw-r--r--src/feature/nodelist/nodefamily_st.h7
-rw-r--r--src/feature/nodelist/nodelist.c6
-rw-r--r--src/feature/nodelist/nodelist.h2
-rw-r--r--src/feature/nodelist/routerinfo.c7
-rw-r--r--src/feature/nodelist/routerinfo.h2
-rw-r--r--src/feature/nodelist/routerinfo_st.h7
-rw-r--r--src/feature/nodelist/routerlist.c24
-rw-r--r--src/feature/nodelist/routerlist.h2
-rw-r--r--src/feature/nodelist/routerlist_st.h8
-rw-r--r--src/feature/nodelist/routerset.c4
-rw-r--r--src/feature/nodelist/routerset.h5
-rw-r--r--src/feature/nodelist/routerstatus_st.h12
-rw-r--r--src/feature/nodelist/signed_descriptor_st.h8
-rw-r--r--src/feature/nodelist/torcert.c2
-rw-r--r--src/feature/nodelist/torcert.h7
-rw-r--r--src/feature/nodelist/vote_routerstatus_st.h6
-rw-r--r--src/feature/relay/.may_include1
-rw-r--r--src/feature/relay/dns.c2
-rw-r--r--src/feature/relay/dns.h2
-rw-r--r--src/feature/relay/dns_structs.h5
-rw-r--r--src/feature/relay/ext_orport.c2
-rw-r--r--src/feature/relay/ext_orport.h7
-rw-r--r--src/feature/relay/feature_relay.md4
-rw-r--r--src/feature/relay/include.am40
-rw-r--r--src/feature/relay/onion_queue.c2
-rw-r--r--src/feature/relay/onion_queue.h2
-rw-r--r--src/feature/relay/relay_config.c1444
-rw-r--r--src/feature/relay/relay_config.h196
-rw-r--r--src/feature/relay/relay_periodic.c4
-rw-r--r--src/feature/relay/relay_periodic.h15
-rw-r--r--src/feature/relay/relay_stub.c20
-rw-r--r--src/feature/relay/relay_sys.c4
-rw-r--r--src/feature/relay/relay_sys.h10
-rw-r--r--src/feature/relay/router.c110
-rw-r--r--src/feature/relay/router.h10
-rw-r--r--src/feature/relay/routerkeys.c2
-rw-r--r--src/feature/relay/routerkeys.h7
-rw-r--r--src/feature/relay/routermode.c24
-rw-r--r--src/feature/relay/routermode.h22
-rw-r--r--src/feature/relay/selftest.c4
-rw-r--r--src/feature/relay/selftest.h2
-rw-r--r--src/feature/relay/transport_config.c307
-rw-r--r--src/feature/relay/transport_config.h85
-rw-r--r--src/feature/rend/.may_include1
-rw-r--r--src/feature/rend/feature_rend.md7
-rw-r--r--src/feature/rend/include.am22
-rw-r--r--src/feature/rend/rend_authorized_client_st.h8
-rw-r--r--src/feature/rend/rend_encoded_v2_service_descriptor_st.h8
-rw-r--r--src/feature/rend/rend_intro_point_st.h7
-rw-r--r--src/feature/rend/rend_service_descriptor_st.h8
-rw-r--r--src/feature/rend/rendcache.c22
-rw-r--r--src/feature/rend/rendcache.h4
-rw-r--r--src/feature/rend/rendclient.c85
-rw-r--r--src/feature/rend/rendclient.h5
-rw-r--r--src/feature/rend/rendcommon.c2
-rw-r--r--src/feature/rend/rendcommon.h2
-rw-r--r--src/feature/rend/rendmid.c24
-rw-r--r--src/feature/rend/rendmid.h2
-rw-r--r--src/feature/rend/rendparse.c2
-rw-r--r--src/feature/rend/rendparse.h6
-rw-r--r--src/feature/rend/rendservice.c2
-rw-r--r--src/feature/rend/rendservice.h2
-rw-r--r--src/feature/stats/.may_include1
-rw-r--r--src/feature/stats/feature_stats.md10
-rw-r--r--src/feature/stats/geoip_stats.c2
-rw-r--r--src/feature/stats/geoip_stats.h3
-rw-r--r--src/feature/stats/include.am12
-rw-r--r--src/feature/stats/predict_ports.c2
-rw-r--r--src/feature/stats/predict_ports.h4
-rw-r--r--src/feature/stats/rephist.c4
-rw-r--r--src/feature/stats/rephist.h2
-rw-r--r--src/include.am37
-rw-r--r--src/lib/arch/bytes.h23
-rw-r--r--src/lib/arch/lib_arch.md2
-rw-r--r--src/lib/buf/buffers.c5
-rw-r--r--src/lib/buf/buffers.h2
-rw-r--r--src/lib/buf/lib_buf.md13
-rw-r--r--src/lib/cc/compat_compiler.h35
-rw-r--r--src/lib/cc/ctassert.h2
-rw-r--r--src/lib/cc/include.am1
-rw-r--r--src/lib/cc/lib_cc.md2
-rw-r--r--src/lib/cc/tokpaste.h30
-rw-r--r--src/lib/cc/torint.h2
-rw-r--r--src/lib/compress/compress.c2
-rw-r--r--src/lib/compress/compress.h2
-rw-r--r--src/lib/compress/compress_buf.c2
-rw-r--r--src/lib/compress/compress_lzma.c2
-rw-r--r--src/lib/compress/compress_lzma.h2
-rw-r--r--src/lib/compress/compress_none.c2
-rw-r--r--src/lib/compress/compress_none.h2
-rw-r--r--src/lib/compress/compress_sys.h2
-rw-r--r--src/lib/compress/compress_zlib.c2
-rw-r--r--src/lib/compress/compress_zlib.h2
-rw-r--r--src/lib/compress/compress_zstd.c6
-rw-r--r--src/lib/compress/compress_zstd.h2
-rw-r--r--src/lib/compress/lib_compress.md6
-rw-r--r--src/lib/conf/confdecl.h221
-rw-r--r--src/lib/conf/config.md126
-rw-r--r--src/lib/conf/confmacros.h9
-rw-r--r--src/lib/conf/conftesting.h19
-rw-r--r--src/lib/conf/conftypes.h185
-rw-r--r--src/lib/conf/include.am1
-rw-r--r--src/lib/conf/lib_conf.md3
-rw-r--r--src/lib/confmgt/.may_include1
-rw-r--r--src/lib/confmgt/confmgt.c (renamed from src/lib/confmgt/confparse.c)191
-rw-r--r--src/lib/confmgt/confmgt.h (renamed from src/lib/confmgt/confparse.h)134
-rw-r--r--src/lib/confmgt/include.am4
-rw-r--r--src/lib/confmgt/lib_confmgt.md7
-rw-r--r--src/lib/confmgt/structvar.c24
-rw-r--r--src/lib/confmgt/structvar.h2
-rw-r--r--src/lib/confmgt/type_defs.c244
-rw-r--r--src/lib/confmgt/type_defs.h2
-rw-r--r--src/lib/confmgt/typedvar.c22
-rw-r--r--src/lib/confmgt/typedvar.h4
-rw-r--r--src/lib/confmgt/unitparse.c70
-rw-r--r--src/lib/confmgt/unitparse.h5
-rw-r--r--src/lib/confmgt/var_type_def_st.h7
-rw-r--r--src/lib/container/bitarray.h2
-rw-r--r--src/lib/container/bloomfilt.c2
-rw-r--r--src/lib/container/bloomfilt.h2
-rw-r--r--src/lib/container/handles.h25
-rw-r--r--src/lib/container/lib_container.md (renamed from doc/HACKING/design/01b-collections.md)32
-rw-r--r--src/lib/container/map.c2
-rw-r--r--src/lib/container/map.h61
-rw-r--r--src/lib/container/namemap.c7
-rw-r--r--src/lib/container/namemap.h2
-rw-r--r--src/lib/container/namemap_st.h9
-rw-r--r--src/lib/container/order.c2
-rw-r--r--src/lib/container/order.h2
-rw-r--r--src/lib/container/smartlist.c4
-rw-r--r--src/lib/container/smartlist.h4
-rw-r--r--src/lib/crypt_ops/.may_include3
-rw-r--r--src/lib/crypt_ops/aes.h4
-rw-r--r--src/lib/crypt_ops/aes_nss.c6
-rw-r--r--src/lib/crypt_ops/aes_openssl.c9
-rw-r--r--src/lib/crypt_ops/certs.md30
-rw-r--r--src/lib/crypt_ops/compat_openssl.h2
-rw-r--r--src/lib/crypt_ops/crypto_cipher.c2
-rw-r--r--src/lib/crypt_ops/crypto_cipher.h4
-rw-r--r--src/lib/crypt_ops/crypto_curve25519.c2
-rw-r--r--src/lib/crypt_ops/crypto_curve25519.h2
-rw-r--r--src/lib/crypt_ops/crypto_dh.c2
-rw-r--r--src/lib/crypt_ops/crypto_dh.h2
-rw-r--r--src/lib/crypt_ops/crypto_dh_nss.c4
-rw-r--r--src/lib/crypt_ops/crypto_dh_openssl.c8
-rw-r--r--src/lib/crypt_ops/crypto_digest.c5
-rw-r--r--src/lib/crypt_ops/crypto_digest.h35
-rw-r--r--src/lib/crypt_ops/crypto_digest_nss.c12
-rw-r--r--src/lib/crypt_ops/crypto_digest_openssl.c11
-rw-r--r--src/lib/crypt_ops/crypto_ed25519.c2
-rw-r--r--src/lib/crypt_ops/crypto_ed25519.h2
-rw-r--r--src/lib/crypt_ops/crypto_format.c2
-rw-r--r--src/lib/crypt_ops/crypto_format.h2
-rw-r--r--src/lib/crypt_ops/crypto_hkdf.c2
-rw-r--r--src/lib/crypt_ops/crypto_hkdf.h2
-rw-r--r--src/lib/crypt_ops/crypto_init.c68
-rw-r--r--src/lib/crypt_ops/crypto_init.h2
-rw-r--r--src/lib/crypt_ops/crypto_nss_mgt.c6
-rw-r--r--src/lib/crypt_ops/crypto_nss_mgt.h2
-rw-r--r--src/lib/crypt_ops/crypto_ope.c7
-rw-r--r--src/lib/crypt_ops/crypto_ope.h13
-rw-r--r--src/lib/crypt_ops/crypto_openssl_mgt.c44
-rw-r--r--src/lib/crypt_ops/crypto_openssl_mgt.h2
-rw-r--r--src/lib/crypt_ops/crypto_options.inc19
-rw-r--r--src/lib/crypt_ops/crypto_options_st.h23
-rw-r--r--src/lib/crypt_ops/crypto_pwbox.c2
-rw-r--r--src/lib/crypt_ops/crypto_pwbox.h2
-rw-r--r--src/lib/crypt_ops/crypto_rand.c6
-rw-r--r--src/lib/crypt_ops/crypto_rand.h2
-rw-r--r--src/lib/crypt_ops/crypto_rand_fast.c13
-rw-r--r--src/lib/crypt_ops/crypto_rsa.c2
-rw-r--r--src/lib/crypt_ops/crypto_rsa.h2
-rw-r--r--src/lib/crypt_ops/crypto_rsa_nss.c4
-rw-r--r--src/lib/crypt_ops/crypto_rsa_openssl.c6
-rw-r--r--src/lib/crypt_ops/crypto_s2k.c4
-rw-r--r--src/lib/crypt_ops/crypto_s2k.h2
-rw-r--r--src/lib/crypt_ops/crypto_sys.h4
-rw-r--r--src/lib/crypt_ops/crypto_util.c8
-rw-r--r--src/lib/crypt_ops/crypto_util.h2
-rw-r--r--src/lib/crypt_ops/digestset.c2
-rw-r--r--src/lib/crypt_ops/digestset.h2
-rw-r--r--src/lib/crypt_ops/include.am2
-rw-r--r--src/lib/crypt_ops/lib_crypt_ops.md (renamed from doc/HACKING/design/01d-crypto.md)56
-rw-r--r--src/lib/ctime/di_ops.c5
-rw-r--r--src/lib/ctime/di_ops.h25
-rw-r--r--src/lib/ctime/lib_ctime.md14
-rw-r--r--src/lib/defs/dh_sizes.h2
-rw-r--r--src/lib/defs/digest_sizes.h2
-rw-r--r--src/lib/defs/lib_defs.md2
-rw-r--r--src/lib/defs/logging_types.h2
-rw-r--r--src/lib/defs/time.h4
-rw-r--r--src/lib/defs/x25519_sizes.h10
-rw-r--r--src/lib/dispatch/dispatch.h2
-rw-r--r--src/lib/dispatch/dispatch_cfg.c2
-rw-r--r--src/lib/dispatch/dispatch_cfg.h7
-rw-r--r--src/lib/dispatch/dispatch_cfg_st.h14
-rw-r--r--src/lib/dispatch/dispatch_core.c2
-rw-r--r--src/lib/dispatch/dispatch_naming.c9
-rw-r--r--src/lib/dispatch/dispatch_naming.h7
-rw-r--r--src/lib/dispatch/dispatch_new.c2
-rw-r--r--src/lib/dispatch/dispatch_st.h2
-rw-r--r--src/lib/dispatch/lib_dispatch.md14
-rw-r--r--src/lib/dispatch/msgtypes.h2
-rw-r--r--src/lib/encoding/binascii.c2
-rw-r--r--src/lib/encoding/binascii.h2
-rw-r--r--src/lib/encoding/confline.c2
-rw-r--r--src/lib/encoding/confline.h2
-rw-r--r--src/lib/encoding/cstring.c2
-rw-r--r--src/lib/encoding/cstring.h2
-rw-r--r--src/lib/encoding/keyval.c2
-rw-r--r--src/lib/encoding/keyval.h2
-rw-r--r--src/lib/encoding/kvline.c54
-rw-r--r--src/lib/encoding/kvline.h3
-rw-r--r--src/lib/encoding/lib_encoding.md6
-rw-r--r--src/lib/encoding/pem.c4
-rw-r--r--src/lib/encoding/pem.h2
-rw-r--r--src/lib/encoding/qstring.c2
-rw-r--r--src/lib/encoding/qstring.h2
-rw-r--r--src/lib/encoding/time_fmt.c2
-rw-r--r--src/lib/encoding/time_fmt.h2
-rw-r--r--src/lib/err/backtrace.c4
-rw-r--r--src/lib/err/backtrace.h6
-rw-r--r--src/lib/err/lib_err.md13
-rw-r--r--src/lib/err/torerr.c31
-rw-r--r--src/lib/err/torerr.h3
-rw-r--r--src/lib/err/torerr_sys.c5
-rw-r--r--src/lib/err/torerr_sys.h2
-rw-r--r--src/lib/evloop/compat_libevent.c6
-rw-r--r--src/lib/evloop/compat_libevent.h8
-rw-r--r--src/lib/evloop/evloop_sys.c2
-rw-r--r--src/lib/evloop/evloop_sys.h2
-rw-r--r--src/lib/evloop/lib_evloop.md7
-rw-r--r--src/lib/evloop/procmon.c6
-rw-r--r--src/lib/evloop/procmon.h2
-rw-r--r--src/lib/evloop/time_periodic.md (renamed from doc/HACKING/design/01c-time.md)27
-rw-r--r--src/lib/evloop/timers.c12
-rw-r--r--src/lib/evloop/timers.h3
-rw-r--r--src/lib/evloop/token_bucket.c2
-rw-r--r--src/lib/evloop/token_bucket.h2
-rw-r--r--src/lib/evloop/workqueue.c20
-rw-r--r--src/lib/evloop/workqueue.h8
-rw-r--r--src/lib/fdio/fdio.c9
-rw-r--r--src/lib/fdio/fdio.h5
-rw-r--r--src/lib/fdio/lib_fdio.md5
-rw-r--r--src/lib/fs/conffile.c2
-rw-r--r--src/lib/fs/conffile.h2
-rw-r--r--src/lib/fs/dir.c2
-rw-r--r--src/lib/fs/dir.h2
-rw-r--r--src/lib/fs/files.c2
-rw-r--r--src/lib/fs/files.h2
-rw-r--r--src/lib/fs/freespace.c2
-rw-r--r--src/lib/fs/lib_fs.md9
-rw-r--r--src/lib/fs/lockfile.c2
-rw-r--r--src/lib/fs/lockfile.h2
-rw-r--r--src/lib/fs/mmap.c18
-rw-r--r--src/lib/fs/mmap.h7
-rw-r--r--src/lib/fs/path.c7
-rw-r--r--src/lib/fs/path.h4
-rw-r--r--src/lib/fs/storagedir.c2
-rw-r--r--src/lib/fs/storagedir.h6
-rw-r--r--src/lib/fs/userdb.c2
-rw-r--r--src/lib/fs/userdb.h2
-rw-r--r--src/lib/fs/winlib.c2
-rw-r--r--src/lib/fs/winlib.h2
-rw-r--r--src/lib/geoip/country.h8
-rw-r--r--src/lib/geoip/geoip.c18
-rw-r--r--src/lib/geoip/geoip.h3
-rw-r--r--src/lib/geoip/lib_geoip.md3
-rw-r--r--src/lib/intmath/addsub.c2
-rw-r--r--src/lib/intmath/addsub.h2
-rw-r--r--src/lib/intmath/bits.c2
-rw-r--r--src/lib/intmath/bits.h2
-rw-r--r--src/lib/intmath/cmp.h2
-rw-r--r--src/lib/intmath/lib_intmath.md2
-rw-r--r--src/lib/intmath/logic.h2
-rw-r--r--src/lib/intmath/muldiv.c16
-rw-r--r--src/lib/intmath/muldiv.h4
-rw-r--r--src/lib/intmath/weakrng.c2
-rw-r--r--src/lib/intmath/weakrng.h5
-rw-r--r--src/lib/lib.md131
-rw-r--r--src/lib/lock/compat_mutex.c2
-rw-r--r--src/lib/lock/compat_mutex.h7
-rw-r--r--src/lib/lock/compat_mutex_pthreads.c8
-rw-r--r--src/lib/lock/compat_mutex_winthreads.c2
-rw-r--r--src/lib/lock/lib_lock.md6
-rw-r--r--src/lib/log/escape.c2
-rw-r--r--src/lib/log/escape.h2
-rw-r--r--src/lib/log/lib_log.md10
-rw-r--r--src/lib/log/log.c97
-rw-r--r--src/lib/log/log.h23
-rw-r--r--src/lib/log/log_sys.c2
-rw-r--r--src/lib/log/log_sys.h2
-rw-r--r--src/lib/log/ratelim.c2
-rw-r--r--src/lib/log/ratelim.h4
-rw-r--r--src/lib/log/util_bug.c6
-rw-r--r--src/lib/log/util_bug.h11
-rw-r--r--src/lib/log/win32err.c2
-rw-r--r--src/lib/log/win32err.h2
-rw-r--r--src/lib/malloc/lib_malloc.md76
-rw-r--r--src/lib/malloc/malloc.c2
-rw-r--r--src/lib/malloc/malloc.h2
-rw-r--r--src/lib/malloc/map_anon.c6
-rw-r--r--src/lib/malloc/map_anon.h2
-rw-r--r--src/lib/math/fp.c18
-rw-r--r--src/lib/math/fp.h2
-rw-r--r--src/lib/math/laplace.c2
-rw-r--r--src/lib/math/laplace.h2
-rw-r--r--src/lib/math/lib_math.md6
-rw-r--r--src/lib/math/prob_distr.c230
-rw-r--r--src/lib/math/prob_distr.h132
-rw-r--r--src/lib/memarea/lib_memarea.md28
-rw-r--r--src/lib/memarea/memarea.c2
-rw-r--r--src/lib/memarea/memarea.h5
-rw-r--r--src/lib/meminfo/lib_meminfo.md5
-rw-r--r--src/lib/meminfo/meminfo.c6
-rw-r--r--src/lib/meminfo/meminfo.h2
-rw-r--r--src/lib/net/address.c6
-rw-r--r--src/lib/net/address.h26
-rw-r--r--src/lib/net/alertsock.c2
-rw-r--r--src/lib/net/alertsock.h2
-rw-r--r--src/lib/net/buffers_net.c2
-rw-r--r--src/lib/net/buffers_net.h2
-rw-r--r--src/lib/net/gethostname.c2
-rw-r--r--src/lib/net/gethostname.h2
-rw-r--r--src/lib/net/inaddr.c8
-rw-r--r--src/lib/net/inaddr.h2
-rw-r--r--src/lib/net/inaddr_st.h2
-rw-r--r--src/lib/net/lib_net.md6
-rw-r--r--src/lib/net/nettypes.h2
-rw-r--r--src/lib/net/network_sys.c2
-rw-r--r--src/lib/net/network_sys.h4
-rw-r--r--src/lib/net/resolve.c2
-rw-r--r--src/lib/net/resolve.h2
-rw-r--r--src/lib/net/socket.c3
-rw-r--r--src/lib/net/socket.h2
-rw-r--r--src/lib/net/socketpair.c7
-rw-r--r--src/lib/net/socketpair.h7
-rw-r--r--src/lib/net/socks5_status.h12
-rw-r--r--src/lib/osinfo/lib_osinfo.md8
-rw-r--r--src/lib/osinfo/uname.c2
-rw-r--r--src/lib/osinfo/uname.h2
-rw-r--r--src/lib/process/daemon.c2
-rw-r--r--src/lib/process/daemon.h2
-rw-r--r--src/lib/process/env.c3
-rw-r--r--src/lib/process/env.h2
-rw-r--r--src/lib/process/lib_process.md2
-rw-r--r--src/lib/process/pidfile.c2
-rw-r--r--src/lib/process/pidfile.h2
-rw-r--r--src/lib/process/process.c3
-rw-r--r--src/lib/process/process.h21
-rw-r--r--src/lib/process/process_sys.c2
-rw-r--r--src/lib/process/process_sys.h2
-rw-r--r--src/lib/process/process_unix.c2
-rw-r--r--src/lib/process/process_unix.h2
-rw-r--r--src/lib/process/process_win32.c2
-rw-r--r--src/lib/process/process_win32.h2
-rw-r--r--src/lib/process/restrict.c2
-rw-r--r--src/lib/process/restrict.h2
-rw-r--r--src/lib/process/setuid.c6
-rw-r--r--src/lib/process/setuid.h2
-rw-r--r--src/lib/process/waitpid.c2
-rw-r--r--src/lib/process/waitpid.h2
-rw-r--r--src/lib/process/winprocess_sys.c2
-rw-r--r--src/lib/process/winprocess_sys.h2
-rw-r--r--src/lib/pubsub/lib_pubsub.md14
-rw-r--r--src/lib/pubsub/pub_binding_st.h2
-rw-r--r--src/lib/pubsub/publish_subscribe.md144
-rw-r--r--src/lib/pubsub/pubsub.h2
-rw-r--r--src/lib/pubsub/pubsub_build.c2
-rw-r--r--src/lib/pubsub/pubsub_build.h7
-rw-r--r--src/lib/pubsub/pubsub_builder_st.h2
-rw-r--r--src/lib/pubsub/pubsub_check.c4
-rw-r--r--src/lib/pubsub/pubsub_connect.h2
-rw-r--r--src/lib/pubsub/pubsub_flags.h2
-rw-r--r--src/lib/pubsub/pubsub_macros.h10
-rw-r--r--src/lib/pubsub/pubsub_publish.c2
-rw-r--r--src/lib/pubsub/pubsub_publish.h7
-rw-r--r--src/lib/sandbox/lib_sandbox.md15
-rw-r--r--src/lib/sandbox/sandbox.c19
-rw-r--r--src/lib/sandbox/sandbox.h12
-rw-r--r--src/lib/smartlist_core/lib_smartlist_core.md10
-rw-r--r--src/lib/smartlist_core/smartlist_core.c2
-rw-r--r--src/lib/smartlist_core/smartlist_core.h2
-rw-r--r--src/lib/smartlist_core/smartlist_foreach.h2
-rw-r--r--src/lib/smartlist_core/smartlist_split.c2
-rw-r--r--src/lib/smartlist_core/smartlist_split.h2
-rw-r--r--src/lib/string/compat_ctype.c3
-rw-r--r--src/lib/string/compat_ctype.h2
-rw-r--r--src/lib/string/compat_string.c2
-rw-r--r--src/lib/string/compat_string.h2
-rw-r--r--src/lib/string/lib_string.md13
-rw-r--r--src/lib/string/parse_int.c7
-rw-r--r--src/lib/string/parse_int.h2
-rw-r--r--src/lib/string/printf.c2
-rw-r--r--src/lib/string/printf.h2
-rw-r--r--src/lib/string/scanf.c2
-rw-r--r--src/lib/string/scanf.h2
-rw-r--r--src/lib/string/strings.md (renamed from doc/HACKING/design/01g-strings.md)9
-rw-r--r--src/lib/string/util_string.c23
-rw-r--r--src/lib/string/util_string.h2
-rw-r--r--src/lib/subsys/initialization.md75
-rw-r--r--src/lib/subsys/lib_subsys.md32
-rw-r--r--src/lib/subsys/subsys.h122
-rw-r--r--src/lib/term/getpass.c2
-rw-r--r--src/lib/term/getpass.h2
-rw-r--r--src/lib/term/lib_term.md2
-rw-r--r--src/lib/testsupport/lib_testsupport.md2
-rw-r--r--src/lib/testsupport/testsupport.h55
-rw-r--r--src/lib/thread/compat_pthreads.c2
-rw-r--r--src/lib/thread/compat_threads.c2
-rw-r--r--src/lib/thread/compat_winthreads.c2
-rw-r--r--src/lib/thread/lib_thread.md7
-rw-r--r--src/lib/thread/numcpus.c2
-rw-r--r--src/lib/thread/numcpus.h2
-rw-r--r--src/lib/thread/thread_sys.h4
-rw-r--r--src/lib/thread/threading.md (renamed from doc/HACKING/design/01f-threads.md)20
-rw-r--r--src/lib/thread/threads.h6
-rw-r--r--src/lib/time/compat_time.c2
-rw-r--r--src/lib/time/compat_time.h2
-rw-r--r--src/lib/time/lib_time.md9
-rw-r--r--src/lib/time/time_sys.c2
-rw-r--r--src/lib/time/time_sys.h2
-rw-r--r--src/lib/time/tvdiff.c2
-rw-r--r--src/lib/time/tvdiff.h2
-rw-r--r--src/lib/tls/buffers_tls.c6
-rw-r--r--src/lib/tls/buffers_tls.h2
-rw-r--r--src/lib/tls/lib_tls.md11
-rw-r--r--src/lib/tls/nss_countbytes.c2
-rw-r--r--src/lib/tls/nss_countbytes.h2
-rw-r--r--src/lib/tls/tortls.c7
-rw-r--r--src/lib/tls/tortls.h2
-rw-r--r--src/lib/tls/tortls_internal.h9
-rw-r--r--src/lib/tls/tortls_nss.c6
-rw-r--r--src/lib/tls/tortls_openssl.c8
-rw-r--r--src/lib/tls/tortls_st.h10
-rw-r--r--src/lib/tls/tortls_sys.h2
-rw-r--r--src/lib/tls/x509.c2
-rw-r--r--src/lib/tls/x509.h2
-rw-r--r--src/lib/tls/x509_internal.h2
-rw-r--r--src/lib/tls/x509_nss.c2
-rw-r--r--src/lib/tls/x509_openssl.c6
-rw-r--r--src/lib/trace/debug.h2
-rw-r--r--src/lib/trace/events.h2
-rw-r--r--src/lib/trace/lib_trace.md6
-rw-r--r--src/lib/trace/trace.c2
-rw-r--r--src/lib/trace/trace.h2
-rw-r--r--src/lib/version/git_revision.c17
-rw-r--r--src/lib/version/git_revision.h7
-rw-r--r--src/lib/version/lib_version.md2
-rw-r--r--src/lib/version/torversion.h7
-rw-r--r--src/lib/version/version.c11
-rw-r--r--src/lib/wallclock/approx_time.c8
-rw-r--r--src/lib/wallclock/approx_time.h2
-rw-r--r--src/lib/wallclock/lib_wallclock.md11
-rw-r--r--src/lib/wallclock/time_to_tm.c3
-rw-r--r--src/lib/wallclock/time_to_tm.h2
-rw-r--r--src/lib/wallclock/timeval.h4
-rw-r--r--src/lib/wallclock/tor_gettimeofday.c2
-rw-r--r--src/lib/wallclock/tor_gettimeofday.h2
-rw-r--r--src/lib/wallclock/wallclock_sys.h2
-rw-r--r--src/mainpage.md147
-rw-r--r--src/test/.may_include2
-rw-r--r--src/test/bench.c2
-rwxr-xr-xsrc/test/bt_test.py4
-rw-r--r--src/test/conf_examples/badnick_1/expected_log_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/badnick_1/expected_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/badnick_1/torrc2
-rw-r--r--src/test/conf_examples/badnick_2/expected_log_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/badnick_2/expected_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/badnick_2/torrc2
-rw-r--r--src/test/conf_examples/bridgeauth_1/error_no_dirauth1
-rw-r--r--src/test/conf_examples/bridgeauth_1/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/bridgeauth_1/expected7
-rw-r--r--src/test/conf_examples/bridgeauth_1/expected_log1
-rw-r--r--src/test/conf_examples/bridgeauth_1/torrc8
-rw-r--r--src/test/conf_examples/contactinfo_notutf8/expected_log_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/contactinfo_notutf8/expected_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/contactinfo_notutf8/torrc4
-rw-r--r--src/test/conf_examples/controlsock/error1
-rw-r--r--src/test/conf_examples/controlsock/torrc1
-rw-r--r--src/test/conf_examples/crypto_accel/expected2
-rw-r--r--src/test/conf_examples/crypto_accel/expected_log1
-rw-r--r--src/test/conf_examples/crypto_accel/expected_log_nss1
-rw-r--r--src/test/conf_examples/crypto_accel/expected_nss2
-rw-r--r--src/test/conf_examples/crypto_accel/torrc3
-rw-r--r--src/test/conf_examples/crypto_accel_req/error1
-rw-r--r--src/test/conf_examples/crypto_accel_req/expected_log_nss1
-rw-r--r--src/test/conf_examples/crypto_accel_req/expected_nss2
-rw-r--r--src/test/conf_examples/crypto_accel_req/torrc3
-rw-r--r--src/test/conf_examples/dirauth_1/error_no_dirauth1
-rw-r--r--src/test/conf_examples/dirauth_1/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/dirauth_1/expected8
-rw-r--r--src/test/conf_examples/dirauth_1/expected_log1
-rw-r--r--src/test/conf_examples/dirauth_1/torrc8
-rw-r--r--src/test/conf_examples/dirauth_2/expected1
-rw-r--r--src/test/conf_examples/dirauth_2/expected_log1
-rw-r--r--src/test/conf_examples/dirauth_2/expected_log_no_dirauth1
-rw-r--r--src/test/conf_examples/dirauth_2/expected_log_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/dirauth_2/expected_no_dirauth0
-rw-r--r--src/test/conf_examples/dirauth_2/expected_no_dirauth_relay0
-rw-r--r--src/test/conf_examples/dirauth_2/torrc5
-rw-r--r--src/test/conf_examples/empty_1/expected0
-rw-r--r--src/test/conf_examples/empty_1/expected_log1
-rw-r--r--src/test/conf_examples/empty_1/torrc0
-rw-r--r--src/test/conf_examples/empty_2/cmdline0
-rw-r--r--src/test/conf_examples/empty_2/expected0
-rw-r--r--src/test/conf_examples/empty_2/expected_log1
-rw-r--r--src/test/conf_examples/empty_2/torrc0
-rw-r--r--src/test/conf_examples/empty_2/torrc.defaults0
-rw-r--r--src/test/conf_examples/empty_3/expected0
-rw-r--r--src/test/conf_examples/empty_3/expected_log1
-rw-r--r--src/test/conf_examples/empty_3/included/empty0
-rw-r--r--src/test/conf_examples/empty_3/torrc1
-rw-r--r--src/test/conf_examples/empty_4/error1
-rw-r--r--src/test/conf_examples/example_1/expected_log1
-rw-r--r--src/test/conf_examples/example_3/expected_log1
-rw-r--r--src/test/conf_examples/include_1/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/include_1/expected_log1
-rw-r--r--src/test/conf_examples/include_bug_31408/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/include_bug_31408/expected_log1
-rw-r--r--src/test/conf_examples/large_1/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/large_1/expected_log1
-rw-r--r--src/test/conf_examples/large_1/expected_log_no_dirauth1
-rw-r--r--src/test/conf_examples/large_1/expected_no_dirauth158
-rw-r--r--src/test/conf_examples/lzma_zstd_1/expected0
-rw-r--r--src/test/conf_examples/lzma_zstd_1/expected_log1
-rw-r--r--src/test/conf_examples/lzma_zstd_1/expected_log_lzma1
-rw-r--r--src/test/conf_examples/lzma_zstd_1/expected_log_lzma_zstd1
-rw-r--r--src/test/conf_examples/lzma_zstd_1/expected_log_zstd1
-rw-r--r--src/test/conf_examples/lzma_zstd_1/expected_lzma0
-rw-r--r--src/test/conf_examples/lzma_zstd_1/expected_lzma_zstd0
-rw-r--r--src/test/conf_examples/lzma_zstd_1/expected_zstd0
-rw-r--r--src/test/conf_examples/lzma_zstd_1/torrc1
-rw-r--r--src/test/conf_examples/missing_cl_arg/cmdline1
-rw-r--r--src/test/conf_examples/missing_cl_arg/error1
-rw-r--r--src/test/conf_examples/missing_cl_arg/torrc0
-rw-r--r--src/test/conf_examples/nss_1/expected0
-rw-r--r--src/test/conf_examples/nss_1/expected_log1
-rw-r--r--src/test/conf_examples/nss_1/expected_log_nss1
-rw-r--r--src/test/conf_examples/nss_1/expected_nss0
-rw-r--r--src/test/conf_examples/nss_1/torrc1
-rw-r--r--src/test/conf_examples/obsolete_1/expected_log1
-rw-r--r--src/test/conf_examples/obsolete_1/torrc136
-rw-r--r--src/test/conf_examples/obsolete_2/expected_log1
-rw-r--r--src/test/conf_examples/obsolete_2/torrc3
-rw-r--r--src/test/conf_examples/obsolete_3/expected0
-rw-r--r--src/test/conf_examples/obsolete_3/expected_log1
-rw-r--r--src/test/conf_examples/obsolete_3/torrc4
-rw-r--r--src/test/conf_examples/ops_1/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/ops_1/expected_log1
-rw-r--r--src/test/conf_examples/ops_2/expected_log1
-rw-r--r--src/test/conf_examples/ops_3/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/ops_3/expected_log1
-rw-r--r--src/test/conf_examples/ops_4/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/ops_4/expected_log1
-rw-r--r--src/test/conf_examples/ops_5/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/ops_5/expected_log1
-rw-r--r--src/test/conf_examples/ops_6/expected_log1
-rw-r--r--src/test/conf_examples/pt_01/expected0
-rw-r--r--src/test/conf_examples/pt_01/expected_log1
-rw-r--r--src/test/conf_examples/pt_01/torrc7
-rw-r--r--src/test/conf_examples/pt_02/error1
-rw-r--r--src/test/conf_examples/pt_02/expected_log_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/pt_02/expected_no_dirauth_relay8
-rw-r--r--src/test/conf_examples/pt_02/torrc13
-rw-r--r--src/test/conf_examples/pt_03/expected1
-rw-r--r--src/test/conf_examples/pt_03/expected_log1
-rw-r--r--src/test/conf_examples/pt_03/expected_log_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/pt_03/expected_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/pt_03/torrc4
-rw-r--r--src/test/conf_examples/pt_04/expected3
-rw-r--r--src/test/conf_examples/pt_04/expected_log1
-rw-r--r--src/test/conf_examples/pt_04/expected_log_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/pt_04/expected_no_dirauth_relay3
-rw-r--r--src/test/conf_examples/pt_04/torrc6
-rw-r--r--src/test/conf_examples/pt_05/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/pt_05/expected4
-rw-r--r--src/test/conf_examples/pt_05/expected_log1
-rw-r--r--src/test/conf_examples/pt_05/torrc6
-rw-r--r--src/test/conf_examples/pt_06/expected6
-rw-r--r--src/test/conf_examples/pt_06/expected_log1
-rw-r--r--src/test/conf_examples/pt_06/expected_log_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/pt_06/expected_no_dirauth_relay6
-rw-r--r--src/test/conf_examples/pt_06/torrc9
-rw-r--r--src/test/conf_examples/pt_07/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/pt_07/expected4
-rw-r--r--src/test/conf_examples/pt_07/expected_log1
-rw-r--r--src/test/conf_examples/pt_07/torrc6
-rw-r--r--src/test/conf_examples/pt_08/error1
-rw-r--r--src/test/conf_examples/pt_08/expected_log_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/pt_08/expected_no_dirauth_relay2
-rw-r--r--src/test/conf_examples/pt_08/torrc7
-rw-r--r--src/test/conf_examples/pt_09/error1
-rw-r--r--src/test/conf_examples/pt_09/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/pt_09/torrc7
-rw-r--r--src/test/conf_examples/relay_01/expected0
-rw-r--r--src/test/conf_examples/relay_01/expected_log1
-rw-r--r--src/test/conf_examples/relay_01/torrc5
-rw-r--r--src/test/conf_examples/relay_02/error1
-rw-r--r--src/test/conf_examples/relay_02/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_02/torrc7
-rw-r--r--src/test/conf_examples/relay_03/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_03/expected2
-rw-r--r--src/test/conf_examples/relay_03/expected_log1
-rw-r--r--src/test/conf_examples/relay_03/torrc5
-rw-r--r--src/test/conf_examples/relay_04/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_04/expected2
-rw-r--r--src/test/conf_examples/relay_04/expected_log1
-rw-r--r--src/test/conf_examples/relay_04/torrc4
-rw-r--r--src/test/conf_examples/relay_05/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_05/expected3
-rw-r--r--src/test/conf_examples/relay_05/expected_log1
-rw-r--r--src/test/conf_examples/relay_05/torrc5
-rw-r--r--src/test/conf_examples/relay_06/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_06/expected3
-rw-r--r--src/test/conf_examples/relay_06/expected_log1
-rw-r--r--src/test/conf_examples/relay_06/torrc5
-rw-r--r--src/test/conf_examples/relay_07/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_07/expected3
-rw-r--r--src/test/conf_examples/relay_07/expected_log1
-rw-r--r--src/test/conf_examples/relay_07/torrc5
-rw-r--r--src/test/conf_examples/relay_08/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_08/expected3
-rw-r--r--src/test/conf_examples/relay_08/expected_log1
-rw-r--r--src/test/conf_examples/relay_08/torrc6
-rw-r--r--src/test/conf_examples/relay_09/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_09/expected3
-rw-r--r--src/test/conf_examples/relay_09/expected_log1
-rw-r--r--src/test/conf_examples/relay_09/torrc6
-rw-r--r--src/test/conf_examples/relay_10/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_10/expected3
-rw-r--r--src/test/conf_examples/relay_10/expected_log1
-rw-r--r--src/test/conf_examples/relay_10/torrc7
-rw-r--r--src/test/conf_examples/relay_11/error1
-rw-r--r--src/test/conf_examples/relay_11/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_11/torrc4
-rw-r--r--src/test/conf_examples/relay_12/error1
-rw-r--r--src/test/conf_examples/relay_12/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_12/torrc4
-rw-r--r--src/test/conf_examples/relay_13/error1
-rw-r--r--src/test/conf_examples/relay_13/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_13/torrc4
-rw-r--r--src/test/conf_examples/relay_14/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_14/expected1
-rw-r--r--src/test/conf_examples/relay_14/expected_log1
-rw-r--r--src/test/conf_examples/relay_14/torrc4
-rw-r--r--src/test/conf_examples/relay_15/error1
-rw-r--r--src/test/conf_examples/relay_15/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_15/torrc5
-rw-r--r--src/test/conf_examples/relay_16/error1
-rw-r--r--src/test/conf_examples/relay_16/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_16/torrc4
-rw-r--r--src/test/conf_examples/relay_17/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_17/expected4
-rw-r--r--src/test/conf_examples/relay_17/expected_log1
-rw-r--r--src/test/conf_examples/relay_17/torrc6
-rw-r--r--src/test/conf_examples/relay_18/error1
-rw-r--r--src/test/conf_examples/relay_18/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_18/torrc4
-rw-r--r--src/test/conf_examples/relay_19/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_19/expected3
-rw-r--r--src/test/conf_examples/relay_19/expected_log1
-rw-r--r--src/test/conf_examples/relay_19/torrc5
-rw-r--r--src/test/conf_examples/relay_20/error1
-rw-r--r--src/test/conf_examples/relay_20/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_20/torrc5
-rw-r--r--src/test/conf_examples/relay_21/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_21/expected3
-rw-r--r--src/test/conf_examples/relay_21/expected_log1
-rw-r--r--src/test/conf_examples/relay_21/torrc5
-rw-r--r--src/test/conf_examples/relay_22/error1
-rw-r--r--src/test/conf_examples/relay_22/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_22/torrc6
-rw-r--r--src/test/conf_examples/relay_23/error1
-rw-r--r--src/test/conf_examples/relay_23/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_23/torrc5
-rw-r--r--src/test/conf_examples/relay_24/error1
-rw-r--r--src/test/conf_examples/relay_24/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_24/torrc5
-rw-r--r--src/test/conf_examples/relay_25/error1
-rw-r--r--src/test/conf_examples/relay_25/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_25/torrc5
-rw-r--r--src/test/conf_examples/relay_26/error1
-rw-r--r--src/test/conf_examples/relay_26/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_26/torrc5
-rw-r--r--src/test/conf_examples/relay_27/error1
-rw-r--r--src/test/conf_examples/relay_27/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_27/torrc5
-rw-r--r--src/test/conf_examples/relay_28/error1
-rw-r--r--src/test/conf_examples/relay_28/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_28/torrc5
-rw-r--r--src/test/conf_examples/relay_29/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_29/expected2
-rw-r--r--src/test/conf_examples/relay_29/expected_log1
-rw-r--r--src/test/conf_examples/relay_29/torrc5
-rw-r--r--src/test/conf_failures/README5
-rw-r--r--src/test/conf_failures/fail-error-success/error1
-rw-r--r--src/test/conf_failures/fail-error-success/torrc0
-rw-r--r--src/test/conf_failures/fail-error/error1
-rw-r--r--src/test/conf_failures/fail-error/torrc1
-rw-r--r--src/test/conf_failures/fail-expected-error/expected0
-rw-r--r--src/test/conf_failures/fail-expected-error/torrc1
-rw-r--r--src/test/conf_failures/fail-expected-log/expected0
-rw-r--r--src/test/conf_failures/fail-expected-log/expected_log1
-rw-r--r--src/test/conf_failures/fail-expected-log/torrc0
-rw-r--r--src/test/conf_failures/fail-expected/expected1
-rw-r--r--src/test/conf_failures/fail-expected/torrc0
-rw-r--r--src/test/ed25519_exts_ref.py25
-rw-r--r--src/test/fakechans.h2
-rw-r--r--src/test/fakecircs.c91
-rw-r--r--src/test/fakecircs.h17
-rw-r--r--src/test/fuzz/.may_include1
-rw-r--r--src/test/fuzz/fuzz_consensus.c2
-rw-r--r--src/test/fuzz/fuzz_descriptor.c2
-rw-r--r--src/test/fuzz/fuzz_diff.c2
-rw-r--r--src/test/fuzz/fuzz_diff_apply.c2
-rw-r--r--src/test/fuzz/fuzz_extrainfo.c2
-rw-r--r--src/test/fuzz/fuzz_hsdescv2.c2
-rw-r--r--src/test/fuzz/fuzz_hsdescv3.c2
-rw-r--r--src/test/fuzz/fuzz_http.c2
-rw-r--r--src/test/fuzz/fuzz_http_connect.c2
-rw-r--r--src/test/fuzz/fuzz_iptsv2.c2
-rw-r--r--src/test/fuzz/fuzz_microdesc.c2
-rw-r--r--src/test/fuzz/fuzz_socks.c2
-rw-r--r--src/test/fuzz/fuzz_strops.c2
-rw-r--r--src/test/fuzz/fuzz_vrs.c2
-rw-r--r--src/test/fuzz/fuzzing.h2
-rw-r--r--src/test/fuzz/fuzzing_common.c2
-rw-r--r--src/test/hs_build_address.py5
-rw-r--r--src/test/hs_indexes.py5
-rw-r--r--src/test/hs_ntor_ref.py5
-rw-r--r--src/test/hs_test_helpers.c79
-rw-r--r--src/test/hs_test_helpers.h9
-rw-r--r--src/test/include.am13
-rw-r--r--src/test/log_test_helpers.c2
-rw-r--r--src/test/log_test_helpers.h2
-rwxr-xr-xsrc/test/ntor_ref.py7
-rw-r--r--src/test/ope_ref.py5
-rw-r--r--src/test/opts_test_helpers.c38
-rw-r--r--src/test/opts_test_helpers.h22
-rw-r--r--src/test/prob_distr_mpfr_ref.c2
-rw-r--r--src/test/ptr_helpers.c2
-rw-r--r--src/test/ptr_helpers.h2
-rw-r--r--src/test/rend_test_helpers.c2
-rw-r--r--src/test/rend_test_helpers.h2
-rw-r--r--src/test/resolve_test_helpers.c2
-rw-r--r--src/test/resolve_test_helpers.h2
-rw-r--r--src/test/rng_test_helpers.c2
-rw-r--r--src/test/rng_test_helpers.h2
-rw-r--r--src/test/slow_ed25519.py5
-rw-r--r--src/test/slownacl_curve25519.py7
-rw-r--r--src/test/sr_commit_calc_ref.py5
-rw-r--r--src/test/sr_srv_calc_ref.py5
-rw-r--r--src/test/test-memwipe.c2
-rw-r--r--src/test/test-process.c2
-rw-r--r--src/test/test-timers.c4
-rw-r--r--src/test/test.c168
-rw-r--r--src/test/test.h101
-rw-r--r--src/test/test_accounting.c18
-rw-r--r--src/test/test_addr.c10
-rw-r--r--src/test/test_address.c2
-rw-r--r--src/test/test_address_set.c2
-rw-r--r--src/test/test_bridges.c4
-rw-r--r--src/test/test_bt_cl.c6
-rw-r--r--src/test/test_btrack.c2
-rw-r--r--src/test/test_buffers.c2
-rw-r--r--src/test/test_bwmgt.c12
-rw-r--r--src/test/test_cell_formats.c2
-rw-r--r--src/test/test_cell_queue.c2
-rw-r--r--src/test/test_channel.c33
-rw-r--r--src/test/test_channelpadding.c4
-rw-r--r--src/test/test_channeltls.c4
-rw-r--r--src/test/test_checkdir.c2
-rw-r--r--src/test/test_circuitbuild.c2
-rw-r--r--src/test/test_circuitlist.c6
-rw-r--r--src/test/test_circuitmux.c395
-rw-r--r--src/test/test_circuitmux_ewma.c228
-rw-r--r--src/test/test_circuitpadding.c84
-rw-r--r--src/test/test_circuitstats.c4
-rw-r--r--src/test/test_circuituse.c2
-rwxr-xr-xsrc/test/test_cmdline.sh17
-rw-r--r--src/test/test_compat_libevent.c4
-rw-r--r--src/test/test_config.c408
-rw-r--r--src/test/test_confmgr.c186
-rw-r--r--src/test/test_confparse.c63
-rw-r--r--src/test/test_connection.c100
-rw-r--r--src/test/test_connection.h5
-rw-r--r--src/test/test_conscache.c2
-rw-r--r--src/test/test_consdiff.c2
-rw-r--r--src/test/test_consdiffmgr.c6
-rw-r--r--src/test/test_containers.c2
-rw-r--r--src/test/test_controller.c302
-rw-r--r--src/test/test_controller_events.c137
-rw-r--r--src/test/test_crypto.c8
-rw-r--r--src/test/test_crypto_ope.c2
-rw-r--r--src/test/test_crypto_openssl.c2
-rw-r--r--src/test/test_crypto_rng.c2
-rw-r--r--src/test/test_crypto_slow.c4
-rw-r--r--src/test/test_data.c2
-rw-r--r--src/test/test_dir.c568
-rw-r--r--src/test/test_dir_common.c2
-rw-r--r--src/test/test_dir_common.h2
-rw-r--r--src/test/test_dir_handle_get.c87
-rw-r--r--src/test/test_dispatch.c8
-rw-r--r--src/test/test_dns.c189
-rw-r--r--src/test/test_dos.c4
-rw-r--r--src/test/test_entryconn.c4
-rw-r--r--src/test/test_entrynodes.c6
-rw-r--r--src/test/test_extorport.c2
-rw-r--r--src/test/test_geoip.c2
-rw-r--r--src/test/test_guardfraction.c2
-rw-r--r--src/test/test_handles.c2
-rw-r--r--src/test/test_helpers.c90
-rw-r--r--src/test/test_helpers.h5
-rw-r--r--src/test/test_hs.c2
-rw-r--r--src/test/test_hs_cache.c145
-rw-r--r--src/test/test_hs_cell.c2
-rw-r--r--src/test/test_hs_client.c430
-rw-r--r--src/test/test_hs_common.c47
-rw-r--r--src/test/test_hs_config.c2
-rw-r--r--src/test/test_hs_control.c521
-rw-r--r--src/test/test_hs_descriptor.c62
-rw-r--r--src/test/test_hs_dos.c2
-rw-r--r--src/test/test_hs_intropoint.c2
-rw-r--r--src/test/test_hs_ntor.c2
-rwxr-xr-xsrc/test/test_hs_ntor.sh2
-rw-r--r--src/test/test_hs_ntor_cl.c2
-rw-r--r--src/test/test_hs_service.c23
-rw-r--r--src/test/test_introduce.c2
-rwxr-xr-xsrc/test/test_key_expiration.sh26
-rwxr-xr-xsrc/test/test_keygen.sh24
-rw-r--r--src/test/test_keypin.c2
-rw-r--r--src/test/test_link_handshake.c12
-rw-r--r--src/test/test_logging.c2
-rw-r--r--src/test/test_mainloop.c22
-rw-r--r--src/test/test_microdesc.c6
-rw-r--r--src/test/test_namemap.c2
-rw-r--r--src/test/test_netinfo.c2
-rw-r--r--src/test/test_nodelist.c167
-rw-r--r--src/test/test_ntor_cl.c2
-rw-r--r--src/test/test_oom.c2
-rw-r--r--src/test/test_oos.c2
-rw-r--r--src/test/test_options.c2142
-rw-r--r--src/test/test_options_act.c272
-rw-r--r--src/test/test_parsecommon.c2
-rwxr-xr-xsrc/test/test_parseconf.sh583
-rw-r--r--src/test/test_pem.c2
-rw-r--r--src/test/test_periodic_event.c2
-rw-r--r--src/test/test_policy.c2
-rw-r--r--src/test/test_prob_distr.c32
-rw-r--r--src/test/test_process.c2
-rw-r--r--src/test/test_process_descs.c19
-rw-r--r--src/test/test_process_slow.c2
-rw-r--r--src/test/test_procmon.c5
-rw-r--r--src/test/test_proto_haproxy.c66
-rw-r--r--src/test/test_proto_http.c2
-rw-r--r--src/test/test_proto_misc.c2
-rw-r--r--src/test/test_protover.c2
-rw-r--r--src/test/test_pt.c5
-rw-r--r--src/test/test_ptr_slow.c2
-rw-r--r--src/test/test_pubsub_build.c2
-rw-r--r--src/test/test_pubsub_msg.c2
-rw-r--r--src/test/test_rebind.py3
-rwxr-xr-xsrc/test/test_rebind.sh35
-rw-r--r--src/test/test_relay.c41
-rw-r--r--src/test/test_relaycell.c3
-rw-r--r--src/test/test_relaycrypt.c2
-rw-r--r--src/test/test_rendcache.c43
-rw-r--r--src/test/test_replay.c2
-rw-r--r--src/test/test_rng.c2
-rw-r--r--src/test/test_router.c139
-rw-r--r--src/test/test_routerkeys.c2
-rw-r--r--src/test/test_routerlist.c2
-rw-r--r--src/test/test_routerset.c1029
-rw-r--r--src/test/test_scheduler.c60
-rw-r--r--src/test/test_sendme.c2
-rw-r--r--src/test/test_shared_random.c2
-rw-r--r--src/test/test_slow.c2
-rw-r--r--src/test/test_socks.c39
-rw-r--r--src/test/test_stats.c258
-rw-r--r--src/test/test_status.c608
-rw-r--r--src/test/test_storagedir.c2
-rw-r--r--src/test/test_switch_id.c2
-rw-r--r--src/test/test_threads.c4
-rw-r--r--src/test/test_token_bucket.c2
-rw-r--r--src/test/test_tortls.c4
-rw-r--r--src/test/test_tortls.h2
-rw-r--r--src/test/test_tortls_openssl.c10
-rw-r--r--src/test/test_util.c82
-rw-r--r--src/test/test_util_format.c5
-rw-r--r--src/test/test_util_process.c4
-rw-r--r--src/test/test_voting_flags.c6
-rw-r--r--src/test/test_voting_schedule.c2
-rw-r--r--src/test/test_workqueue.c10
-rw-r--r--src/test/test_x509.c2
-rwxr-xr-xsrc/test/test_zero_length_keys.sh40
-rw-r--r--src/test/testing_common.c21
-rw-r--r--src/test/testing_rsakeys.c2
-rw-r--r--src/tools/.may_include1
-rw-r--r--src/tools/tools.md6
-rw-r--r--src/tools/tor-gencert.c6
-rw-r--r--src/tools/tor-print-ed-signing-cert.c2
-rw-r--r--src/tools/tor-resolve.c8
-rw-r--r--src/tools/tor_runner.c2
-rw-r--r--src/trunnel/.may_include1
-rw-r--r--src/trunnel/hs/.may_include1
-rw-r--r--src/win32/orconfig.h5
1484 files changed, 35023 insertions, 14172 deletions
diff --git a/.travis.yml b/.travis.yml
index 3a160840a7..5e99b04cfb 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -59,6 +59,8 @@ matrix:
## We check asciidoc with distcheck, to make sure we remove doc products
- env: DISTCHECK="yes" ASCIIDOC_OPTIONS="" SKIP_MAKE_CHECK="yes"
+ ## We check disable module relay
+ - env: MODULES_OPTIONS="--disable-module-relay"
## We check disable module dirauth
- env: MODULES_OPTIONS="--disable-module-dirauth"
@@ -77,6 +79,9 @@ matrix:
## We clone our stem repo and run `make test-stem`
- env: TEST_STEM="yes" SKIP_MAKE_CHECK="yes"
+ ## We run `make doxygen` without `make check`.
+ - env: SKIP_MAKE_CHECK="yes" DOXYGEN="yes"
+
## macOS builds are very slow, and we have a limited number of
## concurrent macOS jobs. We're not actively developing Rust, so it is
## the lowest priority.
@@ -127,6 +132,8 @@ addons:
- libscrypt-dev
- libseccomp-dev
- libzstd-dev
+ ## Optional build dependencies
+ - coccinelle
- shellcheck
## Conditional build dependencies
## Always installed, so we don't need sudo
@@ -134,6 +141,7 @@ addons:
- docbook-xsl
- docbook-xml
- xmlto
+ - doxygen
## Utilities
## preventing or diagnosing hangs
- timelimit
@@ -156,6 +164,7 @@ addons:
- pkg-config
## Optional build dependencies
- ccache
+ - coccinelle
- shellcheck
## Conditional build dependencies
## Always installed, because manual brew installs are hard to get right
@@ -172,6 +181,8 @@ addons:
osx_image: xcode11.2
before_install:
+ ## Set pipefail: we use pipes
+ - set -o pipefail || echo "pipefail failed"
## Create empty rust directories for non-Rust builds, so caching succeeds
- if [[ "$RUST_OPTIONS" == "" ]]; then mkdir -p $HOME/.cargo $TRAVIS_BUILD_DIR/src/rust/target; fi
@@ -213,6 +224,9 @@ install:
- if [[ "$CHUTNEY" != "" ]]; then pushd "$CHUTNEY_PATH"; git log -1 ; popd ; fi
## If we're running stem, show the stem version and commit
- if [[ "$TEST_STEM" != "" ]]; then pushd stem; python -c "from stem import stem; print(stem.__version__);"; git log -1; popd; fi
+ ## Get the coccinelle version
+ ## Installs are unreliable on macOS, so we just rely on brew list --versions
+ - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then spatch --version; fi
## We don't want Tor tests to depend on default configuration file at
## ~/.torrc. So we put some random bytes in there, to make sure we get build
## failures in case Tor is reading it during CI jobs.
@@ -232,6 +246,7 @@ script:
## Diagnostic for bug 29437: kill stem if it hangs for 9.5 minutes
## Travis will kill the job after 10 minutes with no output
- if [[ "$TEST_STEM" != "" ]]; then make src/app/tor; timelimit -p -t 540 -s USR1 -T 30 -S ABRT python3 "$STEM_SOURCE_DIR"/run_tests.py --tor src/app/tor --integ --test control.controller --test control.base_controller --test process --log TRACE --log-file stem.log; fi
+ - if [[ "$DOXYGEN" != "" ]]; then make doxygen; fi
## If this build was one that produced coverage, upload it.
- if [[ "$COVERAGE_OPTIONS" != "" ]]; then coveralls -b . --exclude src/test --exclude src/trunnel --gcov-options '\-p' || echo "Coverage failed"; fi
diff --git a/ChangeLog b/ChangeLog
index 5b86efe7bd..b5dc9f692a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,1844 @@
+Changes in version 0.4.3.2-alpha - 2020-02-10
+ This is the second stable alpha release in the Tor 0.4.3.x series. It
+ fixes several bugs present in the previous alpha release. Anybody
+ running the previous alpha should upgrade, and look for bugs in this
+ one instead.
+
+ o Major bugfixes (onion service client, authorization):
+ - On a NEWNYM signal, purge entries from the ephemeral client
+ authorization cache. The permanent ones are kept. Fixes bug 33139;
+ bugfix on 0.4.3.1-alpha.
+
+ o Minor features (best practices tracker):
+ - Practracker now supports a --regen-overbroad option to regenerate
+ the exceptions file, but only to revise exceptions to be _less_
+ tolerant of best-practices violations. Closes ticket 32372.
+
+ o Minor features (continuous integration):
+ - Run Doxygen Makefile target on Travis, so we can learn about
+ regressions in our internal documentation. Closes ticket 32455.
+ - Stop allowing failures on the Travis CI stem tests job. It looks
+ like all the stem hangs we were seeing before are now fixed.
+ Closes ticket 33075.
+
+ o Minor bugfixes (build system):
+ - Revise configure options that were either missing or incorrect in
+ the configure summary. Fixes bug 32230; bugfix on 0.4.3.1-alpha.
+
+ o Minor bugfixes (controller protocol):
+ - Fix a memory leak introduced by refactoring of control reply
+ formatting code. Fixes bug 33039; bugfix on 0.4.3.1-alpha.
+ - Fix a memory leak in GETINFO responses. Fixes bug 33103; bugfix
+ on 0.4.3.1-alpha.
+ - When receiving "ACTIVE" or "DORMANT" signals on the control port,
+ report them as SIGNAL events. Previously we would log a bug
+ warning. Fixes bug 33104; bugfix on 0.4.0.1-alpha.
+
+ o Minor bugfixes (logging):
+ - If we encounter a bug when flushing a buffer to a TLS connection,
+ only log the bug once per invocation of the Tor process.
+ Previously we would log with every occurrence, which could cause
+ us to run out of disk space. Fixes bug 33093; bugfix
+ on 0.3.2.2-alpha.
+ - When logging a bug, do not say "Future instances of this warning
+ will be silenced" unless we are actually going to silence them.
+ Previously we would say this whenever a BUG() check failed in the
+ code. Fixes bug 33095; bugfix on 0.4.1.1-alpha.
+
+ o Minor bugfixes (onion service v2):
+ - Move a series of v2 onion service warnings to protocol-warning
+ level because they can all be triggered remotely by a malformed
+ request. Fixes bug 32706; bugfix on 0.1.1.14-alpha.
+
+ o Minor bugfixes (onion service v3, client authorization):
+ - When removing client authorization credentials using the control
+ port, also remove the associated descriptor, so the onion service
+ can no longer be contacted. Fixes bug 33148; bugfix
+ on 0.4.3.1-alpha.
+
+ o Minor bugfixes (pluggable transports):
+ - When receiving a message on standard error from a pluggable
+ transport, log it at info level, rather than as a warning. Fixes
+ bug 33005; bugfix on 0.4.0.1-alpha.
+
+ o Minor bugfixes (rust, build):
+ - Fix a syntax warning given by newer versions of Rust that was
+ creating problems for our continuous integration. Fixes bug 33212;
+ bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (TLS bug handling):
+ - When encountering a bug in buf_read_from_tls(), return a "MISC"
+ error code rather than "WANTWRITE". This change might help avoid
+ some CPU-wasting loops if the bug is ever triggered. Bug reported
+ by opara. Fixes bug 32673; bugfix on 0.3.0.4-alpha.
+
+ o Code simplification and refactoring (mainloop):
+ - Simplify the ip_address_changed() function by removing redundant
+ checks. Closes ticket 33091.
+
+ o Documentation (manpage):
+ - Split "Circuit Timeout" options and "Node Selection" options into
+ their own sections of the tor manpage. Closes tickets 32928 and
+ 32929. Work by Swati Thacker as part of Google Season of Docs.
+
+
+Changes in version 0.4.2.6 - 2020-01-30
+ This is the second stable release in the 0.4.2.x series. It backports
+ several bugfixes from 0.4.3.1-alpha, including some that had affected
+ the Linux seccomp2 sandbox or Windows services. If you're running with
+ one of those configurations, you'll probably want to upgrade;
+ otherwise, you should be fine with 0.4.2.5.
+
+ o Major bugfixes (linux seccomp sandbox, backport from 0.4.3.1-alpha):
+ - Correct how we use libseccomp. Particularly, stop assuming that
+ rules are applied in a particular order or that more rules are
+ processed after the first match. Neither is the case! In
+ libseccomp <2.4.0 this led to some rules having no effect.
+ libseccomp 2.4.0 changed how rules are generated, leading to a
+ different ordering, which in turn led to a fatal crash during
+ startup. Fixes bug 29819; bugfix on 0.2.5.1-alpha. Patch by
+ Peter Gerber.
+ - Fix crash when reloading logging configuration while the
+ experimental sandbox is enabled. Fixes bug 32841; bugfix on
+ 0.4.1.7. Patch by Peter Gerber.
+
+ o Minor bugfixes (correctness checks, backport from 0.4.3.1-alpha):
+ - Use GCC/Clang's printf-checking feature to make sure that
+ tor_assertf() arguments are correctly typed. Fixes bug 32765;
+ bugfix on 0.4.1.1-alpha.
+
+ o Minor bugfixes (logging, crash, backport from 0.4.3.1-alpha):
+ - Avoid a possible crash when trying to log a (fatal) assertion
+ failure about mismatched magic numbers in configuration objects.
+ Fixes bug 32771; bugfix on 0.4.2.1-alpha.
+
+ o Minor bugfixes (testing, backport from 0.4.3.1-alpha):
+ - When TOR_DISABLE_PRACTRACKER is set, do not apply it to the
+ test_practracker.sh script. Doing so caused a test failure. Fixes
+ bug 32705; bugfix on 0.4.2.1-alpha.
+ - When TOR_DISABLE_PRACTRACKER is set, log a notice to stderr when
+ skipping practracker checks. Fixes bug 32705; bugfix
+ on 0.4.2.1-alpha.
+
+ o Minor bugfixes (windows service, backport from 0.4.3.1-alpha):
+ - Initialize the publish/subscribe system when running as a windows
+ service. Fixes bug 32778; bugfix on 0.4.1.1-alpha.
+
+ o Testing (backport from 0.4.3.1-alpha):
+ - Turn off Tor's Sandbox in Chutney jobs, and run those jobs on
+ Ubuntu Bionic. Turning off the Sandbox is a work-around, until we
+ fix the sandbox errors in 32722. Closes ticket 32240.
+ - Re-enable the Travis CI macOS Chutney build, but don't let it
+ prevent the Travis job from finishing. (The Travis macOS jobs are
+ slow, so we don't want to have it delay the whole CI process.)
+ Closes ticket 32629.
+
+ o Testing (continuous integration, backport from 0.4.3.1-alpha):
+ - Use zstd in our Travis Linux builds. Closes ticket 32242.
+
+
+Changes in version 0.4.1.8 - 2020-01-30
+ This release backports several bugfixes from later release series,
+ including some that had affected the Linux seccomp2 sandbox or Windows
+ services. If you're running with one of those configurations, you'll
+ probably want to upgrade; otherwise, you should be fine with your
+ current version of 0.4.1.x.
+
+ o Major bugfixes (linux seccomp sandbox, backport from 0.4.3.1-alpha):
+ - Correct how we use libseccomp. Particularly, stop assuming that
+ rules are applied in a particular order or that more rules are
+ processed after the first match. Neither is the case! In
+ libseccomp <2.4.0 this led to some rules having no effect.
+ libseccomp 2.4.0 changed how rules are generated, leading to a
+ different ordering, which in turn led to a fatal crash during
+ startup. Fixes bug 29819; bugfix on 0.2.5.1-alpha. Patch by
+ Peter Gerber.
+ - Fix crash when reloading logging configuration while the
+ experimental sandbox is enabled. Fixes bug 32841; bugfix on
+ 0.4.1.7. Patch by Peter Gerber.
+
+ o Minor bugfixes (crash, backport form 0.4.2.4-rc):
+ - When running Tor with an option like --verify-config or
+ --dump-config that does not start the event loop, avoid crashing
+ if we try to exit early because of an error. Fixes bug 32407;
+ bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (windows service, backport from 0.4.3.1-alpha):
+ - Initialize the publish/subscribe system when running as a windows
+ service. Fixes bug 32778; bugfix on 0.4.1.1-alpha.
+
+ o Testing (backport from 0.4.3.1-alpha):
+ - Turn off Tor's Sandbox in Chutney jobs, and run those jobs on
+ Ubuntu Bionic. Turning off the Sandbox is a work-around, until we
+ fix the sandbox errors in 32722. Closes ticket 32240.
+ - Re-enable the Travis CI macOS Chutney build, but don't let it
+ prevent the Travis job from finishing. (The Travis macOS jobs are
+ slow, so we don't want to have it delay the whole CI process.)
+ Closes ticket 32629.
+
+ o Testing (continuous integration, backport from 0.4.3.1-alpha):
+ - Use zstd in our Travis Linux builds. Closes ticket 32242.
+
+
+Changes in version 0.4.3.1-alpha - 2020-01-22
+ This is the first alpha release in the 0.4.3.x series. It includes
+ improved support for application integration of onion services, support
+ for building in a client-only mode, and newly improved internal
+ documentation (online at https://src-ref.docs.torproject.org/tor/). It
+ also has numerous other small bugfixes and features, as well as
+ improvements to our code's internal organization that should help us
+ write better code in the future.
+
+ o New system requirements:
+ - When building Tor, you now need to have Python 3 in order to run
+ the integration tests. (Python 2 is officially unsupported
+ upstream, as of 1 Jan 2020.) Closes ticket 32608.
+
+ o Major features (build system):
+ - The relay code can now be disabled using the --disable-module-relay
+ configure option. When this option is set, we also disable the
+ dirauth module. Closes ticket 32123.
+ - When Tor is compiled --disable-module-relay, we also omit the code
+ used to act as a directory cache. Closes ticket 32487.
+
+ o Major features (directory authority, ed25519):
+ - Add support for banning a relay's ed25519 keys in the approved-
+ routers file. This will help us migrate away from RSA keys in the
+ future. Previously, only RSA keys could be banned in approved-
+ routers. Resolves ticket 22029. Patch by Neel Chauhan.
+
+ o Major features (onion service, controller):
+ - New control port commands to manage client-side onion service
+ authorization credentials. The ONION_CLIENT_AUTH_ADD command adds
+ a credential, ONION_CLIENT_AUTH_REMOVE deletes a credential, and
+ ONION_CLIENT_AUTH_VIEW lists the credentials. Closes ticket 30381.
+
+ o Major features (onion service, SOCKS5):
+ - Introduce a new SocksPort flag, ExtendedErrors, to support more
+ detailed error codes in information for applications that support
+ them. Closes ticket 30382; implements proposal 304.
+
+ o Major features (proxy):
+ - In addition to its current supported proxy types (HTTP CONNECT,
+ SOCKS4, and SOCKS5), Tor can now make its OR connections through a
+ HAProxy server. A new torrc option was added to specify the
+ address/port of the server: TCPProxy <protocol> <host>:<port>.
+ Currently the only supported protocol for the option is haproxy.
+ Closes ticket 31518. Patch done by Suphanat Chunhapanya (haxxpop).
+
+ o Major bugfixes (linux seccomp sandbox):
+ - Correct how we use libseccomp. Particularly, stop assuming that
+ rules are applied in a particular order or that more rules are
+ processed after the first match. Neither is the case! In
+ libseccomp <2.4.0 this led to some rules having no effect.
+ libseccomp 2.4.0 changed how rules are generated, leading to a
+ different ordering, which in turn led to a fatal crash during
+ startup. Fixes bug 29819; bugfix on 0.2.5.1-alpha. Patch by
+ Peter Gerber.
+ - Fix crash when reloading logging configuration while the
+ experimental sandbox is enabled. Fixes bug 32841; bugfix on
+ 0.4.1.7. Patch by Peter Gerber.
+
+ o Major bugfixes (networking):
+ - Correctly handle IPv6 addresses in SOCKS5 RESOLVE_PTR requests,
+ and accept strings as well as binary addresses. Fixes bug 32315;
+ bugfix on 0.3.5.1-alpha.
+
+ o Major bugfixes (onion service):
+ - Report HS circuit failure back into the HS subsystem so we take
+ appropriate action with regards to the client introduction point
+ failure cache. This improves reachability of onion services, since
+ now clients notice failing introduction circuits properly. Fixes
+ bug 32020; bugfix on 0.3.2.1-alpha.
+
+ o Minor feature (configure, build system):
+ - Output a list of enabled/disabled features at the end of the
+ configure process in a pleasing way. Closes ticket 31373.
+
+ o Minor feature (heartbeat, onion service):
+ - Add the DoS INTRODUCE2 defenses counter to the heartbeat DoS
+ message. Closes ticket 31371.
+
+ o Minor features (configuration validation):
+ - Configuration validation can now be done by per-module callbacks,
+ rather than a global validation function. This will let us reduce
+ the size of config.c and some of its more cumbersome functions.
+ Closes ticket 31241.
+
+ o Minor features (configuration):
+ - If a configured hardware crypto accelerator in AccelName is
+ prefixed with "!", Tor now exits when it cannot be found. Closes
+ ticket 32406.
+ - We now use flag-driven logic to warn about obsolete configuration
+ fields, so that we can include their names. In 0.4.2, we used a
+ special type, which prevented us from generating good warnings.
+ Implements ticket 32404.
+
+ o Minor features (controller):
+ - Add stream isolation data to STREAM event. Closes ticket 19859.
+ - Implement a new GETINFO command to fetch microdescriptor
+ consensus. Closes ticket 31684.
+
+ o Minor features (debugging, directory system):
+ - Don't crash when we find a non-guard with a guard-fraction value
+ set. Instead, log a bug warning, in an attempt to figure out how
+ this happened. Diagnostic for ticket 32868.
+
+ o Minor features (defense in depth):
+ - Add additional checks around tor_vasprintf() usage, in case the
+ function returns an error. Patch by Tobias Stoeckmann. Fixes
+ ticket 31147.
+
+ o Minor features (developer tooling):
+ - Remove the 0.2.9.x series branches from git scripts (git-merge-
+ forward.sh, git-pull-all.sh, git-push-all.sh, git-setup-dirs.sh).
+ Closes ticket 32772.
+
+ o Minor features (developer tools):
+ - Add a check_cocci_parse.sh script that checks that new code is
+ parseable by Coccinelle. Add an exceptions file for unparseable
+ files, and run the script from travis CI. Closes ticket 31919.
+ - Call the check_cocci_parse.sh script from a 'check-cocci' Makefile
+ target. Closes ticket 31919.
+ - Add a rename_c_identifiers.py tool to rename a bunch of C
+ identifiers at once, and generate a well-formed commit message
+ describing the change. This should help with refactoring. Closes
+ ticket 32237.
+ - Add some scripts in "scripts/coccinelle" to invoke the Coccinelle
+ semantic patching tool with the correct flags. These flags are
+ fairly easy to forget, and these scripts should help us use
+ Coccinelle more effectively in the future. Closes ticket 31705.
+
+ o Minor features (Doxygen):
+ - Update Doxygen configuration file to a more recent template (from
+ 1.8.15). Closes ticket 32110.
+ - "make doxygen" now works with out-of-tree builds. Closes
+ ticket 32113.
+ - Make sure that doxygen outputs documentation for all of our C
+ files. Previously, some were missing @file declarations, causing
+ them to be ignored. Closes ticket 32307.
+ - Our "make doxygen" target now respects --enable-fatal-warnings by
+ default, and does not warn about items that are missing
+ documentation. To warn about missing documentation, run configure
+ with the "--enable-missing-doc-warnings" flag: doing so suspends
+ fatal warnings for doxygen. Closes ticket 32385.
+
+ o Minor features (git scripts):
+ - Add TOR_EXTRA_CLONE_ARGS to git-setup-dirs.sh for git clone
+ customisation. Closes ticket 32347.
+ - Add git-setup-dirs.sh, which sets up an upstream git repository
+ and worktrees for tor maintainers. Closes ticket 29603.
+ - Add TOR_EXTRA_REMOTE_* to git-setup-dirs.sh for a custom extra
+ remote. Closes ticket 32347.
+ - Call the check_cocci_parse.sh script from the git commit and push
+ hooks. Closes ticket 31919.
+ - Make git-push-all.sh skip unchanged branches when pushing to
+ upstream. The script already skipped unchanged test branches.
+ Closes ticket 32216.
+ - Make git-setup-dirs.sh create a master symlink in the worktree
+ directory. Closes ticket 32347.
+ - Skip unmodified source files when doing some existing git hook
+ checks. Related to ticket 31919.
+
+ o Minor features (IPv6, client):
+ - Make Tor clients tell dual-stack exits that they prefer IPv6
+ connections. This change is equivalent to setting the PreferIPv6
+ flag on SOCKSPorts (and most other listener ports). Tor Browser
+ has been setting this flag for some time, and we want to remove a
+ client distinguisher at exits. Closes ticket 32637.
+
+ o Minor features (portability, android):
+ - When building for Android, disable some tests that depend on $HOME
+ and/or pwdb, which Android doesn't have. Closes ticket 32825.
+ Patch from Hans-Christoph Steiner.
+
+ o Minor features (relay modularity):
+ - Split the relay and server pluggable transport config code into
+ separate files in the relay module. Disable this code when the
+ relay module is disabled. Closes part of ticket 32213.
+ - When the relay module is disabled, reject attempts to set the
+ ORPort, DirPort, DirCache, BridgeRelay, ExtORPort, or
+ ServerTransport* options, rather than ignoring the values of these
+ options. Closes part of ticket 32213.
+
+ o Minor features (relay):
+ - When the relay module is disabled, change the default config so
+ that DirCache is 0, and ClientOnly is 1. Closes ticket 32410.
+
+ o Minor features (release tools):
+ - Port our ChangeLog formatting and sorting tools to Python 3.
+ Closes ticket 32704.
+
+ o Minor features (testing):
+ - Detect some common failure cases for test_parseconf.sh in
+ src/test/conf_failures. Closes ticket 32451.
+ - Allow test_parseconf.sh to test expected log outputs for successful
+ configs, as well as failed configs. Closes ticket 32451.
+ - The test_parseconf.sh script now supports result variants for any
+ combination of the optional libraries lzma, nss, and zstd. Closes
+ ticket 32397.
+
+ o Minor features (tests, Android):
+ - When running the unit tests on Android, create temporary files in
+ a subdirectory of /data/local/tmp. Closes ticket 32172. Based on a
+ patch from Hans-Christoph Steiner.
+
+ o Minor bugfixes (bridges):
+ - Lowercase the configured value of BridgeDistribution before adding
+ it to the descriptor. Fixes bug 32753; bugfix on 0.3.2.3-alpha.
+
+ o Minor bugfixes (build system):
+ - Fix "make autostyle" for out-of-tree builds. Fixes bug 32370;
+ bugfix on 0.4.1.2-alpha.
+
+ o Minor bugfixes (configuration handling):
+ - Make control_event_conf_changed() take in a config_line_t instead
+ of a smartlist of alternating key/value entries. Fixes bug 31531;
+ bugfix on 0.2.3.3-alpha. Patch by Neel Chauhan.
+
+ o Minor bugfixes (configuration):
+ - Check for multiplication overflow when parsing memory units inside
+ configuration. Fixes bug 30920; bugfix on 0.0.9rc1.
+ - When dumping the configuration, stop adding a trailing space after
+ the option name when there is no option value. This issue only
+ affects options that accept an empty value or list. (Most options
+ reject empty values, or delete the entire line from the dumped
+ options.) Fixes bug 32352; bugfix on 0.0.9pre6.
+ - Avoid changing the user's value of HardwareAccel as stored by
+ SAVECONF, when AccelName is set but HardwareAccel is not. Fixes
+ bug 32382; bugfix on 0.2.2.1-alpha.
+ - When creating a KeyDirectory with the same location as the
+ DataDirectory (not recommended), respect the DataDirectory's
+ group-readable setting if one has not been set for the
+ KeyDirectory. Fixes bug 27992; bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (controller):
+ - In routerstatus_has_changed(), check all the fields that are
+ output over the control port. Fixes bug 20218; bugfix
+ on 0.1.1.11-alpha
+
+ o Minor bugfixes (correctness checks):
+ - Use GCC/Clang's printf-checking feature to make sure that
+ tor_assertf() arguments are correctly typed. Fixes bug 32765;
+ bugfix on 0.4.1.1-alpha.
+
+ o Minor bugfixes (developer tools):
+ - Allow paths starting with ./ in scripts/add_c_file.py. Fixes bug
+ 31336; bugfix on 0.4.1.2-alpha.
+
+ o Minor bugfixes (dirauth module):
+ - Split the dirauth config code into a separate file in the dirauth
+ module. Disable this code when the dirauth module is disabled.
+ Closes ticket 32213.
+ - When the dirauth module is disabled, reject attempts to set the
+ AuthoritativeDir option, rather than ignoring the value of the
+ option. Fixes bug 32213; bugfix on 0.3.4.1-alpha.
+
+ o Minor bugfixes (embedded Tor):
+ - When starting Tor any time after the first time in a process,
+ register the thread in which it is running as the main thread.
+ Previously, we only did this on Windows, which could lead to bugs
+ like 23081 on non-Windows platforms. Fixes bug 32884; bugfix
+ on 0.3.3.1-alpha.
+
+ o Minor bugfixes (git scripts):
+ - Avoid sleeping before the last push in git-push-all.sh. Closes
+ ticket 32216.
+ - Forward all unrecognised arguments in git-push-all.sh to git push.
+ Closes ticket 32216.
+
+ o Minor bugfixes (hidden service v3):
+ - Do not rely on a "circuit established" flag for intro circuits but
+ instead always query the HS circuit map. This is to avoid sync
+ issue with that flag and the map. Fixes bug 32094; bugfix
+ on 0.3.2.1-alpha.
+
+ o Minor bugfixes (logging, crash):
+ - Avoid a possible crash when trying to log a (fatal) assertion
+ failure about mismatched magic numbers in configuration objects.
+ Fixes bug 32771; bugfix on 0.4.2.1-alpha.
+
+ o Minor bugfixes (onion service v2):
+ - When sending the INTRO cell for a v2 Onion Service, look at the
+ failure cache alongside timeout values to check if the intro point
+ is marked as failed. Previously, we only looked at the relay
+ timeout values. Fixes bug 25568; bugfix on 0.2.7.3-rc. Patch by
+ Neel Chauhan.
+
+ o Minor bugfixes (onion services v3, client):
+ - Properly handle the client rendezvous circuit timeout. Previously
+ Tor would sometimes timeout a rendezvous circuit awaiting the
+ introduction ACK, and find itself unable to re-establish all
+ circuits because the rendezvous circuit timed out too early. Fixes
+ bug 32021; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfixes (onion services):
+ - In cancel_descriptor_fetches(), use
+ connection_list_by_type_purpose() instead of
+ connection_list_by_type_state(). Fixes bug 32639; bugfix on
+ 0.3.2.1-alpha. Patch by Neel Chauhan.
+
+ o Minor bugfixes (scripts):
+ - Fix update_versions.py for out-of-tree builds. Fixes bug 32371;
+ bugfix on 0.4.0.1-alpha.
+
+ o Minor bugfixes (test):
+ - Use the same code to find the tor binary in all of our test
+ scripts. This change makes sure we are always using the coverage
+ binary when coverage is enabled. Fixes bug 32368; bugfix
+ on 0.2.7.3-rc.
+
+ o Minor bugfixes (testing):
+ - Stop ignoring "tor --dump-config" errors in test_parseconf.sh.
+ Fixes bug 32468; bugfix on 0.4.2.1-alpha.
+ - When TOR_DISABLE_PRACTRACKER is set, do not apply it to the
+ test_practracker.sh script. Doing so caused a test failure. Fixes
+ bug 32705; bugfix on 0.4.2.1-alpha.
+ - When TOR_DISABLE_PRACTRACKER is set, log a notice to stderr when
+ skipping practracker checks. Fixes bug 32705; bugfix
+ on 0.4.2.1-alpha.
+
+ o Minor bugfixes (tests):
+ - Our option-validation tests no longer depend on specially
+ configured non-default, non-passing sets of options. Previously,
+ the tests had been written to assume that options would _not_ be
+ set to their defaults, which led to needless complexity and
+ verbosity. Fixes bug 32175; bugfix on 0.2.8.1-alpha.
+
+ o Minor bugfixes (windows service):
+ - Initialize the publish/subscribe system when running as a windows
+ service. Fixes bug 32778; bugfix on 0.4.1.1-alpha.
+
+ o Deprecated features:
+ - Deprecate the ClientAutoIPv6ORPort option. This option was not
+ true "Happy Eyeballs", and often failed on connections that
+ weren't reliably dual-stack. Closes ticket 32942. Patch by
+ Neel Chauhan.
+
+ o Documentation:
+ - Provide a quickstart guide for a Circuit Padding Framework, and
+ documentation for researchers to implement and study circuit
+ padding machines. Closes ticket 28804.
+ - Add documentation in 'HelpfulTools.md' to describe how to build a
+ tag file. Closes ticket 32779.
+ - Create a high-level description of the long-term software
+ architecture goals. Closes ticket 32206.
+ - Describe the --dump-config command in the manual page. Closes
+ ticket 32467.
+ - Unite coding advice from this_not_that.md in torguts repo into our
+ coding standards document. Resolves ticket 31853.
+
+ o Removed features:
+ - Our Doxygen configuration no longer generates LaTeX output. The
+ reference manual produced by doing this was over 4000 pages long,
+ and generally unusable. Closes ticket 32099.
+ - The option "TestingEstimatedDescriptorPropagationTime" is now
+ marked as obsolete. It has had no effect since 0.3.0.7, when
+ clients stopped rejecting consensuses "from the future". Closes
+ ticket 32807.
+ - We no longer support consensus methods before method 28; these
+ methods were only used by authorities running versions of Tor that
+ are now at end-of-life. In effect, this means that clients,
+ relays, and authorities now assume that authorities will be
+ running version 0.3.5.x or later. Closes ticket 32695.
+
+ o Testing:
+ - Add more test cases for tor's UTF-8 validation function. Also,
+ check the arguments passed to the function for consistency. Closes
+ ticket 32845.
+ - Improve test coverage for relay and dirauth config code, focusing
+ on option validation and normalization. Closes ticket 32213.
+ - Improve the consistency of test_parseconf.sh output, and run all
+ the tests, even if one fails. Closes ticket 32213.
+ - Re-enable the Travis CI macOS Chutney build, but don't let it
+ prevent the Travis job from finishing. (The Travis macOS jobs are
+ slow, so we don't want to have it delay the whole CI process.)
+ Closes ticket 32629.
+ - Run the practracker unit tests in the pre-commit git hook. Closes
+ ticket 32609.
+ - Turn off Tor's Sandbox in Chutney jobs, and run those jobs on
+ Ubuntu Bionic. Turning off the Sandbox is a work-around, until we
+ fix the sandbox errors in 32722. Closes ticket 32240.
+
+ o Code simplification and refactoring (channel):
+ - Channel layer had a variable length cell handler that was not used
+ and thus removed. Closes ticket 32892.
+
+ o Code simplification and refactoring (configuration):
+ - Immutability is now implemented as a flag on individual
+ configuration options rather than as part of the option-transition
+ checking code. Closes ticket 32344.
+ - Instead of keeping a list of configuration options to check for
+ relative paths, check all the options whose type is "FILENAME".
+ Solves part of ticket 32339.
+ - Our default log (which ordinarily sends NOTICE-level messages to
+ standard output) is now handled in a more logical manner.
+ Previously, we replaced the configured log options if they were
+ empty. Now, we interpret an empty set of log options as meaning
+ "use the default log". Closes ticket 31999.
+ - Remove some unused arguments from the options_validate() function,
+ to simplify our code and tests. Closes ticket 32187.
+ - Simplify the options_validate() code so that it looks at the
+ default options directly, rather than taking default options as an
+ argument. This change lets us simplify its interface. Closes
+ ticket 32185.
+ - Use our new configuration architecture to move most authority-
+ related options to the directory authority module. Closes
+ ticket 32806.
+ - When parsing the command line, handle options that determine our
+ "quiet level" and our mode of operation (e.g., --dump-config and
+ so on) all in one table. Closes ticket 32003.
+
+ o Code simplification and refactoring (controller):
+ - Create a new abstraction for formatting control protocol reply
+ lines based on key-value pairs. Refactor some existing control
+ protocol code to take advantage of this. Closes ticket 30984.
+ - Create a helper function that can fetch network status or
+ microdesc consensuses. Closes ticket 31684.
+
+ o Code simplification and refactoring (dirauth modularization):
+ - Remove the last remaining HAVE_MODULE_DIRAUTH inside a function.
+ Closes ticket 32163.
+ - Replace some confusing identifiers in process_descs.c. Closes
+ ticket 29826.
+ - Simplify some relay and dirauth config code. Closes ticket 32213.
+
+ o Code simplification and refactoring (misc):
+ - Make all the structs we declare follow the same naming convention
+ of ending with "_t". Closes ticket 32415.
+ - Move and rename some configuration-related code for clarity.
+ Closes ticket 32304.
+ - Our include.am files are now broken up by subdirectory.
+ Previously, src/core/include.am covered all of the subdirectories
+ in "core", "feature", and "app". Closes ticket 32137.
+ - Remove underused NS*() macros from test code: they make our tests
+ more confusing, especially for code-formatting tools. Closes
+ ticket 32887.
+
+ o Code simplification and refactoring (relay modularization):
+ - Disable relay_periodic when the relay module is disabled. Closes
+ ticket 32244.
+ - Disable relay_sys when the relay module is disabled. Closes
+ ticket 32245.
+
+ o Code simplification and refactoring (tool support):
+ - Add numerous missing dependencies to our include files, so that
+ they can be included in different reasonable orders and still
+ compile. Addresses part of ticket 32764.
+ - Fix some parts of our code that were difficult for Coccinelle to
+ parse. Related to ticket 31705.
+ - Fix some small issues in our code that prevented automatic
+ formatting tools from working. Addresses part of ticket 32764.
+
+ o Documentation (manpage):
+ - Alphabetize the Client Options section of the tor manpage. Closes
+ ticket 32846.
+ - Alphabetize the General Options section of the tor manpage. Closes
+ ticket 32708.
+ - In the tor(1) manpage, reword and improve formatting of the
+ COMMAND-LINE OPTIONS and DESCRIPTION sections. Closes ticket
+ 32277. Based on work by Swati Thacker as part of Google Season
+ of Docs.
+ - In the tor(1) manpage, reword and improve formatting of the FILES,
+ SEE ALSO, and BUGS sections. Closes ticket 32176. Based on work by
+ Swati Thacker as part of Google Season of Docs.
+
+ o Testing (circuit, EWMA):
+ - Add unit tests for circuitmux and EWMA subsystems. Closes
+ ticket 32196.
+
+ o Testing (continuous integration):
+ - Use zstd in our Travis Linux builds. Closes ticket 32242.
+
+
+Changes in version 0.4.2.5 - 2019-12-09
+ This is the first stable release in the 0.4.2.x series. This series
+ improves reliability and stability, and includes several stability and
+ correctness improvements for onion services. It also fixes many smaller
+ bugs present in previous series.
+
+ Per our support policy, we will support the 0.4.2.x series for nine
+ months, or until three months after the release of a stable 0.4.3.x:
+ whichever is longer. If you need longer-term support, please stick
+ with 0.3.5.x, which will we plan to support until Feb 2022.
+
+ Per our support policy, we will support the 0.4.2.x series for nine
+ months, or until three months after the release of a stable 0.4.3.x:
+ whichever is longer. If you need longer-term support, please stick
+ with 0.3.5.x, which will we plan to support until Feb 2022.
+
+ Below are the changes since 0.4.1.4-rc. For a complete list of changes
+ since 0.4.1.5, see the ReleaseNotes file.
+
+ o Minor features (geoip):
+ - Update geoip and geoip6 to the December 3 2019 Maxmind GeoLite2
+ Country database. Closes ticket 32685.
+
+ o Testing:
+ - Require C99 standards-conforming code in Travis CI, but allow GNU
+ gcc extensions. Also activates clang's -Wtypedef-redefinition
+ warnings. Build some jobs with -std=gnu99, and some jobs without.
+ Closes ticket 32500.
+
+
+Changes in version 0.4.1.7 - 2019-12-09
+ This release backports several bugfixes to improve stability and
+ correctness. Anyone experiencing build problems or crashes with 0.4.1.6,
+ including all relays relying on AccountingMax, should upgrade.
+
+ o Major features (directory authorities, backport from 0.4.2.2-alpha):
+ - Directory authorities now reject relays running all currently
+ deprecated release series. The currently supported release series
+ are: 0.2.9, 0.3.5, 0.4.0, 0.4.1, and 0.4.2. Closes ticket 31549.
+
+ o Major bugfixes (embedded Tor, backport from 0.4.2.2-alpha):
+ - Avoid a possible crash when restarting Tor in embedded mode and
+ enabling a different set of publish/subscribe messages. Fixes bug
+ 31898; bugfix on 0.4.1.1-alpha.
+
+ o Major bugfixes (relay, backport from 0.4.2.3-alpha):
+ - Relays now respect their AccountingMax bandwidth again. When
+ relays entered "soft" hibernation (which typically starts when
+ we've hit 90% of our AccountingMax), we had stopped checking
+ whether we should enter hard hibernation. Soft hibernation refuses
+ new connections and new circuits, but the existing circuits can
+ continue, meaning that relays could have exceeded their configured
+ AccountingMax. Fixes bug 32108; bugfix on 0.4.0.1-alpha.
+
+ o Major bugfixes (torrc parsing, backport from 0.4.2.2-alpha):
+ - Stop ignoring torrc options after an %include directive, when the
+ included directory ends with a file that does not contain any
+ config options (but does contain comments or whitespace). Fixes
+ bug 31408; bugfix on 0.3.1.1-alpha.
+
+ o Major bugfixes (v3 onion services, backport from 0.4.2.3-alpha):
+ - Onion services now always use the exact number of intro points
+ configured with the HiddenServiceNumIntroductionPoints option (or
+ fewer if nodes are excluded). Before, a service could sometimes
+ pick more intro points than configured. Fixes bug 31548; bugfix
+ on 0.3.2.1-alpha.
+
+ o Minor features (continuous integration, backport from 0.4.2.2-alpha):
+ - When building on Appveyor and Travis, pass the "-k" flag to make,
+ so that we are informed of all compilation failures, not just the
+ first one or two. Closes ticket 31372.
+
+ o Minor features (geoip, backport from 0.4.2.5):
+ - Update geoip and geoip6 to the December 3 2019 Maxmind GeoLite2
+ Country database. Closes ticket 32685.
+
+ o Minor bugfixes (Appveyor CI, backport from 0.4.2.2-alpha):
+ - Avoid spurious errors when Appveyor CI fails before the install step.
+ Fixes bug 31884; bugfix on 0.3.4.2-alpha.
+
+ o Minor bugfixes (client, onion service v3, backport from 0.4.2.4-rc):
+ - Fix a BUG() assertion that occurs within a very small race window
+ between when a client intro circuit opens and when its descriptor
+ gets cleaned up from the cache. The circuit is now closed early,
+ which will trigger a re-fetch of the descriptor and continue the
+ connection. Fixes bug 28970; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfixes (connections, backport from 0.4.2.3-rc):
+ - Avoid trying to read data from closed connections, which can cause
+ needless loops in Libevent and infinite loops in Shadow. Fixes bug
+ 30344; bugfix on 0.1.1.1-alpha.
+
+ o Minor bugfixes (error handling, backport from 0.4.2.1-alpha):
+ - On abort, try harder to flush the output buffers of log messages.
+ On some platforms (macOS), log messages could be discarded when
+ the process terminates. Fixes bug 31571; bugfix on 0.3.5.1-alpha.
+ - Report the tor version whenever an assertion fails. Previously, we
+ only reported the Tor version on some crashes, and some non-fatal
+ assertions. Fixes bug 31571; bugfix on 0.3.5.1-alpha.
+ - When tor aborts due to an error, close log file descriptors before
+ aborting. Closing the logs makes some OSes flush log file buffers,
+ rather than deleting buffered log lines. Fixes bug 31594; bugfix
+ on 0.2.5.2-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.2.2-alpha):
+ - Add a missing check for HAVE_PTHREAD_H, because the backtrace code
+ uses mutexes. Fixes bug 31614; bugfix on 0.2.5.2-alpha.
+ - Disable backtrace signal handlers when shutting down tor. Fixes
+ bug 31614; bugfix on 0.2.5.2-alpha.
+ - Rate-limit our the logging message about the obsolete .exit
+ notation. Previously, there was no limit on this warning, which
+ could potentially be triggered many times by a hostile website.
+ Fixes bug 31466; bugfix on 0.2.2.1-alpha.
+
+ o Minor bugfixes (logging, protocol violations, backport from 0.4.2.2-alpha):
+ - Do not log a nonfatal assertion failure when receiving a VERSIONS
+ cell on a connection using the obsolete v1 link protocol. Log a
+ protocol_warn instead. Fixes bug 31107; bugfix on 0.2.4.4-alpha.
+
+ o Minor bugfixes (mainloop, periodic events, in-process API, backport from 0.4.2.3-alpha):
+ - Reset the periodic events' "enabled" flag when Tor is shut down
+ cleanly. Previously, this flag was left on, which caused periodic
+ events not to be re-enabled when Tor was relaunched in-process
+ with tor_api.h after a shutdown. Fixes bug 32058; bugfix
+ on 0.3.3.1-alpha.
+
+ o Minor bugfixes (multithreading, backport from 0.4.2.2-alpha):
+ - Avoid some undefined behaviour when freeing mutexes. Fixes bug
+ 31736; bugfix on 0.0.7.
+
+ o Minor bugfixes (process management, backport from 0.4.2.3-alpha):
+ - Remove overly strict assertions that triggered when a pluggable
+ transport failed to launch. Fixes bug 31091; bugfix
+ on 0.4.0.1-alpha.
+ - Remove an assertion in the Unix process backend. This assertion
+ would trigger when we failed to find the executable for a child
+ process. Fixes bug 31810; bugfix on 0.4.0.1-alpha.
+
+ o Minor bugfixes (relay, backport from 0.4.2.2-alpha):
+ - Avoid crashing when starting with a corrupt keys directory where
+ the old ntor key and the new ntor key are identical. Fixes bug
+ 30916; bugfix on 0.2.4.8-alpha.
+
+ o Minor bugfixes (testing, backport from 0.4.2.3-alpha):
+ - When testing port rebinding, don't busy-wait for tor to log.
+ Instead, actually sleep for a short time before polling again.
+ Also improve the formatting of control commands and log messages.
+ Fixes bug 31837; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (tests, SunOS, backport from 0.4.2.2-alpha):
+ - Avoid a map_anon_nofork test failure due to a signed/unsigned
+ integer comparison. Fixes bug 31897; bugfix on 0.4.1.1-alpha.
+
+ o Minor bugfixes (tls, logging, backport from 0.4.2.3-alpha):
+ - Log bugs about the TLS read buffer's length only once, rather than
+ filling the logs with similar warnings. Fixes bug 31939; bugfix
+ on 0.3.0.4-rc.
+
+ o Documentation (backport from 0.4.2.2-alpha):
+ - Explain why we can't destroy the backtrace buffer mutex. Explain
+ why we don't need to destroy the log mutex. Closes ticket 31736.
+
+ o Testing (continuous integration, backport from 0.4.2.3-alpha):
+ - Disable all but one Travis CI macOS build, to mitigate slow
+ scheduling of Travis macOS jobs. Closes ticket 32177.
+ - Run the chutney IPv6 networks as part of Travis CI. Closes
+ ticket 30860.
+ - Simplify the Travis CI build matrix, and optimise for build time.
+ Closes ticket 31859.
+ - Use Windows Server 2019 instead of Windows Server 2016 in our
+ Appveyor builds. Closes ticket 32086.
+
+ o Testing (continuous integration, backport from 0.4.2.4-rc):
+ - In Travis, use Xcode 11.2 on macOS 10.14. Closes ticket 32241.
+ - Use Ubuntu Bionic images for our Travis CI builds, so we can get a
+ recent version of coccinelle. But leave chutney on Ubuntu Trusty,
+ until we can fix some Bionic permissions issues (see ticket
+ 32240). Related to ticket 31919.
+ - Install the mingw OpenSSL package in Appveyor. This makes sure
+ that the OpenSSL headers and libraries match in Tor's Appveyor
+ builds. (This bug was triggered by an Appveyor image update.)
+ Fixes bug 32449; bugfix on 0.3.5.6-rc.
+
+ o Testing (continuous integration, backport from 0.4.2.5):
+ - Require C99 standards-conforming code in Travis CI, but allow GNU gcc
+ extensions. Also activates clang's -Wtypedef-redefinition warnings.
+ Build some jobs with -std=gnu99, and some jobs without.
+ Closes ticket 32500.
+
+
+Changes in version 0.4.0.6 - 2019-12-09
+ This is the second stable release in the 0.4.0.x series. This release
+ backports several bugfixes to improve stability and correctness. Anyone
+ experiencing build problems or crashes with 0.4.0.5, including all relays
+ relying on AccountingMax, should upgrade.
+
+ Note that, per our support policy, support for the 0.4.0.x series will end
+ on 2 Feb 2020. Anyone still running 0.4.0.x should plan to upgrade to the
+ latest stable release, or downgrade to 0.3.5.x, which will get long-term
+ support until 1 Feb 2022.
+
+ o Directory authority changes (backport from 0.4.1.5):
+ - The directory authority "dizum" has a new IP address. Closes
+ ticket 31406.
+
+ o Major bugfixes (bridges, backport from 0.4.1.2-alpha):
+ - Consider our directory information to have changed when our list
+ of bridges changes. Previously, Tor would not re-compute the
+ status of its directory information when bridges changed, and
+ therefore would not realize that it was no longer able to build
+ circuits. Fixes part of bug 29875.
+ - Do not count previously configured working bridges towards our
+ total of working bridges. Previously, when Tor's list of bridges
+ changed, it would think that the old bridges were still usable,
+ and delay fetching router descriptors for the new ones. Fixes part
+ of bug 29875; bugfix on 0.3.0.1-alpha.
+
+ o Major bugfixes (circuit build, guard, backport from 0.4.1.4-rc):
+ - When considering upgrading circuits from "waiting for guard" to
+ "open", always ignore circuits that are marked for close. Otherwise,
+ we can end up in the situation where a subsystem is notified that
+ a closing circuit has just opened, leading to undesirable
+ behavior. Fixes bug 30871; bugfix on 0.3.0.1-alpha.
+
+ o Major bugfixes (Onion service reachability, backport from 0.4.1.3-alpha):
+ - Properly clean up the introduction point map when circuits change
+ purpose from onion service circuits to pathbias, measurement, or
+ other circuit types. This should fix some service-side instances
+ of introduction point failure. Fixes bug 29034; bugfix
+ on 0.3.2.1-alpha.
+
+ o Major bugfixes (onion service v3, backport from 0.4.1.1-alpha):
+ - Fix an unreachable bug in which an introduction point could try to
+ send an INTRODUCE_ACK with a status code that Trunnel would refuse
+ to encode, leading the relay to assert(). We've consolidated the
+ ABI values into Trunnel now. Fixes bug 30454; bugfix
+ on 0.3.0.1-alpha.
+ - Clients can now handle unknown status codes from INTRODUCE_ACK
+ cells. (The NACK behavior will stay the same.) This will allow us
+ to extend status codes in the future without breaking the normal
+ client behavior. Fixes another part of bug 30454; bugfix
+ on 0.3.0.1-alpha.
+
+ o Major bugfixes (relay, backport from 0.4.2.3-alpha):
+ - Relays now respect their AccountingMax bandwidth again. When
+ relays entered "soft" hibernation (which typically starts when
+ we've hit 90% of our AccountingMax), we had stopped checking
+ whether we should enter hard hibernation. Soft hibernation refuses
+ new connections and new circuits, but the existing circuits can
+ continue, meaning that relays could have exceeded their configured
+ AccountingMax. Fixes bug 32108; bugfix on 0.4.0.1-alpha.
+
+ o Major bugfixes (torrc parsing, backport from 0.4.2.2-alpha):
+ - Stop ignoring torrc options after an %include directive, when the
+ included directory ends with a file that does not contain any
+ config options (but does contain comments or whitespace). Fixes
+ bug 31408; bugfix on 0.3.1.1-alpha.
+
+ o Major bugfixes (v3 onion services, backport from 0.4.2.3-alpha):
+ - Onion services now always use the exact number of intro points
+ configured with the HiddenServiceNumIntroductionPoints option (or
+ fewer if nodes are excluded). Before, a service could sometimes
+ pick more intro points than configured. Fixes bug 31548; bugfix
+ on 0.3.2.1-alpha.
+
+ o Minor features (compile-time modules, backport from version 0.4.1.1-alpha):
+ - Add a "--list-modules" command to print a list of which compile-
+ time modules are enabled. Closes ticket 30452.
+
+ o Minor features (continuous integration, backport from 0.4.1.1-alpha):
+ - Remove sudo configuration lines from .travis.yml as they are no
+ longer needed with current Travis build environment. Resolves
+ issue 30213.
+
+ o Minor features (continuous integration, backport from 0.4.1.4-rc):
+ - Our Travis configuration now uses Chutney to run some network
+ integration tests automatically. Closes ticket 29280.
+
+ o Minor features (continuous integration, backport from 0.4.2.2-alpha):
+ - When building on Appveyor and Travis, pass the "-k" flag to make,
+ so that we are informed of all compilation failures, not just the
+ first one or two. Closes ticket 31372.
+
+ o Minor features (fallback directory list, backport from 0.4.1.4-rc):
+ - Replace the 157 fallbacks originally introduced in Tor 0.3.5.6-rc
+ in December 2018 (of which ~122 were still functional), with a
+ list of 148 fallbacks (70 new, 78 existing, 79 removed) generated
+ in June 2019. Closes ticket 28795.
+
+ o Minor features (geoip, backport from 0.4.2.5):
+ - Update geoip and geoip6 to the December 3 2019 Maxmind GeoLite2
+ Country database. Closes ticket 32685.
+
+ o Minor features (stem tests, backport from 0.4.2.1-alpha):
+ - Change "make test-stem" so it only runs the stem tests that use
+ tor. This change makes test-stem faster and more reliable. Closes
+ ticket 31554.
+
+ o Minor bugfixes (Appveyor CI, backport from 0.4.2.2-alpha):
+ - Avoid spurious errors when Appveyor CI fails before the install step.
+ Fixes bug 31884; bugfix on 0.3.4.2-alpha.
+
+ o Minor bugfixes (build system, backport form 0.4.2.1-alpha):
+ - Do not include the deprecated <sys/sysctl.h> on Linux or Windows
+ systems. Fixes bug 31673; bugfix on 0.2.5.4-alpha.
+
+ o Minor bugfixes (circuit isolation, backport from 0.4.1.3-alpha):
+ - Fix a logic error that prevented the SessionGroup sub-option from
+ being accepted. Fixes bug 22619; bugfix on 0.2.7.2-alpha.
+
+ o Minor bugfixes (circuit padding, backport from 0.4.1.4-rc):
+ - On relays, properly check that a padding machine is absent before
+ logging a warning about it being absent. Fixes bug 30649; bugfix
+ on 0.4.0.1-alpha.
+
+ o Minor bugfixes (client, onion service v3, backport from 0.4.2.4-rc):
+ - Fix a BUG() assertion that occurs within a very small race window
+ between when a client intro circuit opens and when its descriptor
+ gets cleaned up from the cache. The circuit is now closed early,
+ which will trigger a re-fetch of the descriptor and continue the
+ connection. Fixes bug 28970; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfixes (clock skew detection, backport from 0.4.1.5):
+ - Don't believe clock skew results from NETINFO cells that appear to
+ arrive before we sent the VERSIONS cells they are responding to.
+ Previously, we would accept them up to 3 minutes "in the past".
+ Fixes bug 31343; bugfix on 0.2.4.4-alpha.
+
+ o Minor bugfixes (compilation warning, backport from 0.4.1.5):
+ - Fix a compilation warning on Windows about casting a function
+ pointer for GetTickCount64(). Fixes bug 31374; bugfix
+ on 0.2.9.1-alpha.
+
+ o Minor bugfixes (compilation, backport from 0.4.1.5):
+ - Avoid using labs() on time_t, which can cause compilation warnings
+ on 64-bit Windows builds. Fixes bug 31343; bugfix on 0.2.4.4-alpha.
+
+ o Minor bugfixes (compilation, backport from 0.4.2.1-alpha):
+ - Suppress spurious float-conversion warnings from GCC when calling
+ floating-point classifier functions on FreeBSD. Fixes part of bug
+ 31687; bugfix on 0.3.1.5-alpha.
+
+ o Minor bugfixes (compilation, unusual configurations, backport from 0.4.1.1-alpha):
+ - Avoid failures when building with the ALL_BUGS_ARE_FATAL option
+ due to missing declarations of abort(), and prevent other such
+ failures in the future. Fixes bug 30189; bugfix on 0.3.4.1-alpha.
+
+ o Minor bugfixes (configuration, proxies, backport from 0.4.1.2-alpha):
+ - Fix a bug that prevented us from supporting SOCKS5 proxies that
+ want authentication along with configured (but unused!)
+ ClientTransportPlugins. Fixes bug 29670; bugfix on 0.2.6.1-alpha.
+
+ o Minor bugfixes (connections, backport from 0.4.2.3-rc):
+ - Avoid trying to read data from closed connections, which can cause
+ needless loops in Libevent and infinite loops in Shadow. Fixes bug
+ 30344; bugfix on 0.1.1.1-alpha.
+
+ o Minor bugfixes (continuous integration, backport from 0.4.1.3-alpha):
+ - Allow the test-stem job to fail in Travis, because it sometimes
+ hangs. Fixes bug 30744; bugfix on 0.3.5.4-alpha.
+ - Skip test_rebind on macOS in Travis, because it is unreliable on
+ macOS on Travis. Fixes bug 30713; bugfix on 0.3.5.1-alpha.
+ - Skip test_rebind when the TOR_SKIP_TEST_REBIND environment
+ variable is set. Fixes bug 30713; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (crash on exit, backport from 0.4.1.4-rc):
+ - Avoid a set of possible code paths that could try to use freed
+ memory in routerlist_free() while Tor was exiting. Fixes bug
+ 31003; bugfix on 0.1.2.2-alpha.
+
+ o Minor bugfixes (directory authorities, backport from 0.4.1.3-alpha):
+ - Stop crashing after parsing an unknown descriptor purpose
+ annotation. We think this bug can only be triggered by modifying a
+ local file. Fixes bug 30781; bugfix on 0.2.0.8-alpha.
+
+ o Minor bugfixes (directory authority, backport from 0.4.1.2-alpha):
+ - Move the "bandwidth-file-headers" line in directory authority
+ votes so that it conforms to dir-spec.txt. Fixes bug 30316; bugfix
+ on 0.3.5.1-alpha.
+
+ o Minor bugfixes (error handling, backport from 0.4.2.1-alpha):
+ - On abort, try harder to flush the output buffers of log messages.
+ On some platforms (macOS), log messages could be discarded when
+ the process terminates. Fixes bug 31571; bugfix on 0.3.5.1-alpha.
+ - Report the tor version whenever an assertion fails. Previously, we
+ only reported the Tor version on some crashes, and some non-fatal
+ assertions. Fixes bug 31571; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (FreeBSD, PF-based proxy, IPv6, backport from 0.4.2.1-alpha):
+ - When extracting an IPv6 address from a PF-based proxy, verify that
+ we are actually configured to receive an IPv6 address, and log an
+ internal error if not. Fixes part of bug 31687; bugfix
+ on 0.2.3.4-alpha.
+
+ o Minor bugfixes (guards, backport from 0.4.2.1-alpha):
+ - When tor is missing descriptors for some primary entry guards,
+ make the log message less alarming. It's normal for descriptors to
+ expire, as long as tor fetches new ones soon after. Fixes bug
+ 31657; bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.1.1-alpha):
+ - Do not log a warning when running with an OpenSSL version other
+ than the one Tor was compiled with, if the two versions should be
+ compatible. Previously, we would warn whenever the version was
+ different. Fixes bug 30190; bugfix on 0.2.4.2-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.2.1-alpha):
+ - Change log level of message "Hash of session info was not as
+ expected" to LOG_PROTOCOL_WARN. Fixes bug 12399; bugfix
+ on 0.1.1.10-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.2.2-alpha):
+ - Rate-limit our the logging message about the obsolete .exit
+ notation. Previously, there was no limit on this warning, which
+ could potentially be triggered many times by a hostile website.
+ Fixes bug 31466; bugfix on 0.2.2.1-alpha.
+
+ o Minor bugfixes (logging, protocol violations, backport from 0.4.2.2-alpha):
+ - Do not log a nonfatal assertion failure when receiving a VERSIONS
+ cell on a connection using the obsolete v1 link protocol. Log a
+ protocol_warn instead. Fixes bug 31107; bugfix on 0.2.4.4-alpha.
+
+ o Minor bugfixes (mainloop, periodic events, in-process API, backport from 0.4.2.3-alpha):
+ - Reset the periodic events' "enabled" flag when Tor is shut down
+ cleanly. Previously, this flag was left on, which caused periodic
+ events not to be re-enabled when Tor was relaunched in-process
+ with tor_api.h after a shutdown. Fixes bug 32058; bugfix
+ on 0.3.3.1-alpha.
+
+ o Minor bugfixes (memory leak, backport from 0.4.1.1-alpha):
+ - Avoid a minor memory leak that could occur on relays when failing
+ to create a "keys" directory. Fixes bug 30148; bugfix
+ on 0.3.3.1-alpha.
+
+ o Minor bugfixes (memory leak, backport from 0.4.1.4-rc):
+ - Fix a trivial memory leak when parsing an invalid value
+ from a download schedule in the configuration. Fixes bug
+ 30894; bugfix on 0.3.4.1-alpha.
+
+ o Minor bugfixes (NetBSD, backport from 0.4.1.2-alpha):
+ - Fix usage of minherit() on NetBSD and other platforms that define
+ MAP_INHERIT_{ZERO,NONE} instead of INHERIT_{ZERO,NONE}. Fixes bug
+ 30614; bugfix on 0.4.0.2-alpha. Patch from Taylor Campbell.
+
+ o Minor bugfixes (onion services, backport from 0.4.1.1-alpha):
+ - Avoid a GCC 9.1.1 warning (and possible crash depending on libc
+ implemenation) when failing to load an onion service client
+ authorization file. Fixes bug 30475; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (out-of-memory handler, backport from 0.4.1.2-alpha):
+ - When purging the DNS cache because of an out-of-memory condition,
+ try purging just the older entries at first. Previously, we would
+ always purge the whole thing. Fixes bug 29617; bugfix
+ on 0.3.5.1-alpha.
+
+ o Minor bugfixes (portability, backport from 0.4.1.2-alpha):
+ - Avoid crashing in our tor_vasprintf() implementation on systems
+ that define neither vasprintf() nor _vscprintf(). (This bug has
+ been here long enough that we question whether people are running
+ Tor on such systems, but we're applying the fix out of caution.)
+ Fixes bug 30561; bugfix on 0.2.8.2-alpha. Found and fixed by
+ Tobias Stoeckmann.
+
+ o Minor bugfixes (process management, backport from 0.4.2.3-alpha):
+ - Remove overly strict assertions that triggered when a pluggable
+ transport failed to launch. Fixes bug 31091; bugfix
+ on 0.4.0.1-alpha.
+ - Remove an assertion in the Unix process backend. This assertion
+ would trigger when we failed to find the executable for a child
+ process. Fixes bug 31810; bugfix on 0.4.0.1-alpha.
+
+ o Minor bugfixes (relay, backport from 0.4.2.2-alpha):
+ - Avoid crashing when starting with a corrupt keys directory where
+ the old ntor key and the new ntor key are identical. Fixes bug
+ 30916; bugfix on 0.2.4.8-alpha.
+
+ o Minor bugfixes (rust, backport from 0.4.2.1-alpha):
+ - Correctly exclude a redundant rust build job in Travis. Fixes bug
+ 31463; bugfix on 0.3.5.4-alpha.
+
+ o Minor bugfixes (testing, backport from 0.4.2.3-alpha):
+ - When testing port rebinding, don't busy-wait for tor to log.
+ Instead, actually sleep for a short time before polling again.
+ Also improve the formatting of control commands and log messages.
+ Fixes bug 31837; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (tls, logging, backport from 0.4.2.3-alpha):
+ - Log bugs about the TLS read buffer's length only once, rather than
+ filling the logs with similar warnings. Fixes bug 31939; bugfix
+ on 0.3.0.4-rc.
+
+ o Minor bugfixes (v2 single onion services, backport from 0.4.2.1-alpha):
+ - Always retry v2 single onion service intro and rend circuits with
+ a 3-hop path. Previously, v2 single onion services used a 3-hop
+ path when rendezvous circuits were retried after a remote or
+ delayed failure, but a 1-hop path for immediate retries. Fixes bug
+ 23818; bugfix on 0.2.9.3-alpha.
+ - Make v3 single onion services fall back to a 3-hop intro, when all
+ intro points are unreachable via a 1-hop path. Previously, v3
+ single onion services failed when all intro nodes were unreachable
+ via a 1-hop path. Fixes bug 23507; bugfix on 0.3.2.1-alpha.
+
+ o Documentation (backport from 0.4.2.1-alpha):
+ - Use RFC 2397 data URL scheme to embed an image into tor-exit-
+ notice.html so that operators no longer have to host it
+ themselves. Closes ticket 31089.
+
+ o Testing (backport from 0.4.1.2-alpha):
+ - Specify torrc paths (with empty files) when launching tor in
+ integration tests; refrain from reading user and system torrcs.
+ Resolves issue 29702.
+
+ o Testing (continuous integration, backport from 0.4.1.1-alpha):
+ - In Travis, show stem's tor log after failure. Closes ticket 30234.
+
+ o Testing (continuous integration, backport from 0.4.1.5):
+ - In Travis, make stem log a controller trace to the console, and
+ tail stem's tor log after failure. Closes ticket 30591.
+ - In Travis, only run the stem tests that use a tor binary. Closes
+ ticket 30694.
+
+ o Testing (continuous integration, backport from 0.4.2.3-alpha):
+ - Disable all but one Travis CI macOS build, to mitigate slow
+ scheduling of Travis macOS jobs. Closes ticket 32177.
+ - Run the chutney IPv6 networks as part of Travis CI. Closes
+ ticket 30860.
+ - Simplify the Travis CI build matrix, and optimise for build time.
+ Closes ticket 31859.
+ - Use Windows Server 2019 instead of Windows Server 2016 in our
+ Appveyor builds. Closes ticket 32086.
+
+ o Testing (continuous integration, backport from 0.4.2.4-rc):
+ - Use Ubuntu Bionic images for our Travis CI builds, so we can get a
+ recent version of coccinelle. But leave chutney on Ubuntu Trusty,
+ until we can fix some Bionic permissions issues (see ticket
+ 32240). Related to ticket 31919.
+ - Install the mingw OpenSSL package in Appveyor. This makes sure
+ that the OpenSSL headers and libraries match in Tor's Appveyor
+ builds. (This bug was triggered by an Appveyor image update.)
+ Fixes bug 32449; bugfix on 0.3.5.6-rc.
+ - In Travis, use Xcode 11.2 on macOS 10.14. Closes ticket 32241.
+
+ o Testing (continuous integration, backport from 0.4.2.5):
+ - Require C99 standards-conforming code in Travis CI, but allow GNU gcc
+ extensions. Also activates clang's -Wtypedef-redefinition warnings.
+ Build some jobs with -std=gnu99, and some jobs without.
+ Closes ticket 32500.
+
+Changes in version 0.3.5.9 - 2019-12-09
+ Tor 0.3.5.9 backports serveral fixes from later releases, including
+ several that affect bridge users, relay stability, onion services,
+ and much more.
+
+ o Directory authority changes (backport from 0.4.1.5):
+ - The directory authority "dizum" has a new IP address. Closes
+ ticket 31406.
+
+ o Major bugfixes (bridges, backport from 0.4.1.2-alpha):
+ - Consider our directory information to have changed when our list
+ of bridges changes. Previously, Tor would not re-compute the
+ status of its directory information when bridges changed, and
+ therefore would not realize that it was no longer able to build
+ circuits. Fixes part of bug 29875.
+ - Do not count previously configured working bridges towards our
+ total of working bridges. Previously, when Tor's list of bridges
+ changed, it would think that the old bridges were still usable,
+ and delay fetching router descriptors for the new ones. Fixes part
+ of bug 29875; bugfix on 0.3.0.1-alpha.
+
+ o Major bugfixes (circuit build, guard, backport from 0.4.1.4-rc):
+ - When considering upgrading circuits from "waiting for guard" to
+ "open", always ignore circuits that are marked for close. Otherwise,
+ we can end up in the situation where a subsystem is notified that
+ a closing circuit has just opened, leading to undesirable
+ behavior. Fixes bug 30871; bugfix on 0.3.0.1-alpha.
+
+ o Major bugfixes (NSS, relay, backport from 0.4.0.4-rc):
+ - When running with NSS, disable TLS 1.2 ciphersuites that use
+ SHA384 for their PRF. Due to an NSS bug, the TLS key exporters for
+ these ciphersuites don't work -- which caused relays to fail to
+ handshake with one another when these ciphersuites were enabled.
+ Fixes bug 29241; bugfix on 0.3.5.1-alpha.
+
+ o Major bugfixes (Onion service reachability, backport from 0.4.1.3-alpha):
+ - Properly clean up the introduction point map when circuits change
+ purpose from onion service circuits to pathbias, measurement, or
+ other circuit types. This should fix some service-side instances
+ of introduction point failure. Fixes bug 29034; bugfix
+ on 0.3.2.1-alpha.
+
+ o Major bugfixes (onion service v3, backport from 0.4.1.1-alpha):
+ - Fix an unreachable bug in which an introduction point could try to
+ send an INTRODUCE_ACK with a status code that Trunnel would refuse
+ to encode, leading the relay to assert(). We've consolidated the
+ ABI values into Trunnel now. Fixes bug 30454; bugfix
+ on 0.3.0.1-alpha.
+ - Clients can now handle unknown status codes from INTRODUCE_ACK
+ cells. (The NACK behavior will stay the same.) This will allow us
+ to extend status codes in the future without breaking the normal
+ client behavior. Fixes another part of bug 30454; bugfix
+ on 0.3.0.1-alpha.
+
+ o Major bugfixes (torrc parsing, backport from 0.4.2.2-alpha):
+ - Stop ignoring torrc options after an %include directive, when the
+ included directory ends with a file that does not contain any
+ config options (but does contain comments or whitespace). Fixes
+ bug 31408; bugfix on 0.3.1.1-alpha.
+
+ o Major bugfixes (v3 onion services, backport from 0.4.2.3-alpha):
+ - Onion services now always use the exact number of intro points
+ configured with the HiddenServiceNumIntroductionPoints option (or
+ fewer if nodes are excluded). Before, a service could sometimes
+ pick more intro points than configured. Fixes bug 31548; bugfix
+ on 0.3.2.1-alpha.
+
+ o Minor features (address selection, backport from 0.4.0.3-alpha):
+ - Treat the subnet 100.64.0.0/10 as public for some purposes;
+ private for others. This subnet is the RFC 6598 (Carrier Grade
+ NAT) IP range, and is deployed by many ISPs as an alternative to
+ RFC 1918 that does not break existing internal networks. Tor now
+ blocks SOCKS and control ports on these addresses and warns users
+ if client ports or ExtORPorts are listening on a RFC 6598 address.
+ Closes ticket 28525. Patch by Neel Chauhan.
+
+ o Minor features (bandwidth authority, backport from 0.4.0.4-rc):
+ - Make bandwidth authorities ignore relays that are reported in the
+ bandwidth file with the flag "vote=0". This change allows us to
+ report unmeasured relays for diagnostic reasons without including
+ their bandwidth in the bandwidth authorities' vote. Closes
+ ticket 29806.
+
+ o Minor features (compile-time modules, backport from version 0.4.1.1-alpha):
+ - Add a "--list-modules" command to print a list of which compile-
+ time modules are enabled. Closes ticket 30452.
+
+ o Minor features (continuous integration, backport from 0.4.0.4-rc):
+ - On Travis Rust builds, cleanup Rust registry and refrain from
+ caching the "target/" directory to speed up builds. Resolves
+ issue 29962.
+
+ o Minor features (continuous integration, backport from 0.4.0.5):
+ - In Travis, tell timelimit to use stem's backtrace signals, and
+ launch python directly from timelimit, so python receives the
+ signals from timelimit, rather than make. Closes ticket 30117.
+
+ o Minor features (continuous integration, backport from 0.4.1.1-alpha):
+ - Remove sudo configuration lines from .travis.yml as they are no
+ longer needed with current Travis build environment. Resolves
+ issue 30213.
+
+ o Minor features (continuous integration, backport from 0.4.1.4-rc):
+ - Our Travis configuration now uses Chutney to run some network
+ integration tests automatically. Closes ticket 29280.
+
+ o Minor features (continuous integration, backport from 0.4.2.2-alpha):
+ - When building on Appveyor and Travis, pass the "-k" flag to make,
+ so that we are informed of all compilation failures, not just the
+ first one or two. Closes ticket 31372.
+
+ o Minor features (fallback directory list, backport from 0.4.1.4-rc):
+ - Replace the 157 fallbacks originally introduced in Tor 0.3.5.6-rc
+ in December 2018 (of which ~122 were still functional), with a
+ list of 148 fallbacks (70 new, 78 existing, 79 removed) generated
+ in June 2019. Closes ticket 28795.
+
+ o Minor features (geoip, backport from 0.4.2.5):
+ - Update geoip and geoip6 to the December 3 2019 Maxmind GeoLite2
+ Country database. Closes ticket 32685.
+
+ o Minor features (NSS, diagnostic, backport from 0.4.0.4-rc):
+ - Try to log an error from NSS (if there is any) and a more useful
+ description of our situation if we are using NSS and a call to
+ SSL_ExportKeyingMaterial() fails. Diagnostic for ticket 29241.
+
+ o Minor features (stem tests, backport from 0.4.2.1-alpha):
+ - Change "make test-stem" so it only runs the stem tests that use
+ tor. This change makes test-stem faster and more reliable. Closes
+ ticket 31554.
+
+ o Minor bugfixes (security, backport from 0.4.0.4-rc):
+ - Verify in more places that we are not about to create a buffer
+ with more than INT_MAX bytes, to avoid possible OOB access in the
+ event of bugs. Fixes bug 30041; bugfix on 0.2.0.16. Found and
+ fixed by Tobias Stoeckmann.
+ - Fix a potential double free bug when reading huge bandwidth files.
+ The issue is not exploitable in the current Tor network because
+ the vulnerable code is only reached when directory authorities
+ read bandwidth files, but bandwidth files come from a trusted
+ source (usually the authorities themselves). Furthermore, the
+ issue is only exploitable in rare (non-POSIX) 32-bit architectures,
+ which are not used by any of the current authorities. Fixes bug
+ 30040; bugfix on 0.3.5.1-alpha. Bug found and fixed by
+ Tobias Stoeckmann.
+
+ o Minor bugfix (continuous integration, backport from 0.4.0.4-rc):
+ - Reset coverage state on disk after Travis CI has finished. This
+ should prevent future coverage merge errors from causing the test
+ suite for the "process" subsystem to fail. The process subsystem
+ was introduced in 0.4.0.1-alpha. Fixes bug 29036; bugfix
+ on 0.2.9.15.
+ - Terminate test-stem if it takes more than 9.5 minutes to run.
+ (Travis terminates the job after 10 minutes of no output.)
+ Diagnostic for 29437. Fixes bug 30011; bugfix on 0.3.5.4-alpha.
+
+ o Minor bugfixes (Appveyor CI, backport from 0.4.2.2-alpha):
+ - Avoid spurious errors when Appveyor CI fails before the install step.
+ Fixes bug 31884; bugfix on 0.3.4.2-alpha.
+
+ o Minor bugfixes (build system, backport form 0.4.2.1-alpha):
+ - Do not include the deprecated <sys/sysctl.h> on Linux or Windows
+ systems. Fixes bug 31673; bugfix on 0.2.5.4-alpha.
+
+ o Minor bugfixes (C correctness, backport from 0.4.0.4-rc):
+ - Fix an unlikely memory leak in consensus_diff_apply(). Fixes bug
+ 29824; bugfix on 0.3.1.1-alpha. This is Coverity warning
+ CID 1444119.
+
+ o Minor bugfixes (circuit isolation, backport from 0.4.1.3-alpha):
+ - Fix a logic error that prevented the SessionGroup sub-option from
+ being accepted. Fixes bug 22619; bugfix on 0.2.7.2-alpha.
+
+ o Minor bugfixes (client, onion service v3, backport from 0.4.2.4-rc):
+ - Fix a BUG() assertion that occurs within a very small race window
+ between when a client intro circuit opens and when its descriptor
+ gets cleaned up from the cache. The circuit is now closed early,
+ which will trigger a re-fetch of the descriptor and continue the
+ connection. Fixes bug 28970; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfixes (clock skew detection, backport from 0.4.1.5):
+ - Don't believe clock skew results from NETINFO cells that appear to
+ arrive before we sent the VERSIONS cells they are responding to.
+ Previously, we would accept them up to 3 minutes "in the past".
+ Fixes bug 31343; bugfix on 0.2.4.4-alpha.
+
+ o Minor bugfixes (compilation warning, backport from 0.4.1.5):
+ - Fix a compilation warning on Windows about casting a function
+ pointer for GetTickCount64(). Fixes bug 31374; bugfix
+ on 0.2.9.1-alpha.
+
+ o Minor bugfixes (compilation, backport from 0.4.0.2-alpha):
+ - Silence a compiler warning in test-memwipe.c on OpenBSD. Fixes bug
+ 29145; bugfix on 0.2.9.3-alpha. Patch from Kris Katterjohn.
+
+ o Minor bugfixes (compilation, backport from 0.4.1.5):
+ - Avoid using labs() on time_t, which can cause compilation warnings
+ on 64-bit Windows builds. Fixes bug 31343; bugfix on 0.2.4.4-alpha.
+
+ o Minor bugfixes (compilation, backport from 0.4.2.1-alpha):
+ - Suppress spurious float-conversion warnings from GCC when calling
+ floating-point classifier functions on FreeBSD. Fixes part of bug
+ 31687; bugfix on 0.3.1.5-alpha.
+
+ o Minor bugfixes (compilation, unusual configurations, backport from 0.4.1.1-alpha):
+ - Avoid failures when building with the ALL_BUGS_ARE_FATAL option
+ due to missing declarations of abort(), and prevent other such
+ failures in the future. Fixes bug 30189; bugfix on 0.3.4.1-alpha.
+
+ o Minor bugfixes (configuration, proxies, backport from 0.4.1.2-alpha):
+ - Fix a bug that prevented us from supporting SOCKS5 proxies that
+ want authentication along with configured (but unused!)
+ ClientTransportPlugins. Fixes bug 29670; bugfix on 0.2.6.1-alpha.
+
+ o Minor bugfixes (connections, backport from 0.4.2.3-rc):
+ - Avoid trying to read data from closed connections, which can cause
+ needless loops in Libevent and infinite loops in Shadow. Fixes bug
+ 30344; bugfix on 0.1.1.1-alpha.
+
+ o Minor bugfixes (continuous integration, backport from 0.4.1.3-alpha):
+ - Allow the test-stem job to fail in Travis, because it sometimes
+ hangs. Fixes bug 30744; bugfix on 0.3.5.4-alpha.
+ - Skip test_rebind on macOS in Travis, because it is unreliable on
+ macOS on Travis. Fixes bug 30713; bugfix on 0.3.5.1-alpha.
+ - Skip test_rebind when the TOR_SKIP_TEST_REBIND environment
+ variable is set. Fixes bug 30713; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (crash on exit, backport from 0.4.1.4-rc):
+ - Avoid a set of possible code paths that could try to use freed
+ memory in routerlist_free() while Tor was exiting. Fixes bug
+ 31003; bugfix on 0.1.2.2-alpha.
+
+ o Minor bugfixes (directory authorities, backport from 0.4.1.3-alpha):
+ - Stop crashing after parsing an unknown descriptor purpose
+ annotation. We think this bug can only be triggered by modifying a
+ local file. Fixes bug 30781; bugfix on 0.2.0.8-alpha.
+
+ o Minor bugfixes (directory authority, backport from 0.4.1.2-alpha):
+ - Move the "bandwidth-file-headers" line in directory authority
+ votes so that it conforms to dir-spec.txt. Fixes bug 30316; bugfix
+ on 0.3.5.1-alpha.
+
+ o Minor bugfixes (error handling, backport from 0.4.2.1-alpha):
+ - On abort, try harder to flush the output buffers of log messages.
+ On some platforms (macOS), log messages could be discarded when
+ the process terminates. Fixes bug 31571; bugfix on 0.3.5.1-alpha.
+ - Report the tor version whenever an assertion fails. Previously, we
+ only reported the Tor version on some crashes, and some non-fatal
+ assertions. Fixes bug 31571; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (FreeBSD, PF-based proxy, IPv6, backport from 0.4.2.1-alpha):
+ - When extracting an IPv6 address from a PF-based proxy, verify that
+ we are actually configured to receive an IPv6 address, and log an
+ internal error if not. Fixes part of bug 31687; bugfix
+ on 0.2.3.4-alpha.
+
+ o Minor bugfixes (guards, backport from 0.4.2.1-alpha):
+ - When tor is missing descriptors for some primary entry guards,
+ make the log message less alarming. It's normal for descriptors to
+ expire, as long as tor fetches new ones soon after. Fixes bug
+ 31657; bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.0.2-alpha):
+ - Avoid logging that we are relaxing a circuit timeout when that
+ timeout is fixed. Fixes bug 28698; bugfix on 0.2.4.7-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.0.3-alpha):
+ - Correct a misleading error message when IPv4Only or IPv6Only is
+ used but the resolved address can not be interpreted as an address
+ of the specified IP version. Fixes bug 13221; bugfix on
+ 0.2.3.9-alpha. Patch from Kris Katterjohn.
+ - Log the correct port number for listening sockets when "auto" is
+ used to let Tor pick the port number. Previously, port 0 was
+ logged instead of the actual port number. Fixes bug 29144; bugfix
+ on 0.3.5.1-alpha. Patch from Kris Katterjohn.
+ - Stop logging a BUG() warning when Tor is waiting for exit
+ descriptors. Fixes bug 28656; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.1.1-alpha):
+ - Do not log a warning when running with an OpenSSL version other
+ than the one Tor was compiled with, if the two versions should be
+ compatible. Previously, we would warn whenever the version was
+ different. Fixes bug 30190; bugfix on 0.2.4.2-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.2.1-alpha):
+ - Change log level of message "Hash of session info was not as
+ expected" to LOG_PROTOCOL_WARN. Fixes bug 12399; bugfix
+ on 0.1.1.10-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.2.2-alpha):
+ - Rate-limit our the logging message about the obsolete .exit
+ notation. Previously, there was no limit on this warning, which
+ could potentially be triggered many times by a hostile website.
+ Fixes bug 31466; bugfix on 0.2.2.1-alpha.
+
+ o Minor bugfixes (logging, protocol violations, backport from 0.4.2.2-alpha):
+ - Do not log a nonfatal assertion failure when receiving a VERSIONS
+ cell on a connection using the obsolete v1 link protocol. Log a
+ protocol_warn instead. Fixes bug 31107; bugfix on 0.2.4.4-alpha.
+
+ o Minor bugfixes (mainloop, periodic events, in-process API, backport from 0.4.2.3-alpha):
+ - Reset the periodic events' "enabled" flag when Tor is shut down
+ cleanly. Previously, this flag was left on, which caused periodic
+ events not to be re-enabled when Tor was relaunched in-process
+ with tor_api.h after a shutdown. Fixes bug 32058; bugfix
+ on 0.3.3.1-alpha.
+
+ o Minor bugfixes (memory leak, backport from 0.4.1.1-alpha):
+ - Avoid a minor memory leak that could occur on relays when failing
+ to create a "keys" directory. Fixes bug 30148; bugfix
+ on 0.3.3.1-alpha.
+
+ o Minor bugfixes (memory leak, backport from 0.4.1.4-rc):
+ - Fix a trivial memory leak when parsing an invalid value
+ from a download schedule in the configuration. Fixes bug
+ 30894; bugfix on 0.3.4.1-alpha.
+
+ o Minor bugfixes (memory management, backport from 0.4.0.3-alpha):
+ - Refactor the shared random state's memory management so that it
+ actually takes ownership of the shared random value pointers.
+ Fixes bug 29706; bugfix on 0.2.9.1-alpha.
+
+ o Minor bugfixes (memory management, testing, backport from 0.4.0.3-alpha):
+ - Stop leaking parts of the shared random state in the shared-random
+ unit tests. Fixes bug 29599; bugfix on 0.2.9.1-alpha.
+
+ o Minor bugfixes (onion services, backport from 0.4.1.1-alpha):
+ - Avoid a GCC 9.1.1 warning (and possible crash depending on libc
+ implemenation) when failing to load an onion service client
+ authorization file. Fixes bug 30475; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (out-of-memory handler, backport from 0.4.1.2-alpha):
+ - When purging the DNS cache because of an out-of-memory condition,
+ try purging just the older entries at first. Previously, we would
+ always purge the whole thing. Fixes bug 29617; bugfix
+ on 0.3.5.1-alpha.
+
+ o Minor bugfixes (portability, backport from 0.4.1.2-alpha):
+ - Avoid crashing in our tor_vasprintf() implementation on systems
+ that define neither vasprintf() nor _vscprintf(). (This bug has
+ been here long enough that we question whether people are running
+ Tor on such systems, but we're applying the fix out of caution.)
+ Fixes bug 30561; bugfix on 0.2.8.2-alpha. Found and fixed by
+ Tobias Stoeckmann.
+
+ o Minor bugfixes (relay, backport from 0.4.2.2-alpha):
+ - Avoid crashing when starting with a corrupt keys directory where
+ the old ntor key and the new ntor key are identical. Fixes bug
+ 30916; bugfix on 0.2.4.8-alpha.
+
+ o Minor bugfixes (rust, backport from 0.4.0.5):
+ - Abort on panic in all build profiles, instead of potentially
+ unwinding into C code. Fixes bug 27199; bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (rust, backport from 0.4.2.1-alpha):
+ - Correctly exclude a redundant rust build job in Travis. Fixes bug
+ 31463; bugfix on 0.3.5.4-alpha.
+
+ o Minor bugfixes (single onion services, backport from 0.4.0.3-alpha):
+ - Allow connections to single onion services to remain idle without
+ being disconnected. Previously, relays acting as rendezvous points
+ for single onion services were mistakenly closing idle rendezvous
+ circuits after 60 seconds, thinking that they were unused
+ directory-fetching circuits that had served their purpose. Fixes
+ bug 29665; bugfix on 0.2.1.26.
+
+ o Minor bugfixes (stats, backport from 0.4.0.3-alpha):
+ - When ExtraInfoStatistics is 0, stop including PaddingStatistics in
+ relay and bridge extra-info documents. Fixes bug 29017; bugfix
+ on 0.3.1.1-alpha.
+
+ o Minor bugfixes (testing, backport from 0.4.0.3-alpha):
+ - Downgrade some LOG_ERR messages in the address/* tests to
+ warnings. The LOG_ERR messages were occurring when we had no
+ configured network. We were failing the unit tests, because we
+ backported 28668 to 0.3.5.8, but did not backport 29530. Fixes bug
+ 29530; bugfix on 0.3.5.8.
+ - Fix our gcov wrapper script to look for object files at the
+ correct locations. Fixes bug 29435; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (testing, backport from 0.4.0.4-rc):
+ - Backport the 0.3.4 src/test/test-network.sh to 0.2.9. We need a
+ recent test-network.sh to use new chutney features in CI. Fixes
+ bug 29703; bugfix on 0.2.9.1-alpha.
+ - Fix a test failure on Windows caused by an unexpected "BUG"
+ warning in our tests for tor_gmtime_r(-1). Fixes bug 29922; bugfix
+ on 0.2.9.3-alpha.
+
+ o Minor bugfixes (testing, backport from 0.4.2.3-alpha):
+ - When testing port rebinding, don't busy-wait for tor to log.
+ Instead, actually sleep for a short time before polling again.
+ Also improve the formatting of control commands and log messages.
+ Fixes bug 31837; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (TLS protocol, backport form 0.4.0.4-rc):
+ - When classifying a client's selection of TLS ciphers, if the
+ client ciphers are not yet available, do not cache the result.
+ Previously, we had cached the unavailability of the cipher list
+ and never looked again, which in turn led us to assume that the
+ client only supported the ancient V1 link protocol. This, in turn,
+ was causing Stem integration tests to stall in some cases. Fixes
+ bug 30021; bugfix on 0.2.4.8-alpha.
+
+ o Minor bugfixes (tls, logging, backport from 0.4.2.3-alpha):
+ - Log bugs about the TLS read buffer's length only once, rather than
+ filling the logs with similar warnings. Fixes bug 31939; bugfix
+ on 0.3.0.4-rc.
+
+ o Minor bugfixes (v2 single onion services, backport from 0.4.2.1-alpha):
+ - Always retry v2 single onion service intro and rend circuits with
+ a 3-hop path. Previously, v2 single onion services used a 3-hop
+ path when rendezvous circuits were retried after a remote or
+ delayed failure, but a 1-hop path for immediate retries. Fixes bug
+ 23818; bugfix on 0.2.9.3-alpha.
+ - Make v3 single onion services fall back to a 3-hop intro, when all
+ intro points are unreachable via a 1-hop path. Previously, v3
+ single onion services failed when all intro nodes were unreachable
+ via a 1-hop path. Fixes bug 23507; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfixes (Windows, CI, backport from 0.4.0.3-alpha):
+ - Skip the Appveyor 32-bit Windows Server 2016 job, and 64-bit
+ Windows Server 2012 R2 job. The remaining 2 jobs still provide
+ coverage of 64/32-bit, and Windows Server 2016/2012 R2. Also set
+ fast_finish, so failed jobs terminate the build immediately. Fixes
+ bug 29601; bugfix on 0.3.5.4-alpha.
+
+ o Documentation (backport from 0.4.2.1-alpha):
+ - Use RFC 2397 data URL scheme to embed an image into tor-exit-
+ notice.html so that operators no longer have to host it
+ themselves. Closes ticket 31089.
+
+ o Testing (backport from 0.4.1.2-alpha):
+ - Specify torrc paths (with empty files) when launching tor in
+ integration tests; refrain from reading user and system torrcs.
+ Resolves issue 29702.
+
+ o Testing (continuous integration, backport from 0.4.1.1-alpha):
+ - In Travis, show stem's tor log after failure. Closes ticket 30234.
+
+ o Testing (continuous integration, backport from 0.4.1.5):
+ - In Travis, make stem log a controller trace to the console, and
+ tail stem's tor log after failure. Closes ticket 30591.
+ - In Travis, only run the stem tests that use a tor binary. Closes
+ ticket 30694.
+
+ o Testing (continuous integration, backport from 0.4.2.3-alpha):
+ - Disable all but one Travis CI macOS build, to mitigate slow
+ scheduling of Travis macOS jobs. Closes ticket 32177.
+ - Run the chutney IPv6 networks as part of Travis CI. Closes
+ ticket 30860.
+ - Simplify the Travis CI build matrix, and optimise for build time.
+ Closes ticket 31859.
+ - Use Windows Server 2019 instead of Windows Server 2016 in our
+ Appveyor builds. Closes ticket 32086.
+
+ o Testing (continuous integration, backport from 0.4.2.4-rc):
+ - Use Ubuntu Bionic images for our Travis CI builds, so we can get a
+ recent version of coccinelle. But leave chutney on Ubuntu Trusty,
+ until we can fix some Bionic permissions issues (see ticket
+ 32240). Related to ticket 31919.
+ - Install the mingw OpenSSL package in Appveyor. This makes sure
+ that the OpenSSL headers and libraries match in Tor's Appveyor
+ builds. (This bug was triggered by an Appveyor image update.)
+ Fixes bug 32449; bugfix on 0.3.5.6-rc.
+ - In Travis, use Xcode 11.2 on macOS 10.14. Closes ticket 32241.
+
+ o Testing (continuous integration, backport from 0.4.2.5):
+ - Require C99 standards-conforming code in Travis CI, but allow GNU gcc
+ extensions. Also activates clang's -Wtypedef-redefinition warnings.
+ Build some jobs with -std=gnu99, and some jobs without.
+ Closes ticket 32500.
+
+Changes in version 0.4.2.4-rc - 2019-11-15
+ Tor 0.4.2.4-rc is the first release candidate in its series. It fixes
+ several bugs from earlier versions, including a few that would result in
+ stack traces or incorrect behavior.
+
+ o Minor features (build system):
+ - Make pkg-config use --prefix when cross-compiling, if
+ PKG_CONFIG_PATH is not set. Closes ticket 32191.
+
+ o Minor features (geoip):
+ - Update geoip and geoip6 to the November 6 2019 Maxmind GeoLite2
+ Country database. Closes ticket 32440.
+
+ o Minor bugfixes (client, onion service v3):
+ - Fix a BUG() assertion that occurs within a very small race window
+ between when a client intro circuit opens and when its descriptor
+ gets cleaned up from the cache. The circuit is now closed early,
+ which will trigger a re-fetch of the descriptor and continue the
+ connection. Fixes bug 28970; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfixes (code quality):
+ - Fix "make check-includes" so it runs correctly on out-of-tree
+ builds. Fixes bug 31335; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (configuration):
+ - Log the option name when skipping an obsolete option. Fixes bug
+ 32295; bugfix on 0.4.2.1-alpha.
+
+ o Minor bugfixes (crash):
+ - When running Tor with an option like --verify-config or
+ --dump-config that does not start the event loop, avoid crashing
+ if we try to exit early because of an error. Fixes bug 32407;
+ bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (directory):
+ - When checking if a directory connection is anonymous, test if the
+ circuit was marked for close before looking at its channel. This
+ avoids a BUG() stacktrace if the circuit was previously closed.
+ Fixes bug 31958; bugfix on 0.4.2.1-alpha.
+
+ o Minor bugfixes (shellcheck):
+ - Fix minor shellcheck errors in the git-*.sh scripts. Fixes bug
+ 32402; bugfix on 0.4.2.1-alpha.
+ - Start checking most scripts for shellcheck errors again. Fixes bug
+ 32402; bugfix on 0.4.2.1-alpha.
+
+ o Testing (continuous integration):
+ - Use Ubuntu Bionic images for our Travis CI builds, so we can get a
+ recent version of coccinelle. But leave chutney on Ubuntu Trusty,
+ until we can fix some Bionic permissions issues (see ticket
+ 32240). Related to ticket 31919.
+ - Install the mingw OpenSSL package in Appveyor. This makes sure
+ that the OpenSSL headers and libraries match in Tor's Appveyor
+ builds. (This bug was triggered by an Appveyor image update.)
+ Fixes bug 32449; bugfix on 0.3.5.6-rc.
+ - In Travis, use Xcode 11.2 on macOS 10.14. Closes ticket 32241.
+
+
+Changes in version 0.4.2.3-alpha - 2019-10-24
+ This release fixes several bugs from the previous alpha release, and
+ from earlier versions of Tor.
+
+ o Major bugfixes (relay):
+ - Relays now respect their AccountingMax bandwidth again. When
+ relays entered "soft" hibernation (which typically starts when
+ we've hit 90% of our AccountingMax), we had stopped checking
+ whether we should enter hard hibernation. Soft hibernation refuses
+ new connections and new circuits, but the existing circuits can
+ continue, meaning that relays could have exceeded their configured
+ AccountingMax. Fixes bug 32108; bugfix on 0.4.0.1-alpha.
+
+ o Major bugfixes (v3 onion services):
+ - Onion services now always use the exact number of intro points
+ configured with the HiddenServiceNumIntroductionPoints option (or
+ fewer if nodes are excluded). Before, a service could sometimes
+ pick more intro points than configured. Fixes bug 31548; bugfix
+ on 0.3.2.1-alpha.
+
+ o Minor feature (onion services, control port):
+ - The ADD_ONION command's keyword "BEST" now defaults to ED25519-V3
+ (v3) onion services. Previously it defaulted to RSA1024 (v2).
+ Closes ticket 29669.
+
+ o Minor features (testing):
+ - When running tests that attempt to look up hostnames, replace the
+ libc name lookup functions with ones that do not actually touch
+ the network. This way, the tests complete more quickly in the
+ presence of a slow or missing DNS resolver. Closes ticket 31841.
+
+ o Minor features (testing, continuous integration):
+ - Disable all but one Travis CI macOS build, to mitigate slow
+ scheduling of Travis macOS jobs. Closes ticket 32177.
+ - Run the chutney IPv6 networks as part of Travis CI. Closes
+ ticket 30860.
+ - Simplify the Travis CI build matrix, and optimise for build time.
+ Closes ticket 31859.
+ - Use Windows Server 2019 instead of Windows Server 2016 in our
+ Appveyor builds. Closes ticket 32086.
+
+ o Minor bugfixes (build system):
+ - Interpret "--disable-module-dirauth=no" correctly. Fixes bug
+ 32124; bugfix on 0.3.4.1-alpha.
+ - Interpret "--with-tcmalloc=no" correctly. Fixes bug 32124; bugfix
+ on 0.2.0.20-rc.
+ - Stop failing when jemalloc is requested, but tcmalloc is not
+ found. Fixes bug 32124; bugfix on 0.3.5.1-alpha.
+ - When pkg-config is not installed, or a library that depends on
+ pkg-config is not found, tell the user what to do to fix the
+ problem. Fixes bug 31922; bugfix on 0.3.1.1-alpha.
+
+ o Minor bugfixes (connections):
+ - Avoid trying to read data from closed connections, which can cause
+ needless loops in Libevent and infinite loops in Shadow. Fixes bug
+ 30344; bugfix on 0.1.1.1-alpha.
+
+ o Minor bugfixes (error handling):
+ - Always lock the backtrace buffer before it is used. Fixes bug
+ 31734; bugfix on 0.2.5.3-alpha.
+
+ o Minor bugfixes (mainloop, periodic events, in-process API):
+ - Reset the periodic events' "enabled" flag when Tor is shut down
+ cleanly. Previously, this flag was left on, which caused periodic
+ events not to be re-enabled when Tor was relaunched in-process
+ with tor_api.h after a shutdown. Fixes bug 32058; bugfix
+ on 0.3.3.1-alpha.
+
+ o Minor bugfixes (process management):
+ - Remove overly strict assertions that triggered when a pluggable
+ transport failed to launch. Fixes bug 31091; bugfix
+ on 0.4.0.1-alpha.
+ - Remove an assertion in the Unix process backend. This assertion
+ would trigger when we failed to find the executable for a child
+ process. Fixes bug 31810; bugfix on 0.4.0.1-alpha.
+
+ o Minor bugfixes (testing):
+ - Avoid intermittent test failures due to a test that had relied on
+ inconsistent timing sources. Fixes bug 31995; bugfix
+ on 0.3.1.3-alpha.
+ - When testing port rebinding, don't busy-wait for tor to log.
+ Instead, actually sleep for a short time before polling again.
+ Also improve the formatting of control commands and log messages.
+ Fixes bug 31837; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (tls, logging):
+ - Log bugs about the TLS read buffer's length only once, rather than
+ filling the logs with similar warnings. Fixes bug 31939; bugfix
+ on 0.3.0.4-rc.
+
+ o Minor bugfixes (v3 onion services):
+ - Fix an implicit conversion from ssize_t to size_t discovered by
+ Coverity. Fixes bug 31682; bugfix on 0.4.2.1-alpha.
+ - Fix a memory leak in an unlikely error code path when encoding HS
+ DoS establish intro extension cell. Fixes bug 32063; bugfix
+ on 0.4.2.1-alpha.
+ - When cleaning up intro circuits for a v3 onion service, don't
+ remove circuits that have an established or pending circuit, even
+ if they ran out of retries. This way, we don't remove a circuit on
+ its last retry. Fixes bug 31652; bugfix on 0.3.2.1-alpha.
+
+ o Documentation:
+ - Correct the description of "GuardLifetime". Fixes bug 31189;
+ bugfix on 0.3.0.1-alpha.
+ - Make clear in the man page, in both the bandwidth section and the
+ AccountingMax section, that Tor counts in powers of two, not
+ powers of ten: 1 GByte is 1024*1024*1024 bytes, not one billion
+ bytes. Resolves ticket 32106.
+
+
Changes in version 0.4.2.2-alpha - 2019-10-07
This release fixes several bugs from the previous alpha release, and
from earlier versions. It also includes a change in authorities, so
@@ -159,6 +2000,12 @@ Changes in version 0.4.1.6 - 2019-09-19
arguments. Previously, it required two or more arguments, and ignored
the first. Fixes bug 31772; bugfix on 0.4.1.1-alpha.
+ o Minor bugfixes (FreeBSD, PF-based proxy, IPv6, backport from 0.4.2.1-alpha):
+ - When extracting an IPv6 address from a PF-based proxy, verify that
+ we are actually configured to receive an IPv6 address, and log an
+ internal error if not. Fixes part of bug 31687; bugfix
+ on 0.2.3.4-alpha.
+
o Minor bugfixes (guards, backport from 0.4.2.1-alpha):
- When tor is missing descriptors for some primary entry guards,
make the log message less alarming. It's normal for descriptors to
diff --git a/Doxyfile.in b/Doxyfile.in
index 4caf421097..503c1302db 100644
--- a/Doxyfile.in
+++ b/Doxyfile.in
@@ -1,96 +1,150 @@
-# Doxyfile 1.5.6
+# Doxyfile 1.8.15
+
+# (Tor's Doxyfile is automatically generated from "Doxyfile.in". Don't
+# edit Doxyfile; edit Doxyfile.in.)
# This file describes the settings to be used by the documentation system
-# doxygen (www.doxygen.org) for a project
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
#
-# All text after a hash (#) is considered a comment and will be ignored
+# All text after a single hash (#) is considered a comment and will be ignored.
# The format is:
-# TAG = value [value, ...]
-# For lists items can also be appended using:
-# TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (" ")
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
-# This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all
+# This tag specifies the encoding used for all characters in the configuration
+# file that follow. The default is UTF-8 which is also the encoding used for all
# text before the first occurrence of this tag. Doxygen uses libiconv (or the
# iconv built into libc) for the transcoding. See
-# http://www.gnu.org/software/libiconv for the list of possible encodings.
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
+# The default value is: UTF-8.
DOXYFILE_ENCODING = UTF-8
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
-# by quotes) that should identify the project.
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
-PROJECT_NAME = tor
+PROJECT_NAME = Tor
-# The PROJECT_NUMBER tag can be used to enter a project or revision number.
-# This could be handy for archiving the generated documentation or
-# if some version control system is used.
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
PROJECT_NUMBER = @VERSION@
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
-# base path where the generated documentation will be put.
-# If a relative path is entered, it will be relative to the location
-# where doxygen was started. If left blank the current directory will be used.
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
-OUTPUT_DIRECTORY = @top_builddir@/doc/doxygen
+PROJECT_LOGO =
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
-# 4096 sub-directories (in 2 levels) under the output directory of each output
-# format and will distribute the generated files over these directories.
-# Enabling this option can be useful when feeding doxygen a huge amount of
-# source files, where putting all generated files in the same directory would
-# otherwise cause performance problems for the file system.
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = @abs_top_builddir@/doc/doxygen
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
CREATE_SUBDIRS = NO
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
-# The default language is English, other supported languages are:
-# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
-# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
-# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
-# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
-# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish,
-# and Ukrainian.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
OUTPUT_LANGUAGE = English
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
-# include brief member descriptions after the members that are listed in
-# the file and class documentation (similar to JavaDoc).
-# Set to NO to disable this.
+# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all generated output in the proper direction.
+# Possible values are: None, LTR, RTL and Context.
+# The default value is: None.
+
+OUTPUT_TEXT_DIRECTION = None
-BRIEF_MEMBER_DESC = NO
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
-# the brief description of a member or function before the detailed description.
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
+# The default value is: YES.
REPEAT_BRIEF = YES
-# This tag implements a quasi-intelligent brief description abbreviator
-# that is used to form the text in various listings. Each string
-# in this list, if found as the leading text of the brief description, will be
-# stripped from the text and the result after processing the whole list, is
-# used as the annotated text. Otherwise, the brief description is used as-is.
-# If left blank, the following values are used ("$name" is automatically
-# replaced with the name of the entity): "The $name class" "The $name widget"
-# "The $name file" "is" "provides" "specifies" "contains"
-# "represents" "a" "an" "the"
-
-ABBREVIATE_BRIEF =
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
-# Doxygen will generate a detailed section even if there is only a brief
+# doxygen will generate a detailed section even if there is only a brief
# description.
+# The default value is: NO.
ALWAYS_DETAILED_SEC = NO
@@ -98,482 +152,735 @@ ALWAYS_DETAILED_SEC = NO
# inherited members of a class in the documentation of that class as if those
# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
+# The default value is: NO.
INLINE_INHERITED_MEMB = NO
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
-# path before files name in the file list and in the header files. If set
-# to NO the shortest path that makes the file name unique will be used.
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
-FULL_PATH_NAMES = NO
+FULL_PATH_NAMES = YES
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
-# can be used to strip a user-defined part of the path. Stripping is
-# only done if one of the specified strings matches the left-hand part of
-# the path. The tag can be used to show relative paths in the file list.
-# If left blank the directory from which doxygen is run is used as the
-# path to strip.
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
-STRIP_FROM_PATH =
+STRIP_FROM_PATH = ./src
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
-# the path mentioned in the documentation of a class, which tells
-# the reader which header file to include in order to use a class.
-# If left blank only the name of the header file containing the class
-# definition is used. Otherwise one should specify the include paths that
-# are normally passed to the compiler using the -I flag.
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
STRIP_FROM_INC_PATH =
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
-# (but less readable) file names. This can be useful is your file systems
-# doesn't support long names like on DOS, Mac, or CD-ROM.
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
SHORT_NAMES = NO
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
-# will interpret the first line (until the first dot) of a JavaDoc-style
-# comment as the brief description. If set to NO, the JavaDoc
-# comments will behave just like regular Qt-style comments
-# (thus requiring an explicit @brief command for a brief description.)
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
JAVADOC_AUTOBRIEF = NO
-# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
-# interpret the first line (until the first dot) of a Qt-style
-# comment as the brief description. If set to NO, the comments
-# will behave just like regular Qt-style comments (thus requiring
-# an explicit \brief command for a brief description.)
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
QT_AUTOBRIEF = NO
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
-# treat a multi-line C++ special comment block (i.e. a block of //! or ///
-# comments) as a brief description. This used to be the default behaviour.
-# The new default is to treat a multi-line C++ comment block as a detailed
-# description. Set this tag to YES if you prefer the old behaviour instead.
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
MULTILINE_CPP_IS_BRIEF = NO
-# If the DETAILS_AT_TOP tag is set to YES then Doxygen
-# will output the detailed description near the top, like JavaDoc.
-# If set to NO, the detailed description appears after the member
-# documentation.
-
-# DETAILS_AT_TOP = NO
-
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
-# member inherits the documentation from any documented member that it
-# re-implements.
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
INHERIT_DOCS = YES
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
-# a new page for each member. If set to NO, the documentation of a member will
-# be part of the file/class/namespace that contains it.
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
SEPARATE_MEMBER_PAGES = NO
-# The TAB_SIZE tag can be used to set the number of spaces in a tab.
-# Doxygen uses this value to replace tabs by spaces in code fragments.
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
TAB_SIZE = 8
-# This tag can be used to specify a number of aliases that acts
-# as commands in the documentation. An alias has the form "name=value".
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to
-# put the command \sideeffect (or @sideeffect) in the documentation, which
-# will result in a user-defined paragraph with heading "Side Effects:".
-# You can put \n's in the value part of an alias to insert newlines.
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines (in the resulting output). You can put ^^ in the value part of an
+# alias to insert a newline as if a physical newline was in the original file.
+# When you need a literal { or } or , in the value part of an alias you have to
+# escape them by means of a backslash (\), this can lead to conflicts with the
+# commands \{ and \} for these it is advised to use the version @{ and @} or use
+# a double escape (\\{ and \\})
ALIASES =
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
-# sources only. Doxygen will then generate output that is more tailored for C.
-# For instance, some of the names that are used will be different. The list
-# of all members will be omitted, etc.
+ALIASES += refdir{1}="\ref src/\1 \"\1\""
+
+ALIASES += ticket{1}="[ticket \1](https://bugs.torproject.org/\1)"
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
OPTIMIZE_OUTPUT_FOR_C = YES
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
-# sources only. Doxygen will then generate output that is more tailored for
-# Java. For instance, namespaces will be presented as packages, qualified
-# scopes will look different, etc.
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
OPTIMIZE_OUTPUT_JAVA = NO
# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
-# sources only. Doxygen will then generate output that is more tailored for
-# Fortran.
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
OPTIMIZE_FOR_FORTRAN = NO
# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
-# sources. Doxygen will then generate output that is tailored for
-# VHDL.
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
OPTIMIZE_OUTPUT_VHDL = NO
+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
+# sources only. Doxygen will then generate output that is more tailored for that
+# language. For instance, namespaces will be presented as modules, types will be
+# separated into more groups, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_SLICE = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
+# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
+# tries to guess whether the code is fixed or free formatted code, this is the
+# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat
+# .inc files as Fortran files (default is PHP), and .f files as C (default is
+# Fortran), use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING = dox=md h=C c=C inc=C md=md
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See https://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = YES
+
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 0.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS = 0
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
-# to include (a tag file for) the STL sources as input, then you should
-# set this tag to YES in order to let doxygen match functions declarations and
-# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
-# func(std::string) {}). This also make the inheritance and collaboration
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
BUILTIN_STL_SUPPORT = NO
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
+# The default value is: NO.
CPP_CLI_SUPPORT = NO
-# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
-# Doxygen will parse them like normal C++ but will assume all classes use public
-# instead of private inheritance when no explicit protection keyword is present.
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
SIP_SUPPORT = NO
-# For Microsoft's IDL there are propget and propput attributes to indicate getter
-# and setter methods for a property. Setting this option to YES (the default)
-# will make doxygen to replace the get and set methods by a property in the
-# documentation. This will only work if the methods are indeed getting or
-# setting a simple type. If this is not the case, or you want to show the
-# methods anyway, you should set this option to NO.
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
IDL_PROPERTY_SUPPORT = NO
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
+# tag is set to YES then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
+# The default value is: NO.
DISTRIBUTE_GROUP_DOC = NO
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
-# the same type (for instance a group of public functions) to be put as a
-# subgroup of that type (e.g. under the Public Functions section). Set it to
-# NO to prevent subgrouping. Alternatively, this can be done per class using
-# the \nosubgrouping command.
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
SUBGROUPING = YES
-# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
-# is documented as struct, union, or enum with the name of the typedef. So
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
# with name TypeT. When disabled the typedef will appear as a member of a file,
-# namespace, or class. And the struct will be named TypeS. This can typically
-# be useful for C code in case the coding convention dictates that all compound
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = YES
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
-TYPEDEF_HIDES_STRUCT = NO
+LOOKUP_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
-# documentation are documented, even if no documentation was available.
-# Private class members and static file members will be hidden unless
-# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
EXTRACT_ALL = NO
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
-# will be included in the documentation.
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
EXTRACT_PRIVATE = NO
-# If the EXTRACT_STATIC tag is set to YES all static members of a file
-# will be included in the documentation.
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
EXTRACT_STATIC = YES
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
-# defined locally in source files will be included in the documentation.
-# If set to NO only classes defined in header files are included.
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
EXTRACT_LOCAL_CLASSES = YES
-# This flag is only useful for Objective-C code. When set to YES local
-# methods, which are defined in the implementation section but not in
-# the interface are included in the documentation.
-# If set to NO (the default) only methods in the interface are included.
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
EXTRACT_LOCAL_METHODS = NO
# If this flag is set to YES, the members of anonymous namespaces will be
# extracted and appear in the documentation as a namespace called
-# 'anonymous_namespace{file}', where file will be replaced with the base
-# name of the file that contains the anonymous namespace. By default
-# anonymous namespace are hidden.
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
EXTRACT_ANON_NSPACES = NO
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
-# undocumented members of documented classes, files or namespaces.
-# If set to NO (the default) these members will be included in the
-# various overviews, but no documentation section is generated.
-# This option has no effect if EXTRACT_ALL is enabled.
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
HIDE_UNDOC_MEMBERS = NO
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
-# undocumented classes that are normally visible in the class hierarchy.
-# If set to NO (the default) these classes will be included in the various
-# overviews. This option has no effect if EXTRACT_ALL is enabled.
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
HIDE_UNDOC_CLASSES = NO
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
-# friend (class|struct|union) declarations.
-# If set to NO (the default) these declarations will be included in the
-# documentation.
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO, these declarations will be
+# included in the documentation.
+# The default value is: NO.
HIDE_FRIEND_COMPOUNDS = NO
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
-# documentation blocks found inside the body of a function.
-# If set to NO (the default) these blocks will be appended to the
-# function's detailed documentation block.
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
HIDE_IN_BODY_DOCS = NO
-# The INTERNAL_DOCS tag determines if documentation
-# that is typed after a \internal command is included. If the tag is set
-# to NO (the default) then the documentation will be excluded.
-# Set it to YES to include the internal documentation.
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
INTERNAL_DOCS = NO
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
-# file names in lower-case letters. If set to YES upper-case letters are also
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES, upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
CASE_SENSE_NAMES = YES
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
-# will show members with their full class and namespace scopes in the
-# documentation. If set to YES the scope will be hidden.
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = YES
-HIDE_SCOPE_NAMES = NO
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
-# will put a list of the files that are included by a file in the documentation
-# of that file.
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
SHOW_INCLUDE_FILES = YES
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
-# is inserted in the documentation for inline members.
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
INLINE_INFO = YES
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
-# will sort the (detailed) documentation of file and class members
-# alphabetically by member name. If set to NO the members will appear in
-# declaration order.
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
SORT_MEMBER_DOCS = YES
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
-# brief documentation of file, namespace and class members alphabetically
-# by member name. If set to NO (the default) the members will appear in
-# declaration order.
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
SORT_BRIEF_DOCS = NO
-# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
-# hierarchy of group names into alphabetical order. If set to NO (the default)
-# the group names will appear in their defined order.
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
SORT_GROUP_NAMES = NO
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
-# sorted by fully-qualified names, including namespaces. If set to
-# NO (the default), the class list will be sorted only by class name,
-# not including the namespace part.
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the
-# alphabetical list.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
SORT_BY_SCOPE_NAME = NO
-# The GENERATE_TODOLIST tag can be used to enable (YES) or
-# disable (NO) the todo list. This list is created by putting \todo
-# commands in the documentation.
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
GENERATE_TODOLIST = YES
-# The GENERATE_TESTLIST tag can be used to enable (YES) or
-# disable (NO) the test list. This list is created by putting \test
-# commands in the documentation.
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
GENERATE_TESTLIST = YES
-# The GENERATE_BUGLIST tag can be used to enable (YES) or
-# disable (NO) the bug list. This list is created by putting \bug
-# commands in the documentation.
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
GENERATE_BUGLIST = YES
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
-# disable (NO) the deprecated list. This list is created by putting
-# \deprecated commands in the documentation.
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
GENERATE_DEPRECATEDLIST= YES
-# The ENABLED_SECTIONS tag can be used to enable conditional
-# documentation sections, marked by \if sectionname ... \endif.
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
ENABLED_SECTIONS =
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
-# the initial value of a variable or define consists of for it to appear in
-# the documentation. If the initializer consists of more lines than specified
-# here it will be hidden. Use a value of 0 to hide initializers completely.
-# The appearance of the initializer of individual variables and defines in the
-# documentation can be controlled using \showinitializer or \hideinitializer
-# command in the documentation regardless of this setting.
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
MAX_INITIALIZER_LINES = 30
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
-# at the bottom of the documentation of classes and structs. If set to YES the
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
SHOW_USED_FILES = YES
-# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
-# This will remove the Files entry from the Quick Index and from the
-# Folder Tree View (if specified). The default is YES.
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
SHOW_FILES = YES
-# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
-# Namespaces page. This will remove the Namespaces entry from the Quick Index
-# and from the Folder Tree View (if specified). The default is YES.
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
SHOW_NAMESPACES = YES
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
# doxygen should invoke to get the current version for each file (typically from
# the version control system). Doxygen will invoke the program by executing (via
-# popen()) the command <command> <input-file>, where <command> is the value of
-# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
-# provided by doxygen. Whatever the program writes to standard output
-# is used as the file version. See the manual for examples.
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
FILE_VERSION_FILTER =
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
+# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
-# The QUIET tag can be used to turn on/off the messages that are generated
-# by doxygen. Possible values are YES and NO. If left blank NO is used.
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
QUIET = NO
# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated by doxygen. Possible values are YES and NO. If left blank
-# NO is used.
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
WARNINGS = YES
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
-# automatically be disabled.
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
-WARN_IF_UNDOCUMENTED = YES
+WARN_IF_UNDOCUMENTED = @DOXYGEN_WARN_ON_MISSING@
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some
-# parameters in a documented function, or documenting parameters that
-# don't exist or using markup commands wrongly.
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
WARN_IF_DOC_ERROR = YES
-# This WARN_NO_PARAMDOC option can be abled to get warnings for
-# functions that are documented, but have no documentation for their parameters
-# or return value. If set to NO (the default) doxygen will only warn about
-# wrong or incomplete parameter documentation, but not about the absence of
-# documentation.
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation. If
+# EXTRACT_ALL is set to YES then this flag will automatically be disabled.
+# The default value is: NO.
WARN_NO_PARAMDOC = NO
-# The WARN_FORMAT tag determines the format of the warning messages that
-# doxygen can produce. The string should contain the $file, $line, and $text
-# tags, which will be replaced by the file and line number from which the
-# warning originated and the warning text. Optionally the format may contain
-# $version, which will be replaced by the version of the file (if it could
-# be obtained via FILE_VERSION_FILTER)
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered.
+# The default value is: NO.
+
+WARN_AS_ERROR = @DOXYGEN_FATAL_WARNINGS@
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
WARN_FORMAT = "$file:$line: $text"
-# The WARN_LOGFILE tag can be used to specify a file to which warning
-# and error messages should be written. If left blank the output is written
-# to stderr.
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
WARN_LOGFILE =
#---------------------------------------------------------------------------
-# configuration options related to the input files
+# Configuration options related to the input files
#---------------------------------------------------------------------------
-# The INPUT tag can be used to specify the files and/or directories that contain
-# documented source files. You may enter file names like "myfile.cpp" or
-# directories like "/usr/src/myproject". Separate the files or directories
-# with spaces.
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
-INPUT = @top_srcdir@/src/lib \
- @top_srcdir@/src/core \
- @top_srcdir@/src/feature \
- @top_srcdir@/src/app
+INPUT = ./src/
# This tag can be used to specify the character encoding of the source files
-# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
-# also the default input encoding. Doxygen uses libiconv (or the iconv built
-# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
-# the list of possible encodings.
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
+# possible encodings.
+# The default value is: UTF-8.
INPUT_ENCODING = UTF-8
# If the value of the INPUT tag contains directories, you can use the
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank the following patterns are tested:
-# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
-# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
+# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
+# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
FILE_PATTERNS = *.c \
- *.h
+ *.h \
+ *.inc \
+ *.md
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories
-# should be searched for input files as well. Possible values are YES and NO.
-# If left blank NO is used.
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
RECURSIVE = YES
-# The EXCLUDE tag can be used to specify files and/or directories that should
+# The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
-EXCLUDE = tree.h
+EXCLUDE = ./src/ext \
+ ./src/trunnel \
+ ./src/test \
+ ./src/rust/registry
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
-# directories that are symbolic links (a Unix filesystem feature) are excluded
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
# from the input.
+# The default value is: NO.
EXCLUDE_SYMLINKS = NO
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
-# certain files from those directories. Note that the wildcards are matched
-# against the file with absolute path, so to exclude all test directories
-# for example use the pattern */test/*
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
EXCLUDE_PATTERNS =
@@ -582,510 +889,1169 @@ EXCLUDE_PATTERNS =
# output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass,
# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
EXCLUDE_SYMBOLS =
-# The EXAMPLE_PATH tag can be used to specify one or more files or
-# directories that contain example code fragments that are included (see
-# the \include command).
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
EXAMPLE_PATH =
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank all files are included.
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
-EXAMPLE_PATTERNS =
+EXAMPLE_PATTERNS = *
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
-# searched for input files to be used with the \include or \dontinclude
-# commands irrespective of the value of the RECURSIVE tag.
-# Possible values are YES and NO. If left blank NO is used.
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
EXAMPLE_RECURSIVE = NO
-# The IMAGE_PATH tag can be used to specify one or more files or
-# directories that contain image that are included in the documentation (see
-# the \image command).
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
IMAGE_PATH =
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
-# by executing (via popen()) the command <filter> <input-file>, where <filter>
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
-# input file. Doxygen will then use the output that the filter program writes
-# to standard output. If FILTER_PATTERNS is specified, this tag will be
-# ignored.
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
-# basis. Doxygen will compare the file name with each pattern and apply the
-# filter if there is a match. The filters are a list of the form:
-# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
-# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
-# is applied to all files.
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
FILTER_PATTERNS =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER) will be used to filter the input files when producing source
-# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
FILTER_SOURCE_FILES = NO
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
#---------------------------------------------------------------------------
-# configuration options related to source browsing
+# Configuration options related to source browsing
#---------------------------------------------------------------------------
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will
-# be generated. Documented entities will be cross-referenced with these sources.
-# Note: To get rid of all source code in the generated output, make sure also
-# VERBATIM_HEADERS is set to NO.
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
SOURCE_BROWSER = YES
-# Setting the INLINE_SOURCES tag to YES will include the body
-# of functions and classes directly in the documentation.
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
INLINE_SOURCES = NO
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
-# doxygen to hide any special comment blocks from generated source code
-# fragments. Normal C and C++ comments will always remain visible.
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
-STRIP_CODE_COMMENTS = YES
+STRIP_CODE_COMMENTS = NO
-# If the REFERENCED_BY_RELATION tag is set to YES
-# then for each documented function all documented
-# functions referencing it will be listed.
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# entity all documented functions referencing it will be listed.
+# The default value is: NO.
REFERENCED_BY_RELATION = YES
-# If the REFERENCES_RELATION tag is set to YES
-# then for each documented function all documented entities
-# called/used by that function will be listed.
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
-REFERENCES_RELATION = YES
+REFERENCES_RELATION = NO
-# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
-# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
-# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
-# link to the source code. Otherwise they will link to the documentstion.
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
REFERENCES_LINK_SOURCE = YES
-# If the USE_HTAGS tag is set to YES then the references to source code
-# will point to the HTML generated by the htags(1) tool instead of doxygen
-# built-in source browser. The htags tool is part of GNU's global source
-# tagging system (see http://www.gnu.org/software/global/global.html). You
-# will need version 4.8.6 or higher.
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see https://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
USE_HTAGS = NO
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
-# will generate a verbatim copy of the header file for each class for
-# which an include is specified. Set to NO to disable this.
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
+# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
-# of all compounds will be generated. Enable this if the project
-# contains a lot of classes, structs, unions or interfaces.
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
-ALPHABETICAL_INDEX = NO
+ALPHABETICAL_INDEX = YES
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
-# in which this list will be split (can be a number in the range [1..20])
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
COLS_IN_ALPHA_INDEX = 5
-# In case all classes in a project start with a common prefix, all
-# classes will be put under the same header in the alphabetical index.
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
-# should be ignored while generating the index headers.
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
IGNORE_PREFIX =
#---------------------------------------------------------------------------
-# configuration options related to the HTML output
+# Configuration options related to the HTML output
#---------------------------------------------------------------------------
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
-# generate HTML output.
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
GENERATE_HTML = YES
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `html' will be used as the default path.
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = html
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
-# doxygen will generate files with .html extension.
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FILE_EXTENSION = .html
-# The HTML_HEADER tag can be used to specify a personal HTML header for
-# each generated HTML page. If it is left blank doxygen will generate a
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_HEADER =
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard footer.
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FOOTER =
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
-# style sheet that is used by each HTML page. It can be used to
-# fine-tune the look of the HTML output. If the tag is left blank doxygen
-# will generate a default style sheet. Note that doxygen will try to copy
-# the style sheet file to the HTML output directory, so don't put your own
-# stylesheet in the HTML output directory as well, or it will be erased!
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_STYLESHEET =
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files
-# will be generated that can be used as input for tools like the
-# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
-# of the generated HTML documentation.
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET = doc/tor-doxygen.css
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 150
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via Javascript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have Javascript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS = YES
-GENERATE_HTMLHELP = NO
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = NO
-# If the GENERATE_DOCSET tag is set to YES, additional index files
-# will be generated that can be used as input for Apple's Xcode 3
-# integrated development environment, introduced with OSX 10.5 (Leopard).
-# To create a documentation set, doxygen will generate a Makefile in the
-# HTML output directory. Running make will produce the docset in that
-# directory and running "make install" will install the docset in
-# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
-# it at startup.
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: https://developer.apple.com/xcode/), introduced with OSX
+# 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
+# genXcode/_index.html for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_DOCSET = NO
-# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
-# feed. A documentation feed provides an umbrella under which multiple
-# documentation sets from a single provider (such as a company or product suite)
-# can be grouped.
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
-DOCSET_FEEDNAME = "Doxygen generated docs for Tor"
+DOCSET_FEEDNAME = "Doxygen generated docs"
-# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
-# should uniquely identify the documentation set bundle. This should be a
-# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
-# will append .docset to the name.
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
-DOCSET_BUNDLE_ID = org.torproject.Tor
+DOCSET_BUNDLE_ID = org.doxygen.Project
-# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
-# documentation will contain sections that can be hidden and shown after the
-# page has loaded. For this to work a browser that supports
-# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
-# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
-HTML_DYNAMIC_SECTIONS = NO
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
-# be used to specify the file name of the resulting .chm file. You
-# can add a path in front of the file if the result should not be
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_FILE =
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
-# be used to specify the location (absolute path including file name) of
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
-# the HTML help compiler on the generated index.hhp.
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
HHC_LOCATION =
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
-# controls if a separate .chi index file is generated (YES) or that
-# it should be included in the master .chm file (NO).
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the master .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
GENERATE_CHI = NO
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
-# is used to encode HtmlHelp index (hhk), content (hhc) and project file
-# content.
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_INDEX_ENCODING =
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
-# controls whether a binary table of contents is generated (YES) or a
-# normal table of contents (NO) in the .chm file.
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
BINARY_TOC = NO
-# The TOC_EXPAND flag can be set to YES to add extra items for group members
-# to the contents of the HTML help documentation and to the tree view.
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
TOC_EXPAND = NO
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
-# top of each HTML page. The value NO (the default) enables the index and
-# the value YES disables it.
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
DISABLE_INDEX = NO
-# This tag can be used to set the number of enum values (range [1..20])
-# that doxygen will group on one line in the generated HTML documentation.
-
-ENUM_VALUES_PER_LINE = 4
-
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
-# structure should be generated to display hierarchical information.
-# If the tag value is set to FRAME, a side panel will be generated
-# containing a tree-like index structure (just like the one that
-# is generated for HTML Help). For this to work a browser that supports
-# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
-# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
-# probably better off using the HTML help feature. Other possible values
-# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
-# and Class Hiererachy pages using a tree view instead of an ordered list;
-# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
-# disables this behavior completely. For backwards compatibility with previous
-# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
-# respectively.
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = NO
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
-# used to set the initial width (in pixels) of the frame in which the tree
-# is shown.
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
TREEVIEW_WIDTH = 250
-# Use this tag to change the font size of Latex formulas included
-# as images in the HTML documentation. The default is 10. Note that
-# when you change the font size after a successful doxygen run you need
-# to manually remove any form_*.png images from the HTML output directory
-# to force them to be regenerated.
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_FONTSIZE = 10
+# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# https://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from https://www.mathjax.org before deployment.
+# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: https://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: https://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
#---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
+# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
-# generate Latex output.
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
-GENERATE_LATEX = YES
+GENERATE_LATEX = NO
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `latex' will be used as the default path.
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_OUTPUT = latex
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
-# invoked. If left blank `latex' will be used as the default command name.
-
-LATEX_CMD_NAME = latex
-
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
-# generate index for LaTeX. If left blank `makeindex' will be used as the
-# default command name.
+# invoked.
+#
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME =
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
MAKEINDEX_CMD_NAME = makeindex
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
-# LaTeX documents. This may be useful for small projects and may help to
-# save some trees in general.
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: \makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
-COMPACT_LATEX = NO
+LATEX_MAKEINDEX_CMD = \makeindex
-# The PAPER_TYPE tag can be used to set the paper type that is used
-# by the printer. Possible values are: a4, a4wide, letter, legal and
-# executive. If left blank a4wide will be used.
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
-PAPER_TYPE = a4wide
+COMPACT_LATEX = NO
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
-# packages that should be included in the LaTeX output.
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
EXTRA_PACKAGES =
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
-# the generated latex document. The header should contain everything until
-# the first chapter. If it is left blank doxygen will generate a
-# standard header. Notice: only use this tag if you know what you are doing!
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER =
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will
-# contain links (just like the HTML output) instead of page references
-# This makes the output suitable for online browsing using a pdf viewer.
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
-PDF_HYPERLINKS = NO
+LATEX_FOOTER =
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
-# plain latex in the generated Makefile. Set this option to YES to get a
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
-USE_PDFLATEX = NO
+USE_PDFLATEX = YES
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
-# command to the generated LaTeX files. This will instruct LaTeX to keep
-# running if errors occur, instead of asking the user for help.
-# This option is also used when generating formulas in HTML.
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_BATCHMODE = NO
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not
-# include the index chapters (such as File Index, Compound Index, etc.)
-# in the output.
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HIDE_INDICES = NO
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP = NO
+
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY =
+
#---------------------------------------------------------------------------
-# configuration options related to the RTF output
+# Configuration options related to the RTF output
#---------------------------------------------------------------------------
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
-# The RTF output is optimized for Word 97 and may not look very pretty with
-# other RTF readers or editors.
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
GENERATE_RTF = NO
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `rtf' will be used as the default path.
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_OUTPUT = rtf
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
-# RTF documents. This may be useful for small projects and may help to
-# save some trees in general.
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
COMPACT_RTF = NO
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
-# will contain hyperlink fields. The RTF file will
-# contain links (just like the HTML output) instead of page references.
-# This makes the output suitable for online browsing using WORD or other
-# programs which support those fields.
-# Note: wordpad (write) and others do not support links.
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_HYPERLINKS = NO
# Load stylesheet definitions from file. Syntax is similar to doxygen's
-# config file, i.e. a series of assignments. You only have to provide
+# configuration file, i.e. a series of assignments. You only have to provide
# replacements, missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_STYLESHEET_FILE =
-# Set optional variables used in the generation of an rtf document.
-# Syntax is similar to doxygen's config file.
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_EXTENSIONS_FILE =
+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
+# with syntax highlighting in the RTF output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_SOURCE_CODE = NO
+
#---------------------------------------------------------------------------
-# configuration options related to the man page output
+# Configuration options related to the man page output
#---------------------------------------------------------------------------
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
-# generate man pages
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
GENERATE_MAN = NO
-# The MAN_OUTPUT tag is used to specify where the man pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `man' will be used as the default path.
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_OUTPUT = man
-# The MAN_EXTENSION tag determines the extension that is added to
-# the generated man pages (default is the subroutine's section .3)
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_EXTENSION = .3
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
-# then it will generate one additional man file for each entity
-# documented in the real man page(s). These additional files
-# only source the real man page, but without them the man command
-# would be unable to find the correct page. The default is NO.
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_LINKS = NO
#---------------------------------------------------------------------------
-# configuration options related to the XML output
+# Configuration options related to the XML output
#---------------------------------------------------------------------------
-# If the GENERATE_XML tag is set to YES Doxygen will
-# generate an XML file that captures the structure of
-# the code including all documentation.
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
GENERATE_XML = NO
-# The XML_OUTPUT tag is used to specify where the XML pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `xml' will be used as the default path.
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
XML_OUTPUT = xml
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
-# dump the program listings (including syntax highlighting
-# and cross-referencing information) to the XML output. Note that
-# enabling this will significantly increase the size of the XML output.
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
XML_PROGRAMLISTING = YES
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_NS_MEMB_FILE_SCOPE = NO
+
#---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
+# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
-# generate an AutoGen Definitions (see autogen.sf.net) file
-# that captures the structure of the code including all
-# documentation. Note that this feature is still experimental
-# and incomplete at the moment.
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
+# The default value is: NO.
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
-# configuration options related to the Perl module output
+# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will
-# generate a Perl module file that captures the structure of
-# the code including all documentation. Note that this
-# feature is still experimental and incomplete at the
-# moment.
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
GENERATE_PERLMOD = NO
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able
-# to generate PDF and DVI output from the Perl module output.
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_LATEX = NO
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
-# nicely formatted so it can be parsed by a human reader. This is useful
-# if you want to understand what is going on. On the other hand, if this
-# tag is set to NO the size of the Perl module output will be much smaller
-# and Perl will parse it just the same.
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_PRETTY = YES
-# The names of the make variables in the generated doxyrules.make file
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
-# This is useful so different doxyrules.make files included by the same
-# Makefile don't overwrite each other's variables.
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_MAKEVAR_PREFIX =
@@ -1093,108 +2059,136 @@ PERLMOD_MAKEVAR_PREFIX =
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
-# evaluate all C-preprocessor directives found in the sources and include
-# files.
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
ENABLE_PREPROCESSING = YES
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
-# names in the source code. If set to NO (the default) only conditional
-# compilation will be performed. Macro expansion can be done in a controlled
-# way by setting EXPAND_ONLY_PREDEF to YES.
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-MACRO_EXPANSION = NO
+MACRO_EXPANSION = YES
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
-# then the macro expansion is limited to the macros specified with the
-# PREDEFINED and EXPAND_AS_DEFINED tags.
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-EXPAND_ONLY_PREDEF = NO
+EXPAND_ONLY_PREDEF = YES
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
-# in the INCLUDE_PATH (see below) will be search if a #include is found.
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
-# contain include files that are not input files but should be processed by
-# the preprocessor.
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
INCLUDE_PATH =
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
-# directories. If left blank, the patterns specified with FILE_PATTERNS will
-# be used.
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
INCLUDE_FILE_PATTERNS =
-# The PREDEFINED tag can be used to specify one or more macro names that
-# are defined before the preprocessor is started (similar to the -D option of
-# gcc). The argument of the tag is a list of macros of the form: name
-# or name=definition (no spaces). If the definition and the = are
-# omitted =1 is assumed. To prevent a macro definition from being
-# undefined via #undef or recursively expanded use the := operator
-# instead of the = operator.
-
-PREDEFINED =
-
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
-# this tag can be used to specify a list of macro names that should be expanded.
-# The macro definition that is found in the sources will be used.
-# Use the PREDEFINED tag if you want to use a different macro definition.
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED = "MOCK_IMPL(a,b,c)=a b c" \
+ "MOCK_DECL(a,b,c)=a b c" \
+ __attribute__(x)= \
+ "BEGIN_CONF_STRUCT(x)=struct x {" \
+ "END_CONF_STRUCT(x)=};" \
+ "CONF_VAR(a,b,c,d)=b a;" \
+ "CHECK_PRINTF(a, b)="
+
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_AS_DEFINED =
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
-# doxygen's preprocessor will remove all function-like macros that are alone
-# on a line, have an all uppercase name, and do not end with a semicolon. Such
-# function macros are typically used for boiler-plate code, and will confuse
-# the parser if not removed.
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
-# Configuration::additions related to external references
+# Configuration options related to external references
#---------------------------------------------------------------------------
-# The TAGFILES option can be used to specify one or more tagfiles.
-# Optionally an initial location of the external documentation
-# can be added for each tagfile. The format of a tag file without
-# this location is as follows:
-# TAGFILES = file1 file2 ...
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
# Adding location for the tag files is done as follows:
-# TAGFILES = file1=loc1 "file2 = loc2" ...
-# where "loc1" and "loc2" can be relative or absolute paths or
-# URLs. If a location is present for each tag, the installdox tool
-# does not have to be run to correct the links.
-# Note that each tag file must have a unique name
-# (where the name does NOT include the path)
-# If a tag file is not located in the directory in which doxygen
-# is run, you must also specify the path to the tagfile here.
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
TAGFILES =
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create
-# a tag file that is based on the input files it reads.
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
GENERATE_TAGFILE =
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed
-# in the class index. If set to NO only the inherited external classes
-# will be listed.
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
ALLEXTERNALS = NO
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
-# in the modules index. If set to NO, only the current project's groups will
-# be listed.
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
EXTERNAL_GROUPS = YES
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
# The PERL_PATH should be the absolute path and name of the perl script
-# interpreter (i.e. the result of `which perl').
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
PERL_PATH = /usr/bin/perl
@@ -1202,196 +2196,317 @@ PERL_PATH = /usr/bin/perl
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
-# or super classes. Setting the tag to NO turns the diagrams off. Note that
-# this option is superseded by the HAVE_DOT option below. This is only a
-# fallback. It is recommended to install and use dot, since it yields more
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
# powerful graphs.
+# The default value is: YES.
CLASS_DIAGRAMS = YES
# You can define message sequence charts within doxygen comments using the \msc
-# command. Doxygen will then run the mscgen tool (see
-# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
# documentation. The MSCGEN_PATH tag allows you to specify the directory where
# the mscgen tool resides. If left empty the tool is assumed to be found in the
# default search path.
MSCGEN_PATH =
-# If set to YES, the inheritance and collaboration graphs will hide
-# inheritance and usage relations if the target is undocumented
-# or is not a class.
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
HIDE_UNDOC_RELATIONS = YES
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
-# available from the path. This tool is part of Graphviz, a graph visualization
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section
-# have no effect if this option is set to NO (the default)
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
HAVE_DOT = NO
-# By default doxygen will write a font called FreeSans.ttf to the output
-# directory and reference it in all dot files that doxygen generates. This
-# font does not include all possible unicode characters however, so when you need
-# these (or just want a differently looking font) you can specify the font name
-# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
-# which can be done by putting it in a standard location or by setting the
-# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
-# containing the font.
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_FONTNAME =
+DOT_FONTNAME = Helvetica
-# By default doxygen will tell dot to use the output directory to look for the
-# FreeSans.ttf font (which doxygen will put there itself). If you specify a
-# different font using DOT_FONTNAME you can set the path where dot
-# can find it using this tag.
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTPATH =
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect inheritance relations. Setting this tag to YES will force the
-# the CLASS_DIAGRAMS tag to NO.
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
CLASS_GRAPH = YES
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect implementation dependencies (inheritance, containment, and
-# class references variables) of the class with other documented classes.
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
COLLABORATION_GRAPH = YES
-# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for groups, showing the direct groups dependencies
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
GROUP_GRAPHS = YES
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
UML_LOOK = NO
-# If set to YES, the inheritance and collaboration graphs will show the
-# relations between templates and their instances.
-
-TEMPLATE_RELATIONS = YES
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
-# tags are set to YES then doxygen will generate a graph for each documented
-# file showing the direct and indirect include dependencies of the file with
-# other documented files.
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
INCLUDE_GRAPH = YES
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
-# documented header file showing the documented files that directly or
-# indirectly include this file.
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
INCLUDED_BY_GRAPH = YES
-# If the CALL_GRAPH and HAVE_DOT options are set to YES then
-# doxygen will generate a call dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable call graphs
-# for selected functions only using the \callgraph command.
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
CALL_GRAPH = NO
-# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
-# doxygen will generate a caller dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable caller
-# graphs for selected functions only using the \callergraph command.
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
CALLER_GRAPH = NO
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
-# will graphical hierarchy of all classes instead of a textual one.
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
GRAPHICAL_HIERARCHY = YES
-# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
-# then doxygen will show the dependencies a directory has on other directories
-# in a graphical way. The dependency relations are determined by the #include
-# relations between the files in the directories.
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
DIRECTORY_GRAPH = YES
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot. Possible values are png, jpg, or gif
-# If left blank png will be used.
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_IMAGE_FORMAT = png
-# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_PATH =
# The DOTFILE_DIRS tag can be used to specify one or more directories that
-# contain dot files that are included in the documentation (see the
-# \dotfile command).
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
DOTFILE_DIRS =
-# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
-# nodes that will be shown in the graph. If the number of nodes in a graph
-# becomes larger than this value, doxygen will truncate the graph, which is
-# visualized by representing a node as a red box. Note that doxygen if the
-# number of direct children of the root node in a graph is already larger than
-# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
-# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+
+PLANTUML_JAR_PATH =
+
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_GRAPH_MAX_NODES = 50
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
-# graphs generated by dot. A depth value of 3 means that only nodes reachable
-# from the root by following a path via at most 3 edges will be shown. Nodes
-# that lay further from the root node will be omitted. Note that setting this
-# option to 1 or 2 may greatly reduce the computation time needed for large
-# code bases. Also note that the size of a graph can be further restricted by
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
MAX_DOT_GRAPH_DEPTH = 0
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is enabled by default, which results in a transparent
-# background. Warning: Depending on the platform used, enabling this option
-# may lead to badly anti-aliased labels on the edges of a graph (i.e. they
-# become hard to read).
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_TRANSPARENT = NO
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
-# makes dot run faster, but since only newer versions of dot (>1.8.10)
-# support this, this feature is disabled by default.
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_MULTI_TARGETS = NO
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
-# generate a legend page explaining the meaning of the various boxes and
-# arrows in the dot generated graphs.
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
GENERATE_LEGEND = YES
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
-# remove the intermediate dot files that are used to generate
-# the various graphs.
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_CLEANUP = YES
-
-#---------------------------------------------------------------------------
-# Configuration::additions related to the search engine
-#---------------------------------------------------------------------------
-
-# The SEARCHENGINE tag specifies whether or not a search engine should be
-# used. If set to NO the values of all tags below this one will be ignored.
-
-SEARCHENGINE = NO
diff --git a/Makefile.am b/Makefile.am
index f6346fe0fc..1041494da7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -21,7 +21,12 @@ AM_CPPFLAGS=\
-I$(top_srcdir)/src/ext/trunnel \
-I$(top_srcdir)/src/trunnel
-AM_CFLAGS=@TOR_SYSTEMD_CFLAGS@ @CFLAGS_BUGTRAP@ @TOR_LZMA_CFLAGS@ @TOR_ZSTD_CFLAGS@
+AM_CFLAGS= \
+ @TOR_SYSTEMD_CFLAGS@ \
+ @CFLAGS_BUGTRAP@ \
+ @TOR_LZMA_CFLAGS@ \
+ @TOR_ZSTD_CFLAGS@
+
SHELL=@SHELL@
if COVERAGE_ENABLED
@@ -160,37 +165,52 @@ include contrib/include.am
manpages: $(nodist_man1_MANS)
EXTRA_DIST+= \
- ChangeLog \
- CONTRIBUTING \
- CODE_OF_CONDUCT \
- INSTALL \
- LICENSE \
- Makefile.nmake \
- README \
- ReleaseNotes \
- scripts/maint/checkIncludes.py \
- scripts/maint/checkSpace.pl \
- scripts/maint/checkShellScripts.sh \
- scripts/maint/practracker/README \
- scripts/maint/practracker/exceptions.txt \
- scripts/maint/practracker/includes.py \
- scripts/maint/practracker/metrics.py \
- scripts/maint/practracker/practracker.py \
- scripts/maint/practracker/practracker_tests.py \
- scripts/maint/practracker/problem.py \
- scripts/maint/practracker/testdata/.may_include \
- scripts/maint/practracker/testdata/a.c \
- scripts/maint/practracker/testdata/b.c \
- scripts/maint/practracker/testdata/ex0-expected.txt \
- scripts/maint/practracker/testdata/ex0.txt \
- scripts/maint/practracker/testdata/ex1-expected.txt \
- scripts/maint/practracker/testdata/ex1.txt \
- scripts/maint/practracker/testdata/ex1-overbroad-expected.txt \
- scripts/maint/practracker/testdata/ex.txt \
- scripts/maint/practracker/testdata/header.h \
- scripts/maint/practracker/testdata/not_c_file \
- scripts/maint/practracker/test_practracker.sh \
- scripts/maint/practracker/util.py
+ ChangeLog \
+ CONTRIBUTING \
+ CODE_OF_CONDUCT \
+ INSTALL \
+ LICENSE \
+ Makefile.nmake \
+ README \
+ ReleaseNotes \
+ scripts/maint/checkIncludes.py \
+ scripts/maint/checkSpace.pl \
+ scripts/maint/checkSpaceTest.sh \
+ scripts/maint/checkspace_tests/dubious.c \
+ scripts/maint/checkspace_tests/dubious.h \
+ scripts/maint/checkspace_tests/expected.txt \
+ scripts/maint/checkspace_tests/good_guard.h \
+ scripts/maint/checkspace_tests/same_guard.h \
+ scripts/maint/checkspace_tests/subdir/dubious.c \
+ scripts/maint/checkShellScripts.sh \
+ scripts/maint/practracker/README \
+ scripts/maint/practracker/exceptions.txt \
+ scripts/maint/practracker/includes.py \
+ scripts/maint/practracker/metrics.py \
+ scripts/maint/practracker/practracker.py \
+ scripts/maint/practracker/practracker_tests.py \
+ scripts/maint/practracker/problem.py \
+ scripts/maint/practracker/testdata/.may_include \
+ scripts/maint/practracker/testdata/a.c \
+ scripts/maint/practracker/testdata/b.c \
+ scripts/maint/practracker/testdata/ex0-expected.txt \
+ scripts/maint/practracker/testdata/ex0.txt \
+ scripts/maint/practracker/testdata/ex1-expected.txt \
+ scripts/maint/practracker/testdata/ex1.txt \
+ scripts/maint/practracker/testdata/ex1-overbroad-expected.txt \
+ scripts/maint/practracker/testdata/ex1-regen-expected.txt \
+ scripts/maint/practracker/testdata/ex1-regen-overbroad-expected.txt \
+ scripts/maint/practracker/testdata/ex.txt \
+ scripts/maint/practracker/testdata/header.h \
+ scripts/maint/practracker/testdata/not_c_file \
+ scripts/maint/practracker/test_practracker.sh \
+ scripts/maint/practracker/util.py \
+ scripts/coccinelle/apply.sh \
+ scripts/coccinelle/check_cocci_parse.sh \
+ scripts/coccinelle/exceptions.txt \
+ scripts/coccinelle/test-operator-cleanup \
+ scripts/coccinelle/tor-coccinelle.h \
+ scripts/coccinelle/try_parse.sh
## This tells etags how to find mockable function definitions.
AM_ETAGSFLAGS=--regex='{c}/MOCK_IMPL([^,]+,\W*\([a-zA-Z0-9_]+\)\W*,/\1/s'
@@ -238,8 +258,10 @@ dist-rpm: dist-gzip
echo "RPM build finished"; \
#end of dist-rpm
-doxygen:
- doxygen && cd doc/doxygen/latex && make
+.PHONY: doxygen
+doxygen: Doxyfile
+ mkdir -p doc/doxygen
+ (cd "$(top_srcdir)" && doxygen "$(abs_top_builddir)/Doxyfile")
test: all
$(top_builddir)/src/test/test
@@ -247,7 +269,11 @@ test: all
shellcheck:
$(top_srcdir)/scripts/maint/checkShellScripts.sh
-check-local: check-spaces check-changes check-includes shellcheck
+check-local: \
+ check-spaces \
+ check-changes \
+ check-includes \
+ shellcheck
need-chutney-path:
@if test ! -d "$$CHUTNEY_PATH"; then \
@@ -317,9 +343,19 @@ test-stem: need-stem-path $(TESTING_TOR_BINARY)
test-stem-full: need-stem-path $(TESTING_TOR_BINARY)
@$(PYTHON) "$$STEM_SOURCE_DIR"/run_tests.py --tor "$(TESTING_TOR_BINARY)" --all --log notice --target RUN_ALL,ONLINE -v;
-test-full: need-stem-path need-chutney-path check test-network test-stem
+test-full: \
+ need-stem-path \
+ need-chutney-path \
+ check \
+ test-network \
+ test-stem
-test-full-online: need-stem-path need-chutney-path check test-network test-stem-full
+test-full-online: \
+ need-stem-path \
+ need-chutney-path \
+ check \
+ test-network \
+ test-stem-full
# We can't delete the gcno files, because they are created when tor is compiled
reset-gcov:
@@ -355,6 +391,10 @@ coverage-html-full: all
genhtml --branch-coverage -o "$(HTML_COVER_DIR)" "$(HTML_COVER_DIR)/lcov.info"
# For scripts: avoid src/ext and src/trunnel.
+# Keep these lists consistent:
+# - OWNED_TOR_C_FILES in Makefile.am
+# - CHECK_FILES in pre-commit.git-hook and pre-push.git-hook
+# - try_parse in check_cocci_parse.sh
OWNED_TOR_C_FILES=\
$(top_srcdir)/src/lib/*/*.[ch] \
$(top_srcdir)/src/core/*/*.[ch] \
@@ -380,6 +420,9 @@ if USEPYTHON
@$(PYTHON) $(top_srcdir)/scripts/maint/practracker/practracker.py $(top_srcdir) $(TOR_PRACTRACKER_OPTIONS)
endif
+check-cocci:
+ VERBOSE=1 $(top_srcdir)/scripts/coccinelle/check_cocci_parse.sh $(OWNED_TOR_C_FILES)
+
practracker-regen:
$(PYTHON) $(top_srcdir)/scripts/maint/practracker/practracker.py --regen $(top_srcdir)
@@ -469,7 +512,7 @@ update-versions:
.PHONY: callgraph
callgraph:
- $(top_builddir)/scripts/maint/run_calltool.sh
+ cd $(top_builddir); $(abs_top_srcdir)/scripts/maint/run_calltool.sh
version:
@echo "Tor @VERSION@"
@@ -480,19 +523,19 @@ version:
.PHONY: autostyle-ifdefs
autostyle-ifdefs:
- $(PYTHON) scripts/maint/annotate_ifdef_directives.py $(OWNED_TOR_C_FILES)
+ $(PYTHON) $(top_srcdir)/scripts/maint/annotate_ifdef_directives.py $(OWNED_TOR_C_FILES)
.PHONY: autostyle-ifdefs
autostyle-operators:
- $(PERL) scripts/coccinelle/test-operator-cleanup $(OWNED_TOR_C_FILES)
+ $(PERL) $(top_srcdir)/scripts/coccinelle/test-operator-cleanup $(OWNED_TOR_C_FILES)
.PHONY: rectify-includes
rectify-includes:
- $(PYTHON) scripts/maint/rectify_include_paths.py
+ cd $(top_srcdir); $(PYTHON) $(abs_top_srcdir)/scripts/maint/rectify_include_paths.py
.PHONY: update-copyright
update-copyright:
- $(PERL) scripts/maint/updateCopyright.pl $(OWNED_TOR_C_FILES)
+ $(PERL) $(top_srcdir)/scripts/maint/updateCopyright.pl $(OWNED_TOR_C_FILES)
.PHONY: autostyle
autostyle: update-versions rustfmt autostyle-ifdefs rectify-includes
diff --git a/ReleaseNotes b/ReleaseNotes
index ad24efd606..7d981e2c42 100644
--- a/ReleaseNotes
+++ b/ReleaseNotes
@@ -2,6 +2,1747 @@ This document summarizes new features and bugfixes in each stable
release of Tor. If you want to see more detailed descriptions of the
changes in each development snapshot, see the ChangeLog file.
+Changes in version 0.4.2.6 - 2020-01-30
+ This is the second stable release in the 0.4.2.x series. It backports
+ several bugfixes from 0.4.3.1-alpha, including some that had affected
+ the Linux seccomp2 sandbox or Windows services. If you're running with
+ one of those configurations, you'll probably want to upgrade;
+ otherwise, you should be fine with 0.4.2.5.
+
+ o Major bugfixes (linux seccomp sandbox, backport from 0.4.3.1-alpha):
+ - Correct how we use libseccomp. Particularly, stop assuming that
+ rules are applied in a particular order or that more rules are
+ processed after the first match. Neither is the case! In
+ libseccomp <2.4.0 this led to some rules having no effect.
+ libseccomp 2.4.0 changed how rules are generated, leading to a
+ different ordering, which in turn led to a fatal crash during
+ startup. Fixes bug 29819; bugfix on 0.2.5.1-alpha. Patch by
+ Peter Gerber.
+ - Fix crash when reloading logging configuration while the
+ experimental sandbox is enabled. Fixes bug 32841; bugfix on
+ 0.4.1.7. Patch by Peter Gerber.
+
+ o Minor bugfixes (correctness checks, backport from 0.4.3.1-alpha):
+ - Use GCC/Clang's printf-checking feature to make sure that
+ tor_assertf() arguments are correctly typed. Fixes bug 32765;
+ bugfix on 0.4.1.1-alpha.
+
+ o Minor bugfixes (logging, crash, backport from 0.4.3.1-alpha):
+ - Avoid a possible crash when trying to log a (fatal) assertion
+ failure about mismatched magic numbers in configuration objects.
+ Fixes bug 32771; bugfix on 0.4.2.1-alpha.
+
+ o Minor bugfixes (testing, backport from 0.4.3.1-alpha):
+ - When TOR_DISABLE_PRACTRACKER is set, do not apply it to the
+ test_practracker.sh script. Doing so caused a test failure. Fixes
+ bug 32705; bugfix on 0.4.2.1-alpha.
+ - When TOR_DISABLE_PRACTRACKER is set, log a notice to stderr when
+ skipping practracker checks. Fixes bug 32705; bugfix
+ on 0.4.2.1-alpha.
+
+ o Minor bugfixes (windows service, backport from 0.4.3.1-alpha):
+ - Initialize the publish/subscribe system when running as a windows
+ service. Fixes bug 32778; bugfix on 0.4.1.1-alpha.
+
+ o Testing (backport from 0.4.3.1-alpha):
+ - Turn off Tor's Sandbox in Chutney jobs, and run those jobs on
+ Ubuntu Bionic. Turning off the Sandbox is a work-around, until we
+ fix the sandbox errors in 32722. Closes ticket 32240.
+ - Re-enable the Travis CI macOS Chutney build, but don't let it
+ prevent the Travis job from finishing. (The Travis macOS jobs are
+ slow, so we don't want to have it delay the whole CI process.)
+ Closes ticket 32629.
+
+ o Testing (continuous integration, backport from 0.4.3.1-alpha):
+ - Use zstd in our Travis Linux builds. Closes ticket 32242.
+
+
+Changes in version 0.4.1.8 - 2020-01-30
+ This release backports several bugfixes from later release series,
+ including some that had affected the Linux seccomp2 sandbox or Windows
+ services. If you're running with one of those configurations, you'll
+ probably want to upgrade; otherwise, you should be fine with your
+ current version of 0.4.1.x.
+
+ o Major bugfixes (linux seccomp sandbox, backport from 0.4.3.1-alpha):
+ - Correct how we use libseccomp. Particularly, stop assuming that
+ rules are applied in a particular order or that more rules are
+ processed after the first match. Neither is the case! In
+ libseccomp <2.4.0 this led to some rules having no effect.
+ libseccomp 2.4.0 changed how rules are generated, leading to a
+ different ordering, which in turn led to a fatal crash during
+ startup. Fixes bug 29819; bugfix on 0.2.5.1-alpha. Patch by
+ Peter Gerber.
+ - Fix crash when reloading logging configuration while the
+ experimental sandbox is enabled. Fixes bug 32841; bugfix on
+ 0.4.1.7. Patch by Peter Gerber.
+
+ o Minor bugfixes (crash, backport form 0.4.2.4-rc):
+ - When running Tor with an option like --verify-config or
+ --dump-config that does not start the event loop, avoid crashing
+ if we try to exit early because of an error. Fixes bug 32407;
+ bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (windows service, backport from 0.4.3.1-alpha):
+ - Initialize the publish/subscribe system when running as a windows
+ service. Fixes bug 32778; bugfix on 0.4.1.1-alpha.
+
+ o Testing (backport from 0.4.3.1-alpha):
+ - Turn off Tor's Sandbox in Chutney jobs, and run those jobs on
+ Ubuntu Bionic. Turning off the Sandbox is a work-around, until we
+ fix the sandbox errors in 32722. Closes ticket 32240.
+ - Re-enable the Travis CI macOS Chutney build, but don't let it
+ prevent the Travis job from finishing. (The Travis macOS jobs are
+ slow, so we don't want to have it delay the whole CI process.)
+ Closes ticket 32629.
+
+ o Testing (continuous integration, backport from 0.4.3.1-alpha):
+ - Use zstd in our Travis Linux builds. Closes ticket 32242.
+
+
+Changes in version 0.4.2.5 - 2019-12-09
+ This is the first stable release in the 0.4.2.x series. This series
+ improves reliability and stability, and includes several stability and
+ correctness improvements for onion services. It also fixes many smaller
+ bugs present in previous series.
+
+ Per our support policy, we will support the 0.4.2.x series for nine
+ months, or until three months after the release of a stable 0.4.3.x:
+ whichever is longer. If you need longer-term support, please stick
+ with 0.3.5.x, which will we plan to support until Feb 2022.
+
+ Below are the changes since 0.4.1.4-rc. For a complete list of only
+ the changes since 0.4.2.4-rc, see the ChangeLog file.
+
+ o Major features (directory authorities):
+ - Directory authorities now reject relays running all currently
+ deprecated release series. The currently supported release series
+ are: 0.2.9, 0.3.5, 0.4.0, 0.4.1, and 0.4.2. Closes ticket 31549.
+
+ o Major features (onion service v3, denial of service):
+ - Add onion service introduction denial of service defenses. Intro
+ points can now rate-limit client introduction requests, using
+ parameters that can be sent by the service within the
+ ESTABLISH_INTRO cell. If the cell extension for this is not used,
+ the intro point will honor the consensus parameters. Closes
+ ticket 30924.
+
+ o Major bugfixes (circuit build, guard):
+ - When considering upgrading circuits from "waiting for guard" to
+ "open", always ignore circuits that are marked for close.
+ Previously we could end up in the situation where a subsystem is
+ notified of a circuit opening, but the circuit is still marked for
+ close, leading to undesirable behavior. Fixes bug 30871; bugfix
+ on 0.3.0.1-alpha.
+
+ o Major bugfixes (crash, Linux, Android):
+ - Tolerate systems (including some Android installations) where
+ madvise and MADV_DONTDUMP are available at build-time, but not at
+ run time. Previously, these systems would notice a failed syscall
+ and abort. Fixes bug 31570; bugfix on 0.4.1.1-alpha.
+ - Tolerate systems (including some Linux installations) where
+ madvise and/or MADV_DONTFORK are available at build-time, but not
+ at run time. Previously, these systems would notice a failed
+ syscall and abort. Fixes bug 31696; bugfix on 0.4.1.1-alpha.
+
+ o Major bugfixes (embedded Tor):
+ - Avoid a possible crash when restarting Tor in embedded mode and
+ enabling a different set of publish/subscribe messages. Fixes bug
+ 31898; bugfix on 0.4.1.1-alpha.
+
+ o Major bugfixes (relay):
+ - Relays now respect their AccountingMax bandwidth again. When
+ relays entered "soft" hibernation (which typically starts when
+ we've hit 90% of our AccountingMax), we had stopped checking
+ whether we should enter hard hibernation. Soft hibernation refuses
+ new connections and new circuits, but the existing circuits can
+ continue, meaning that relays could have exceeded their configured
+ AccountingMax. Fixes bug 32108; bugfix on 0.4.0.1-alpha.
+
+ o Major bugfixes (torrc parsing):
+ - Stop ignoring torrc options after an %include directive, when the
+ included directory ends with a file that does not contain any
+ config options (but does contain comments or whitespace). Fixes
+ bug 31408; bugfix on 0.3.1.1-alpha.
+
+ o Major bugfixes (v3 onion services):
+ - Onion services now always use the exact number of intro points
+ configured with the HiddenServiceNumIntroductionPoints option (or
+ fewer if nodes are excluded). Before, a service could sometimes
+ pick more intro points than configured. Fixes bug 31548; bugfix
+ on 0.3.2.1-alpha.
+
+ o Minor feature (onion services, control port):
+ - The ADD_ONION command's keyword "BEST" now defaults to ED25519-V3
+ (v3) onion services. Previously it defaulted to RSA1024 (v2).
+ Closes ticket 29669.
+
+ o Minor features (auto-formatting scripts):
+ - When annotating C macros, never generate a line that our check-
+ spaces script would reject. Closes ticket 31759.
+ - When annotating C macros, try to remove cases of double-negation.
+ Closes ticket 31779.
+
+ o Minor features (best practices tracker):
+ - Our best-practices tracker now integrates with our include-checker
+ tool to keep track of how many layering violations we have not yet
+ fixed. We hope to reduce this number over time to improve Tor's
+ modularity. Closes ticket 31176.
+ - Add a TOR_PRACTRACKER_OPTIONS variable for passing arguments to
+ practracker from the environment. We may want this for continuous
+ integration. Closes ticket 31309.
+ - Give a warning rather than an error when a practracker exception
+ is violated by a small amount, add a --list-overbroad option to
+ practracker that lists exceptions that are stricter than they need
+ to be, and provide an environment variable for disabling
+ practracker. Closes ticket 30752.
+ - Our best-practices tracker now looks at headers as well as C
+ files. Closes ticket 31175.
+
+ o Minor features (build system):
+ - Make pkg-config use --prefix when cross-compiling, if
+ PKG_CONFIG_PATH is not set. Closes ticket 32191.
+ - Add --disable-manpage and --disable-html-manual options to
+ configure script. This will enable shortening build times by not
+ building documentation. Resolves issue 19381.
+
+ o Minor features (compilation):
+ - Log a more useful error message when we are compiling and one of
+ the compile-time hardening options we have selected can be linked
+ but not executed. Closes ticket 27530.
+
+ o Minor features (configuration):
+ - The configuration code has been extended to allow splitting
+ configuration data across multiple objects. Previously, all
+ configuration data needed to be kept in a single object, which
+ tended to become bloated. Closes ticket 31240.
+
+ o Minor features (continuous integration):
+ - When building on Appveyor and Travis, pass the "-k" flag to make,
+ so that we are informed of all compilation failures, not just the
+ first one or two. Closes ticket 31372.
+ - When running CI builds on Travis, put some random data in
+ ~/.torrc, to make sure no tests are reading the Tor configuration
+ file from its default location. Resolves issue 30102.
+
+ o Minor features (debugging):
+ - Log a nonfatal assertion failure if we encounter a configuration
+ line whose command is "CLEAR" but which has a nonempty value. This
+ should be impossible, according to the rules of our configuration
+ line parsing. Closes ticket 31529.
+
+ o Minor features (geoip):
+ - Update geoip and geoip6 to the December 3 2019 Maxmind GeoLite2
+ Country database. Closes ticket 32685.
+
+ o Minor features (git hooks):
+ - Our pre-commit git hook now checks for a special file before
+ running practracker, so that practracker only runs on branches
+ that are based on master. Since the pre-push hook calls the pre-
+ commit hook, practracker will also only run before pushes of
+ branches based on master. Closes ticket 30979.
+
+ o Minor features (git scripts):
+ - Add a "--" command-line argument, to separate git-push-all.sh
+ script arguments from arguments that are passed through to git
+ push. Closes ticket 31314.
+ - Add a -r <remote-name> argument to git-push-all.sh, so the script
+ can push test branches to a personal remote. Closes ticket 31314.
+ - Add a -t <test-branch-prefix> argument to git-merge-forward.sh and
+ git-push-all.sh, which makes these scripts create, merge forward,
+ and push test branches. Closes ticket 31314.
+ - Add a -u argument to git-merge-forward.sh, so that the script can
+ re-use existing test branches after a merge failure and fix.
+ Closes ticket 31314.
+ - Add a TOR_GIT_PUSH env var, which sets the default git push
+ command and arguments for git-push-all.sh. Closes ticket 31314.
+ - Add a TOR_PUSH_DELAY variable to git-push-all.sh, which makes the
+ script push master and maint branches with a delay between each
+ branch. These delays trigger the CI jobs in a set order, which
+ should show the most likely failures first. Also make pushes
+ atomic by default, and make the script pass any command-line
+ arguments to git push. Closes ticket 29879.
+ - Call the shellcheck script from the pre-commit hook. Closes
+ ticket 30967.
+ - Skip pushing test branches that are the same as a remote
+ maint/release/master branch in git-push-all.sh by default. Add a
+ -s argument, so git-push-all.sh can push all test branches. Closes
+ ticket 31314.
+
+ o Minor features (IPv6, logging):
+ - Log IPv6 addresses as well as IPv4 addresses when describing
+ routerinfos, routerstatuses, and nodes. Closes ticket 21003.
+
+ o Minor features (maintenance scripts):
+ - Add a Coccinelle script to detect bugs caused by incrementing or
+ decrementing a variable inside a call to log_debug(). Since
+ log_debug() is a macro whose arguments are conditionally
+ evaluated, it is usually an error to do this. One such bug was
+ 30628, in which SENDME cells were miscounted by a decrement
+ operator inside a log_debug() call. Closes ticket 30743.
+
+ o Minor features (onion service v3):
+ - Do not allow single hop clients to fetch or post an HS descriptor
+ from an HSDir. Closes ticket 24964.
+
+ o Minor features (onion service):
+ - Disallow single-hop clients at the introduction point. We've
+ removed Tor2web support a while back and single-hop rendezvous
+ attempts are blocked at the relays. This change should remove load
+ off the network from spammy clients. Close ticket 24963.
+
+ o Minor features (onion services v3):
+ - Assist users who try to setup v2 client authorization in v3 onion
+ services by pointing them to the right documentation. Closes
+ ticket 28966.
+
+ o Minor features (stem tests):
+ - Change "make test-stem" so it only runs the stem tests that use
+ tor. This change makes test-stem faster and more reliable. Closes
+ ticket 31554.
+
+ o Minor features (testing):
+ - When running tests that attempt to look up hostnames, replace the
+ libc name lookup functions with ones that do not actually touch
+ the network. This way, the tests complete more quickly in the
+ presence of a slow or missing DNS resolver. Closes ticket 31841.
+ - Add a script to invoke "tor --dump-config" and "tor
+ --verify-config" with various configuration options, and see
+ whether tor's resulting configuration or error messages are what
+ we expect. Use it for integration testing of our +Option and
+ /Option flags. Closes ticket 31637.
+ - Improve test coverage for our existing configuration parsing and
+ management API. Closes ticket 30893.
+ - Add integration tests to make sure that practracker gives the
+ outputs we expect. Closes ticket 31477.
+ - The practracker self-tests are now run as part of the Tor test
+ suite. Closes ticket 31304.
+
+ o Minor features (testing, continuous integration):
+ - Disable all but one Travis CI macOS build, to mitigate slow
+ scheduling of Travis macOS jobs. Closes ticket 32177.
+ - Run the chutney IPv6 networks as part of Travis CI. Closes
+ ticket 30860.
+ - Simplify the Travis CI build matrix, and optimise for build time.
+ Closes ticket 31859.
+ - Use Windows Server 2019 instead of Windows Server 2016 in our
+ Appveyor builds. Closes ticket 32086.
+
+ o Minor features (token bucket):
+ - Implement a generic token bucket that uses a single counter, for
+ use in anti-DoS onion service work. Closes ticket 30687.
+
+ o Minor bugfixes (Appveyor continuous integration):
+ - Avoid spurious errors when Appveyor CI fails before the install
+ step. Fixes bug 31884; bugfix on 0.3.4.2-alpha.
+
+ o Minor bugfixes (best practices tracker):
+ - Fix a few issues in the best-practices script, including tests,
+ tab tolerance, error reporting, and directory-exclusion logic.
+ Fixes bug 29746; bugfix on 0.4.1.1-alpha.
+ - When running check-best-practices, only consider files in the src
+ subdirectory. Previously we had recursively considered all
+ subdirectories, which made us get confused by the temporary
+ directories made by "make distcheck". Fixes bug 31578; bugfix
+ on 0.4.1.1-alpha.
+
+ o Minor bugfixes (build system):
+ - Interpret "--disable-module-dirauth=no" correctly. Fixes bug
+ 32124; bugfix on 0.3.4.1-alpha.
+ - Interpret "--with-tcmalloc=no" correctly. Fixes bug 32124; bugfix
+ on 0.2.0.20-rc.
+ - Stop failing when jemalloc is requested, but tcmalloc is not
+ found. Fixes bug 32124; bugfix on 0.3.5.1-alpha.
+ - When pkg-config is not installed, or a library that depends on
+ pkg-config is not found, tell the user what to do to fix the
+ problem. Fixes bug 31922; bugfix on 0.3.1.1-alpha.
+ - Do not include the deprecated <sys/sysctl.h> on Linux or Windows
+ systems. Fixes bug 31673; bugfix on 0.2.5.4-alpha.
+
+ o Minor bugfixes (chutney, makefiles, documentation):
+ - "make test-network-all" now shows the warnings from each test-
+ network.sh run on the console, so developers see new warnings
+ early. We've also improved the documentation for this feature, and
+ renamed a Makefile variable so the code is self-documenting. Fixes
+ bug 30455; bugfix on 0.3.0.4-rc.
+
+ o Minor bugfixes (client, onion service v3):
+ - Fix a BUG() assertion that occurs within a very small race window
+ between when a client intro circuit opens and when its descriptor
+ gets cleaned up from the cache. The circuit is now closed early,
+ which will trigger a re-fetch of the descriptor and continue the
+ connection. Fixes bug 28970; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfixes (code quality):
+ - Fix "make check-includes" so it runs correctly on out-of-tree
+ builds. Fixes bug 31335; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (compilation):
+ - Add more stub functions to fix compilation on Android with link-
+ time optimization when --disable-module-dirauth is used.
+ Previously, these compilation settings would make the compiler
+ look for functions that didn't exist. Fixes bug 31552; bugfix
+ on 0.4.1.1-alpha.
+ - Suppress spurious float-conversion warnings from GCC when calling
+ floating-point classifier functions on FreeBSD. Fixes part of bug
+ 31687; bugfix on 0.3.1.5-alpha.
+
+ o Minor bugfixes (configuration):
+ - Invalid floating-point values in the configuration file are now
+ treated as errors in the configuration. Previously, they were
+ ignored and treated as zero. Fixes bug 31475; bugfix on 0.0.1.
+
+ o Minor bugfixes (connections):
+ - Avoid trying to read data from closed connections, which can cause
+ needless loops in Libevent and infinite loops in Shadow. Fixes bug
+ 30344; bugfix on 0.1.1.1-alpha.
+
+ o Minor bugfixes (controller protocol):
+ - Fix the MAPADDRESS controller command to accept one or more
+ arguments. Previously, it required two or more arguments, and
+ ignored the first. Fixes bug 31772; bugfix on 0.4.1.1-alpha.
+
+ o Minor bugfixes (coverity):
+ - Add an assertion when parsing a BEGIN cell so that coverity can be
+ sure that we are not about to dereference a NULL address. Fixes
+ bug 31026; bugfix on 0.2.4.7-alpha. This is CID 1447296.
+ - In our siphash implementation, when building for coverity, use
+ memcpy in place of a switch statement, so that coverity can tell
+ we are not accessing out-of-bounds memory. Fixes bug 31025; bugfix
+ on 0.2.8.1-alpha. This is tracked as CID 1447293 and 1447295.
+ - Fix several coverity warnings from our unit tests. Fixes bug
+ 31030; bugfix on 0.2.4.1-alpha, 0.3.2.1-alpha, and 0.4.0.1-alpha.
+
+ o Minor bugfixes (crash):
+ - When running Tor with an option like --verify-config or
+ --dump-config that does not start the event loop, avoid crashing
+ if we try to exit early because of an error. Fixes bug 32407;
+ bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (developer tooling):
+ - Only log git script changes in the post-merge script when the
+ merge was to the master branch. Fixes bug 31040; bugfix
+ on 0.4.1.1-alpha.
+
+ o Minor bugfixes (directory authorities):
+ - Return a distinct status when formatting annotations fails. Fixes
+ bug 30780; bugfix on 0.2.0.8-alpha.
+
+ o Minor bugfixes (error handling):
+ - Always lock the backtrace buffer before it is used. Fixes bug
+ 31734; bugfix on 0.2.5.3-alpha.
+ - On abort, try harder to flush the output buffers of log messages.
+ On some platforms (macOS), log messages could be discarded when
+ the process terminates. Fixes bug 31571; bugfix on 0.3.5.1-alpha.
+ - Report the tor version whenever an assertion fails. Previously, we
+ only reported the Tor version on some crashes, and some non-fatal
+ assertions. Fixes bug 31571; bugfix on 0.3.5.1-alpha.
+ - When tor aborts due to an error, close log file descriptors before
+ aborting. Closing the logs makes some OSes flush log file buffers,
+ rather than deleting buffered log lines. Fixes bug 31594; bugfix
+ on 0.2.5.2-alpha.
+
+ o Minor bugfixes (FreeBSD, PF-based proxy, IPv6):
+ - When extracting an IPv6 address from a PF-based proxy, verify that
+ we are actually configured to receive an IPv6 address, and log an
+ internal error if not. Fixes part of bug 31687; bugfix
+ on 0.2.3.4-alpha.
+
+ o Minor bugfixes (git hooks):
+ - Remove a duplicate call to practracker from the pre-push hook. The
+ pre-push hook already calls the pre-commit hook, which calls
+ practracker. Fixes bug 31462; bugfix on 0.4.1.1-alpha.
+
+ o Minor bugfixes (git scripts):
+ - Stop hard-coding the bash path in the git scripts. Some OSes don't
+ have bash in /usr/bin, others have an ancient bash at this path.
+ Fixes bug 30840; bugfix on 0.4.0.1-alpha.
+ - Stop hard-coding the tor master branch name and worktree path in
+ the git scripts. Fixes bug 30841; bugfix on 0.4.0.1-alpha.
+ - Allow git-push-all.sh to be run from any directory. Previously,
+ the script only worked if run from an upstream worktree directory.
+ Closes ticket 31678.
+
+ o Minor bugfixes (guards):
+ - When tor is missing descriptors for some primary entry guards,
+ make the log message less alarming. It's normal for descriptors to
+ expire, as long as tor fetches new ones soon after. Fixes bug
+ 31657; bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (ipv6):
+ - Check for private IPv6 addresses alongside their IPv4 equivalents
+ when authorities check descriptors. Previously, we only checked
+ for private IPv4 addresses. Fixes bug 31088; bugfix on
+ 0.2.3.21-rc. Patch by Neel Chauhan.
+ - When parsing microdescriptors, we should check the IPv6 exit
+ policy alongside IPv4. Previously, we checked both exit policies
+ for only router info structures, while microdescriptors were
+ IPv4-only. Fixes bug 27284; bugfix on 0.2.3.1-alpha. Patch by
+ Neel Chauhan.
+
+ o Minor bugfixes (logging):
+ - Add a missing check for HAVE_PTHREAD_H, because the backtrace code
+ uses mutexes. Fixes bug 31614; bugfix on 0.2.5.2-alpha.
+ - Disable backtrace signal handlers when shutting down tor. Fixes
+ bug 31614; bugfix on 0.2.5.2-alpha.
+ - Rate-limit our the logging message about the obsolete .exit
+ notation. Previously, there was no limit on this warning, which
+ could potentially be triggered many times by a hostile website.
+ Fixes bug 31466; bugfix on 0.2.2.1-alpha.
+ - When initialising log domain masks, only set known log domains.
+ Fixes bug 31854; bugfix on 0.2.1.1-alpha.
+ - Change log level of message "Hash of session info was not as
+ expected" to LOG_PROTOCOL_WARN. Fixes bug 12399; bugfix
+ on 0.1.1.10-alpha.
+ - Fix a code issue that would have broken our parsing of log domains
+ as soon as we had 33 of them. Fortunately, we still only have 29.
+ Fixes bug 31451; bugfix on 0.4.1.4-rc.
+
+ o Minor bugfixes (logging, protocol violations):
+ - Do not log a nonfatal assertion failure when receiving a VERSIONS
+ cell on a connection using the obsolete v1 link protocol. Log a
+ protocol_warn instead. Fixes bug 31107; bugfix on 0.2.4.4-alpha.
+
+ o Minor bugfixes (mainloop, periodic events, in-process API):
+ - Reset the periodic events' "enabled" flag when Tor is shut down
+ cleanly. Previously, this flag was left on, which caused periodic
+ events not to be re-enabled when Tor was relaunched in-process
+ with tor_api.h after a shutdown. Fixes bug 32058; bugfix
+ on 0.3.3.1-alpha.
+
+ o Minor bugfixes (memory management):
+ - Stop leaking a small amount of memory in nt_service_install(), in
+ unreachable code. Fixes bug 30799; bugfix on 0.2.0.7-alpha. Patch
+ by Xiaoyin Liu.
+
+ o Minor bugfixes (modules):
+ - Explain what the optional Directory Authority module is, and what
+ happens when it is disabled. Fixes bug 31825; bugfix
+ on 0.3.4.1-alpha.
+
+ o Minor bugfixes (multithreading):
+ - Avoid some undefined behaviour when freeing mutexes. Fixes bug
+ 31736; bugfix on 0.0.7.
+
+ o Minor bugfixes (networking, IP addresses):
+ - When parsing addresses via Tor's internal DNS lookup API, reject
+ IPv4 addresses in square brackets, and accept IPv6 addresses in
+ square brackets. This change completes the work started in 23082,
+ making address parsing consistent between tor's internal DNS
+ lookup and address parsing APIs. Fixes bug 30721; bugfix
+ on 0.2.1.5-alpha.
+ - When parsing addresses via Tor's internal address:port parsing and
+ DNS lookup APIs, require IPv6 addresses with ports to have square
+ brackets. But allow IPv6 addresses without ports, whether or not
+ they have square brackets. Fixes bug 30721; bugfix
+ on 0.2.1.5-alpha.
+
+ o Minor bugfixes (onion service v3):
+ - When purging the client descriptor cache, close any introduction
+ point circuits associated with purged cache entries. This avoids
+ picking those circuits later when connecting to the same
+ introduction points. Fixes bug 30921; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfixes (onion services):
+ - In the hs_ident_circuit_t data structure, remove the unused field
+ circuit_type and the respective argument in hs_ident_circuit_new().
+ This field was set by clients (for introduction) and services (for
+ introduction and rendezvous) but was never used afterwards. Fixes
+ bug 31490; bugfix on 0.3.2.1-alpha. Patch by Neel Chauhan.
+
+ o Minor bugfixes (operator tools):
+ - Make tor-print-ed-signing-cert(1) print certificate expiration
+ date in RFC 1123 and UNIX timestamp formats, to make output
+ machine readable. Fixes bug 31012; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (process management):
+ - Remove overly strict assertions that triggered when a pluggable
+ transport failed to launch. Fixes bug 31091; bugfix
+ on 0.4.0.1-alpha.
+ - Remove an assertion in the Unix process backend. This assertion
+ would trigger when we failed to find the executable for a child
+ process. Fixes bug 31810; bugfix on 0.4.0.1-alpha.
+
+ o Minor bugfixes (relay):
+ - Avoid crashing when starting with a corrupt keys directory where
+ the old ntor key and the new ntor key are identical. Fixes bug
+ 30916; bugfix on 0.2.4.8-alpha.
+
+ o Minor bugfixes (rust):
+ - Correctly exclude a redundant rust build job in Travis. Fixes bug
+ 31463; bugfix on 0.3.5.4-alpha.
+ - Raise the minimum rustc version to 1.31.0, as checked by configure
+ and CI. Fixes bug 31442; bugfix on 0.3.5.4-alpha.
+
+ o Minor bugfixes (sendme, code structure):
+ - Rename the trunnel SENDME file definition from sendme.trunnel to
+ sendme_cell.trunnel to avoid having twice sendme.{c|h} in the
+ repository. Fixes bug 30769; bugfix on 0.4.1.1-alpha.
+
+ o Minor bugfixes (statistics):
+ - Stop removing the ed25519 signature if the extra info file is too
+ big. If the signature data was removed, but the keyword was kept,
+ this could result in an unparseable extra info file. Fixes bug
+ 30958; bugfix on 0.2.7.2-alpha.
+
+ o Minor bugfixes (subsystems):
+ - Make the subsystem init order match the subsystem module
+ dependencies. Call windows process security APIs as early as
+ possible. Initialize logging before network and time, so that
+ network and time can use logging. Fixes bug 31615; bugfix
+ on 0.4.0.1-alpha.
+
+ o Minor bugfixes (testing):
+ - Avoid intermittent test failures due to a test that had relied on
+ inconsistent timing sources. Fixes bug 31995; bugfix
+ on 0.3.1.3-alpha.
+ - When testing port rebinding, don't busy-wait for tor to log.
+ Instead, actually sleep for a short time before polling again.
+ Also improve the formatting of control commands and log messages.
+ Fixes bug 31837; bugfix on 0.3.5.1-alpha.
+ - Teach the util/socketpair_ersatz test to work correctly when we
+ have no network stack configured. Fixes bug 30804; bugfix
+ on 0.2.5.1-alpha.
+
+ o Minor bugfixes (tests, SunOS):
+ - Avoid a map_anon_nofork test failure due to a signed/unsigned
+ integer comparison. Fixes bug 31897; bugfix on 0.4.1.1-alpha.
+
+ o Minor bugfixes (tls, logging):
+ - Log bugs about the TLS read buffer's length only once, rather than
+ filling the logs with similar warnings. Fixes bug 31939; bugfix
+ on 0.3.0.4-rc.
+
+ o Minor bugfixes (v2 single onion services):
+ - Always retry v2 single onion service intro and rend circuits with
+ a 3-hop path. Previously, v2 single onion services used a 3-hop
+ path when rendezvous circuits were retried after a remote or
+ delayed failure, but a 1-hop path for immediate retries. Fixes bug
+ 23818; bugfix on 0.2.9.3-alpha.
+
+ o Minor bugfixes (v3 onion services):
+ - When cleaning up intro circuits for a v3 onion service, don't
+ remove circuits that have an established or pending circuit, even
+ if they ran out of retries. This way, we don't remove a circuit on
+ its last retry. Fixes bug 31652; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfixes (v3 single onion services):
+ - Always retry v3 single onion service intro and rend circuits with
+ a 3-hop path. Previously, v3 single onion services used a 3-hop
+ path when rend circuits were retried after a remote or delayed
+ failure, but a 1-hop path for immediate retries. Fixes bug 23818;
+ bugfix on 0.3.2.1-alpha.
+ - Make v3 single onion services fall back to a 3-hop intro, when all
+ intro points are unreachable via a 1-hop path. Previously, v3
+ single onion services failed when all intro nodes were unreachable
+ via a 1-hop path. Fixes bug 23507; bugfix on 0.3.2.1-alpha.
+
+ o Code simplification and refactoring:
+ - Refactor connection_control_process_inbuf() to reduce the size of
+ a practracker exception. Closes ticket 31840.
+ - Refactor the microdescs_parse_from_string() function into smaller
+ pieces, for better comprehensibility. Closes ticket 31675.
+ - Use SEVERITY_MASK_IDX() to find the LOG_* mask indexes in the unit
+ tests and fuzzers, rather than using hard-coded values. Closes
+ ticket 31334.
+ - Interface for function `decrypt_desc_layer` cleaned up. Closes
+ ticket 31589.
+
+ o Documentation:
+ - Correct the description of "GuardLifetime". Fixes bug 31189;
+ bugfix on 0.3.0.1-alpha.
+ - Make clear in the man page, in both the bandwidth section and the
+ AccountingMax section, that Tor counts in powers of two, not
+ powers of ten: 1 GByte is 1024*1024*1024 bytes, not one billion
+ bytes. Resolves ticket 32106.
+ - Document the signal-safe logging behaviour in the tor man page.
+ Also add some comments to the relevant functions. Closes
+ ticket 31839.
+ - Explain why we can't destroy the backtrace buffer mutex. Explain
+ why we don't need to destroy the log mutex. Closes ticket 31736.
+ - The Tor source code repository now includes a (somewhat dated)
+ description of Tor's modular architecture, in doc/HACKING/design.
+ This is based on the old "tor-guts.git" repository, which we are
+ adopting and superseding. Closes ticket 31849.
+ - Improve documentation in circuit padding subsystem. Patch by
+ Tobias Pulls. Closes ticket 31113.
+ - Include an example usage for IPv6 ORPort in our sample torrc.
+ Closes ticket 31320; patch from Ali Raheem.
+ - Use RFC 2397 data URL scheme to embed an image into tor-exit-
+ notice.html so that operators no longer have to host it
+ themselves. Closes ticket 31089.
+
+ o Removed features:
+ - No longer include recommended package digests in votes as detailed
+ in proposal 301. The RecommendedPackages torrc option is
+ deprecated and will no longer have any effect. "package" lines
+ will still be considered when computing consensuses for consensus
+ methods that include them. (This change has no effect on the list
+ of recommended Tor versions, which is still in use.) Closes
+ ticket 29738.
+ - Remove torctl.in from contrib/dist directory. Resolves
+ ticket 30550.
+
+ o Testing:
+ - Require C99 standards-conforming code in Travis CI, but allow GNU
+ gcc extensions. Also activates clang's -Wtypedef-redefinition
+ warnings. Build some jobs with -std=gnu99, and some jobs without.
+ Closes ticket 32500.
+ - Run shellcheck for all non-third-party shell scripts that are
+ shipped with Tor. Closes ticket 29533.
+ - When checking shell scripts, ignore any user-created directories.
+ Closes ticket 30967.
+
+ o Code simplification and refactoring (config handling):
+ - Extract our variable manipulation code from confparse.c to a new
+ lower-level typedvar.h module. Closes ticket 30864.
+ - Lower another layer of object management from confparse.c to a
+ more general tool. Now typed structure members are accessible via
+ an abstract type. Implements ticket 30914.
+ - Move our backend logic for working with configuration and state
+ files into a lower-level library, since it no longer depends on
+ any tor-specific functionality. Closes ticket 31626.
+ - Numerous simplifications in configuration-handling logic: remove
+ duplicated macro definitions, replace magical names with flags,
+ and refactor "TestingTorNetwork" to use the same default-option
+ logic as the rest of Tor. Closes ticket 30935.
+ - Replace our ad-hoc set of flags for configuration variables and
+ configuration variable types with fine-grained orthogonal flags
+ corresponding to the actual behavior we want. Closes ticket 31625.
+
+ o Code simplification and refactoring (misc):
+ - Eliminate some uses of lower-level control reply abstractions,
+ primarily in the onion_helper functions. Closes ticket 30889.
+ - Rework bootstrap tracking to use the new publish-subscribe
+ subsystem. Closes ticket 29976.
+ - Rewrite format_node_description() and router_get_verbose_nickname()
+ to use strlcpy() and strlcat(). The previous implementation used
+ memcpy() and pointer arithmetic, which was error-prone. Closes
+ ticket 31545. This is CID 1452819.
+ - Split extrainfo_dump_to_string() into smaller functions. Closes
+ ticket 30956.
+ - Use the ptrdiff_t type consistently for expressing variable
+ offsets and pointer differences. Previously we incorrectly (but
+ harmlessly) used int and sometimes off_t for these cases. Closes
+ ticket 31532.
+ - Use the subsystems mechanism to manage the main event loop code.
+ Closes ticket 30806.
+ - Various simplifications and minor improvements to the circuit
+ padding machines. Patch by Tobias Pulls. Closes tickets 31112
+ and 31098.
+
+ o Documentation (hard-coded directories):
+ - Improve the documentation for the DirAuthority and FallbackDir
+ torrc options. Closes ticket 30955.
+
+ o Documentation (tor.1 man page):
+ - Fix typo in tor.1 man page: the option is "--help", not "-help".
+ Fixes bug 31008; bugfix on 0.2.2.9-alpha.
+
+ o Testing (continuous integration):
+ - Use Ubuntu Bionic images for our Travis CI builds, so we can get a
+ recent version of coccinelle. But leave chutney on Ubuntu Trusty,
+ until we can fix some Bionic permissions issues (see ticket
+ 32240). Related to ticket 31919.
+ - Install the mingw OpenSSL package in Appveyor. This makes sure
+ that the OpenSSL headers and libraries match in Tor's Appveyor
+ builds. (This bug was triggered by an Appveyor image update.)
+ Fixes bug 32449; bugfix on 0.3.5.6-rc.
+ - In Travis, use Xcode 11.2 on macOS 10.14. Closes ticket 32241.
+
+
+Changes in version 0.4.1.7 - 2019-12-09
+ This release backports several bugfixes to improve stability and
+ correctness. Anyone experiencing build problems or crashes with 0.4.1.6,
+ including all relays relying on AccountingMax, should upgrade.
+
+ o Major features (directory authorities, backport from 0.4.2.2-alpha):
+ - Directory authorities now reject relays running all currently
+ deprecated release series. The currently supported release series
+ are: 0.2.9, 0.3.5, 0.4.0, 0.4.1, and 0.4.2. Closes ticket 31549.
+
+ o Major bugfixes (embedded Tor, backport from 0.4.2.2-alpha):
+ - Avoid a possible crash when restarting Tor in embedded mode and
+ enabling a different set of publish/subscribe messages. Fixes bug
+ 31898; bugfix on 0.4.1.1-alpha.
+
+ o Major bugfixes (relay, backport from 0.4.2.3-alpha):
+ - Relays now respect their AccountingMax bandwidth again. When
+ relays entered "soft" hibernation (which typically starts when
+ we've hit 90% of our AccountingMax), we had stopped checking
+ whether we should enter hard hibernation. Soft hibernation refuses
+ new connections and new circuits, but the existing circuits can
+ continue, meaning that relays could have exceeded their configured
+ AccountingMax. Fixes bug 32108; bugfix on 0.4.0.1-alpha.
+
+ o Major bugfixes (torrc parsing, backport from 0.4.2.2-alpha):
+ - Stop ignoring torrc options after an %include directive, when the
+ included directory ends with a file that does not contain any
+ config options (but does contain comments or whitespace). Fixes
+ bug 31408; bugfix on 0.3.1.1-alpha.
+
+ o Major bugfixes (v3 onion services, backport from 0.4.2.3-alpha):
+ - Onion services now always use the exact number of intro points
+ configured with the HiddenServiceNumIntroductionPoints option (or
+ fewer if nodes are excluded). Before, a service could sometimes
+ pick more intro points than configured. Fixes bug 31548; bugfix
+ on 0.3.2.1-alpha.
+
+ o Minor features (continuous integration, backport from 0.4.2.2-alpha):
+ - When building on Appveyor and Travis, pass the "-k" flag to make,
+ so that we are informed of all compilation failures, not just the
+ first one or two. Closes ticket 31372.
+
+ o Minor features (geoip, backport from 0.4.2.5):
+ - Update geoip and geoip6 to the December 3 2019 Maxmind GeoLite2
+ Country database. Closes ticket 32685.
+
+ o Minor bugfixes (Appveyor CI, backport from 0.4.2.2-alpha):
+ - Avoid spurious errors when Appveyor CI fails before the install step.
+ Fixes bug 31884; bugfix on 0.3.4.2-alpha.
+
+ o Minor bugfixes (client, onion service v3, backport from 0.4.2.4-rc):
+ - Fix a BUG() assertion that occurs within a very small race window
+ between when a client intro circuit opens and when its descriptor
+ gets cleaned up from the cache. The circuit is now closed early,
+ which will trigger a re-fetch of the descriptor and continue the
+ connection. Fixes bug 28970; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfixes (connections, backport from 0.4.2.3-rc):
+ - Avoid trying to read data from closed connections, which can cause
+ needless loops in Libevent and infinite loops in Shadow. Fixes bug
+ 30344; bugfix on 0.1.1.1-alpha.
+
+ o Minor bugfixes (error handling, backport from 0.4.2.1-alpha):
+ - On abort, try harder to flush the output buffers of log messages.
+ On some platforms (macOS), log messages could be discarded when
+ the process terminates. Fixes bug 31571; bugfix on 0.3.5.1-alpha.
+ - Report the tor version whenever an assertion fails. Previously, we
+ only reported the Tor version on some crashes, and some non-fatal
+ assertions. Fixes bug 31571; bugfix on 0.3.5.1-alpha.
+ - When tor aborts due to an error, close log file descriptors before
+ aborting. Closing the logs makes some OSes flush log file buffers,
+ rather than deleting buffered log lines. Fixes bug 31594; bugfix
+ on 0.2.5.2-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.2.2-alpha):
+ - Add a missing check for HAVE_PTHREAD_H, because the backtrace code
+ uses mutexes. Fixes bug 31614; bugfix on 0.2.5.2-alpha.
+ - Disable backtrace signal handlers when shutting down tor. Fixes
+ bug 31614; bugfix on 0.2.5.2-alpha.
+ - Rate-limit our the logging message about the obsolete .exit
+ notation. Previously, there was no limit on this warning, which
+ could potentially be triggered many times by a hostile website.
+ Fixes bug 31466; bugfix on 0.2.2.1-alpha.
+
+ o Minor bugfixes (logging, protocol violations, backport from 0.4.2.2-alpha):
+ - Do not log a nonfatal assertion failure when receiving a VERSIONS
+ cell on a connection using the obsolete v1 link protocol. Log a
+ protocol_warn instead. Fixes bug 31107; bugfix on 0.2.4.4-alpha.
+
+ o Minor bugfixes (mainloop, periodic events, in-process API, backport from 0.4.2.3-alpha):
+ - Reset the periodic events' "enabled" flag when Tor is shut down
+ cleanly. Previously, this flag was left on, which caused periodic
+ events not to be re-enabled when Tor was relaunched in-process
+ with tor_api.h after a shutdown. Fixes bug 32058; bugfix
+ on 0.3.3.1-alpha.
+
+ o Minor bugfixes (multithreading, backport from 0.4.2.2-alpha):
+ - Avoid some undefined behaviour when freeing mutexes. Fixes bug
+ 31736; bugfix on 0.0.7.
+
+ o Minor bugfixes (process management, backport from 0.4.2.3-alpha):
+ - Remove overly strict assertions that triggered when a pluggable
+ transport failed to launch. Fixes bug 31091; bugfix
+ on 0.4.0.1-alpha.
+ - Remove an assertion in the Unix process backend. This assertion
+ would trigger when we failed to find the executable for a child
+ process. Fixes bug 31810; bugfix on 0.4.0.1-alpha.
+
+ o Minor bugfixes (relay, backport from 0.4.2.2-alpha):
+ - Avoid crashing when starting with a corrupt keys directory where
+ the old ntor key and the new ntor key are identical. Fixes bug
+ 30916; bugfix on 0.2.4.8-alpha.
+
+ o Minor bugfixes (testing, backport from 0.4.2.3-alpha):
+ - When testing port rebinding, don't busy-wait for tor to log.
+ Instead, actually sleep for a short time before polling again.
+ Also improve the formatting of control commands and log messages.
+ Fixes bug 31837; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (tests, SunOS, backport from 0.4.2.2-alpha):
+ - Avoid a map_anon_nofork test failure due to a signed/unsigned
+ integer comparison. Fixes bug 31897; bugfix on 0.4.1.1-alpha.
+
+ o Minor bugfixes (tls, logging, backport from 0.4.2.3-alpha):
+ - Log bugs about the TLS read buffer's length only once, rather than
+ filling the logs with similar warnings. Fixes bug 31939; bugfix
+ on 0.3.0.4-rc.
+
+ o Documentation (backport from 0.4.2.2-alpha):
+ - Explain why we can't destroy the backtrace buffer mutex. Explain
+ why we don't need to destroy the log mutex. Closes ticket 31736.
+
+ o Testing (continuous integration, backport from 0.4.2.3-alpha):
+ - Disable all but one Travis CI macOS build, to mitigate slow
+ scheduling of Travis macOS jobs. Closes ticket 32177.
+ - Run the chutney IPv6 networks as part of Travis CI. Closes
+ ticket 30860.
+ - Simplify the Travis CI build matrix, and optimise for build time.
+ Closes ticket 31859.
+ - Use Windows Server 2019 instead of Windows Server 2016 in our
+ Appveyor builds. Closes ticket 32086.
+
+ o Testing (continuous integration, backport from 0.4.2.4-rc):
+ - In Travis, use Xcode 11.2 on macOS 10.14. Closes ticket 32241.
+ - Use Ubuntu Bionic images for our Travis CI builds, so we can get a
+ recent version of coccinelle. But leave chutney on Ubuntu Trusty,
+ until we can fix some Bionic permissions issues (see ticket
+ 32240). Related to ticket 31919.
+ - Install the mingw OpenSSL package in Appveyor. This makes sure
+ that the OpenSSL headers and libraries match in Tor's Appveyor
+ builds. (This bug was triggered by an Appveyor image update.)
+ Fixes bug 32449; bugfix on 0.3.5.6-rc.
+
+ o Testing (continuous integration, backport from 0.4.2.5):
+ - Require C99 standards-conforming code in Travis CI, but allow GNU gcc
+ extensions. Also activates clang's -Wtypedef-redefinition warnings.
+ Build some jobs with -std=gnu99, and some jobs without.
+ Closes ticket 32500.
+
+
+Changes in version 0.4.0.6 - 2019-12-09
+ This is the second stable release in the 0.4.0.x series. This release
+ backports several bugfixes to improve stability and correctness. Anyone
+ experiencing build problems or crashes with 0.4.0.5, including all relays
+ relying on AccountingMax, should upgrade.
+
+ Note that, per our support policy, support for the 0.4.0.x series will end
+ on 2 Feb 2020. Anyone still running 0.4.0.x should plan to upgrade to the
+ latest stable release, or downgrade to 0.3.5.x, which will get long-term
+ support until 1 Feb 2022.
+
+ o Directory authority changes (backport from 0.4.1.5):
+ - The directory authority "dizum" has a new IP address. Closes
+ ticket 31406.
+
+ o Major bugfixes (bridges, backport from 0.4.1.2-alpha):
+ - Consider our directory information to have changed when our list
+ of bridges changes. Previously, Tor would not re-compute the
+ status of its directory information when bridges changed, and
+ therefore would not realize that it was no longer able to build
+ circuits. Fixes part of bug 29875.
+ - Do not count previously configured working bridges towards our
+ total of working bridges. Previously, when Tor's list of bridges
+ changed, it would think that the old bridges were still usable,
+ and delay fetching router descriptors for the new ones. Fixes part
+ of bug 29875; bugfix on 0.3.0.1-alpha.
+
+ o Major bugfixes (circuit build, guard, backport from 0.4.1.4-rc):
+ - When considering upgrading circuits from "waiting for guard" to
+ "open", always ignore circuits that are marked for close. Otherwise,
+ we can end up in the situation where a subsystem is notified that
+ a closing circuit has just opened, leading to undesirable
+ behavior. Fixes bug 30871; bugfix on 0.3.0.1-alpha.
+
+ o Major bugfixes (Onion service reachability, backport from 0.4.1.3-alpha):
+ - Properly clean up the introduction point map when circuits change
+ purpose from onion service circuits to pathbias, measurement, or
+ other circuit types. This should fix some service-side instances
+ of introduction point failure. Fixes bug 29034; bugfix
+ on 0.3.2.1-alpha.
+
+ o Major bugfixes (onion service v3, backport from 0.4.1.1-alpha):
+ - Fix an unreachable bug in which an introduction point could try to
+ send an INTRODUCE_ACK with a status code that Trunnel would refuse
+ to encode, leading the relay to assert(). We've consolidated the
+ ABI values into Trunnel now. Fixes bug 30454; bugfix
+ on 0.3.0.1-alpha.
+ - Clients can now handle unknown status codes from INTRODUCE_ACK
+ cells. (The NACK behavior will stay the same.) This will allow us
+ to extend status codes in the future without breaking the normal
+ client behavior. Fixes another part of bug 30454; bugfix
+ on 0.3.0.1-alpha.
+
+ o Major bugfixes (relay, backport from 0.4.2.3-alpha):
+ - Relays now respect their AccountingMax bandwidth again. When
+ relays entered "soft" hibernation (which typically starts when
+ we've hit 90% of our AccountingMax), we had stopped checking
+ whether we should enter hard hibernation. Soft hibernation refuses
+ new connections and new circuits, but the existing circuits can
+ continue, meaning that relays could have exceeded their configured
+ AccountingMax. Fixes bug 32108; bugfix on 0.4.0.1-alpha.
+
+ o Major bugfixes (torrc parsing, backport from 0.4.2.2-alpha):
+ - Stop ignoring torrc options after an %include directive, when the
+ included directory ends with a file that does not contain any
+ config options (but does contain comments or whitespace). Fixes
+ bug 31408; bugfix on 0.3.1.1-alpha.
+
+ o Major bugfixes (v3 onion services, backport from 0.4.2.3-alpha):
+ - Onion services now always use the exact number of intro points
+ configured with the HiddenServiceNumIntroductionPoints option (or
+ fewer if nodes are excluded). Before, a service could sometimes
+ pick more intro points than configured. Fixes bug 31548; bugfix
+ on 0.3.2.1-alpha.
+
+ o Minor features (compile-time modules, backport from version 0.4.1.1-alpha):
+ - Add a "--list-modules" command to print a list of which compile-
+ time modules are enabled. Closes ticket 30452.
+
+ o Minor features (continuous integration, backport from 0.4.1.1-alpha):
+ - Remove sudo configuration lines from .travis.yml as they are no
+ longer needed with current Travis build environment. Resolves
+ issue 30213.
+
+ o Minor features (continuous integration, backport from 0.4.1.4-rc):
+ - Our Travis configuration now uses Chutney to run some network
+ integration tests automatically. Closes ticket 29280.
+
+ o Minor features (continuous integration, backport from 0.4.2.2-alpha):
+ - When building on Appveyor and Travis, pass the "-k" flag to make,
+ so that we are informed of all compilation failures, not just the
+ first one or two. Closes ticket 31372.
+
+ o Minor features (fallback directory list, backport from 0.4.1.4-rc):
+ - Replace the 157 fallbacks originally introduced in Tor 0.3.5.6-rc
+ in December 2018 (of which ~122 were still functional), with a
+ list of 148 fallbacks (70 new, 78 existing, 79 removed) generated
+ in June 2019. Closes ticket 28795.
+
+ o Minor features (geoip, backport from 0.4.2.5):
+ - Update geoip and geoip6 to the December 3 2019 Maxmind GeoLite2
+ Country database. Closes ticket 32685.
+
+ o Minor features (stem tests, backport from 0.4.2.1-alpha):
+ - Change "make test-stem" so it only runs the stem tests that use
+ tor. This change makes test-stem faster and more reliable. Closes
+ ticket 31554.
+
+ o Minor bugfixes (Appveyor CI, backport from 0.4.2.2-alpha):
+ - Avoid spurious errors when Appveyor CI fails before the install step.
+ Fixes bug 31884; bugfix on 0.3.4.2-alpha.
+
+ o Minor bugfixes (build system, backport form 0.4.2.1-alpha):
+ - Do not include the deprecated <sys/sysctl.h> on Linux or Windows
+ systems. Fixes bug 31673; bugfix on 0.2.5.4-alpha.
+
+ o Minor bugfixes (circuit isolation, backport from 0.4.1.3-alpha):
+ - Fix a logic error that prevented the SessionGroup sub-option from
+ being accepted. Fixes bug 22619; bugfix on 0.2.7.2-alpha.
+
+ o Minor bugfixes (circuit padding, backport from 0.4.1.4-rc):
+ - On relays, properly check that a padding machine is absent before
+ logging a warning about it being absent. Fixes bug 30649; bugfix
+ on 0.4.0.1-alpha.
+
+ o Minor bugfixes (client, onion service v3, backport from 0.4.2.4-rc):
+ - Fix a BUG() assertion that occurs within a very small race window
+ between when a client intro circuit opens and when its descriptor
+ gets cleaned up from the cache. The circuit is now closed early,
+ which will trigger a re-fetch of the descriptor and continue the
+ connection. Fixes bug 28970; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfixes (clock skew detection, backport from 0.4.1.5):
+ - Don't believe clock skew results from NETINFO cells that appear to
+ arrive before we sent the VERSIONS cells they are responding to.
+ Previously, we would accept them up to 3 minutes "in the past".
+ Fixes bug 31343; bugfix on 0.2.4.4-alpha.
+
+ o Minor bugfixes (compilation warning, backport from 0.4.1.5):
+ - Fix a compilation warning on Windows about casting a function
+ pointer for GetTickCount64(). Fixes bug 31374; bugfix
+ on 0.2.9.1-alpha.
+
+ o Minor bugfixes (compilation, backport from 0.4.1.5):
+ - Avoid using labs() on time_t, which can cause compilation warnings
+ on 64-bit Windows builds. Fixes bug 31343; bugfix on 0.2.4.4-alpha.
+
+ o Minor bugfixes (compilation, backport from 0.4.2.1-alpha):
+ - Suppress spurious float-conversion warnings from GCC when calling
+ floating-point classifier functions on FreeBSD. Fixes part of bug
+ 31687; bugfix on 0.3.1.5-alpha.
+
+ o Minor bugfixes (compilation, unusual configurations, backport from 0.4.1.1-alpha):
+ - Avoid failures when building with the ALL_BUGS_ARE_FATAL option
+ due to missing declarations of abort(), and prevent other such
+ failures in the future. Fixes bug 30189; bugfix on 0.3.4.1-alpha.
+
+ o Minor bugfixes (configuration, proxies, backport from 0.4.1.2-alpha):
+ - Fix a bug that prevented us from supporting SOCKS5 proxies that
+ want authentication along with configured (but unused!)
+ ClientTransportPlugins. Fixes bug 29670; bugfix on 0.2.6.1-alpha.
+
+ o Minor bugfixes (connections, backport from 0.4.2.3-rc):
+ - Avoid trying to read data from closed connections, which can cause
+ needless loops in Libevent and infinite loops in Shadow. Fixes bug
+ 30344; bugfix on 0.1.1.1-alpha.
+
+ o Minor bugfixes (continuous integration, backport from 0.4.1.3-alpha):
+ - Allow the test-stem job to fail in Travis, because it sometimes
+ hangs. Fixes bug 30744; bugfix on 0.3.5.4-alpha.
+ - Skip test_rebind on macOS in Travis, because it is unreliable on
+ macOS on Travis. Fixes bug 30713; bugfix on 0.3.5.1-alpha.
+ - Skip test_rebind when the TOR_SKIP_TEST_REBIND environment
+ variable is set. Fixes bug 30713; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (crash on exit, backport from 0.4.1.4-rc):
+ - Avoid a set of possible code paths that could try to use freed
+ memory in routerlist_free() while Tor was exiting. Fixes bug
+ 31003; bugfix on 0.1.2.2-alpha.
+
+ o Minor bugfixes (directory authorities, backport from 0.4.1.3-alpha):
+ - Stop crashing after parsing an unknown descriptor purpose
+ annotation. We think this bug can only be triggered by modifying a
+ local file. Fixes bug 30781; bugfix on 0.2.0.8-alpha.
+
+ o Minor bugfixes (directory authority, backport from 0.4.1.2-alpha):
+ - Move the "bandwidth-file-headers" line in directory authority
+ votes so that it conforms to dir-spec.txt. Fixes bug 30316; bugfix
+ on 0.3.5.1-alpha.
+
+ o Minor bugfixes (error handling, backport from 0.4.2.1-alpha):
+ - On abort, try harder to flush the output buffers of log messages.
+ On some platforms (macOS), log messages could be discarded when
+ the process terminates. Fixes bug 31571; bugfix on 0.3.5.1-alpha.
+ - Report the tor version whenever an assertion fails. Previously, we
+ only reported the Tor version on some crashes, and some non-fatal
+ assertions. Fixes bug 31571; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (FreeBSD, PF-based proxy, IPv6, backport from 0.4.2.1-alpha):
+ - When extracting an IPv6 address from a PF-based proxy, verify that
+ we are actually configured to receive an IPv6 address, and log an
+ internal error if not. Fixes part of bug 31687; bugfix
+ on 0.2.3.4-alpha.
+
+ o Minor bugfixes (guards, backport from 0.4.2.1-alpha):
+ - When tor is missing descriptors for some primary entry guards,
+ make the log message less alarming. It's normal for descriptors to
+ expire, as long as tor fetches new ones soon after. Fixes bug
+ 31657; bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.1.1-alpha):
+ - Do not log a warning when running with an OpenSSL version other
+ than the one Tor was compiled with, if the two versions should be
+ compatible. Previously, we would warn whenever the version was
+ different. Fixes bug 30190; bugfix on 0.2.4.2-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.2.1-alpha):
+ - Change log level of message "Hash of session info was not as
+ expected" to LOG_PROTOCOL_WARN. Fixes bug 12399; bugfix
+ on 0.1.1.10-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.2.2-alpha):
+ - Rate-limit our the logging message about the obsolete .exit
+ notation. Previously, there was no limit on this warning, which
+ could potentially be triggered many times by a hostile website.
+ Fixes bug 31466; bugfix on 0.2.2.1-alpha.
+
+ o Minor bugfixes (logging, protocol violations, backport from 0.4.2.2-alpha):
+ - Do not log a nonfatal assertion failure when receiving a VERSIONS
+ cell on a connection using the obsolete v1 link protocol. Log a
+ protocol_warn instead. Fixes bug 31107; bugfix on 0.2.4.4-alpha.
+
+ o Minor bugfixes (mainloop, periodic events, in-process API, backport from 0.4.2.3-alpha):
+ - Reset the periodic events' "enabled" flag when Tor is shut down
+ cleanly. Previously, this flag was left on, which caused periodic
+ events not to be re-enabled when Tor was relaunched in-process
+ with tor_api.h after a shutdown. Fixes bug 32058; bugfix
+ on 0.3.3.1-alpha.
+
+ o Minor bugfixes (memory leak, backport from 0.4.1.1-alpha):
+ - Avoid a minor memory leak that could occur on relays when failing
+ to create a "keys" directory. Fixes bug 30148; bugfix
+ on 0.3.3.1-alpha.
+
+ o Minor bugfixes (memory leak, backport from 0.4.1.4-rc):
+ - Fix a trivial memory leak when parsing an invalid value
+ from a download schedule in the configuration. Fixes bug
+ 30894; bugfix on 0.3.4.1-alpha.
+
+ o Minor bugfixes (NetBSD, backport from 0.4.1.2-alpha):
+ - Fix usage of minherit() on NetBSD and other platforms that define
+ MAP_INHERIT_{ZERO,NONE} instead of INHERIT_{ZERO,NONE}. Fixes bug
+ 30614; bugfix on 0.4.0.2-alpha. Patch from Taylor Campbell.
+
+ o Minor bugfixes (onion services, backport from 0.4.1.1-alpha):
+ - Avoid a GCC 9.1.1 warning (and possible crash depending on libc
+ implemenation) when failing to load an onion service client
+ authorization file. Fixes bug 30475; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (out-of-memory handler, backport from 0.4.1.2-alpha):
+ - When purging the DNS cache because of an out-of-memory condition,
+ try purging just the older entries at first. Previously, we would
+ always purge the whole thing. Fixes bug 29617; bugfix
+ on 0.3.5.1-alpha.
+
+ o Minor bugfixes (portability, backport from 0.4.1.2-alpha):
+ - Avoid crashing in our tor_vasprintf() implementation on systems
+ that define neither vasprintf() nor _vscprintf(). (This bug has
+ been here long enough that we question whether people are running
+ Tor on such systems, but we're applying the fix out of caution.)
+ Fixes bug 30561; bugfix on 0.2.8.2-alpha. Found and fixed by
+ Tobias Stoeckmann.
+
+ o Minor bugfixes (process management, backport from 0.4.2.3-alpha):
+ - Remove overly strict assertions that triggered when a pluggable
+ transport failed to launch. Fixes bug 31091; bugfix
+ on 0.4.0.1-alpha.
+ - Remove an assertion in the Unix process backend. This assertion
+ would trigger when we failed to find the executable for a child
+ process. Fixes bug 31810; bugfix on 0.4.0.1-alpha.
+
+ o Minor bugfixes (relay, backport from 0.4.2.2-alpha):
+ - Avoid crashing when starting with a corrupt keys directory where
+ the old ntor key and the new ntor key are identical. Fixes bug
+ 30916; bugfix on 0.2.4.8-alpha.
+
+ o Minor bugfixes (rust, backport from 0.4.2.1-alpha):
+ - Correctly exclude a redundant rust build job in Travis. Fixes bug
+ 31463; bugfix on 0.3.5.4-alpha.
+
+ o Minor bugfixes (testing, backport from 0.4.2.3-alpha):
+ - When testing port rebinding, don't busy-wait for tor to log.
+ Instead, actually sleep for a short time before polling again.
+ Also improve the formatting of control commands and log messages.
+ Fixes bug 31837; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (tls, logging, backport from 0.4.2.3-alpha):
+ - Log bugs about the TLS read buffer's length only once, rather than
+ filling the logs with similar warnings. Fixes bug 31939; bugfix
+ on 0.3.0.4-rc.
+
+ o Minor bugfixes (v2 single onion services, backport from 0.4.2.1-alpha):
+ - Always retry v2 single onion service intro and rend circuits with
+ a 3-hop path. Previously, v2 single onion services used a 3-hop
+ path when rendezvous circuits were retried after a remote or
+ delayed failure, but a 1-hop path for immediate retries. Fixes bug
+ 23818; bugfix on 0.2.9.3-alpha.
+ - Make v3 single onion services fall back to a 3-hop intro, when all
+ intro points are unreachable via a 1-hop path. Previously, v3
+ single onion services failed when all intro nodes were unreachable
+ via a 1-hop path. Fixes bug 23507; bugfix on 0.3.2.1-alpha.
+
+ o Documentation (backport from 0.4.2.1-alpha):
+ - Use RFC 2397 data URL scheme to embed an image into tor-exit-
+ notice.html so that operators no longer have to host it
+ themselves. Closes ticket 31089.
+
+ o Testing (backport from 0.4.1.2-alpha):
+ - Specify torrc paths (with empty files) when launching tor in
+ integration tests; refrain from reading user and system torrcs.
+ Resolves issue 29702.
+
+ o Testing (continuous integration, backport from 0.4.1.1-alpha):
+ - In Travis, show stem's tor log after failure. Closes ticket 30234.
+
+ o Testing (continuous integration, backport from 0.4.1.5):
+ - In Travis, make stem log a controller trace to the console, and
+ tail stem's tor log after failure. Closes ticket 30591.
+ - In Travis, only run the stem tests that use a tor binary. Closes
+ ticket 30694.
+
+ o Testing (continuous integration, backport from 0.4.2.3-alpha):
+ - Disable all but one Travis CI macOS build, to mitigate slow
+ scheduling of Travis macOS jobs. Closes ticket 32177.
+ - Run the chutney IPv6 networks as part of Travis CI. Closes
+ ticket 30860.
+ - Simplify the Travis CI build matrix, and optimise for build time.
+ Closes ticket 31859.
+ - Use Windows Server 2019 instead of Windows Server 2016 in our
+ Appveyor builds. Closes ticket 32086.
+
+ o Testing (continuous integration, backport from 0.4.2.4-rc):
+ - Use Ubuntu Bionic images for our Travis CI builds, so we can get a
+ recent version of coccinelle. But leave chutney on Ubuntu Trusty,
+ until we can fix some Bionic permissions issues (see ticket
+ 32240). Related to ticket 31919.
+ - Install the mingw OpenSSL package in Appveyor. This makes sure
+ that the OpenSSL headers and libraries match in Tor's Appveyor
+ builds. (This bug was triggered by an Appveyor image update.)
+ Fixes bug 32449; bugfix on 0.3.5.6-rc.
+ - In Travis, use Xcode 11.2 on macOS 10.14. Closes ticket 32241.
+
+ o Testing (continuous integration, backport from 0.4.2.5):
+ - Require C99 standards-conforming code in Travis CI, but allow GNU gcc
+ extensions. Also activates clang's -Wtypedef-redefinition warnings.
+ Build some jobs with -std=gnu99, and some jobs without.
+ Closes ticket 32500.
+
+
+Changes in version 0.3.5.9 - 2019-12-09
+ Tor 0.3.5.9 backports serveral fixes from later releases, including
+ several that affect bridge users, relay stability, onion services,
+ and much more.
+
+ o Directory authority changes (backport from 0.4.1.5):
+ - The directory authority "dizum" has a new IP address. Closes
+ ticket 31406.
+
+ o Major bugfixes (bridges, backport from 0.4.1.2-alpha):
+ - Consider our directory information to have changed when our list
+ of bridges changes. Previously, Tor would not re-compute the
+ status of its directory information when bridges changed, and
+ therefore would not realize that it was no longer able to build
+ circuits. Fixes part of bug 29875.
+ - Do not count previously configured working bridges towards our
+ total of working bridges. Previously, when Tor's list of bridges
+ changed, it would think that the old bridges were still usable,
+ and delay fetching router descriptors for the new ones. Fixes part
+ of bug 29875; bugfix on 0.3.0.1-alpha.
+
+ o Major bugfixes (circuit build, guard, backport from 0.4.1.4-rc):
+ - When considering upgrading circuits from "waiting for guard" to
+ "open", always ignore circuits that are marked for close. Otherwise,
+ we can end up in the situation where a subsystem is notified that
+ a closing circuit has just opened, leading to undesirable
+ behavior. Fixes bug 30871; bugfix on 0.3.0.1-alpha.
+
+ o Major bugfixes (NSS, relay, backport from 0.4.0.4-rc):
+ - When running with NSS, disable TLS 1.2 ciphersuites that use
+ SHA384 for their PRF. Due to an NSS bug, the TLS key exporters for
+ these ciphersuites don't work -- which caused relays to fail to
+ handshake with one another when these ciphersuites were enabled.
+ Fixes bug 29241; bugfix on 0.3.5.1-alpha.
+
+ o Major bugfixes (Onion service reachability, backport from 0.4.1.3-alpha):
+ - Properly clean up the introduction point map when circuits change
+ purpose from onion service circuits to pathbias, measurement, or
+ other circuit types. This should fix some service-side instances
+ of introduction point failure. Fixes bug 29034; bugfix
+ on 0.3.2.1-alpha.
+
+ o Major bugfixes (onion service v3, backport from 0.4.1.1-alpha):
+ - Fix an unreachable bug in which an introduction point could try to
+ send an INTRODUCE_ACK with a status code that Trunnel would refuse
+ to encode, leading the relay to assert(). We've consolidated the
+ ABI values into Trunnel now. Fixes bug 30454; bugfix
+ on 0.3.0.1-alpha.
+ - Clients can now handle unknown status codes from INTRODUCE_ACK
+ cells. (The NACK behavior will stay the same.) This will allow us
+ to extend status codes in the future without breaking the normal
+ client behavior. Fixes another part of bug 30454; bugfix
+ on 0.3.0.1-alpha.
+
+ o Major bugfixes (torrc parsing, backport from 0.4.2.2-alpha):
+ - Stop ignoring torrc options after an %include directive, when the
+ included directory ends with a file that does not contain any
+ config options (but does contain comments or whitespace). Fixes
+ bug 31408; bugfix on 0.3.1.1-alpha.
+
+ o Major bugfixes (v3 onion services, backport from 0.4.2.3-alpha):
+ - Onion services now always use the exact number of intro points
+ configured with the HiddenServiceNumIntroductionPoints option (or
+ fewer if nodes are excluded). Before, a service could sometimes
+ pick more intro points than configured. Fixes bug 31548; bugfix
+ on 0.3.2.1-alpha.
+
+ o Minor features (address selection, backport from 0.4.0.3-alpha):
+ - Treat the subnet 100.64.0.0/10 as public for some purposes;
+ private for others. This subnet is the RFC 6598 (Carrier Grade
+ NAT) IP range, and is deployed by many ISPs as an alternative to
+ RFC 1918 that does not break existing internal networks. Tor now
+ blocks SOCKS and control ports on these addresses and warns users
+ if client ports or ExtORPorts are listening on a RFC 6598 address.
+ Closes ticket 28525. Patch by Neel Chauhan.
+
+ o Minor features (bandwidth authority, backport from 0.4.0.4-rc):
+ - Make bandwidth authorities ignore relays that are reported in the
+ bandwidth file with the flag "vote=0". This change allows us to
+ report unmeasured relays for diagnostic reasons without including
+ their bandwidth in the bandwidth authorities' vote. Closes
+ ticket 29806.
+
+ o Minor features (compile-time modules, backport from version 0.4.1.1-alpha):
+ - Add a "--list-modules" command to print a list of which compile-
+ time modules are enabled. Closes ticket 30452.
+
+ o Minor features (continuous integration, backport from 0.4.0.4-rc):
+ - On Travis Rust builds, cleanup Rust registry and refrain from
+ caching the "target/" directory to speed up builds. Resolves
+ issue 29962.
+
+ o Minor features (continuous integration, backport from 0.4.0.5):
+ - In Travis, tell timelimit to use stem's backtrace signals, and
+ launch python directly from timelimit, so python receives the
+ signals from timelimit, rather than make. Closes ticket 30117.
+
+ o Minor features (continuous integration, backport from 0.4.1.1-alpha):
+ - Remove sudo configuration lines from .travis.yml as they are no
+ longer needed with current Travis build environment. Resolves
+ issue 30213.
+
+ o Minor features (continuous integration, backport from 0.4.1.4-rc):
+ - Our Travis configuration now uses Chutney to run some network
+ integration tests automatically. Closes ticket 29280.
+
+ o Minor features (continuous integration, backport from 0.4.2.2-alpha):
+ - When building on Appveyor and Travis, pass the "-k" flag to make,
+ so that we are informed of all compilation failures, not just the
+ first one or two. Closes ticket 31372.
+
+ o Minor features (fallback directory list, backport from 0.4.1.4-rc):
+ - Replace the 157 fallbacks originally introduced in Tor 0.3.5.6-rc
+ in December 2018 (of which ~122 were still functional), with a
+ list of 148 fallbacks (70 new, 78 existing, 79 removed) generated
+ in June 2019. Closes ticket 28795.
+
+ o Minor features (geoip, backport from 0.4.2.5):
+ - Update geoip and geoip6 to the December 3 2019 Maxmind GeoLite2
+ Country database. Closes ticket 32685.
+
+ o Minor features (NSS, diagnostic, backport from 0.4.0.4-rc):
+ - Try to log an error from NSS (if there is any) and a more useful
+ description of our situation if we are using NSS and a call to
+ SSL_ExportKeyingMaterial() fails. Diagnostic for ticket 29241.
+
+ o Minor features (stem tests, backport from 0.4.2.1-alpha):
+ - Change "make test-stem" so it only runs the stem tests that use
+ tor. This change makes test-stem faster and more reliable. Closes
+ ticket 31554.
+
+ o Minor bugfixes (security, backport from 0.4.0.4-rc):
+ - Verify in more places that we are not about to create a buffer
+ with more than INT_MAX bytes, to avoid possible OOB access in the
+ event of bugs. Fixes bug 30041; bugfix on 0.2.0.16. Found and
+ fixed by Tobias Stoeckmann.
+ - Fix a potential double free bug when reading huge bandwidth files.
+ The issue is not exploitable in the current Tor network because
+ the vulnerable code is only reached when directory authorities
+ read bandwidth files, but bandwidth files come from a trusted
+ source (usually the authorities themselves). Furthermore, the
+ issue is only exploitable in rare (non-POSIX) 32-bit architectures,
+ which are not used by any of the current authorities. Fixes bug
+ 30040; bugfix on 0.3.5.1-alpha. Bug found and fixed by
+ Tobias Stoeckmann.
+
+ o Minor bugfix (continuous integration, backport from 0.4.0.4-rc):
+ - Reset coverage state on disk after Travis CI has finished. This
+ should prevent future coverage merge errors from causing the test
+ suite for the "process" subsystem to fail. The process subsystem
+ was introduced in 0.4.0.1-alpha. Fixes bug 29036; bugfix
+ on 0.2.9.15.
+ - Terminate test-stem if it takes more than 9.5 minutes to run.
+ (Travis terminates the job after 10 minutes of no output.)
+ Diagnostic for 29437. Fixes bug 30011; bugfix on 0.3.5.4-alpha.
+
+ o Minor bugfixes (Appveyor CI, backport from 0.4.2.2-alpha):
+ - Avoid spurious errors when Appveyor CI fails before the install step.
+ Fixes bug 31884; bugfix on 0.3.4.2-alpha.
+
+ o Minor bugfixes (build system, backport form 0.4.2.1-alpha):
+ - Do not include the deprecated <sys/sysctl.h> on Linux or Windows
+ systems. Fixes bug 31673; bugfix on 0.2.5.4-alpha.
+
+ o Minor bugfixes (C correctness, backport from 0.4.0.4-rc):
+ - Fix an unlikely memory leak in consensus_diff_apply(). Fixes bug
+ 29824; bugfix on 0.3.1.1-alpha. This is Coverity warning
+ CID 1444119.
+
+ o Minor bugfixes (circuit isolation, backport from 0.4.1.3-alpha):
+ - Fix a logic error that prevented the SessionGroup sub-option from
+ being accepted. Fixes bug 22619; bugfix on 0.2.7.2-alpha.
+
+ o Minor bugfixes (client, onion service v3, backport from 0.4.2.4-rc):
+ - Fix a BUG() assertion that occurs within a very small race window
+ between when a client intro circuit opens and when its descriptor
+ gets cleaned up from the cache. The circuit is now closed early,
+ which will trigger a re-fetch of the descriptor and continue the
+ connection. Fixes bug 28970; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfixes (clock skew detection, backport from 0.4.1.5):
+ - Don't believe clock skew results from NETINFO cells that appear to
+ arrive before we sent the VERSIONS cells they are responding to.
+ Previously, we would accept them up to 3 minutes "in the past".
+ Fixes bug 31343; bugfix on 0.2.4.4-alpha.
+
+ o Minor bugfixes (compilation warning, backport from 0.4.1.5):
+ - Fix a compilation warning on Windows about casting a function
+ pointer for GetTickCount64(). Fixes bug 31374; bugfix
+ on 0.2.9.1-alpha.
+
+ o Minor bugfixes (compilation, backport from 0.4.0.2-alpha):
+ - Silence a compiler warning in test-memwipe.c on OpenBSD. Fixes bug
+ 29145; bugfix on 0.2.9.3-alpha. Patch from Kris Katterjohn.
+
+ o Minor bugfixes (compilation, backport from 0.4.1.5):
+ - Avoid using labs() on time_t, which can cause compilation warnings
+ on 64-bit Windows builds. Fixes bug 31343; bugfix on 0.2.4.4-alpha.
+
+ o Minor bugfixes (compilation, backport from 0.4.2.1-alpha):
+ - Suppress spurious float-conversion warnings from GCC when calling
+ floating-point classifier functions on FreeBSD. Fixes part of bug
+ 31687; bugfix on 0.3.1.5-alpha.
+
+ o Minor bugfixes (compilation, unusual configurations, backport from 0.4.1.1-alpha):
+ - Avoid failures when building with the ALL_BUGS_ARE_FATAL option
+ due to missing declarations of abort(), and prevent other such
+ failures in the future. Fixes bug 30189; bugfix on 0.3.4.1-alpha.
+
+ o Minor bugfixes (configuration, proxies, backport from 0.4.1.2-alpha):
+ - Fix a bug that prevented us from supporting SOCKS5 proxies that
+ want authentication along with configured (but unused!)
+ ClientTransportPlugins. Fixes bug 29670; bugfix on 0.2.6.1-alpha.
+
+ o Minor bugfixes (connections, backport from 0.4.2.3-rc):
+ - Avoid trying to read data from closed connections, which can cause
+ needless loops in Libevent and infinite loops in Shadow. Fixes bug
+ 30344; bugfix on 0.1.1.1-alpha.
+
+ o Minor bugfixes (continuous integration, backport from 0.4.1.3-alpha):
+ - Allow the test-stem job to fail in Travis, because it sometimes
+ hangs. Fixes bug 30744; bugfix on 0.3.5.4-alpha.
+ - Skip test_rebind on macOS in Travis, because it is unreliable on
+ macOS on Travis. Fixes bug 30713; bugfix on 0.3.5.1-alpha.
+ - Skip test_rebind when the TOR_SKIP_TEST_REBIND environment
+ variable is set. Fixes bug 30713; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (crash on exit, backport from 0.4.1.4-rc):
+ - Avoid a set of possible code paths that could try to use freed
+ memory in routerlist_free() while Tor was exiting. Fixes bug
+ 31003; bugfix on 0.1.2.2-alpha.
+
+ o Minor bugfixes (directory authorities, backport from 0.4.1.3-alpha):
+ - Stop crashing after parsing an unknown descriptor purpose
+ annotation. We think this bug can only be triggered by modifying a
+ local file. Fixes bug 30781; bugfix on 0.2.0.8-alpha.
+
+ o Minor bugfixes (directory authority, backport from 0.4.1.2-alpha):
+ - Move the "bandwidth-file-headers" line in directory authority
+ votes so that it conforms to dir-spec.txt. Fixes bug 30316; bugfix
+ on 0.3.5.1-alpha.
+
+ o Minor bugfixes (error handling, backport from 0.4.2.1-alpha):
+ - On abort, try harder to flush the output buffers of log messages.
+ On some platforms (macOS), log messages could be discarded when
+ the process terminates. Fixes bug 31571; bugfix on 0.3.5.1-alpha.
+ - Report the tor version whenever an assertion fails. Previously, we
+ only reported the Tor version on some crashes, and some non-fatal
+ assertions. Fixes bug 31571; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (FreeBSD, PF-based proxy, IPv6, backport from 0.4.2.1-alpha):
+ - When extracting an IPv6 address from a PF-based proxy, verify that
+ we are actually configured to receive an IPv6 address, and log an
+ internal error if not. Fixes part of bug 31687; bugfix
+ on 0.2.3.4-alpha.
+
+ o Minor bugfixes (guards, backport from 0.4.2.1-alpha):
+ - When tor is missing descriptors for some primary entry guards,
+ make the log message less alarming. It's normal for descriptors to
+ expire, as long as tor fetches new ones soon after. Fixes bug
+ 31657; bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.0.2-alpha):
+ - Avoid logging that we are relaxing a circuit timeout when that
+ timeout is fixed. Fixes bug 28698; bugfix on 0.2.4.7-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.0.3-alpha):
+ - Correct a misleading error message when IPv4Only or IPv6Only is
+ used but the resolved address can not be interpreted as an address
+ of the specified IP version. Fixes bug 13221; bugfix on
+ 0.2.3.9-alpha. Patch from Kris Katterjohn.
+ - Log the correct port number for listening sockets when "auto" is
+ used to let Tor pick the port number. Previously, port 0 was
+ logged instead of the actual port number. Fixes bug 29144; bugfix
+ on 0.3.5.1-alpha. Patch from Kris Katterjohn.
+ - Stop logging a BUG() warning when Tor is waiting for exit
+ descriptors. Fixes bug 28656; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.1.1-alpha):
+ - Do not log a warning when running with an OpenSSL version other
+ than the one Tor was compiled with, if the two versions should be
+ compatible. Previously, we would warn whenever the version was
+ different. Fixes bug 30190; bugfix on 0.2.4.2-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.2.1-alpha):
+ - Change log level of message "Hash of session info was not as
+ expected" to LOG_PROTOCOL_WARN. Fixes bug 12399; bugfix
+ on 0.1.1.10-alpha.
+
+ o Minor bugfixes (logging, backport from 0.4.2.2-alpha):
+ - Rate-limit our the logging message about the obsolete .exit
+ notation. Previously, there was no limit on this warning, which
+ could potentially be triggered many times by a hostile website.
+ Fixes bug 31466; bugfix on 0.2.2.1-alpha.
+
+ o Minor bugfixes (logging, protocol violations, backport from 0.4.2.2-alpha):
+ - Do not log a nonfatal assertion failure when receiving a VERSIONS
+ cell on a connection using the obsolete v1 link protocol. Log a
+ protocol_warn instead. Fixes bug 31107; bugfix on 0.2.4.4-alpha.
+
+ o Minor bugfixes (mainloop, periodic events, in-process API, backport from 0.4.2.3-alpha):
+ - Reset the periodic events' "enabled" flag when Tor is shut down
+ cleanly. Previously, this flag was left on, which caused periodic
+ events not to be re-enabled when Tor was relaunched in-process
+ with tor_api.h after a shutdown. Fixes bug 32058; bugfix
+ on 0.3.3.1-alpha.
+
+ o Minor bugfixes (memory leak, backport from 0.4.1.1-alpha):
+ - Avoid a minor memory leak that could occur on relays when failing
+ to create a "keys" directory. Fixes bug 30148; bugfix
+ on 0.3.3.1-alpha.
+
+ o Minor bugfixes (memory leak, backport from 0.4.1.4-rc):
+ - Fix a trivial memory leak when parsing an invalid value
+ from a download schedule in the configuration. Fixes bug
+ 30894; bugfix on 0.3.4.1-alpha.
+
+ o Minor bugfixes (memory management, backport from 0.4.0.3-alpha):
+ - Refactor the shared random state's memory management so that it
+ actually takes ownership of the shared random value pointers.
+ Fixes bug 29706; bugfix on 0.2.9.1-alpha.
+
+ o Minor bugfixes (memory management, testing, backport from 0.4.0.3-alpha):
+ - Stop leaking parts of the shared random state in the shared-random
+ unit tests. Fixes bug 29599; bugfix on 0.2.9.1-alpha.
+
+ o Minor bugfixes (onion services, backport from 0.4.1.1-alpha):
+ - Avoid a GCC 9.1.1 warning (and possible crash depending on libc
+ implemenation) when failing to load an onion service client
+ authorization file. Fixes bug 30475; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (out-of-memory handler, backport from 0.4.1.2-alpha):
+ - When purging the DNS cache because of an out-of-memory condition,
+ try purging just the older entries at first. Previously, we would
+ always purge the whole thing. Fixes bug 29617; bugfix
+ on 0.3.5.1-alpha.
+
+ o Minor bugfixes (portability, backport from 0.4.1.2-alpha):
+ - Avoid crashing in our tor_vasprintf() implementation on systems
+ that define neither vasprintf() nor _vscprintf(). (This bug has
+ been here long enough that we question whether people are running
+ Tor on such systems, but we're applying the fix out of caution.)
+ Fixes bug 30561; bugfix on 0.2.8.2-alpha. Found and fixed by
+ Tobias Stoeckmann.
+
+ o Minor bugfixes (relay, backport from 0.4.2.2-alpha):
+ - Avoid crashing when starting with a corrupt keys directory where
+ the old ntor key and the new ntor key are identical. Fixes bug
+ 30916; bugfix on 0.2.4.8-alpha.
+
+ o Minor bugfixes (rust, backport from 0.4.0.5):
+ - Abort on panic in all build profiles, instead of potentially
+ unwinding into C code. Fixes bug 27199; bugfix on 0.3.3.1-alpha.
+
+ o Minor bugfixes (rust, backport from 0.4.2.1-alpha):
+ - Correctly exclude a redundant rust build job in Travis. Fixes bug
+ 31463; bugfix on 0.3.5.4-alpha.
+
+ o Minor bugfixes (single onion services, backport from 0.4.0.3-alpha):
+ - Allow connections to single onion services to remain idle without
+ being disconnected. Previously, relays acting as rendezvous points
+ for single onion services were mistakenly closing idle rendezvous
+ circuits after 60 seconds, thinking that they were unused
+ directory-fetching circuits that had served their purpose. Fixes
+ bug 29665; bugfix on 0.2.1.26.
+
+ o Minor bugfixes (stats, backport from 0.4.0.3-alpha):
+ - When ExtraInfoStatistics is 0, stop including PaddingStatistics in
+ relay and bridge extra-info documents. Fixes bug 29017; bugfix
+ on 0.3.1.1-alpha.
+
+ o Minor bugfixes (testing, backport from 0.4.0.3-alpha):
+ - Downgrade some LOG_ERR messages in the address/* tests to
+ warnings. The LOG_ERR messages were occurring when we had no
+ configured network. We were failing the unit tests, because we
+ backported 28668 to 0.3.5.8, but did not backport 29530. Fixes bug
+ 29530; bugfix on 0.3.5.8.
+ - Fix our gcov wrapper script to look for object files at the
+ correct locations. Fixes bug 29435; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (testing, backport from 0.4.0.4-rc):
+ - Backport the 0.3.4 src/test/test-network.sh to 0.2.9. We need a
+ recent test-network.sh to use new chutney features in CI. Fixes
+ bug 29703; bugfix on 0.2.9.1-alpha.
+ - Fix a test failure on Windows caused by an unexpected "BUG"
+ warning in our tests for tor_gmtime_r(-1). Fixes bug 29922; bugfix
+ on 0.2.9.3-alpha.
+
+ o Minor bugfixes (testing, backport from 0.4.2.3-alpha):
+ - When testing port rebinding, don't busy-wait for tor to log.
+ Instead, actually sleep for a short time before polling again.
+ Also improve the formatting of control commands and log messages.
+ Fixes bug 31837; bugfix on 0.3.5.1-alpha.
+
+ o Minor bugfixes (TLS protocol, backport form 0.4.0.4-rc):
+ - When classifying a client's selection of TLS ciphers, if the
+ client ciphers are not yet available, do not cache the result.
+ Previously, we had cached the unavailability of the cipher list
+ and never looked again, which in turn led us to assume that the
+ client only supported the ancient V1 link protocol. This, in turn,
+ was causing Stem integration tests to stall in some cases. Fixes
+ bug 30021; bugfix on 0.2.4.8-alpha.
+
+ o Minor bugfixes (tls, logging, backport from 0.4.2.3-alpha):
+ - Log bugs about the TLS read buffer's length only once, rather than
+ filling the logs with similar warnings. Fixes bug 31939; bugfix
+ on 0.3.0.4-rc.
+
+ o Minor bugfixes (v2 single onion services, backport from 0.4.2.1-alpha):
+ - Always retry v2 single onion service intro and rend circuits with
+ a 3-hop path. Previously, v2 single onion services used a 3-hop
+ path when rendezvous circuits were retried after a remote or
+ delayed failure, but a 1-hop path for immediate retries. Fixes bug
+ 23818; bugfix on 0.2.9.3-alpha.
+ - Make v3 single onion services fall back to a 3-hop intro, when all
+ intro points are unreachable via a 1-hop path. Previously, v3
+ single onion services failed when all intro nodes were unreachable
+ via a 1-hop path. Fixes bug 23507; bugfix on 0.3.2.1-alpha.
+
+ o Minor bugfixes (Windows, CI, backport from 0.4.0.3-alpha):
+ - Skip the Appveyor 32-bit Windows Server 2016 job, and 64-bit
+ Windows Server 2012 R2 job. The remaining 2 jobs still provide
+ coverage of 64/32-bit, and Windows Server 2016/2012 R2. Also set
+ fast_finish, so failed jobs terminate the build immediately. Fixes
+ bug 29601; bugfix on 0.3.5.4-alpha.
+
+ o Documentation (backport from 0.4.2.1-alpha):
+ - Use RFC 2397 data URL scheme to embed an image into tor-exit-
+ notice.html so that operators no longer have to host it
+ themselves. Closes ticket 31089.
+
+ o Testing (backport from 0.4.1.2-alpha):
+ - Specify torrc paths (with empty files) when launching tor in
+ integration tests; refrain from reading user and system torrcs.
+ Resolves issue 29702.
+
+ o Testing (continuous integration, backport from 0.4.1.1-alpha):
+ - In Travis, show stem's tor log after failure. Closes ticket 30234.
+
+ o Testing (continuous integration, backport from 0.4.1.5):
+ - In Travis, make stem log a controller trace to the console, and
+ tail stem's tor log after failure. Closes ticket 30591.
+ - In Travis, only run the stem tests that use a tor binary. Closes
+ ticket 30694.
+
+ o Testing (continuous integration, backport from 0.4.2.3-alpha):
+ - Disable all but one Travis CI macOS build, to mitigate slow
+ scheduling of Travis macOS jobs. Closes ticket 32177.
+ - Run the chutney IPv6 networks as part of Travis CI. Closes
+ ticket 30860.
+ - Simplify the Travis CI build matrix, and optimise for build time.
+ Closes ticket 31859.
+ - Use Windows Server 2019 instead of Windows Server 2016 in our
+ Appveyor builds. Closes ticket 32086.
+
+ o Testing (continuous integration, backport from 0.4.2.4-rc):
+ - Use Ubuntu Bionic images for our Travis CI builds, so we can get a
+ recent version of coccinelle. But leave chutney on Ubuntu Trusty,
+ until we can fix some Bionic permissions issues (see ticket
+ 32240). Related to ticket 31919.
+ - Install the mingw OpenSSL package in Appveyor. This makes sure
+ that the OpenSSL headers and libraries match in Tor's Appveyor
+ builds. (This bug was triggered by an Appveyor image update.)
+ Fixes bug 32449; bugfix on 0.3.5.6-rc.
+ - In Travis, use Xcode 11.2 on macOS 10.14. Closes ticket 32241.
+
+ o Testing (continuous integration, backport from 0.4.2.5):
+ - Require C99 standards-conforming code in Travis CI, but allow GNU gcc
+ extensions. Also activates clang's -Wtypedef-redefinition warnings.
+ Build some jobs with -std=gnu99, and some jobs without.
+ Closes ticket 32500.
+
+
Changes in version 0.4.1.6 - 2019-09-19
This release backports several bugfixes to improve stability and
correctness. Anyone experiencing build problems or crashes with 0.4.1.5,
@@ -42,6 +1783,12 @@ Changes in version 0.4.1.6 - 2019-09-19
arguments. Previously, it required two or more arguments, and ignored
the first. Fixes bug 31772; bugfix on 0.4.1.1-alpha.
+ o Minor bugfixes (FreeBSD, PF-based proxy, IPv6, backport from 0.4.2.1-alpha):
+ - When extracting an IPv6 address from a PF-based proxy, verify that
+ we are actually configured to receive an IPv6 address, and log an
+ internal error if not. Fixes part of bug 31687; bugfix
+ on 0.2.3.4-alpha.
+
o Minor bugfixes (guards, backport from 0.4.2.1-alpha):
- When tor is missing descriptors for some primary entry guards,
make the log message less alarming. It's normal for descriptors to
diff --git a/changes/bug29819 b/changes/bug29819
deleted file mode 100644
index d37ac83d66..0000000000
--- a/changes/bug29819
+++ /dev/null
@@ -1,8 +0,0 @@
- o Minor bugfixes (linux seccomp sandbox):
- - Correct how we use libseccomp. Particularly, stop assuming that
- rules are applied in a particular order or that more rules are
- processed after the first match. Neither is the case! In libseccomp
- <2.4.0 this lead to some rules having no effect. Libseccomp 2.4.0
- changed how rules are generated leading to a different ordering
- which in turn lead to a fatal crash during startup. Fixes bug
- 29819; bugfix on 0.2.5.1-alpha. Patch by Peter Gerber.
diff --git a/changes/bug30344 b/changes/bug30344
deleted file mode 100644
index 37561bf944..0000000000
--- a/changes/bug30344
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes (connection):
- - Avoid reading data from closed connections, which can cause needless
- loops in libevent and infinite loops in Shadow. Fixes bug 30344; bugfix
- on 0.1.1.1-alpha.
diff --git a/changes/bug31335 b/changes/bug31335
deleted file mode 100644
index f633cf8b24..0000000000
--- a/changes/bug31335
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (code quality):
- - Fix "make check-includes" so it runs correctly on out-of-tree builds.
- Fixes bug 31335; bugfix on 0.3.5.1-alpha.
diff --git a/changes/bug31652 b/changes/bug31652
deleted file mode 100644
index c4eca7994a..0000000000
--- a/changes/bug31652
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor bugfixes (onion services):
- - When we clean up intro circuits for a v3 onion service, don't remove
- circuits that have an established or pending circuit even if ran out of
- retries. This way, we don't cleanup the circuit of the last retry. Fixes
- bug 31652; bugfix on 0.3.2.1-alpha.
diff --git a/changes/bug31669 b/changes/bug31669
new file mode 100644
index 0000000000..8079c98f62
--- /dev/null
+++ b/changes/bug31669
@@ -0,0 +1,4 @@
+ o Minor bugfixes (onion services v3):
+ - Relax severity of a log message that can appear naturally when decoding
+ onion service descriptors as a relay. Also add some diagnostics to debug
+ any future bugs in that area. Fixes bug 31669; bugfix on 0.3.0.1-alpha. \ No newline at end of file
diff --git a/changes/bug31734 b/changes/bug31734
deleted file mode 100644
index ce989ea5db..0000000000
--- a/changes/bug31734
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (error handling):
- - Always lock the backtrace buffer before it is used.
- Fixes bug 31734; bugfix on 0.2.5.3-alpha.
diff --git a/changes/bug31810 b/changes/bug31810
deleted file mode 100644
index 628d12f09b..0000000000
--- a/changes/bug31810
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes (process management):
- - Remove assertion in the Unix process backend. This assertion would trigger
- when a new process is spawned where the executable is not found leading to
- a stack trace from the child process. Fixes bug 31810; bugfix on 0.4.0.1-alpha.
diff --git a/changes/bug31837 b/changes/bug31837
deleted file mode 100644
index 0f976edfe0..0000000000
--- a/changes/bug31837
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor bugfixes (testing):
- - When testing port rebinding, don't busy-wait for tor to log. Instead,
- actually sleep for a short time before polling again. Also improve the
- formatting of control commands and log messages.
- Fixes bug 31837; bugfix on 0.3.5.1-alpha.
diff --git a/changes/bug31922 b/changes/bug31922
deleted file mode 100644
index e6f31ce66a..0000000000
--- a/changes/bug31922
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes (configuration):
- - When pkg-config is not installed, or a library that depends on
- pkg-config is not found, tell the user what to do to fix the
- problem. Fixes bug 31922; bugfix on 0.3.1.1-alpha.
diff --git a/changes/bug31939 b/changes/bug31939
deleted file mode 100644
index a36ea495d6..0000000000
--- a/changes/bug31939
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (tls, logging):
- - Log TLS read buffer length bugs once, rather than filling the logs
- with similar warnings. Fixes bug 31939; bugfix on 0.3.0.4-rc.
diff --git a/changes/bug31995 b/changes/bug31995
deleted file mode 100644
index c7ddd437a6..0000000000
--- a/changes/bug31995
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (testing):
- - Avoid intermittent test failures due to a test that had relied on
- inconsistent timing sources. Fixes bug 31995; bugfix on 0.3.1.3-alpha.
diff --git a/changes/bug32106 b/changes/bug32106
deleted file mode 100644
index c6e8e95860..0000000000
--- a/changes/bug32106
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor features (documentation):
- - Make clear in the man page, in both the bandwidth section and the
- accountingmax section, that Tor counts in powers of two, not
- powers of ten: 1 GByte is 1024*1024*1024 bytes, not one billion
- bytes. Resolves ticket 32106.
diff --git a/changes/bug32108 b/changes/bug32108
deleted file mode 100644
index 2806fa3e5d..0000000000
--- a/changes/bug32108
+++ /dev/null
@@ -1,8 +0,0 @@
- o Major bugfixes (relay):
- - Relays now respect their AccountingMax bandwidth again. When relays
- entered "soft" hibernation (which typically starts when we've hit
- 90% of our AccountingMax), we had stopped checking whether we should
- enter hard hibernation. Soft hibernation refuses new connections and
- new circuits, but the existing circuits can continue, meaning that
- relays could have exceeded their configured AccountingMax. Fixes
- bug 32108; bugfix on 0.4.0.1-alpha.
diff --git a/changes/bug32124 b/changes/bug32124
deleted file mode 100644
index 164b33c7e3..0000000000
--- a/changes/bug32124
+++ /dev/null
@@ -1,7 +0,0 @@
- o Minor bugfixes (build system):
- - Stop failing when jemalloc is requested, but tcmalloc is not found.
- Fixes bug 32124; bugfix on 0.3.5.1-alpha.
- - Interpret --disable-module-dirauth=no correctly.
- Fixes bug 32124; bugfix on 0.3.4.1-alpha.
- - Interpret --with-tcmalloc=no correctly.
- Fixes bug 32124; bugfix on 0.2.0.20-rc.
diff --git a/changes/bug32295 b/changes/bug32295
deleted file mode 100644
index e5e5a4399d..0000000000
--- a/changes/bug32295
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (configuration):
- - Log the option name when skipping an obsolete option.
- Fixes bug 32295; bugfix on 0.4.2.1-alpha.
diff --git a/changes/bug32402 b/changes/bug32402
deleted file mode 100644
index 0654389be3..0000000000
--- a/changes/bug32402
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (shellcheck):
- - Start checking most scripts for shellcheck errors again.
- Fixes bug 32402; bugfix on 0.4.2.1-alpha.
diff --git a/changes/bug32402_git_scripts b/changes/bug32402_git_scripts
deleted file mode 100644
index 2b10a8998a..0000000000
--- a/changes/bug32402_git_scripts
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (shellcheck):
- - Fix minor shellcheck errors in the git-*.sh scripts.
- Fixes bug 32402; bugfix on 0.4.2.1-alpha.
diff --git a/changes/bug32449 b/changes/bug32449
deleted file mode 100644
index 213d8a1014..0000000000
--- a/changes/bug32449
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor bugfixes (CI, appveyor):
- - Install the mingw OpenSSL package in Appveyor. This makes sure that
- the OpenSSL headers and libraries match in Tor's Appveyor builds.
- (This bug was triggered by an Appveyor image update.)
- Fixes bug 32449; bugfix on 0.3.5.6-rc.
diff --git a/changes/bug32588 b/changes/bug32588
new file mode 100644
index 0000000000..f31f2ce1ad
--- /dev/null
+++ b/changes/bug32588
@@ -0,0 +1,4 @@
+ o Minor bugfixes (relays):
+ - Stop advertising incorrect IPv6 ORPorts in relay and bridge descriptors,
+ when the IPv6 port was configured as "auto".
+ Fixes bug 32588; bugfix on 0.2.3.9-alpha
diff --git a/changes/bug32753 b/changes/bug32753
deleted file mode 100644
index 6f59c7729d..0000000000
--- a/changes/bug32753
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (bridges):
- - Lowercase the value of BridgeDistribution from torrc before adding it to
- the descriptor. Fixes bug 32753; bugfix on 0.3.2.3-alpha.
diff --git a/changes/bug32771 b/changes/bug32771
deleted file mode 100644
index 606bcf4be4..0000000000
--- a/changes/bug32771
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes (logging, crash):
- - Avoid a possible crash when trying to log a (fatal) assertion failure
- about mismatched magic numbers in configuration objects. Fixes bug 32771;
- bugfix on 0.4.2.1-alpha.
diff --git a/changes/bug32778 b/changes/bug32778
deleted file mode 100644
index ccb6104692..0000000000
--- a/changes/bug32778
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (windows service):
- - Initialize publish/subscribe system when running as a windows service.
- Fixes bug 32778; bugfix on 0.4.1.1-alpha.
diff --git a/changes/bug32841 b/changes/bug32841
deleted file mode 100644
index 48568f6a61..0000000000
--- a/changes/bug32841
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes (linux seccomp sandbox):
- - Fix crash when reloading logging configuration while the
- experimental sandbox is enabled. Fixes bug 32841; bugfix
- on 0.4.1.7. Patch by Peter Gerber.
diff --git a/changes/bug32884 b/changes/bug32884
deleted file mode 100644
index 9ab1d24464..0000000000
--- a/changes/bug32884
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor bugfixes (embedded Tor):
- - When starting Tor any time after the first time in a process, register
- the thread in which it is running as the main thread. Previously, we
- only did this on Windows, which could lead to bugs like 23081 on
- non-Windows platforms. Fixes bug 32884; bugfix on 0.3.3.1-alpha.
diff --git a/changes/bug33087 b/changes/bug33087
index 7acf72a835..ab6df58cc6 100644
--- a/changes/bug33087
+++ b/changes/bug33087
@@ -2,3 +2,6 @@
- Stop closing stderr and stdout during shutdown. Closing these file
descriptors can hide sanitiser logs.
Fixes bug 33087; bugfix on 0.4.1.6.
+ - Flush stderr, stdout, and file logs during shutdown, if supported by the
+ OS. This change helps make sure that any final logs are recorded.
+ Fixes bug 33087; bugfix on 0.4.1.6.
diff --git a/changes/bug33093_logging b/changes/bug33093_logging
deleted file mode 100644
index e26e4a64af..0000000000
--- a/changes/bug33093_logging
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor bugfixes (logging):
- - If we encounter a bug when flushing a buffer to a TLS connection,
- only log the bug once per invocation of the Tor process. Previously we
- would log with every occurrence, which could cause us to run out of
- disk space. Fixes bug 33093; bugfix on 0.3.2.2-alpha.
diff --git a/changes/bug33095_041 b/changes/bug33095_041
deleted file mode 100644
index 7d1f04e279..0000000000
--- a/changes/bug33095_041
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor bugfixes (logging, bug reporting):
- - When logging a bug, do not say "Future instances of this warning
- will be silenced" unless we are actually going to do
- so. Previously we would say this whenever a BUG() check failed in
- the code. Fixes bug 33095; bugfix on 0.4.1.1-alpha.
diff --git a/changes/bug33104 b/changes/bug33104
deleted file mode 100644
index b5478df108..0000000000
--- a/changes/bug33104
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes (controller):
- - When receiving "ACTIVE" or "DORMANT" signals on the control port,
- report them as SIGNAL events. Fixes bug 33104; bugfix on
- 0.4.0.1-alpha.
diff --git a/changes/bug33374 b/changes/bug33374
new file mode 100644
index 0000000000..d1141faf78
--- /dev/null
+++ b/changes/bug33374
@@ -0,0 +1,5 @@
+ o Minor bugfixes (coding best practices checks):
+ - Allow the "practracker" coding best practices checking script to read
+ unicode files, when using Python 2. We made the script use unicode
+ literals in 0.4.3.1-alpha, but didn't change the codec for opening files.
+ Fixes bug 33374; bugfix on 0.4.3.1-alpha.
diff --git a/changes/bug33545 b/changes/bug33545
new file mode 100644
index 0000000000..c051b01605
--- /dev/null
+++ b/changes/bug33545
@@ -0,0 +1,4 @@
+ o Minor bugfixes (hidden services):
+ - Block a client-side assert by disallowing the registration of an x25519
+ client auth key that's all zeroes. Fixes bug 33545; bugfix on
+ 0.4.3.1-alpha. Patch based on patch from "cypherpunks". \ No newline at end of file
diff --git a/changes/bug33608 b/changes/bug33608
new file mode 100644
index 0000000000..0e82a8eec9
--- /dev/null
+++ b/changes/bug33608
@@ -0,0 +1,5 @@
+ o Minor bugfixes (client IPv6):
+ - Stop forcing all non-SOCKSPorts to prefer IPv6 exit connections. Instead,
+ prefer IPv6 connections by default, but allow users to change their
+ configs using the "NoPreferIPv6" port flag.
+ Fixes bug 33608; bugfix on 0.4.3.1-alpha.
diff --git a/changes/bug33668 b/changes/bug33668
new file mode 100644
index 0000000000..2b0830d6d8
--- /dev/null
+++ b/changes/bug33668
@@ -0,0 +1,4 @@
+ o Minor bugfixes (--disable-module-relay):
+ - Fix an assertion failure when Tor is build without the relay module,
+ and then invoked with the "User" option. Fixes bug 33668; bugfix on
+ 0.4.3.1-alpha.
diff --git a/changes/bug33674 b/changes/bug33674
new file mode 100644
index 0000000000..bcc3fcab03
--- /dev/null
+++ b/changes/bug33674
@@ -0,0 +1,4 @@
+ o Minor bugfixes (--disable-module-relay,--disable-module-dirauth):
+ - Set some output arguments in the relay and dirauth module stubs, to
+ guard against future stub argument handling bugs like 33668.
+ Fixes bug 33674; bugfix on 0.4.3.1-alpha.
diff --git a/changes/bug33782 b/changes/bug33782
new file mode 100644
index 0000000000..9d4a0e7a79
--- /dev/null
+++ b/changes/bug33782
@@ -0,0 +1,7 @@
+ o Testing:
+ - Avoid conflicts between the fake sockets in tor's unit tests, and real
+ file descriptors. Resolves issues running unit tests with GitHub Actions,
+ where the process that embeds or launches the tests has already opened a
+ large number of file descriptors.
+ Fixes bug 33782; bugfix on 0.2.8.1-alpha.
+ Found and fixed by Putta Khunchalee.
diff --git a/changes/bug33918 b/changes/bug33918
new file mode 100644
index 0000000000..e1467b4aaf
--- /dev/null
+++ b/changes/bug33918
@@ -0,0 +1,3 @@
+ o Minor bugfixes (IPv6, logging):
+ - Stop truncating IPv6 addresses and ports in channel and connection logs.
+ Fixes bug 33918; bugfix on 0.2.4.4-alpha.
diff --git a/changes/bug34130 b/changes/bug34130
new file mode 100644
index 0000000000..b1e5715fdf
--- /dev/null
+++ b/changes/bug34130
@@ -0,0 +1,4 @@
+ o Minor bugfixes (linux seccomp sandbox nss):
+ - Fix startup crash when tor is compiled with --enable-nss and
+ sandbox support is enabled. Fixes bug 34130; bugfix on
+ 0.3.5.1-alpha. Patch by Daniel Pinto.
diff --git a/changes/bug34131 b/changes/bug34131
new file mode 100644
index 0000000000..eb3a3feba2
--- /dev/null
+++ b/changes/bug34131
@@ -0,0 +1,4 @@
+ o Minor bugfixes (logging):
+ - Fix a logic error in a log message about whether an address was
+ invalid. Previously, the code would never report that onion addresses
+ were onion addresses. Fixes bug 34131; bugfix on 0.4.3.1-alpha.
diff --git a/changes/bug34233 b/changes/bug34233
new file mode 100644
index 0000000000..24c7869783
--- /dev/null
+++ b/changes/bug34233
@@ -0,0 +1,4 @@
+ o Minor bugfixes (portability):
+ - Fix a portability error in the configure script, where we
+ were using "==" instead of "=". Fixes bug 34233; bugfix on
+ 0.4.3.5.
diff --git a/changes/bug34299 b/changes/bug34299
new file mode 100644
index 0000000000..464cf0d18a
--- /dev/null
+++ b/changes/bug34299
@@ -0,0 +1,3 @@
+ o Minor bugfixes (man page):
+ - Update the man page to reflect that MinUptimeHidServDirectoryV2
+ defaults to 96 hours. Fixes bug 34299; bugfix on 0.2.6.3-alpha.
diff --git a/changes/doc32971 b/changes/doc32971
new file mode 100644
index 0000000000..014d2a7cec
--- /dev/null
+++ b/changes/doc32971
@@ -0,0 +1,3 @@
+ o Documentation (manpage):
+ - Document __OwningControllerProcess torrc option and specify polling
+ interval. Resolves issue 32971.
diff --git a/changes/geoip-2019-11-06 b/changes/geoip-2019-11-06
deleted file mode 100644
index a470981012..0000000000
--- a/changes/geoip-2019-11-06
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor features (geoip):
- - Update geoip and geoip6 to the November 6 2019 Maxmind GeoLite2
- Country database. Closes ticket 32440.
-
diff --git a/changes/geoip-2019-12-03 b/changes/geoip-2019-12-03
deleted file mode 100644
index ea62b6ee89..0000000000
--- a/changes/geoip-2019-12-03
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor features (geoip):
- - Update geoip and geoip6 to the December 3 2019 Maxmind GeoLite2
- Country database. Closes ticket 32685.
-
diff --git a/changes/ticket28970 b/changes/ticket28970
deleted file mode 100644
index 138c575fcc..0000000000
--- a/changes/ticket28970
+++ /dev/null
@@ -1,6 +0,0 @@
- o Minor bugfixes (clietn, hidden service v3):
- - Fix a BUG() assertion that occurs within a very small race window between
- a client intro circuit opens and its descriptor that gets cleaned up from
- the cache. The circuit is now closed which will trigger a re-fetch of the
- descriptor and continue the HS connection. Fixes bug 28970; bugfix on
- 0.3.2.1-alpha.
diff --git a/changes/ticket29669 b/changes/ticket29669
deleted file mode 100644
index f7e98a16ce..0000000000
--- a/changes/ticket29669
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor feature (hidden service, control port):
- - The ADD_ONION key blob keyword "BEST" now defaults from RSA1024 (v2) to
- ED25519-V3 (v3). Closes ticket 29669.
diff --git a/changes/ticket30860 b/changes/ticket30860
deleted file mode 100644
index b946f735c4..0000000000
--- a/changes/ticket30860
+++ /dev/null
@@ -1,3 +0,0 @@
- o Testing:
- - Run the chutney IPv6 networks as part of Travis CI.
- Closes ticket 30860.
diff --git a/changes/ticket31091 b/changes/ticket31091
deleted file mode 100644
index 3cb9a2c37b..0000000000
--- a/changes/ticket31091
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (pluggable transports):
- - Remove overly strict assertions that triggers when a pluggable transport
- is spawned in an unsuccessful manner. Fixes bug 31091; bugfix on 0.4.0.1-alpha.
diff --git a/changes/ticket31189 b/changes/ticket31189
deleted file mode 100644
index 318941c794..0000000000
--- a/changes/ticket31189
+++ /dev/null
@@ -1,3 +0,0 @@
- o Documentation:
- - Correct the description of "GuardLifetime". Fixes bug 31189; bugfix on
- 0.3.0.1-alpha.
diff --git a/changes/ticket31548 b/changes/ticket31548
deleted file mode 100644
index fef0b5d01f..0000000000
--- a/changes/ticket31548
+++ /dev/null
@@ -1,7 +0,0 @@
- o Major bugfixes (hidden service v3):
- - Make onion service always use the exact amount of configured intro points
- (or less due to node exlusion). Before, a service could sometimes pick
- more intro points than configured with the
- HiddenServiceNumIntroductionPoints option. Fixes bug 31548; bugfix on
- 0.3.2.1-alpha.
-
diff --git a/changes/ticket31682 b/changes/ticket31682
deleted file mode 100644
index 9777dec1f3..0000000000
--- a/changes/ticket31682
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (hidden service v3, coverity):
- - Fix an implicit conversion from ssize_t to size_t discovered by Coverity.
- Fixes bug 31682; bugfix on 0.4.2.1-alpha.
diff --git a/changes/ticket31841 b/changes/ticket31841
deleted file mode 100644
index 6e7fbc1da1..0000000000
--- a/changes/ticket31841
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor features (testing):
- - When running tests that attempt to look up hostname, replace the libc
- name lookup functions with ones that do not actually touch the network.
- This way, the tests complete more quickly in the presence of a slow or
- missing DNS resolver. Closes ticket 31841.
diff --git a/changes/ticket31859 b/changes/ticket31859
deleted file mode 100644
index dbc591e00b..0000000000
--- a/changes/ticket31859
+++ /dev/null
@@ -1,3 +0,0 @@
- o Testing:
- - Simplify the Travis CI build matrix, and optimise for build time.
- Closes ticket 31859.
diff --git a/changes/ticket31919_bionic b/changes/ticket31919_bionic
deleted file mode 100644
index eb41644555..0000000000
--- a/changes/ticket31919_bionic
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor features (continuous integration):
- - Use Ubuntu Bionic images for our Travis CI builds, so we can get
- a recent version of coccinelle. But leave chutney on Ubuntu Trusty,
- until we can fix some Bionic permissions issues (see ticket 32240).
- Related to ticket 31919.
diff --git a/changes/ticket31958 b/changes/ticket31958
deleted file mode 100644
index 8206064dfe..0000000000
--- a/changes/ticket31958
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor bugfixes (directory):
- - When checking if a directory connection is anonymous, test if the circuit
- was marked for close before looking at its channel. This avoids a BUG()
- stacktrace in case it was previously closed. Fixes bug 31958; bugfix on
- 0.4.2.1-alpha.
diff --git a/changes/ticket32058 b/changes/ticket32058
deleted file mode 100644
index b40bcda416..0000000000
--- a/changes/ticket32058
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor bugfixes (mainloop, periodic events):
- - Periodic events enabled flag was not unset properly when shutting down tor
- cleanly. This had the side effect to not re-enable periodic events when
- tor_api.h is used to relaunch tor after a shutdown. Fixes bug 32058;
- bugfix on 0.3.3.1-alpha.
diff --git a/changes/ticket32063 b/changes/ticket32063
deleted file mode 100644
index 2c0246917c..0000000000
--- a/changes/ticket32063
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor bugfixes (hs-v3, memory leak):
- - Fix memory leak in unlikely error code path when encoding HS DoS establish
- intro extension cell. Fixes bug 32063; bugfix on 0.4.2.1-alpha.
diff --git a/changes/ticket32086 b/changes/ticket32086
deleted file mode 100644
index b9312c2bea..0000000000
--- a/changes/ticket32086
+++ /dev/null
@@ -1,3 +0,0 @@
- o Testing:
- - Use Windows Server 2019 instead of Windows Server 2016 in our
- Appveyor builds. Closes ticket 32086.
diff --git a/changes/ticket32191 b/changes/ticket32191
deleted file mode 100644
index 6988328115..0000000000
--- a/changes/ticket32191
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor features (build system):
- - Make pkg-config use --prefix when cross-compiling, if PKG_CONFIG_PATH
- is not set. Closes ticket 32191.
diff --git a/changes/ticket32240 b/changes/ticket32240
deleted file mode 100644
index 35cc3df27e..0000000000
--- a/changes/ticket32240
+++ /dev/null
@@ -1,4 +0,0 @@
- o Testing:
- - Turn off Tor's Sandbox in Chutney jobs, and run those jobs on Ubuntu
- Bionic. Turning off the Sandbox is a work-around, until we fix the
- sandbox errors in 32722. Closes ticket 32240.
diff --git a/changes/ticket32241 b/changes/ticket32241
deleted file mode 100644
index 4243cec175..0000000000
--- a/changes/ticket32241
+++ /dev/null
@@ -1,2 +0,0 @@
- o Testing (continuous integration):
- - In Travis, use Xcode 11.2 on macOS 10.14. Closes ticket 32241.
diff --git a/changes/ticket32242 b/changes/ticket32242
deleted file mode 100644
index d63d5a586e..0000000000
--- a/changes/ticket32242
+++ /dev/null
@@ -1,2 +0,0 @@
- o Testing (continuous integration):
- - Use zstd in our Travis Linux builds. Closes ticket 32242.
diff --git a/changes/ticket32407 b/changes/ticket32407
deleted file mode 100644
index badb09abfe..0000000000
--- a/changes/ticket32407
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes (crash):
- - When running Tor with an option like --verify-config or --dump-config
- that does not start the event loop, avoid crashing if we try to exit
- early because of an error. Fixes bug 32407; bugfix on 0.3.3.1-alpha.
diff --git a/changes/ticket32500 b/changes/ticket32500
deleted file mode 100644
index 2c0f35df72..0000000000
--- a/changes/ticket32500
+++ /dev/null
@@ -1,5 +0,0 @@
- o Testing:
- - Require C99 standards-conforming code in Travis CI, but allow GNU gcc
- extensions. Also activates clang's -Wtypedef-redefinition warnings.
- Build some jobs with -std=gnu99, and some jobs without.
- Closes ticket 32500.
diff --git a/changes/ticket32629 b/changes/ticket32629
deleted file mode 100644
index 740746c572..0000000000
--- a/changes/ticket32629
+++ /dev/null
@@ -1,4 +0,0 @@
- o Testing:
- - Re-enable the Travis CI macOS Chutney build, but allow the job to finish
- before it finishes, because the Travis macOS jobs are slow.
- Closes ticket 32629.
diff --git a/changes/ticket32672 b/changes/ticket32672
new file mode 100644
index 0000000000..351329ba2e
--- /dev/null
+++ b/changes/ticket32672
@@ -0,0 +1,4 @@
+ o Minor features (directory authorities):
+ - Directory authorities now reject descriptors from relays running Tor
+ versions from the 0.2.9 and 0.4.0 series, but still allow the 0.3.5
+ series. Resolves ticket 32672. Patch by Neel Chauhan.
diff --git a/changes/ticket32705_disable b/changes/ticket32705_disable
deleted file mode 100644
index 6d5b0779ab..0000000000
--- a/changes/ticket32705_disable
+++ /dev/null
@@ -1,7 +0,0 @@
- o Minor bugfixes (testing):
- - When TOR_DISABLE_PRACTRACKER is set, do not apply it to the
- test_practracker.sh script. Doing so caused a test failure.
- Fixes bug 32705; bugfix on 0.4.2.1-alpha.
- - When TOR_DISABLE_PRACTRACKER is set, log a notice to stderr
- when skipping practracker checks.
- Fixes bug 32705; bugfix on 0.4.2.1-alpha.
diff --git a/changes/ticket32765 b/changes/ticket32765
deleted file mode 100644
index a9663a5df3..0000000000
--- a/changes/ticket32765
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes (correctness checks):
- - Use GCC/Clang's printf-checking feature to make sure that
- tor_assertf() arguments are correctly typed. Fixes bug 32765;
- bugfix on 0.4.1.1-alpha.
diff --git a/changes/ticket33075 b/changes/ticket33075
deleted file mode 100644
index 69698d90b3..0000000000
--- a/changes/ticket33075
+++ /dev/null
@@ -1,4 +0,0 @@
- o Testing:
- - Stop allowing failures on the Travis CI stem tests job. It looks like all
- the stem hangs we were seeing are now fixed, but let's make sure we see
- them if they happen again. Closes ticket 33075.
diff --git a/changes/ticket33188 b/changes/ticket33188
new file mode 100644
index 0000000000..7bec15b99b
--- /dev/null
+++ b/changes/ticket33188
@@ -0,0 +1,5 @@
+ o Documentation (manpage):
+ - Alphabetize the Server and Directory server sections of the tor
+ manpage. Also split Statistics options into their own section
+ of the manpage. Closes ticket 33188. Work by Swati Thacker as
+ part of Google Season of Docs.
diff --git a/changes/ticket33212 b/changes/ticket33212
deleted file mode 100644
index aeb09e0c67..0000000000
--- a/changes/ticket33212
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes (rust, build):
- - Fix a syntax warning given by newer versions of Rust, and creating
- problems for our continuous integration.
- Fixes bug 33212; bugfix on 0.3.5.1-alpha.
diff --git a/changes/ticket33213 b/changes/ticket33213
new file mode 100644
index 0000000000..f1da591bd1
--- /dev/null
+++ b/changes/ticket33213
@@ -0,0 +1,3 @@
+ o Minor bugfixes (continuous integration):
+ - Remove the buggy and unused mirroring job. Fixes bug 33213;
+ bugfix on 0.3.2.2-alpha.
diff --git a/changes/ticket33458 b/changes/ticket33458
new file mode 100644
index 0000000000..885c6dc505
--- /dev/null
+++ b/changes/ticket33458
@@ -0,0 +1,4 @@
+ o Minor bugfix (onion service v3):
+ - When cleaning the client descriptor cache, an attempt at closing circuits
+ for a non decrypted descriptor (lacking client authorization) lead to an
+ assert(). Fixes bug 33458; bugfix on 0.4.2.1-alpha.
diff --git a/changes/ticket33460 b/changes/ticket33460
new file mode 100644
index 0000000000..21e0fc966c
--- /dev/null
+++ b/changes/ticket33460
@@ -0,0 +1,4 @@
+ o Minor features (usability):
+ - Include more information when failing to parse a configuration value.
+ This should make it easier to tell what's going wrong when a
+ configuration file doesn't parse. Closes ticket 33460.
diff --git a/changes/ticket33646 b/changes/ticket33646
new file mode 100644
index 0000000000..751c5d5bf2
--- /dev/null
+++ b/changes/ticket33646
@@ -0,0 +1,4 @@
+ o Minor bugfixes (build system):
+ - Correctly output the enabled module in the configure summary. Before that,
+ the list shown was just plain wrong. Fixes bug 33646; bugfix on
+ 0.4.3.2-alpha.
diff --git a/changes/ticket33678_043 b/changes/ticket33678_043
new file mode 100644
index 0000000000..12316262fd
--- /dev/null
+++ b/changes/ticket33678_043
@@ -0,0 +1,3 @@
+ o Code simplification and refactoring:
+ - Disable our coding standards best practices tracker in our git hooks.
+ (0.4.3 branches only.) Closes ticket 33678.
diff --git a/changes/ticket33804 b/changes/ticket33804
new file mode 100644
index 0000000000..254246dacf
--- /dev/null
+++ b/changes/ticket33804
@@ -0,0 +1,7 @@
+ o Minor bugfixes (client, SocksPort, IPv6):
+ - Revert PreferIPv6 set by default on the SocksPort because it brokes the
+ torsocks use case. Tor doesn't have a way for an application to request
+ the hostname to be resolved for a specific IP version but torsocks
+ requires that. Up until now, IPv4 was used by default so it is expecting
+ that, and can't handle a possible IPv6 being returned. Fixes bug 33804;
+ bugfix on 0.4.3.1-alpha.
diff --git a/changes/ticket34255_043 b/changes/ticket34255_043
new file mode 100644
index 0000000000..5cfec1d48d
--- /dev/null
+++ b/changes/ticket34255_043
@@ -0,0 +1,3 @@
+ o Documentation:
+ - Fix several doxygen warnings related to imbalanced groups.
+ Closes ticket 34255.
diff --git a/changes/ticket40030 b/changes/ticket40030
new file mode 100644
index 0000000000..c5f3ca4ff9
--- /dev/null
+++ b/changes/ticket40030
@@ -0,0 +1,7 @@
+ o Removed features:
+ - Our "check-local" test target no longer tries to use the Coccinelle
+ semantic patching tool parse all the C files. While it is a good idea
+ to try to make sure Coccinelle works on our C before we run a
+ Coccinelle patch, doing so on every test run has proven to be disruptive.
+ You can still run this tool manually with "make check-cocci". Closes
+ ticket 40030.
diff --git a/configure.ac b/configure.ac
index af143e44ad..e28f957d03 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,17 +4,19 @@ dnl Copyright (c) 2007-2019, The Tor Project, Inc.
dnl See LICENSE for licensing information
AC_PREREQ([2.63])
-AC_INIT([tor],[0.4.2.8-dev])
+AC_INIT([tor],[0.4.3.6-dev])
AC_CONFIG_SRCDIR([src/app/main/tor_main.c])
AC_CONFIG_MACRO_DIR([m4])
+configure_flags="$*"
+
# DO NOT EDIT THIS DEFINITION BY HAND UNLESS YOU KNOW WHAT YOU'RE DOING.
#
# The update_versions.py script updates this definition when the
# version number changes. Tor uses it to make sure that it
# only shuts down for missing "required protocols" when those protocols
# are listed as required by a consensus after this date.
-AC_DEFINE(APPROX_RELEASE_DATE, ["2020-07-09"], # for 0.4.2.8-dev
+AC_DEFINE(APPROX_RELEASE_DATE, ["2020-07-09"], # for 0.4.3.6-dev
[Approximate date when this software was released. (Updated when the version changes.)])
# "foreign" means we don't follow GNU package layout standards
@@ -79,6 +81,24 @@ AC_ARG_ENABLE(nss,
AC_ARG_ENABLE(pic,
AS_HELP_STRING(--enable-pic, [Build Tor's binaries as position-independent code, suitable to link as a library.]))
+AC_ARG_ENABLE(missing-doc-warnings,
+ AS_HELP_STRING(--enable-missing-doc-warnings, [Tell doxygen to warn about missing documentation. Makes doxygen warnings nonfatal.]))
+
+if test "$enable_missing_doc_warnings" = "yes"; then
+ DOXYGEN_FATAL_WARNINGS=NO
+ DOXYGEN_WARN_ON_MISSING=YES
+elif test "$enable_fatal_warnings" = "yes"; then
+ # Fatal warnings from doxygen are nice, but not if we're warning about
+ # missing documentation.
+ DOXYGEN_FATAL_WARNINGS=YES
+ DOXYGEN_WARN_ON_MISSING=NO
+else
+ DOXYGEN_FATAL_WARNINGS=NO
+ DOXYGEN_WARN_ON_MISSING=NO
+fi
+AC_SUBST(DOXYGEN_FATAL_WARNINGS)
+AC_SUBST(DOXYGEN_WARN_ON_MISSING)
+
if test "x$enable_coverage" != "xyes" -a "x$enable_asserts_in_tests" = "xno" ; then
AC_MSG_ERROR([Can't disable assertions outside of coverage build])
fi
@@ -258,13 +278,30 @@ dnl Tor modules options. These options are namespaced with --disable-module-XXX
dnl ---
dnl All our modules.
-m4_define(MODULES, dirauth)
+m4_define(MODULES, relay dirauth dircache)
+
+dnl Relay module.
+AC_ARG_ENABLE([module-relay],
+ AS_HELP_STRING([--disable-module-relay],
+ [Build tor without the Relay modules: tor can not run as a relay, bridge, or authority. Implies --disable-module-dirauth]))
+AM_CONDITIONAL(BUILD_MODULE_RELAY, [test "x$enable_module_relay" != "xno"])
+AM_COND_IF(BUILD_MODULE_RELAY,
+ AC_DEFINE([HAVE_MODULE_RELAY], [1],
+ [Compile with Relay feature support]))
+
+dnl Dircache module. (This cannot be enabled or disabled independently of
+dnl the relay module. It is not listed by --list-modules for this reason.)
+AM_CONDITIONAL(BUILD_MODULE_DIRCACHE,
+ [test "x$enable_module_relay" != "xno"])
+AM_COND_IF(BUILD_MODULE_DIRCACHE,
+ AC_DEFINE([HAVE_MODULE_DIRCACHE], [1],
+ [Compile with directory cache support]))
dnl Directory Authority module.
AC_ARG_ENABLE([module-dirauth],
AS_HELP_STRING([--disable-module-dirauth],
[Build tor without the Directory Authority module: tor can not run as a directory authority or bridge authority]))
-AM_CONDITIONAL(BUILD_MODULE_DIRAUTH,[test "x$enable_module_dirauth" != "xno"])
+AM_CONDITIONAL(BUILD_MODULE_DIRAUTH,[test "x$enable_module_dirauth" != "xno" && test "x$enable_module_relay" != "xno"])
AM_COND_IF(BUILD_MODULE_DIRAUTH,
AC_DEFINE([HAVE_MODULE_DIRAUTH], [1],
[Compile with Directory Authority feature support]))
@@ -323,15 +360,20 @@ AM_CONDITIONAL(BUILD_HTML_DOCS, [test "x$enable_html_manual" != "xno"])
AM_PROG_CC_C_O
AC_PROG_CC_C99
-AC_ARG_VAR([PYTHON], [path to Python binary])
-AC_CHECK_PROGS(PYTHON, [ \
+AC_CACHE_CHECK([for Python 3], [tor_cv_PYTHON],
+ [AC_PATH_PROGS_FEATURE_CHECK([PYTHON], [ \
python3 \
python3.8 python3.7 python3.6 python3.5 python3.4 \
- python \
- python2 python2.7])
+ python ],
+ [["$ac_path_PYTHON" -c 'import sys; sys.exit(sys.version_info[0]<3)' && tor_cv_PYTHON="$ac_path_PYTHON" ac_path_PYTHON_found=:]] )])
+AC_SUBST([PYTHON], [$tor_cv_PYTHON])
+
+PYTHON="$tor_cv_PYTHON"
+
if test "x$PYTHON" = "x"; then
- AC_MSG_WARN([Python unavailable; some tests will not be run.])
+ AC_MSG_WARN([Python 3 unavailable; some tests will not be run.])
fi
+
AM_CONDITIONAL(USEPYTHON, [test "x$PYTHON" != "x"])
dnl List all external rust crates we depend on here. Include the version
@@ -623,6 +665,7 @@ AC_CHECK_FUNCS(
explicit_bzero \
timingsafe_memcmp \
flock \
+ fsync \
ftime \
get_current_dir_name \
getaddrinfo \
@@ -1090,10 +1133,10 @@ dnl Where we do we find lzma?
AC_ARG_ENABLE(lzma,
AS_HELP_STRING(--enable-lzma, [enable support for the LZMA compression scheme.]),
[case "${enableval}" in
- "yes") lzma=true ;;
- "no") lzma=false ;;
+ "yes") ;;
+ "no") ;;
* ) AC_MSG_ERROR(bad value for --enable-lzma) ;;
- esac], [lzma=auto])
+ esac], [enable_lzma=auto])
if test "x$enable_lzma" = "xno"; then
have_lzma=no;
@@ -1122,10 +1165,10 @@ dnl Where we do we find zstd?
AC_ARG_ENABLE(zstd,
AS_HELP_STRING(--enable-zstd, [enable support for the Zstandard compression scheme.]),
[case "${enableval}" in
- "yes") zstd=true ;;
- "no") zstd=false ;;
+ "yes") ;;
+ "no") ;;
* ) AC_MSG_ERROR(bad value for --enable-zstd) ;;
- esac], [zstd=auto])
+ esac], [enable_zstd=auto])
if test "x$enable_zstd" = "xno"; then
have_zstd=no;
@@ -2546,3 +2589,141 @@ https://trac.torproject.org/projects/tor/wiki/doc/TorFragileHardening
fi
AC_OUTPUT
+
+#
+# Mini-report on what will be built.
+#
+
+PPRINT_INIT
+PPRINT_SET_INDENT(1)
+PPRINT_SET_TS(65)
+
+AS_ECHO
+AS_ECHO("Tor Version: ${PPRINT_COLOR_BLDBLU}Tor $PACKAGE_VERSION $PPRINT_COLOR_RST")
+AS_ECHO
+
+PPRINT_SUBTITLE([Build Features])
+
+PPRINT_PROP_STRING([Compiler], [$CC])
+PPRINT_PROP_STRING([Host OS], [$host_os])
+AS_ECHO
+
+test "x$enable_fatal_warnings" = "xyes" && value=1 || value=0
+PPRINT_PROP_BOOL([Warnings are fatal (--enable-fatal-warnings)], $value)
+
+test "x$enable_rust" = "xyes" && value=1 || value=0
+PPRINT_PROP_BOOL([Rust support (--enable-rust)], $value)
+
+test "x$enable_cargo_online_mode" = "xyes" && value=1 || value=0
+PPRINT_PROP_BOOL([Cargo Online Fetch (--enable-cargo-online-mode)], $value)
+
+test "x$enable_android" = "xyes" && value=1 || value=0
+PPRINT_PROP_BOOL([Android support (--enable-android)], $value)
+
+AS_ECHO
+PPRINT_SUBTITLE([Static Build])
+
+test "x$enable_static_tor" = "xyes" && value=1 || value=0
+PPRINT_PROP_BOOL([tor (--enable-static-tor)], $value)
+
+if test "x$enable_static_libevent" = "xyes"; then
+ PPRINT_PROP_STRING([libevent], [$TOR_LIBDIR_libevent])
+else
+ PPRINT_PROP_BOOL([libevent (--enable-static-libevent)], $value)
+fi
+
+if test "x$enable_static_openssl" = "xyes"; then
+ PPRINT_PROP_STRING([libssl], [$TOR_LIBDIR_openssl])
+else
+ PPRINT_PROP_BOOL([libssl (--enable-static-openssl)], $value)
+fi
+
+if test "x$enable_static_zlib" = "xyes"; then
+ PPRINT_PROP_STRING([zlib1g], [$TOR_LIBDIR_zlib])
+else
+ PPRINT_PROP_BOOL([zlib1g (--enable-static-zlib)], $value)
+fi
+
+AS_ECHO
+PPRINT_SUBTITLE([Optional Libraries])
+
+test "x$enable_nss" = "xyes" && value=1 || value=0
+PPRINT_PROP_BOOL([libnss (--enable-nss)], $value)
+
+test "x$enable_seccomp" != "xno" && value=1 || value=0
+PPRINT_PROP_BOOL([libseccomp (--disable-seccomp)], $value)
+
+test "x$enable_libscrypt" != "xno" && value=1 || value=0
+PPRINT_PROP_BOOL([libscrypt (--disable-libscrypt)], $value)
+
+test "x$enable_systemd" = "xyes" && value=1 || value=0
+PPRINT_PROP_BOOL([Systemd support (--enable-systemd)], $value)
+
+test "x$enable_lzma" = "xyes" && value=1 || value=0
+PPRINT_PROP_BOOL([liblzma (--enable-lzma)], $value)
+
+test "x$enable_zstd" = "xyes" && value=1 || value=0
+PPRINT_PROP_BOOL([libzstd (--enable-zstd)], $value)
+
+AS_ECHO
+PPRINT_SUBTITLE([Hardening])
+
+test "x$enable_gcc_hardening" != "xno" && value=1 || value=0
+PPRINT_PROP_BOOL([Compiler Hardening (--disable-gcc-hardening)], $value)
+
+test "x$enable_linker_hardening" != "xno" && value=1 || value=0
+PPRINT_PROP_BOOL([Linker Hardening (--disable-linker-hardening)], $value)
+
+test "x$fragile_hardening" = "xyes" && value=1 || value=0
+PPRINT_PROP_BOOL([Fragile Hardening (--enable-fragile-hardening, dev only)], $value)
+
+AS_ECHO
+PPRINT_SUBTITLE([Modules])
+
+m4_foreach_w([mname], MODULES,
+ [
+ AM_COND_IF(m4_join([], [BUILD_MODULE_], m4_toupper([]mname[])), value=1, value=0)
+ PPRINT_PROP_BOOL([mname (--disable-module-mname)], $value)
+ ]
+)
+
+AS_ECHO
+PPRINT_SUBTITLE([Documentation])
+
+test "x$enable_asciidoc" != "xno" && value=1 || value=0
+PPRINT_PROP_BOOL([AsciiDoc (--disable-asciidoc)], $value)
+
+test "x$enable_manpage" != "xno" && value=1 || value=0
+PPRINT_PROP_BOOL([Man Pages (--disable-manpage)], $value)
+
+test "x$enable_html_manual" != "xno" && value=1 || value=0
+PPRINT_PROP_BOOL([HTML Manual (--disable-html-manual)], $value)
+
+AS_ECHO
+PPRINT_SUBTITLE([Tests])
+
+test "x$enable_unittests" != "xno" && value=1 || value=0
+PPRINT_PROP_BOOL([Unit tests (--disable-unittests)], $value)
+
+test "x$enable_asserts_in_tests" = "xno" && value=1 || value=0
+PPRINT_PROP_BOOL([assert()s enabled (--enable-asserts-in-tests, dev only)], $value)
+
+test "x$enable_coverage" = "xyes" && value=1 || value=0
+PPRINT_PROP_BOOL([Code Coverage (--enable-coverage)], $value)
+
+test "x$enable_libfuzzer" = "xyes" && value=1 || value=0
+PPRINT_PROP_BOOL([libFuzzer support (--enable-libfuzzer)], $value)
+
+test "x$enable_oss_fuzz" = "xyes" && value=1 || value=0
+PPRINT_PROP_BOOL([OSS-Fuzz support (--enable-oss-fuzz)], $value)
+
+AS_ECHO
+PPRINT_SUBTITLE([Install Directories])
+
+report_mandir="`eval eval echo $mandir`"
+PPRINT_PROP_STRING([Binaries], [$BINDIR])
+PPRINT_PROP_STRING([Configuration], [$CONFDIR])
+PPRINT_PROP_STRING([Man Pages], [$report_mandir])
+
+AS_ECHO
+AS_ECHO(["Configure Line: ./configure $configure_flags"])
diff --git a/contrib/client-tools/tor-resolve.py b/contrib/client-tools/tor-resolve.py
index 47ae1a0c38..3562193715 100755
--- a/contrib/client-tools/tor-resolve.py
+++ b/contrib/client-tools/tor-resolve.py
@@ -1,5 +1,10 @@
#!/usr/bin/python
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import socket
import struct
import sys
@@ -82,7 +87,7 @@ def parseHostAndPort(h):
try:
port = int(h[i+1:])
except ValueError:
- print "Bad hostname %r"%h
+ print("Bad hostname %r"%h)
sys.exit(1)
elif h:
try:
@@ -118,15 +123,15 @@ def resolve(hostname, sockshost, socksport, socksver=4, reverse=0):
return None
answer += more
result = parse(answer)
- print "Got answer",result
+ print("Got answer",result)
m = s.recv(1)
if m:
- print "Got extra data too: %r"%m
+ print("Got extra data too: %r"%m)
return result
if __name__ == '__main__':
if len(sys.argv) not in (2,3,4):
- print "Syntax: resolve.py [-4|-5] hostname [sockshost:socksport]"
+ print("Syntax: resolve.py [-4|-5] hostname [sockshost:socksport]")
sys.exit(0)
socksver = 4
reverse = 0
@@ -141,7 +146,7 @@ if __name__ == '__main__':
break
if len(sys.argv) >= 4:
- print "Syntax: resolve.py [-x] [-4|-5] hostname [sockshost:socksport]"
+ print("Syntax: resolve.py [-x] [-4|-5] hostname [sockshost:socksport]")
sys.exit(0)
if len(sys.argv) == 3:
sh,sp = parseHostAndPort(sys.argv[2])
diff --git a/contrib/win32build/tor-mingw.nsi.in b/contrib/win32build/tor-mingw.nsi.in
index ababaa38fc..f1de58e70f 100644
--- a/contrib/win32build/tor-mingw.nsi.in
+++ b/contrib/win32build/tor-mingw.nsi.in
@@ -8,7 +8,7 @@
!include "LogicLib.nsh"
!include "FileFunc.nsh"
!insertmacro GetParameters
-!define VERSION "0.4.2.8-dev"
+!define VERSION "0.4.3.6-dev"
!define INSTALLER "tor-${VERSION}-win32.exe"
!define WEBSITE "https://www.torproject.org/"
!define LICENSE "LICENSE"
diff --git a/doc/HACKING/CircuitPaddingDevelopment.md b/doc/HACKING/CircuitPaddingDevelopment.md
new file mode 100644
index 0000000000..a4e65697b8
--- /dev/null
+++ b/doc/HACKING/CircuitPaddingDevelopment.md
@@ -0,0 +1,1234 @@
+# Circuit Padding Developer Documentation
+
+This document is written for researchers who wish to prototype and evaluate circuit-level padding defenses in Tor.
+
+Written by Mike Perry and George Kadianakis.
+
+# Table of Contents
+
+- [0. Background](#0-background)
+- [1. Introduction](#1-introduction)
+ - [1.1. System Overview](#11-system-overview)
+ - [1.2. Layering Model](#12-layering-model)
+ - [1.3. Computation Model](#13-computation-model)
+ - [1.4. Deployment Constraints](#14-other-deployment-constraints)
+- [2. Creating New Padding Machines](#2-creating-new-padding-machines)
+ - [2.1. Registering a New Padding Machine](#21-registering-a-new-padding-machine)
+ - [2.2. Machine Activation and Shutdown](#22-machine-activation-and-shutdown)
+- [3. Specifying Padding Machines](#3-specifying-padding-machines)
+ - [3.1. Padding Machine States](#31-padding-machine-states)
+ - [3.2. Padding Machine State Transitions](#32-padding-machine-state-transitions)
+ - [3.3. Specifying Per-State Padding](#33-specifying-per-state-padding)
+ - [3.4. Specifying Precise Cell Counts](#34-specifying-precise-cell-counts)
+ - [3.5. Specifying Overhead Limits](#35-specifying-overhead-limits)
+- [4. Evaluating Padding Machines](#4-evaluating-padding-machines)
+ - [4.1. Pure Simulation](#41-pure-simulation)
+ - [4.2. Testing in Chutney](#42-testing-in-chutney)
+ - [4.3. Testing in Shadow](#43-testing-in-shadow)
+ - [4.4. Testing on the Live Network](#44-testing-on-the-live-network)
+- [5. Example Padding Machines](#5-example-padding-machines)
+ - [5.1. Deployed Circuit Setup Machines](#51-deployed-circuit-setup-machines)
+ - [5.2. Adaptive Padding Early](#52-adaptive-padding-early)
+ - [5.3. Sketch of Tamaraw](#53-sketch-of-tamaraw)
+ - [5.4. Other Padding Machines](#54-other-padding-machines)
+- [6. Framework Implementation Details](#6-framework-implementation-details)
+ - [6.1. Memory Allocation Conventions](#61-memory-allocation-conventions)
+ - [6.2. Machine Application Events](#62-machine-application-events)
+ - [6.3. Internal Machine Events](#63-internal-machine-events)
+- [7. Future Features and Optimizations](#7-future-features-and-optimizations)
+ - [7.1. Load Balancing and Flow Control](#71-load-balancing-and-flow-control)
+ - [7.2. Timing and Queuing Optimizations](#72-timing-and-queuing-optimizations)
+ - [7.3. Better Machine Negotiation](#73-better-machine-negotiation)
+ - [7.4. Probabilistic State Transitions](#74-probabilistic-state-transitions)
+ - [7.5. More Complex Pattern Recognition](#75-more-complex-pattern-recognition)
+- [8. Open Research Problems](#8-open-research-problems)
+ - [8.1. Onion Service Circuit Setup](#81-onion-service-circuit-setup)
+ - [8.2. Onion Service Fingerprinting](#82-onion-service-fingerprinting)
+ - [8.3. Open World Fingerprinting](#83-open-world-fingerprinting)
+ - [8.4. Protocol Usage Fingerprinting](#84-protocol-usage-fingerprinting)
+ - [8.5. Datagram Transport Side Channels](#85-datagram-transport-side-channels)
+- [9. Must Read Papers](#9-must-read-papers)
+
+
+## 0. Background
+
+Tor supports both connection-level and circuit-level padding, and both
+systems are live on the network today. The connection-level padding behavior
+is described in [section 2 of
+padding-spec.txt](https://github.com/torproject/torspec/blob/master/padding-spec.txt#L47). The
+circuit-level padding behavior is described in [section 3 of
+padding-spec.txt](https://github.com/torproject/torspec/blob/master/padding-spec.txt#L282).
+
+These two systems are orthogonal and should not be confused. The
+connection-level padding system is only active while the TLS connection is
+otherwise idle. Moreover, it regards circuit-level padding as normal data
+traffic, and hence while the circuit-level padding system is actively padding,
+the connection-level padding system will not add any additional overhead.
+
+While the currently deployed circuit-level padding behavior is quite simple,
+it is built on a flexible framework. This framework supports the description
+of event-driven finite state machine by filling in fields of a simple C
+structure, and is designed to support any delay-free statistically shaped
+cover traffic on individual circuits, with cover traffic flowing to and from a
+node of the implementor's choice (Guard, Middle, Exit, Rendezvous, etc).
+
+This class of system was first proposed in
+[Timing analysis in low-latency mix networks: attacks and defenses](https://www.freehaven.net/anonbib/cache/ShWa-Timing06.pdf)
+by Shmatikov and Wang, and extended for the website traffic fingerprinting
+domain by Juarez et al. in
+[Toward an Efficient Website Fingerprinting Defense](http://arxiv.org/pdf/1512.00524). The
+framework also supports fixed parameterized probability distributions, as
+used in [APE](https://www.cs.kau.se/pulls/hot/thebasketcase-ape/) by Tobias
+Pulls, and many other features.
+
+This document describes how to use Tor's circuit padding framework to
+implement and deploy novel delay-free cover traffic defenses.
+
+## 1. Introduction
+
+The circuit padding framework is the official way to implement padding
+defenses in Tor. It may be used in combination with application-layer
+defenses, and/or obfuscation defenses, or on its own.
+
+Its current design should be enough to deploy most defenses without
+modification, but you can extend it to [provide new
+features](#7-future-features-and-optimizations) as well.
+
+### 1.1. System Overview
+
+Circuit-level padding can occur between Tor clients and relays at any hop of
+one of the client's circuits. Both parties need to support the same padding
+mechanisms for the system to work, and the client must enable it.
+
+We added a padding negotiation relay cell to the Tor protocol that clients use
+to ask a relay to start padding, as well as a torrc directive for researchers
+to pin their clients' relay selection to the subset of Tor nodes that
+implement their custom defenses, to support ethical live network testing and
+evaluation.
+
+Circuit-level padding is performed by 'padding machines'. A padding machine is
+a finite state machine. Every state specifies a different form of
+padding style, or stage of padding, in terms of inter-packet timings and total
+packet counts.
+
+Padding state machines are specified by filling in fields of a C structure,
+which specifies the transitions between padding states based on various events,
+probability distributions of inter-packet delays, and the conditions under
+which padding machines should be applied to circuits.
+
+This compact C structure representation is designed to function as a
+microlanguage, which can be compiled down into a
+bitstring that [can be tuned](#13-computation-model) using various
+optimization methods (such as gradient descent, GAs, or GANs), either in
+bitstring form or C struct form.
+
+The event driven, self-contained nature of this framework is also designed to
+make [evaluation](#4-evaluating-padding-machines) both expedient and rigorously
+reproducible.
+
+This document covers the engineering steps to write, test, and deploy a
+padding machine, as well as how to extend the framework to support new machine
+features.
+
+If you prefer to learn by example, you may want to skip to either the
+[QuickStart Guide](CircuitPaddingQuickStart.md), and/or [Section
+5](#5-example-padding-machines) for example machines to get you up and running
+quickly.
+
+### 1.2. Layering Model
+
+The circuit padding framework is designed to provide one layer in a layered
+system of interchangeable components.
+
+The circuit padding framework operates at the Tor circuit layer. It only deals
+with the inter-cell timings and quantity of cells sent on a circuit. It can
+insert cells on a circuit in arbitrary patterns, and in response to arbitrary
+conditions, but it cannot delay cells. It also does not deal with packet
+sizes, how cells are packed into TLS records, or ways that the Tor protocol
+might be recognized on the wire.
+
+The problem of differentiating Tor traffic from non-Tor traffic based on
+TCP/TLS packet sizes, initial handshake patterns, and DPI characteristics is the
+domain of [pluggable
+transports](https://trac.torproject.org/projects/tor/wiki/doc/AChildsGardenOfPluggableTransports),
+which may optionally be used in conjunction with this framework (or without
+it).
+
+This document focuses primarily on the circuit padding framework's cover
+traffic features, and will only briefly touch on the potential obfuscation and
+application layer coupling points of the framework. Explicit layer coupling
+points can be created by adding either new [machine application
+events](#62-machine-application-events) or new [internal machine
+events](#63-internal-machine-events) to the circuit padding framework, so that
+your padding machines can react to events from other layers.
+
+### 1.3. Computation Model
+
+The circuit padding framework is designed to support succinctly specified
+defenses that can be tuned through [computer-assisted
+optimization](#4-evaluating-padding-machines).
+
+We chose to generalize the original [Adaptive Padding 2-state
+design](https://www.freehaven.net/anonbib/cache/ShWa-Timing06.pdf) into an
+event-driven state machine because state machines are the simplest form of
+sequence recognition devices from [automata
+theory](https://en.wikipedia.org/wiki/Finite-state_machine).
+
+Most importantly: this framing allows cover traffic defenses to be modeled as
+an optimization problem search space, expressed as fields of a C structure
+(which is simultaneously a compact opaque bitstring as well as a symbolic
+vector in an abstract feature space). This kind of space is particularly well
+suited to search by gradient descent, GAs, and GANs.
+
+When performing this optimization search, each padding machine should have a
+fitness function, which will allow two padding machines to be compared for
+relative effectiveness. Optimization searches work best if this fitness can be
+represented as a single number, for example the total amount by which it
+reduces the [Balanced
+Accuracy](https://en.wikipedia.org/wiki/Precision_and_recall#Imbalanced_Data)
+of an adversary's classifier, divided by an amount of traffic overhead.
+
+Before you begin the optimization phase for your defense, you should
+also carefully consider the [features and
+optimizations](#7-future-features-and-optimizations) that we suspect will be
+useful, and also see if you can come up with any more. You should similarly be
+sure to restrict your search space to avoid areas of the bitstring/feature
+vector that you are sure you will not need. For example, some
+[applications](#8-open-research-problems) may not need the histogram
+accounting used by Adaptive Padding, but might need to add other forms of
+[pattern recognition](#75-more-complex-pattern-recognition) to react to
+sequences that resemble HTTP GET and HTTP POST.
+
+### 1.4. Other Deployment Constraints
+
+The framework has some limitations that are the result of deliberate
+choices. We are unlikely to deploy defenses that ignore these limitations.
+
+In particular, we have deliberately not provided any mechanism to delay actual
+user traffic, even though we are keenly aware that if we were to support
+additional delay, defenses would be able to have [more success with less
+bandwidth
+overhead](https://freedom.cs.purdue.edu/anonymity/trilemma/index.html).
+
+In the website traffic fingerprinting domain, [provably optimal
+defenses](https://www.cypherpunks.ca/~iang/pubs/webfingerprint-ccs14.pdf)
+achieve their bandwidth overhead bounds by ensuring that a non-empty queue is
+maintained, by rate limiting traffic below the actual throughput of a circuit.
+For optimal results, this queue must avoid draining to empty, and yet it
+must also be drained fast enough to avoid tremendous queue overhead in fast
+Tor relays, which carry hundreds of thousands of circuits simultaneously.
+
+Unfortunately, Tor's end-to-end flow control is not congestion control. Its
+window sizes are currently fixed. This means there is no signal when queuing
+occurs, and thus no ability to limit queue size through pushback. This means
+there is currently no way to do the fine-grained queue management necessary to
+create such a queue and rate limit traffic effectively enough to keep this
+queue from draining to empty, without also risking that aggregate queuing
+would cause out-of-memory conditions on fast relays.
+
+It may be possible to create a congestion control algorithm that can support
+such fine grained queue management, but this is a [deeply unsolved area of
+research](https://lists.torproject.org/pipermail/tor-dev/2018-November/013562.html).
+
+Even beyond these major technical hurdles, additional latency is also
+unappealing to the wider Internet community, for the simple reason that
+bandwidth [continues to increase
+exponentially](https://ipcarrier.blogspot.com/2014/02/bandwidth-growth-nearly-what-one-would.html)
+where as the speed of light is fixed. Significant engineering effort has been
+devoted to optimizations that reduce the effect of latency on Internet
+protocols. To go against this trend would ensure our irrelevance to the wider
+conversation about traffic analysis defenses for low latency Internet protocols.
+
+On the other hand, through [load
+balancing](https://gitweb.torproject.org/torspec.git/tree/proposals/265-load-balancing-with-overhead.txt)
+and [circuit multiplexing strategies](https://bugs.torproject.org/29494), we
+believe it is possible to add significant bandwidth overhead in the form of
+cover traffic, without significantly impacting end-user performance.
+
+For these reasons, we believe the trade-off should be in favor of adding more
+cover traffic, rather than imposing queuing memory overhead and queuing delay.
+
+As a last resort for narrowly scoped application domains (such as
+shaping Tor service-side onion service traffic to look like other websites or
+different application-layer protocols), delay *may* be added at the
+[application layer](https://petsymposium.org/2017/papers/issue2/paper54-2017-2-source.pdf).
+Any additional cover traffic required by such defenses should still be
+added at the circuit padding layer using this framework, to provide
+engineering efficiency through loose layer coupling and component re-use, as
+well as to provide additional gains against [low
+resolution](https://github.com/torproject/torspec/blob/master/padding-spec.txt#L47)
+end-to-end traffic correlation.
+
+Because such delay-based defenses will impact performance significantly more
+than simply adding cover traffic, they must be optional, and negotiated by
+only specific application layer endpoints that want them. This will have
+consequences for anonymity sets and base rates, if such traffic shaping and
+additional cover traffic is not very carefully constructed.
+
+In terms of acceptable overhead, because Tor onion services
+[currently use](https://metrics.torproject.org/hidserv-rend-relayed-cells.html)
+less than 1% of the
+[total consumed bandwidth](https://metrics.torproject.org/bandwidth-flags.html)
+of the Tor network, and because onion services exist to provide higher
+security as compared to Tor Exit traffic, they are an attractive target for
+higher-overhead defenses. We encourage researchers to target this use case
+for defenses that require more overhead, and/or for the deployment of
+optional negotiated application-layer delays on either the server or the
+client side.
+
+## 2. Creating New Padding Machines
+
+This section explains how to use the existing mechanisms in Tor to define a
+new circuit padding machine. We assume here that you know C, and are at
+least somewhat familiar with Tor development. For more information on Tor
+development in general, see the other files in doc/HACKING/ in a recent Tor
+distribution.
+
+Again, if you prefer to learn by example, you may want to skip to either the
+[QuickStart Guide](CircuitPaddingQuickStart.md), and/or [Section
+5](#5-example-padding-machines) for example machines to get up and running
+quickly.
+
+To create a new padding machine, you must:
+
+ 1. Define your machine using the fields of a heap-allocated
+ `circpad_machine_spec_t` C structure.
+
+ 2. Register this object in the global list of available padding machines,
+ using `circpad_register_padding_machine()`.
+
+ 3. Ensure that your machine is properly negotiated under your desired
+ circuit conditions.
+
+### 2.1. Registering a New Padding Machine
+
+Again, a circuit padding machine is designed to be specified entirely as a [single
+C structure](#13-computation-model).
+
+Your machine definitions should go into their own functions in
+[circuitpadding_machines.c](https://github.com/torproject/tor/blob/master/src/core/or/circuitpadding_machines.c). For
+details on all of the fields involved in specifying a padding machine, see
+[Section 3](#3-specifying-padding-machines).
+
+You must register your machine in `circpad_machines_init()` in
+[circuitpadding.c](https://github.com/torproject/tor/blob/master/src/core/or/circuitpadding.c). To
+add a new padding machine specification, you must allocate a
+`circpad_machine_spec_t` on the heap with `tor_malloc_zero()`, give it a
+human readable name string, and a machine number equivalent to the number of
+machines in the list, and register the structure using
+`circpad_register_padding_machine()`.
+
+Each machine must have a client instance and a relay instance. Register your
+client-side machine instance in the `origin_padding_machines` list, and your
+relay side machine instance in the `relay_padding_machines` list. Once you
+have registered your instance, you do not need to worry about deallocation;
+this is handled for you automatically.
+
+Both machine lists use registration order to signal machine precedence for a
+given `machine_idx` slot on a circuit. This means that machines that are
+registered last are checked for activation *before* machines that are
+registered first. (This reverse precedence ordering allows us to
+deprecate older machines simply by adding new ones after them.)
+
+### 2.2. Machine Activation and Shutdown
+
+After a machine has been successfully registered with the framework, it will
+be instantiated on any client-side circuits that support it. Only client-side
+circuits may initiate padding machines, but either clients or relays may shut
+down padding machines.
+
+#### 2.2.1. Machine Application Conditions
+
+The
+[circpad_machine_conditions_t conditions field](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding.h#L641)
+of your `circpad_machine_spec_t` machine definition instance controls the
+conditions under which your machine will be attached and enabled on a Tor
+circuit, and when it gets shut down.
+
+*All* of your explicitly specified conditions in
+`circpad_machine_spec_t.conditions` *must* be met for the machine to be
+applied to a circuit. If *any* condition ceases to be met, then the machine
+is shut down. (This is checked on every event that arrives, even if the
+condition is unrelated to the event.)
+Another way to look at this is that
+all specified conditions must evaluate to true for the entire duration that
+your machine is running. If any are false, your machine does not run (or
+stops running and shuts down).
+
+In particular, as part of the
+[circpad_machine_conditions_t structure](https://github.com/torproject/tor/blob/master/src/core/or/circuitpadding.h#L149),
+the circuit padding subsystem gives the developer the option to enable a
+machine based on:
+ - The
+ [length](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding.h#L157)
+ on the circuit (via the `min_hops` field).
+ - The
+ [current state](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding.h#L174)
+ of the circuit, such as streams, relay_early, etc. (via the
+ `circpad_circuit_state_t state_mask` field).
+ - The
+ [purpose](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding.h#L178)
+ (i.e. type) of the circuit (via the `circpad_purpose_mask_t purpose_mask`
+ field).
+
+This condition mechanism is the preferred way to determine if a machine should
+apply to a circuit. For information about potentially useful conditions that
+we have considered but have not yet implemented, see [Section
+7.3](#73-better-machine-negotiation). We will happily accept patches for those
+conditions, or any for other additional conditions that are needed for your
+use case.
+
+#### 2.2.2. Detecting and Negotiating Machine Support
+
+When a new machine specification is added to Tor (or removed from Tor), you
+should bump the Padding subprotocol version in `src/core/or/protover.c` and
+`src/rust/protover/protover.rs`, add a field to `protover_summary_flags_t` in
+`or.h`, and set this field in `memoize_protover_summary()` in versions.c. This
+new field must then be checked in `circpad_node_supports_padding()` in
+`circuitpadding.c`.
+
+Note that this protocol version update and associated support check is not
+necessary if your experiments will *only* be using your own relays that
+support your own padding machines. This can be accomplished by using the
+`MiddleNodes` directive; see [Section 4](#4-evaluating-padding-machines) for more information.
+
+If the protocol support check passes for the circuit, then the client sends a
+`RELAY_COMMAND_PADDING_NEGOTIATE` cell towards the
+`circpad_machine_spec_t.target_hop` relay, and immediately enables the
+padding machine, and may begin sending padding. (The framework does not wait
+for the `RELAY_COMMAND_PADDING_NEGOTIATED` response to begin padding,
+so that we can
+switch between machines rapidly.)
+
+#### 2.2.3. Machine Shutdown Mechanisms
+
+Padding machines can be shut down on a circuit in three main ways:
+ 1. During a `circpad_machine_event` callback, when
+ `circpad_machine_spec_t.conditions` no longer applies (client side)
+ 2. After a transition to the CIRCPAD_STATE_END, if
+ `circpad_machine_spec_t.should_negotiate_end` is set (client or relay
+ side)
+ 3. If there is a `RELAY_COMMAND_PADDING_NEGOTIATED` error response from the
+ relay during negotiation.
+
+Each of these cases causes the originating node to send a relay cell towards
+the other side, indicating that shutdown has occurred. The client side sends
+`RELAY_COMMAND_PADDING_NEGOTIATE`, and the relay side sends
+`RELAY_COMMAND_PADDING_NEGOTIATED`.
+
+Because padding from malicious exit nodes can be used to construct active
+timing-based side channels to malicious guard nodes, the client checks that
+padding-related cells only come from relays with active padding machines.
+For this reason, when a client decides to shut down a padding machine,
+the framework frees the mutable `circuit_t.padding_info`, but leaves the
+`circuit_t.padding_machine` pointer set until the
+`RELAY_COMMAND_PADDING_NEGOTIATED` response comes back, to ensure that any
+remaining in-flight padding packets are recognized a valid. Tor does
+not yet close circuits due to violation of this property, but the
+[vanguards addon component "bandguard"](https://github.com/mikeperry-tor/vanguards/blob/master/README_TECHNICAL.md#the-bandguards-subsystem)
+does.
+
+As an optimization, a client may replace a machine with another, by
+sending a `RELAY_COMMAND_PADDING_NEGOTIATE` cell to shut down a machine, and
+immediately sending a `RELAY_COMMAND_PADDING_NEGOTIATE` to start a new machine
+in the same index, without waiting for the response from the first negotiate
+cell.
+
+Unfortunately, there is a known bug as a consequence of this optimization. If
+your machine depends on repeated shutdown and restart of the same machine
+number on the same circuit, please see [Bug
+30922](https://bugs.torproject.org/30992). Depending on your use case, we may
+need to fix that bug or help you find a workaround. See also [Section
+6.1.3](#613-deallocation-and-shutdown) for some more technical details on this
+mechanism.
+
+
+## 3. Specifying Padding Machines
+
+By now, you should understand how to register, negotiate, and control the
+lifetime of your padding machine, but you still don't know how to make it do
+anything yet. This section should help you understand how to specify how your
+machine reacts to events and adds padding to the wire.
+
+If you prefer to learn by example first instead, you may wish to skip to
+[Section 5](#5-example-padding-machines).
+
+
+A padding machine is specified by filling in an instance of
+[circpad_machine_spec_t](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding.h#L605). Instances
+of this structure specify the precise functionality of a machine: it's
+what the circuit padding developer is called to write. These instances
+are created only at startup, and are referenced via `const` pointers during
+normal operation.
+
+In this section we will go through the most important elements of this
+structure.
+
+### 3.1. Padding Machine States
+
+A padding machine is a finite state machine where each state
+specifies a different style of padding.
+
+As an example of a simple padding machine, you could have a state machine
+with the following states: `[START] -> [SETUP] -> [HTTP] -> [END]` where the
+`[SETUP]` state pads in a way that obfuscates the ''circuit setup'' of Tor,
+and the `[HTTP]` state pads in a way that emulates a simple HTTP session. Of
+course, padding machines can be more complicated than that, with dozens of
+states and non-trivial transitions.
+
+Padding developers encode the machine states in the
+[circpad_machine_spec_t structure](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding.h#L655). Each
+machine state is described by a
+[circpad_state_t structure](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding.h#L273)
+and each such structure specifies the style and amount of padding to be sent,
+as well as the possible state transitions.
+
+The function `circpad_machine_states_init()` must be used for allocating and
+initializing the `circpad_machine_spec_t.states` array before states and
+state transitions can be defined, as some of the state object has non-zero
+default values.
+
+### 3.2. Padding Machine State Transitions
+
+As described above, padding machines can have multiple states, to
+support different forms of padding. Machines can transition between
+states based on events that occur either on the circuit level or on
+the machine level.
+
+State transitions are specified using the
+[next_state field](https://github.com/torproject/tor/blob/master/src/core/or/circuitpadding.h#L381)
+of the `circpad_state_t` structure. As a simple example, to transition
+from state `A` to state `B` when event `E` occurs, you would use the
+following code: `A.next_state[E] = B`.
+
+#### 3.2.1. State Transition Events
+
+Here we will go through
+[the various events](https://github.com/torproject/tor/blob/master/src/core/or/circuitpadding.h#L30)
+that can be used to transition between states:
+
+* Circuit-level events
+ * `CIRCPAD_EVENT_NONPADDING_RECV`: A non-padding cell is received
+ * `CIRCPAD_EVENT_NONPADDING_SENT`: A non-adding cell is sent
+ * `CIRCPAD_EVENT_PADDING_SENT`: A padding cell is sent
+ * `CIRCPAD_EVENT_PADDING_RECV`: A padding cell is received
+* Machine-level events
+ * `CIRCPAD_EVENT_INFINITY`: Tried to schedule padding using the ''infinity bin''.
+ * `CIRCPAD_EVENT_BINS_EMPTY`: All histogram bins are empty (out of tokens)
+ * `CIRCPAD_EVENT_LENGTH_COUNT`: State has used all its padding capacity (see `length_dist` below)
+
+### 3.3. Specifying Per-State Padding
+
+Each state of a padding machine specifies either:
+ * A padding histogram describing inter-transmission delays between cells;
+d OR
+ * A parameterized delay probability distribution for inter-transmission
+ delays between cells.
+
+Either mechanism specifies essentially the *minimum inter-transmission time*
+distribution. If non-padding traffic does not get transmitted from this
+endpoint before the delay value sampled from this distribution expires, a
+padding packet is sent.
+
+The choice between histograms and probability distributions can be subtle. A
+rule of thumb is that probability distributions are easy to specify and
+consume very little memory, but might not be able to describe certain types
+of complex padding logic. Histograms, in contrast, can support precise
+packet-count oriented or multimodal delay schemes, and can use token removal
+logic to reduce overhead and shape the total padding+non-padding inter-packet
+delay distribution towards an overall target distribution.
+
+We suggest that you start with a probability distribution if possible, and
+you move to a histogram-based approach only if a probability distribution
+does not suit your needs.
+
+#### 3.3.1. Padding Probability Distributions
+
+The easiest, most compact way to schedule padding using a machine state is to
+use a probability distribution that specifies the possible delays. That can
+be done
+[using the circpad_state_t fields](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding.h#L339)
+`iat_dist`, `dist_max_sample_usec` and `dist_added_shift_usec`.
+
+The Tor circuit padding framework
+[supports multiple types](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding.h#L214)
+of probability distributions, and the developer should use the
+[circpad_distribution_t structure](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding.h#L240)
+to specify them as well as the required parameters.
+
+#### 3.3.2. Padding Histograms
+
+A more advanced way to schedule padding is to use a ''padding
+histogram''. The main advantages of a histogram are that it allows you to
+specify distributions that are not easily parameterized in closed form, or
+require specific packet counts at particular time intervals. Histograms also
+allow you to make use of an optional traffic minimization and shaping
+optimization called *token removal*, which is central to the original
+[Adaptive Padding](https://www.freehaven.net/anonbib/cache/ShWa-Timing06.pdf)
+concept.
+
+If a histogram is used by a state (as opposed to a fixed parameterized
+distribution), then the developer must use the
+[histogram-related fields](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding.h#L285)
+of the `circpad_state_t` structure.
+
+The width of a histogram bin specifies the range of inter-packet delay times,
+whereas its height specifies the amount of tokens in each bin. To sample a
+padding delay from a histogram, we first randomly pick a bin (weighted by the
+amount of tokens in each bin) and then sample a delay from within that bin by
+picking a uniformly random delay using the width of the bin as the range.
+
+Each histogram also has an ''infinity bin'' as its final bin. If the
+''infinity bin'' is chosen,
+we don't schedule any padding (i.e., we schedule padding with
+infinite delay). If the developer does not want infinite delay, they
+should not give any tokens to the ''infinity bin''.
+
+If a token removal strategy is specified (via the
+`circpad_state_t.token_removal` field), each time padding is sent using a
+histogram, the padding machine will remove a token from the appropriate
+histogram bin whenever this endpoint sends *either a padding packet or a
+non-padding packet*. The different removal strategies govern what to do when
+the bin corresponding to the current inter-packet delay is empty.
+
+Token removal is optional. It is useful if you want to do things like specify
+a burst should be at least N packets long, and you only want to add padding
+packets if there are not enough non-padding packets. The cost of doing token
+removal is additional memory allocations for making per-circuit copies of
+your histogram that can be modified.
+
+### 3.4. Specifying Precise Cell Counts
+
+Padding machines should be able to specify the exact amount of padding they
+send. For histogram-based machines this can be done using a specific amount
+of tokens, but another (and perhaps easier) way to do this, is to use the
+[length_dist field](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding.h#L362)
+of the `circpad_state_t` structure.
+
+The `length_dist` field is basically a probability distribution similar to the
+padding probability distributions, which applies to a specific machine state
+and specifies the amount of padding we are willing to send during that state.
+This value gets sampled when we transition to that state (TODO document this
+in the code).
+
+### 3.5. Specifying Overhead Limits
+
+Separately from the length counts, it is possible to rate limit the overhead
+percentage of padding at both the global level across all machines, and on a
+per-machine basis.
+
+At the global level, the overhead percentage of all circuit padding machines
+as compared to total traffic can be limited through the Tor consensus
+parameter `circpad_global_max_padding_pct`. This overhead is defined as the
+percentage of padding cells *sent* out of the sum of non padding and padding
+cells *sent*, and is applied *only after* at least
+`circpad_global_allowed_cells` padding cells are sent by that relay or client
+(to allow for small bursts of pure padding on otherwise idle or freshly
+restarted relays). When both of these limits are hit by a relay or client, no
+further padding cells will be sent, until sufficient non-padding traffic is
+sent to cause the percentage of padding traffic to fall back below the
+threshold.
+
+Additionally, each individual padding machine can rate limit itself by
+filling in the fields `circpad_machine_spec_t.max_padding_percent` and
+`circpad_machine_spec_t.allowed_padding_count`, which behave identically to
+the consensus parameters, but only apply to that specific machine.
+
+## 4. Evaluating Padding Machines
+
+One of the goals of the circuit padding framework is to provide improved
+evaluation and scientific reproducibility for lower cost. This includes both
+the [choice](#13-computation-model) of the compact C structure representation
+(which has an easy-to-produce bitstring representation for optimization by
+gradient descent, GAs, or GANs), as well as rapid prototyping and evaluation.
+
+So far, whenever evaluation cost has been a barrier, each research group has
+developed their own ad-hoc packet-level simulators of various padding
+mechanisms for evaluating website fingerprinting attacks and defenses. The
+process typically involves doing a crawl of Alexa top sites over Tor, and
+recording the Tor cell count and timing information for each page in the
+trace. These traces are then fed to simulations of defenses, which output
+modified trace files.
+
+Because no standardized simulation and evaluation mechanism exists, it is
+often hard to tell if independent implementations of various attacks and
+defenses are in fact true-to-form or even properly calibrated for direct
+comparison, and discrepancies in results across the literature suggests
+this is not always so.
+
+Our preferred outcome with this framework is that machines are tuned
+and optimized on a tracing simulator, but that the final results come from
+an actual live network test of the defense. The traces from this final crawl
+should be preserved as artifacts to be run on the simulator and reproduced
+on the live network by future papers, ideally in journal venues that have an
+artifact preservation policy.
+
+### 4.1. Pure Simulation
+
+When doing initial tuning of padding machines, especially in adversarial
+settings, variations of a padding machine defense may need to be applied to
+network activity hundreds or even millions of times. The wall-clock time
+required to do this kind of tuning using live testing or even Shadow network
+emulation may often be prohibitive.
+
+To help address this, and to better standardize results, Tobias Pulls has
+implemented a [circpad machine trace simulator](https://github.com/pylls/circpad-sim),
+which uses Tor's unit test framework to simulate applying padding machines to
+circuit packet traces via a combination of Tor patches and python scripts. This
+simulator can be used to record traces from clients, Guards, Middles, Exits,
+and any other hop in the path, only for circuits that are run by the
+researcher. This makes it possible to safely record baseline traces and
+ultimately even mount passive attacks on the live network, without impacting
+or recording any normal user traffic.
+
+In this way, a live crawl of the Alexa top sites could be performed once, to
+produce a standard "undefended" corpus. Padding machines can be then quickly
+evaluated and tuned on these simulated traces in a standardized way, and then
+the results can then be [reproduced on the live Tor
+network](#44-Testing-on-the-Live-Network) with the machines running on your own relays.
+
+Please be mindful of the Limitations section of the simulator documentation,
+however, to ensure that you are aware of the edge cases and timing
+approximations that are introduced by this approach.
+
+### 4.2. Testing in Chutney
+
+The Tor Project provides a tool called
+[Chutney](https://github.com/torproject/chutney/) which makes it very easy to
+setup private Tor networks. While getting it work for the first time might
+take you some time of doc reading, the final result is well worth it for the
+following reasons:
+
+- You control all the relays and hence you have greater control and debugging
+ capabilities.
+- You control all the relays and hence you can toggle padding support on/off
+ at will.
+- You don't need to be cautious about overhead or damaging the real Tor
+ network during testing.
+- You don't even need to be online; you can do all your testing offline over
+ localhost.
+
+A final word of warning here is that since Chutney runs over localhost, the
+packet latencies and delays are completely different from the real Tor
+network, so if your padding machines rely on real network timings you will
+get different results on Chutney. You can work around this by using a
+different set of delays if Chutney is used, or by moving your padding
+machines to the real network when you want to do latency-related testing.
+
+### 4.3. Testing in Shadow
+
+[Shadow](https://shadow.github.io/) is an environment for running entire Tor
+network simulations, similar to Chutney, but designed to be both more memory
+efficient, as well as provide an accurate Tor network topology and latency
+model.
+
+While Shadow is significantly more memory efficient than Chutney, and can make
+use of extremely accurate Tor network capacity and latency models, it will not
+be as fast or efficient as the [circpad trace simulator](https://github.com/pylls/circpad-sim),
+if you need to do many many iterations of an experiment to tune your defense.
+
+### 4.4. Testing on the Live Network
+
+Live network testing is the gold standard for verifying that any attack or
+defense is behaving as expected, to minimize the influence of simplifying
+assumptions.
+
+However, it is not ethical, or necessarily possible, to run high-resolution
+traffic analysis attacks on the entire Tor network. But it is both ethical
+and possible to run small scale experiments that target only your own
+clients, who will only use your own Tor relays that support your new padding
+machines.
+
+We provide the `MiddleNodes` torrc directive to enable this, which will allow
+you to specify the fingerprints and/or IP netmasks of relays to be used in
+the second hop position. Options to restrict other hops also exist, if your
+padding system is padding to a different hop. The `HSLayer2Nodes` option
+overrides the `MiddleNodes` option for onion service circuits, if both are
+set. (The
+[vanguards addon](https://github.com/mikeperry-tor/vanguards/README_TECHNICAL.md)
+will set `HSLayer2Nodes`.)
+
+When you run your own clients, and use MiddleNodes to restrict your clients
+to use your relays, you can perform live network evaluations of a defense
+applied to whatever traffic crawl or activity your clients do.
+
+## 5. Example Padding Machines
+
+### 5.1. Deployed Circuit Setup Machines
+
+Tor currently has two padding machines enabled by default, which aim to hide
+certain features of the client-side onion service circuit setup protocol. For
+more details on their precise goal and function, please see
+[proposal 302](https://github.com/torproject/torspec/blob/master/proposals/302-padding-machines-for-onion-clients.txt)
+. In this section we will go over the code of those machines to clarify some
+of the engineering parts:
+
+#### 5.1.1. Overview
+
+The codebase of proposal 302 can be found in
+[circuitpadding_machines.c](https://github.com/torproject/tor/blob/master/src/core/or/circuitpadding_machines.c)
+and specifies four padding machines:
+
+- The [client-side introduction](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding_machines.c#L60) circuit machine.
+- The [relay-side introduction](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding_machines.c#L146) circuit machine.
+- The [client-side rendezvous](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding_machines.c#L257) circuit machine
+- The [relay-side rendezvous](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding_machines.c#L374) circuit machine.
+
+Each of those machines has its own setup function, and
+[they are all initialized](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding.c#L2718)
+by the circuit padding framework. To understand more about them, please
+carefully read the individual setup function for each machine which are
+fairly well documented. Each function goes through the following steps:
+- Machine initialization
+ - Give it a [name](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding_machines.c#L70)
+ - Specify [which hop](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding_machines.c#L73) the padding should go to
+ - Specify whether it should be [client-side](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding_machines.c#L75) or relay-side.
+- Specify for [which types of circuits](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding_machines.c#L78) the machine should apply
+- Specify whether the circuits should be [kept alive](https://github.com/torproject/tor/blob/master/src/core/or/circuitpadding_machines.c#L112) until the machine finishes padding.
+- Sets [padding limits](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding_machines.c#L116) to avoid too much overhead in case of bugs or errors.
+- Setup [machine states](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding_machines.c#L120)
+ - Specify [state transitions](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding_machines.c#L123).
+- Finally [register the machine](https://github.com/torproject/tor/blob/35e978da61efa04af9a5ab2399dff863bc6fb20a/src/core/or/circuitpadding_machines.c#L137) to the global machine list
+
+### 5.2. Adaptive Padding Early
+
+[Adaptive Padding Early](https://www.cs.kau.se/pulls/hot/thebasketcase-ape/)
+is a variant of Adaptive Padding/WTF-PAD that does not use histograms or token
+removal to shift padding distributions, but instead uses fixed parameterized
+distributions to specify inter-packet timing thresholds for burst and gap
+inter-packet delays.
+
+Tobias Pulls's [QuickStart Guide](CircuitPaddingQuickStart.md) describes how
+to get this machine up and running, and has links to branches with a working
+implementation.
+
+### 5.3. Sketch of Tamaraw
+
+The [Tamaraw defense
+paper](https://www.cypherpunks.ca/~iang/pubs/webfingerprint-ccs14.pdf) is the
+only defense to date that provides a proof of optimality for the finite-length
+website traffic fingerprinting domain. These bounds assume that a defense is
+able to perform a full, arbitrary transform of a trace that is under a fixed
+number of packets in length.
+
+The key insight to understand Tamaraw's optimality is that it achieves one
+such optimal transform by delaying traffic below a circuit's throughput. By
+doing this, it creates a queue that is rarely empty, allowing it to produce
+a provably optimal transform with minimal overhead. As [Section
+1.4](#14-other-deployment-constraints) explains, this queue
+cannot be maintained on the live Tor network without risk of out-of-memory
+conditions at relays.
+
+However, if the queue is not maintained in the Tor network, but instead by the
+application layer, it could be deployed by websites that opt in to using it.
+
+In this case, the application layer component would do *optional* constant
+rate shaping, negotiated between a web browser and a website. The Circuit
+Padding Framework can then easily fill in any missing gaps of cover traffic
+packets, and also ensure that only a fixed length number of packets are sent
+in total.
+
+However, for such a defense to be safe, additional care must be taken to
+ensure that the resulting traffic pattern still has a large
+anonymity/confusion set with other traces on the live network.
+
+Accomplishing this is an unsolved problem.
+
+### 5.4. Other Padding Machines
+
+Our partners in this project at RIT have produced a couple prototypes, based
+on their published research designs
+[REB and RBB](https://www.researchgate.net/publication/329743510_UNDERSTANDING_FEATURE_DISCOVERY_IN_WEBSITE_FINGERPRINTING_ATTACKS).
+
+As [their writeup
+explains](https://github.com/notem/tor-rbp-padding-machine-doc), because RBB
+uses delay, the circuit padding machine that they made is a no-delay version.
+
+They also ran into an issue with the 0-delay timing workaround for [bug
+31653](https://bugs.torproject.org/31653). Keep an eye on that bug for updates
+with improved workarounds/fixes.
+
+Their code is [available on github](https://github.com/notem/tor/tree/circuit_padding_rbp_machine).
+
+
+## 6. Framework Implementation Details
+
+If you need to add additional events, conditions, or other features to the
+circuit padding framework, then this section is for you.
+
+### 6.1. Memory Allocation Conventions
+
+If the existing circuit padding features are sufficient for your needs, then
+you do not need to worry about memory management or pointer lifespans. The
+circuit padding framework should take care of this for you automatically.
+
+However, if you need to add new padding machine features to support your
+padding machines, then it will be helpful to understand how circuits
+correspond to the global machine definitions, and how mutable padding machine
+memory is managed.
+
+#### 6.1.1. Circuits and Padding Machines
+
+In Tor, the
+[circuit_t structure](https://github.com/torproject/tor/blob/master/src/core/or/circuit_st.h)
+is the superclass structure for circuit-related state that is used on both
+clients and relays. On clients, the actual datatype of the object pointed to
+by `circuit_t *` is the subclass structure
+[origin_circuit_t](https://github.com/torproject/tor/blob/master/src/core/or/origin_circuit_st.h). The
+macros `CIRCUIT_IS_ORIGIN()` and `TO_ORIGIN_CIRCUIT()` are used to determine
+if a circuit is a client-side (origin) circuit and to cast the pointer safely
+to `origin_circuit_t *`.
+
+Because circuit padding machines can be present at both clients and relays,
+the circuit padding fields are stored in the `circuit_t *` superclass
+structure. Notice that there are actually two sets of circuit padding fields:
+a `const circpad_machine_spec_t *` array, and a `circpad_machine_runtime_t *`
+array. Each of these arrays holds at most two elements, as there can be at
+most two padding machines on each circuit.
+
+The `const circpad_machine_spec_t *` points to a globally allocated machine
+specification. These machine specifications are
+allocated and set up during Tor program startup, in `circpad_machines_init()`
+in
+[circuitpadding.c](https://github.com/torproject/tor/blob/master/src/core/or/circuitpadding.c). Because
+the machine specification object is shared by all circuits, it must not be
+modified or freed until program exit (by `circpad_machines_free()`). The
+`const` qualifier should enforce this at compile time.
+
+The `circpad_machine_runtime_t *` array member points to the mutable runtime
+information for machine specification at that same array index. This runtime
+structure keeps track of the current machine state, packet counts, and other
+information that must be updated as the machine operates. When a padding
+machine is successfully negotiated `circpad_setup_machine_on_circ()` allocates
+the associated runtime information.
+
+#### 6.1.2. Histogram Management
+
+If a `circpad_state_t` of a machine specifies a `token_removal` strategy
+other than `CIRCPAD_TOKEN_REMOVAL_NONE`, then every time
+there is a state transition into this state, `circpad_machine_setup_tokens()`
+will copy the read-only `circpad_state_t.histogram` array into a mutable
+version at `circpad_machine_runtime_t.histogram`. This mutable copy is used
+to decrement the histogram bin accounts as packets are sent, as per the
+specified token removal strategy.
+
+When the state machine transitions out of this state, the mutable histogram copy is freed
+by this same `circpad_machine_setup_tokens()` function.
+
+#### 6.1.3. Deallocation and Shutdown
+
+As an optimization, padding machines can be swapped in and out by the client
+without waiting a full round trip for the relay machine to shut down.
+
+Internally, this is accomplished by immediately freeing the heap-allocated
+`circuit_t.padding_info` field corresponding to that machine, but still preserving the
+`circuit_t.padding_machine` pointer to the global padding machine
+specification until the response comes back from the relay. Once the response
+comes back, that `circuit_t.padding_machine` pointer is set to NULL, if the
+response machine number matches the current machine present.
+
+Because of this partial shutdown condition, we have two macros for iterating
+over machines. `FOR_EACH_ACTIVE_CIRCUIT_MACHINE_BEGIN()` is used to iterate
+over machines that have both a `circuit_t.padding_info` slot and a
+`circuit_t.padding_machine` slot occupied. `FOR_EACH_CIRCUIT_MACHINE_BEGIN()`
+is used when we need to iterate over all machines that are either active or
+are simply waiting for a response to a shutdown request.
+
+If the machine is replaced instead of just shut down, then the client frees
+the `circuit_t.padding_info`, and then sets the `circuit_t.padding_machine`
+and `circuit_t.padding_info` fields for this next machine immediately. This is
+done in `circpad_add_matching_machines()`. In this case, since the new machine
+should have a different machine number, the shut down response from the relay
+is silently discarded, since it will not match the new machine number.
+
+If this sequence of machine teardown and spin-up happens rapidly enough for
+the same machine number (as opposed to different machines), then a race
+condition can happen. This is
+[known bug #30992](https://bugs.torproject.org/30992).
+
+When the relay side decides to shut down a machine, it sends a
+`RELAY_COMMAND_PADDING_NEGOTIATED` towards the client. If this cell matches the
+current machine number on the client, that machine is torn down, by freeing
+the `circuit_t.padding_info` slot and immediately setting
+`circuit_t.padding_machine` slot to NULL.
+
+Additionally, if Tor decides to close a circuit forcibly due to error before
+the padding machine is shut down, then `circuit_t.padding_info` is still
+properly freed by the call to `circpad_circuit_free_all_machineinfos()`
+in `circuit_free_()`.
+
+### 6.2. Machine Application Events
+
+The framework checks client-side origin circuits to see if padding machines
+should be activated or terminated during specific event callbacks in
+`circuitpadding.c`. We list these event callbacks here only for reference. You
+should not modify any of these callbacks to get your machine to run; instead,
+you should use the `circpad_machine_spec_t.conditions` field.
+
+However, you may add new event callbacks if you need other activation events,
+for example to provide obfuscation-layer or application-layer signaling. Any
+new event callbacks should behave exactly like the existing callbacks.
+
+During each of these event callbacks, the framework checks to see if any
+current running padding machines have conditions that no longer apply as a
+result of the event, and shuts those machines down. Then, it checks to see if
+any new padding machines should be activated as a result of the event, based
+on their circuit application conditions. **Remember: Machines are checked in
+reverse order in the machine list. This means that later, more recently added
+machines take precedence over older, earlier entries in each list.**
+
+Both of these checks are performed using the machine application conditions
+that you specify in your machine's `circpad_machine_spec_t.conditions` field.
+
+The machine application event callbacks are prefixed by `circpad_machine_event_` by convention in circuitpadding.c. As of this writing, these callbacks are:
+
+ - `circpad_machine_event_circ_added_hop()`: Called whenever a new hop is
+ added to a circuit.
+ - `circpad_machine_event_circ_built()`: Called when a circuit has completed
+ construction and is
+ opened. <!-- open != ready for traffic. Which do we mean? -nickm -->
+ - `circpad_machine_event_circ_purpose_changed()`: Called when a circuit
+ changes purpose.
+ - `circpad_machine_event_circ_has_no_relay_early()`: Called when a circuit
+ runs out of `RELAY_EARLY` cells.
+ - `circpad_machine_event_circ_has_streams()`: Called when a circuit gets a
+ stream attached.
+ - `circpad_machine_event_circ_has_no_streams()`: Called when the last
+ stream is detached from a circuit.
+
+### 6.3. Internal Machine Events
+
+To provide for some additional capabilities beyond simple finite state machine
+behavior, the circuit padding machines also have internal events that they
+emit to themselves when packet count length limits are hit, when the Infinity
+bin is sampled, and when the histogram bins are emptied of all tokens.
+
+These events are implemented as `circpad_internal_event_*` functions in
+`circuitpadding.c`, which are called from various areas that determine when
+the events should occur.
+
+While the conditions that trigger these internal events to be called may be
+complex, they are processed by the state machine definitions in a nearly
+identical manner as the cell processing events, with the exception that they
+are sent to the current machine only, rather than all machines on the circuit.
+
+
+## 7. Future Features and Optimizations
+
+While implementing the circuit padding framework, our goal was to deploy a
+system that obscured client-side onion service circuit setup and supported
+deployment of WTF-PAD and/or APE. Along the way, we noticed several features
+that might prove useful to others, but were not essential to implement
+immediately. We do not have immediate plans to implement these ideas, but we
+would gladly accept patches that do so.
+
+The following list gives an overview of these improvements, but as this
+document ages, it may become stale. The canonical list of improvements that
+researchers may find useful is tagged in our bugtracker with
+[circpad-researchers](https://trac.torproject.org/projects/tor/query?keywords=~circpad-researchers),
+and the list of improvements that are known to be necessary for some research
+areas are tagged with
+[circpad-researchers-want](https://trac.torproject.org/projects/tor/query?keywords=~circpad-researchers-want).
+
+Please consult those lists for the latest status of these issues. Note that
+not all fixes will be backported to all Tor versions, so be mindful of which
+Tor releases receive which fixes as you conduct your experiments.
+
+### 7.1. Load Balancing and Flow Control
+
+Fortunately, non-Exit bandwidth is already plentiful and exceeds the Exit
+capacity, and we anticipate that if we inform our relay operator community of
+the need for non-Exit bandwidth to satisfy padding overhead requirements,
+they will be able to provide that with relative ease.
+
+Unfortunately, padding machines that have large quantities of overhead will
+require changes to our load balancing system to account for this
+overhead. The necessary changes are documented in
+[Proposal 265](https://gitweb.torproject.org/torspec.git/tree/proposals/265-load-balancing-with-overhead.txt).
+
+Additionally, padding cells are not currently subjected to flow control. For
+high amounts of padding, we may want to change this. See [ticket
+31782](https://bugs.torproject.org/31782) for details.
+
+### 7.2. Timing and Queuing Optimizations
+
+The circuitpadding framework has some timing related issues that may impact
+results. If high-resolution timestamps are fed to opaque deep learning
+trainers, those training models may end up able to differentiate padding
+traffic from non-padding traffic due to these timing bugs.
+
+The circuit padding cell event callbacks come from post-decryption points in
+the cell processing codepath, and from the pre-queue points in the cell send
+codepath. This means that our cell events will not reflect the actual time
+when packets are read or sent on the wire. This is much worse in the send
+direction, as the circuitmux queue, channel outbuf, and kernel TCP buffer will
+impose significant additional delay between when we currently report that a
+packet was sent, and when it actually hits the wire.
+
+[Ticket 29494](https://bugs.torproject.org/29494) has a more detailed
+description of this problem, and an experimental branch that changes the cell
+event callback locations to be from circuitmux post-queue, which with KIST,
+should be an accurate reflection of when they are actually sent on the wire.
+
+If your padding machine and problem space depends on very accurate notions of
+relay-side packet timing, please try that branch and let us know on the
+ticket if you need any further assistance fixing it up.
+
+Additionally, with these changes, it will be possible to provide further
+overhead reducing optimizations by letting machines specify flags to indicate
+that padding should not be sent if there are any cells pending in the cell
+queue, for doing things like extending cell bursts more accurately and with
+less overhead.
+
+However, even if we solve the queuing issues, Tor's current timers are not as
+precise as some padding designs may require. We will still have issues of
+timing precision to solve. [Ticket 31653](https://bugs.torproject.org/31653)
+describes an issue the circuit padding system has with sending 0-delay padding
+cells, and [ticket 32670](https://bugs.torproject.org/32670) describes a
+libevent timer accuracy issue, which causes callbacks to vary up to 10ms from
+their scheduled time, even in absence of load.
+
+All of these issues strongly suggest that you either truncate the resolution
+of any timers you feed to your classifier, or that you omit timestamps
+entirely from the classification problem until these issues are addressed.
+
+### 7.3. Better Machine Negotiation
+
+Circuit padding is applied to circuits through machine conditions.
+
+The following machine conditions may be useful for some use cases, but have
+not been implemented yet:
+ * [Exit Policy-based Stream Conditions](https://bugs.torproject.org/29083)
+ * [Probability to apply machine/Cointoss condition](https://bugs.torproject.org/30092)
+ * [Probability distributions for launching new padding circuit(s)](https://bugs.torproject.org/31783)
+ * [More flexible purpose handling](https://bugs.torproject.org/32040)
+
+Additionally, the following features may help to obscure that padding is being
+negotiated, and/or streamline that negotiation process:
+ * [Always send negotiation cell on all circuits](https://bugs.torproject.org/30172)
+ * [Better shutdown handling](https://bugs.torproject.org/30992)
+ * [Preference-ordered negotiation menu](https://bugs.torproject.org/30348)
+
+### 7.4. Probabilistic State Transitions
+
+Right now, the state machine transitions are fully deterministic. However,
+one could imagine a state machine that uses probabilistic transitions between
+states to simulate a random walk or Hidden Markov Model traversal across
+several pages.
+
+The simplest way to implement this is to make the `circpad_state_t.next_state` array
+into an array of structs that have a next state field, and a probability to
+transition to that state.
+
+If you need this feature, please see [ticket
+31787](https://bugs.torproject.org/31787) for more details.
+
+### 7.5. More Complex Pattern Recognition
+
+State machines are extremely efficient sequence recognition devices. But they
+are not great pattern recognition devices. This is one of the reasons why
+[Adaptive Padding](https://www.freehaven.net/anonbib/cache/ShWa-Timing06.pdf)
+used state machines in combination with histograms, to model the target
+distribution of interpacket delays for transmitted packets.
+
+However, there currently is no such optimization for reaction to patterns of
+*received* traffic. There may also be cases where defenses must react to more
+complex patterns of sent traffic than can be expressed by our current
+histogram and length count events.
+
+For example: if you wish your machine to react to a certain count of incoming
+cells in a row, right now you have to have a state for each cell, and use the
+infinity bin to timeout of the sequence in each state. We could make this more
+compact if each state had an arrival cell counter and inter-cell timeout. Or
+we could make more complex mechanisms to recognize certain patterns of arrival
+traffic in a state.
+
+The best way to build recognition primitives like this into the framework is
+to add additional [Internal Machine Events](#63-internal-machine-events) for
+the pattern in question.
+
+As another simple example, a useful additional event might be to transition
+whenever any of your histogram bins are empty, rather than all of them. To do
+this, you would add `CIRCPAD_EVENT_ANY_BIN_EMPTY` to the enum
+`circpad_event_t` in `circuitpadding.h`. You would then create a function
+`circuitpadding_internal_event_any_bin_empty()`, which would work just like
+`circuitpadding_internal_event_bin_empty()`, and also be called from
+`check_machine_token_supply()` in `circuitpadding.c` but with the check for
+each bin being zero instead of the total. With this change, new machines could
+react to this new event in the same way as any other.
+
+If you have any other ideas that may be useful, please comment on [ticket
+32680](https://bugs.torproject.org/32680).
+
+
+## 8. Open Research Problems
+
+### 8.1. Onion Service Circuit Setup
+
+Our circuit setup padding does not address timing-based features, only
+packet counts. Deep learning can probably see this.
+
+However, before going too deep down the timing rabithole, we may need to make
+[some improvements to Tor](#72-timing-and-queuing-optimizations). Please
+comment on those tickets if you need this.
+
+### 8.2. Onion Service Fingerprinting
+
+We have done nothing to obscure the service side of onion service circuit
+setup. Because service-side onion services will have the reverse traffic byte
+counts as normal clients, they will likely need some kind of [hybrid
+application layer traffic shaping](#53-sketch-of-tamaraw), in addition to
+simple circuit setup obfuscation.
+
+Fingerprinting in
+[combination](https://github.com/mikeperry-tor/vanguards/blob/master/README_SECURITY.md)
+with
+[vanguards](https://github.com/mikeperry-tor/vanguards/blob/master/README_TECHNICAL.md)
+ia also an open issue.
+
+### 8.3. Open World Fingerprinting
+
+Similarly, Open World/clearweb website fingerprinting defenses remain
+an unsolved problem from the practicality point of view. The original WTF-PAD
+defense was never tuned, and it is showing accuracy issues against deep
+learning attacks.
+
+### 8.4. Protocol Usage Fingerprinting
+
+Traffic Fingerprinting to determine the protocol in use by a client has not
+been studied, either from the attack or defense point of view.
+
+### 8.5. Datagram Transport Side Channels
+
+Padding can reduce the accuracy of dropped-cell side channels in such
+transports, but we don't know [how to measure
+this](https://lists.torproject.org/pipermail/tor-dev/2018-November/013562.html).
+
+## 9. Must Read Papers
+
+These are by far the most important papers in the space, to date:
+
+ - [Tamaraw](https://www.cypherpunks.ca/~iang/pubs/webfingerprint-ccs14.pdf)
+ - [Bayes, Not Naive](https://www.petsymposium.org/2017/papers/issue4/paper50-2017-4-source.pdf)
+ - [Anonymity Trilemma](https://eprint.iacr.org/2017/954.pdf)
+ - [WTF-PAD](http://arxiv.org/pdf/1512.00524)
+
+Except for WTF-PAD, these papers were selected because they point towards
+optimality bounds that can be benchmarked against.
+
+We cite them even though we are skeptical that provably optimal defenses can
+be constructed, at least not without trivial or impractical transforms (such as
+those that can be created with unbounded queue capacity, or stored knowledge
+of traces for every possible HTTP trace on the Internet).
+
+We also are not demanding an optimality or security proof for every defense.
+
+Instead, we cite the above as benchmarks. We believe the space, especially the
+open-world case, to be more akin to an optimization problem, where a
+WTF-PAD-like defense must be tuned through an optimizer to produce results
+comparable to provably optimal but practically unrealizable defenses, through
+rigorous adversarial evaluation.
+
+## A. Acknowledgments
+
+This research was supported in part by NSF grants CNS-1619454 and CNS-1526306.
diff --git a/doc/HACKING/CircuitPaddingQuickStart.md b/doc/HACKING/CircuitPaddingQuickStart.md
new file mode 100644
index 0000000000..167ff9f292
--- /dev/null
+++ b/doc/HACKING/CircuitPaddingQuickStart.md
@@ -0,0 +1,263 @@
+# A Padding Machine from Scratch
+
+A quickstart guide by Tobias Pulls.
+
+This document describes the process of building a "padding machine" in tor's new
+circuit padding framework from scratch. Notes were taken as part of porting
+[Adaptive Padding Early
+(APE)](https://www.cs.kau.se/pulls/hot/thebasketcase-ape/) from basket2 to the
+circuit padding framework. The goal is just to document the process and provide
+useful pointers along the way, not create a useful machine.
+
+The quick and dirty plan is to:
+1. clone and compile tor
+2. use newly built tor in TB and at small (non-exit) relay we run
+3. add a bare-bones APE padding machine
+4. run the machine, inspect logs for activity
+5. port APE's state machine without thinking much about parameters
+
+## Clone and compile tor
+
+```bash
+git clone https://git.torproject.org/tor.git
+cd tor
+git checkout tor-0.4.1.5
+```
+Above we use the tag for tor-0.4.1.5 where the circuit padding framework was
+released. Note that this version of the framework is missing many features and
+fixes that have since been merged to origin/master. If you need the newest
+framework features, you should use that master instead.
+
+```bash
+sh autogen.sh
+./configure
+make
+```
+When you run `./configure` you'll be told of missing dependencies and packages
+to install on debian-based distributions. Important: if you plan to run `tor` on
+a relay as part of the real Tor network and your server runs a distribution that
+uses systemd, then I'd recommend that you `apt install dpkg dpkg-dev
+libevent-dev libssl-dev asciidoc quilt dh-apparmor libseccomp-dev dh-systemd
+libsystemd-dev pkg-config dh-autoreconf libfakeroot zlib1g zlib1g-dev automake
+liblzma-dev libzstd-dev` and ensure that tor has systemd support enabled:
+`./configure --enable-systemd`. Without this, on a recent Ubuntu, my tor service
+was forcefully restarted (SIGINT interrupt) by systemd every five minutes.
+
+If you want to install on your localsystem, run `make install`. For our case we
+just want the tor binary at `src/app/tor`.
+
+## Use tor in TB and at a relay
+Download and install a fresh Tor Browser (TB) from torproject.org. Make sure it
+works. From the command line, relative to the folder created when you extracted
+TB, run `./Browser/start-tor-browser --verbose` to get some basic log output.
+Note the version of tor, in my case, `Tor 0.4.0.5 (git-bf071e34aa26e096)` as
+part of TB 8.5.4. Shut down TB, copy the `tor` binary that you compiled earlier
+and replace `Browser/TorBrowser/Tor/tor`. Start TB from the command line again,
+you should see a different version, in my case `Tor 0.4.1.5
+(git-439ca48989ece545)`.
+
+The relay we run is also on linux, and `tor` is located at `/usr/bin/tor`. To
+view relevant logs since last boot `sudo journalctl -b /usr/bin/tor`, where we
+find `Tor 0.4.0.5 running on Linux`. Copy the locally compiled `tor` to the
+relay at a temporary location and then make sure it's ownership and access
+rights are identical to `/usr/bin/tor`. Next, shut down the running tor service
+with `sudo service tor stop`, wait for it to stop (typically 30s), copy our
+locally compiled tor to replace `/usr/bin/tor` then start the service again.
+Checking the logs we see `or 0.4.1.5 (git-439ca48989ece545)`.
+
+Repeatedly shutting down a relay is detrimental to the network and should be
+avoided. Sorry about that.
+
+We have one more step left before we move on the machine: configure TB to always
+use our middle relay. Edit `Browser/TorBrowser/Data/Tor/torrc` and set
+`MiddleNodes <fingerprint>`, where `<fingerprint>` is the fingerprint of the
+relay. Start TB, visit a website, and manually confirm that the middle is used
+by looking at the circuit display.
+
+## Add a bare-bones APE padding machine
+Now the fun part. We have several resources at our disposal (mind that links
+might be broken in the future, just search for the headings):
+- The official [Circuit Padding Developer
+ Documentation](https://storm.torproject.org/shared/ChieH_sLU93313A2gopZYT3x2waJ41hz5Hn2uG1Uuh7).
+- Notes we made on the [implementation of the circuit padding
+ framework](https://github.com/pylls/padding-machines-for-tor/blob/master/notes/circuit-padding-framework.md).
+- The implementation of the current circuit padding machines in tor:
+ [circuitpadding.c](https://gitweb.torproject.org/tor.git/tree/src/core/or/circuitpadding_machines.c)
+ and
+ [circuitpadding_machines.h](https://gitweb.torproject.org/tor.git/tree/src/core/or/circuitpadding_machines.h).
+
+Please consult the above links for details. Moving forward, the focus is to
+describe what was done, not necessarily explaining all the details why.
+
+Since we plan to make changes to tor, create a new branch `git checkout -b
+circuit-padding-ape-machine tor-0.4.1.5`.
+
+We start with declaring two functions, one for the machine at the client and one
+at the relay, in `circuitpadding_machines.h`:
+
+```c
+void circpad_machine_relay_wf_ape(smartlist_t *machines_sl);
+void circpad_machine_client_wf_ape(smartlist_t *machines_sl);
+```
+
+The definitions go into `circuitpadding_machines.c`:
+
+```c
+/**************** Adaptive Padding Early (APE) machine ****************/
+
+/**
+ * Create a relay-side padding machine based on the APE design.
+ */
+void
+circpad_machine_relay_wf_ape(smartlist_t *machines_sl)
+{
+ circpad_machine_spec_t *relay_machine
+ = tor_malloc_zero(sizeof(circpad_machine_spec_t));
+
+ relay_machine->name = "relay_wf_ape";
+ relay_machine->is_origin_side = 0; // relay-side
+
+ // Pad to/from the middle relay, only when the circuit has streams
+ relay_machine->target_hopnum = 2;
+ relay_machine->conditions.min_hops = 2;
+ relay_machine->conditions.state_mask = CIRCPAD_CIRC_STREAMS;
+
+ // limits to help guard against excessive padding
+ relay_machine->allowed_padding_count = 1;
+ relay_machine->max_padding_percent = 1;
+
+ // one state to start with: START (-> END, never takes a slot in states)
+ circpad_machine_states_init(relay_machine, 1);
+ relay_machine->states[CIRCPAD_STATE_START].
+ next_state[CIRCPAD_EVENT_NONPADDING_SENT] =
+ CIRCPAD_STATE_END;
+
+ // register the machine
+ relay_machine->machine_num = smartlist_len(machines_sl);
+ circpad_register_padding_machine(relay_machine, machines_sl);
+
+ log_info(LD_CIRC,
+ "Registered relay WF APE padding machine (%u)",
+ relay_machine->machine_num);
+}
+
+/**
+ * Create a client-side padding machine based on the APE design.
+ */
+void
+circpad_machine_client_wf_ape(smartlist_t *machines_sl)
+{
+ circpad_machine_spec_t *client_machine
+ = tor_malloc_zero(sizeof(circpad_machine_spec_t));
+
+ client_machine->name = "client_wf_ape";
+ client_machine->is_origin_side = 1; // client-side
+
+ /** Pad to/from the middle relay, only when the circuit has streams, and only
+ * for general purpose circuits (typical for web browsing)
+ */
+ client_machine->target_hopnum = 2;
+ client_machine->conditions.min_hops = 2;
+ client_machine->conditions.state_mask = CIRCPAD_CIRC_STREAMS;
+ client_machine->conditions.purpose_mask =
+ circpad_circ_purpose_to_mask(CIRCUIT_PURPOSE_C_GENERAL);
+
+ // limits to help guard against excessive padding
+ client_machine->allowed_padding_count = 1;
+ client_machine->max_padding_percent = 1;
+
+ // one state to start with: START (-> END, never takes a slot in states)
+ circpad_machine_states_init(client_machine, 1);
+ client_machine->states[CIRCPAD_STATE_START].
+ next_state[CIRCPAD_EVENT_NONPADDING_SENT] =
+ CIRCPAD_STATE_END;
+
+ client_machine->machine_num = smartlist_len(machines_sl);
+ circpad_register_padding_machine(client_machine, machines_sl);
+ log_info(LD_CIRC,
+ "Registered client WF APE padding machine (%u)",
+ client_machine->machine_num);
+}
+```
+
+We also have to modify `circpad_machines_init()` in `circuitpadding.c` to
+register our machines:
+
+```c
+ /* Register machines for the APE WF defense */
+ circpad_machine_client_wf_ape(origin_padding_machines);
+ circpad_machine_relay_wf_ape(relay_padding_machines);
+```
+
+We run `make` to get a new `tor` binary and copy it to our local TB.
+
+## Run the machine
+To be able
+to view circuit info events in the console as we launch TB, we add `Log
+[circ]info notice stdout` to `torrc` of TB.
+
+Running TB to visit example.com we first find in the log:
+
+```
+Aug 30 18:36:43.000 [info] circpad_machine_client_hide_intro_circuits(): Registered client intro point hiding padding machine (0)
+Aug 30 18:36:43.000 [info] circpad_machine_relay_hide_intro_circuits(): Registered relay intro circuit hiding padding machine (0)
+Aug 30 18:36:43.000 [info] circpad_machine_client_hide_rend_circuits(): Registered client rendezvous circuit hiding padding machine (1)
+Aug 30 18:36:43.000 [info] circpad_machine_relay_hide_rend_circuits(): Registered relay rendezvous circuit hiding padding machine (1)
+Aug 30 18:36:43.000 [info] circpad_machine_client_wf_ape(): Registered client WF APE padding machine (2)
+Aug 30 18:36:43.000 [info] circpad_machine_relay_wf_ape(): Registered relay WF APE padding machine (2)
+```
+
+All good, our machine is running. Looking further we find:
+
+```
+Aug 30 18:36:55.000 [info] circpad_setup_machine_on_circ(): Registering machine client_wf_ape to origin circ 2 (5)
+Aug 30 18:36:55.000 [info] circpad_node_supports_padding(): Checking padding: supported
+Aug 30 18:36:55.000 [info] circpad_negotiate_padding(): Negotiating padding on circuit 2 (5), command 2
+Aug 30 18:36:55.000 [info] circpad_machine_spec_transition(): Circuit 2 circpad machine 0 transitioning from 0 to 65535
+Aug 30 18:36:55.000 [info] circpad_machine_spec_transitioned_to_end(): Padding machine in end state on circuit 2 (5)
+Aug 30 18:36:55.000 [info] circpad_circuit_machineinfo_free_idx(): Freeing padding info idx 0 on circuit 2 (5)
+Aug 30 18:36:55.000 [info] circpad_handle_padding_negotiated(): Middle node did not accept our padding request on circuit 2 (5)
+```
+We see that our middle support padding (since we upgraded to tor-0.4.1.5), that
+we attempt to negotiate, our machine starts on the client, transitions to the
+end state, and is freed. The last line shows that the middle doesn't have a
+padding machine that can run.
+
+Next, we follow the same steps as earlier and replace the modified `tor` at our
+middle relay. We don't update the logging there to avoid logging on the info
+level on the live network. Looking at the client log again we see that
+negotiation works as before except for the last line: it's missing, so the
+machine is running at the middle as well.
+
+## Implementing the APE state machine
+
+Porting is fairly straightforward: define the states for all machines, add two
+more machines (for the receive portion of WTFP-PAD, beyond AP), and pick
+reasonable parameters for the distributions (I completely winged it now, as when
+implementing APE). The [circuit-padding-ape-machine
+branch](https://github.com/pylls/tor/tree/circuit-padding-ape-machine) contains
+the commits for the full machines with plenty of comments.
+
+Some comments on the process:
+
+- `tor-0.4.1.5` does not support two machines on the same circuit, the following
+ fix has to be made: https://trac.torproject.org/projects/tor/ticket/31111 .
+ The good news is that everything else seems to work after the small change in
+ the fix.
+- APE randomizes its distributions. Currently, this can only be done during
+ start of `tor`. This makes sense in the censorship circumvention setting
+ (`obfs4`), less so for WF defenses: further randomizing each circuit is likely
+ a PITA for attackers with few downsides.
+- it was annoying to figure out that the lack of systemd support in my compiled
+ tor caused systemd to interrupt (SIGINT) my tor process at the middle relay
+ every five minutes. Updated build steps above to hopefully save others the
+ pain.
+- there's for sure some bug on relays when sending padding cells too early (?).
+ It can happen with some probability with the APE implementation due to
+ `circpad_machine_relay_wf_ape_send()`. Will investigate next.
+- Moving the registration of machines from the definition of the machines to
+ `circpad_machines_init()` makes sense, as suggested in the circuit padding doc
+ draft.
+
+Remember that APE is just a proof-of-concept and we make zero claims about its
+ability to withstand WF attacks, in particular those based on deep learning.
diff --git a/doc/HACKING/CodingStandards.md b/doc/HACKING/CodingStandards.md
index 2c273910d1..7999724166 100644
--- a/doc/HACKING/CodingStandards.md
+++ b/doc/HACKING/CodingStandards.md
@@ -219,6 +219,9 @@ deviations from our C whitespace style. Generally, we use:
- No space between a function name and an opening paren. `puts(x)`, not
`puts (x)`.
- Function declarations at the start of the line.
+ - Use `void foo(void)` to declare a function with no arguments. Saying
+ `void foo()` is C++ syntax.
+ - Use `const` for new APIs.
If you use an editor that has plugins for editorconfig.org, the file
`.editorconfig` will help you to conform this coding style.
@@ -235,20 +238,49 @@ We have some wrapper functions like `tor_malloc`, `tor_free`, `tor_strdup`, and
`tor_gettimeofday;` use them instead of their generic equivalents. (They
always succeed or exit.)
+Specifically, Don't use `malloc`, `realloc`, `calloc`, `free`, or
+`strdup`. Use `tor_malloc`, `tor_realloc`, `tor_calloc`, `tor_free`, or
+`tor_strdup`.
+
+Don't use `tor_realloc(x, y\*z)`. Use `tor_reallocarray(x, y, z)` instead.;
+
You can get a full list of the compatibility functions that Tor provides by
looking through `src/lib/*/*.h`. You can see the
available containers in `src/lib/containers/*.h`. You should probably
familiarize yourself with these modules before you write too much code, or
else you'll wind up reinventing the wheel.
-We don't use `strcat` or `strcpy` or `sprintf` of any of those notoriously broken
-old C functions. Use `strlcat`, `strlcpy`, or `tor_snprintf/tor_asprintf` instead.
+
+We don't use `strcat` or `strcpy` or `sprintf` of any of those notoriously
+broken old C functions. We also avoid `strncat` and `strncpy`. Use
+`strlcat`, `strlcpy`, or `tor_snprintf/tor_asprintf` instead.
We don't call `memcmp()` directly. Use `fast_memeq()`, `fast_memneq()`,
-`tor_memeq()`, or `tor_memneq()` for most purposes.
+`tor_memeq()`, or `tor_memneq()` for most purposes. If you really need a
+tristate return value, use `tor_memcmp()` or `fast_memcmp()`.
+
+Don't call `assert()` directly. For hard asserts, use `tor_assert()`. For
+soft asserts, use `tor_assert_nonfatal()` or `BUG()`. If you need to print
+debug information in assert error message, consider using `tor_assertf()` and
+`tor_assertf_nonfatal()`. If you are writing code that is too low-level to
+use the logging subsystem, use `raw_assert()`.
+
+Don't use `toupper()` and `tolower()` functions. Use `TOR_TOUPPER` and
+`TOR_TOLOWER` macros instead. Similarly, use `TOR_ISALPHA`, `TOR_ISALNUM` et.
+al. instead of `isalpha()`, `isalnum()`, etc.
+
+When allocating new string to be added to a smartlist, use
+`smartlist_add_asprintf()` to do both at once.
+
+Avoid calling BSD socket functions directly. Use portable wrappers to work
+with sockets and socket addresses. Also, sockets should be of type
+`tor_socket_t`.
+
+Don't use any of these functions: they aren't portable. Use the
+version prefixed with `tor_` instead: strtok_r, memmem, memstr,
+asprintf, localtime_r, gmtime_r, inet_aton, inet_ntop, inet_pton,
+getpass, ntohll, htonll. (This list is incomplete.)
-Also see a longer list of functions to avoid in:
-https://people.torproject.org/~nickm/tor-auto/internal/this-not-that.html
What code can use what other code?
----------------------------------
@@ -338,8 +370,16 @@ definitions when necessary.)
Assignment operators shouldn't nest inside other expressions. (You can
ignore this inside macro definitions when necessary.)
-Functions not to write
-----------------------
+Binary data and wire formats
+----------------------------
+
+Use pointer to `char` when representing NUL-terminated string. To represent
+arbitrary binary data, use pointer to `uint8_t`. (Many older Tor APIs ignore
+this rule.)
+
+Refrain from attempting to encode integers by casting their pointers to byte
+arrays. Use something like `set_uint32()`/`get_uint32()` instead and don't
+forget about endianness.
Try to never hand-write new code to parse or generate binary
formats. Instead, use trunnel if at all possible. See
@@ -457,6 +497,9 @@ to use it as a function callback), define it with a name like
abc_free_(obj);
}
+When deallocating, don't say e.g. `if (x) tor_free(x)`. The convention is to
+have deallocators do nothing when NULL pointer is passed.
+
Doxygen comment conventions
---------------------------
diff --git a/doc/HACKING/HelpfulTools.md b/doc/HACKING/HelpfulTools.md
index cba57e875d..ae892c34a2 100644
--- a/doc/HACKING/HelpfulTools.md
+++ b/doc/HACKING/HelpfulTools.md
@@ -251,16 +251,16 @@ Now you can run Tor with profiling enabled, and use the pprof utility to look at
performance! See the gperftools manual for more info, but basically:
2. Run `env CPUPROFILE=/tmp/profile src/app/tor -f <path/torrc>`. The profile file
- is not written to until Tor finishes execuction.
+ is not written to until Tor finishes execution.
-3. Run `pprof src/app/tor /tm/profile` to start the REPL.
+3. Run `pprof src/app/tor /tmp/profile` to start the REPL.
Generating and analyzing a callgraph
------------------------------------
0. Build Tor on linux or mac, ideally with -O0 or -fno-inline.
-1. Clone 'https://gitweb.torproject.org/user/nickm/calltool.git/' .
+1. Clone 'https://git.torproject.org/user/nickm/calltool.git/' .
Follow the README in that repository.
Note that currently the callgraph generator can't detect calls that pass
@@ -315,6 +315,30 @@ If you use emacs for editing Tor and nothing else, you could always just say:
There is probably a better way to do this. No, we are probably not going
to clutter the files with emacs stuff.
+Building a tag file (code index)
+--------------------------------
+
+Many functions in tor use `MOCK_IMPL` wrappers for unit tests. Your
+tag-building program must be told how to handle this syntax.
+
+If you're using emacs, you can generate an emacs-compatible tag file using
+`make tags`. This will run your system's `etags`. Tor's build system assumes
+that you're using the emacs-specific version of `etags` (bundled under the
+`xemacs21-bin` package on Debian). This is incompatible with other versions of
+`etags` such as the version provided by Exuberant Ctags.
+
+If you're using vim or emacs, you can also use Universal Ctags to build a tag
+file using the syntax:
+
+ ctags -R -D 'MOCK_IMPL(r,h,a)=r h a' .
+
+If you're using an older version of Universal Ctags, you can use the following
+instead:
+
+ ctags -R --mline-regex-c='/MOCK_IMPL\([^,]+,\W*([a-zA-Z0-9_]+)\W*,/\1/f/{mgroup=1}' .
+
+A vim-compatible tag file will be generated by default. If you use emacs, add
+the `-e` flag to generate an emacs-compatible tag file.
Doxygen
-------
@@ -372,7 +396,7 @@ source code. Here's how to use it:
6. See the Doxygen manual for more information; this summary just
scratches the surface.
-Style and best-pratices checking
+Style and best-practices checking
--------------------------------
We use scripts to check for various problems in the formatting and style
diff --git a/doc/HACKING/Module.md b/doc/HACKING/Module.md
index 9cf36090b4..781bb978f2 100644
--- a/doc/HACKING/Module.md
+++ b/doc/HACKING/Module.md
@@ -8,13 +8,24 @@ module in Tor.
In the context of the tor code base, a module is a subsystem that we can
selectively enable or disable, at `configure` time.
-Currently, there is only one module:
+Currently, tor has these modules:
+ - Relay subsystem (relay)
+ - Directory cache system (dircache).
- Directory Authority subsystem (dirauth)
-It is located in its own directory in `src/feature/dirauth/`. To disable it,
-one need to pass `--disable-module-dirauth` at configure time. All modules
-are currently enabled by default.
+The dirauth code is located in its own directory in `src/feature/dirauth/`.
+
+The relay code is located in a directory named `src/*/*relay`, which is
+being progressively refactored and disabled.
+
+The dircache code is located in `src/*/*dircache`. Right now, it is
+disabled if and only if the relay module is disabled. (We are treating
+them as separate modules because they are logically independent, not
+because you would actually want to run one without the other.)
+
+To disable a module, pass `--disable-module-{dirauth,relay}` at configure
+time. All modules are currently enabled by default.
## Build System ##
@@ -24,7 +35,7 @@ The changes to the build system are pretty straightforward.
contains a list (white-space separated) of the module in tor. Add yours to
the list.
-2. Use the `AC_ARG_ENABLE([module-dirauth]` template for your new module. We
+2. Use the `AC_ARG_ENABLE([module-relay]` template for your new module. We
use the "disable module" approach instead of enabling them one by one. So,
by default, tor will build all the modules.
@@ -32,7 +43,7 @@ The changes to the build system are pretty straightforward.
the C code to conditionally compile things for your module. And the
`BUILD_MODULE_<name>` is also defined for automake files (e.g: include.am).
-3. In the `src/core/include.am` file, locate the `MODULE_DIRAUTH_SOURCES`
+3. In the `src/core/include.am` file, locate the `MODULE_RELAY_SOURCES`
value. You need to create your own `_SOURCES` variable for your module
and then conditionally add the it to `LIBTOR_A_SOURCES` if you should
build the module.
@@ -40,18 +51,14 @@ The changes to the build system are pretty straightforward.
It is then **very** important to add your SOURCES variable to
`src_or_libtor_testing_a_SOURCES` so the tests can build it.
-4. Do the same for header files, locate `ORHEADERS +=` which always add all
- headers of all modules so the symbol can be found for the module entry
- points.
-
Finally, your module will automatically be included in the
-`TOR_MODULES_ALL_ENABLED` variable which is used to build the unit tests. They
-always build everything in order to tests everything.
+`TOR_MODULES_ALL_ENABLED` variable which is used to build the unit tests.
+They always build everything in order to test everything.
## Coding ##
-As mentioned above, a module must be isolated in its own directory (name of
-the module) in `src/feature/`.
+As mentioned above, a module should be isolated in its own directories,
+suffixed with the name of the module, in `src/*/`.
There are couples of "rules" you want to follow:
diff --git a/doc/HACKING/ReleasingTor.md b/doc/HACKING/ReleasingTor.md
index f40e2af573..0f453ca2aa 100644
--- a/doc/HACKING/ReleasingTor.md
+++ b/doc/HACKING/ReleasingTor.md
@@ -197,7 +197,7 @@ new Tor release:
3. Email the packagers (cc'ing tor-team) that a new tarball is up.
The current list of packagers is:
- - {weasel,gk,mikeperry} at torproject dot org
+ - {weasel,sysrqb,mikeperry} at torproject dot org
- {blueness} at gentoo dot org
- {paul} at invizbox dot io
- {vincent} at invizbox dot com
diff --git a/doc/HACKING/design/00-overview.md b/doc/HACKING/design/00-overview.md
deleted file mode 100644
index 2103a9062a..0000000000
--- a/doc/HACKING/design/00-overview.md
+++ /dev/null
@@ -1,124 +0,0 @@
-
-## Overview ##
-
-This document describes the general structure of the Tor codebase, how
-it fits together, what functionality is available for extending Tor,
-and gives some notes on how Tor got that way.
-
-Tor remains a work in progress: We've been working on it for more than a
-decade, and we've learned a lot about good coding since we first
-started. This means, however, that some of the older pieces of Tor will
-have some "code smell" in them that could sure stand a brisk
-refactoring. So when I describe a piece of code, I'll sometimes give a
-note on how it got that way, and whether I still think that's a good
-idea.
-
-The first drafts of this document were written in the Summer and Fall of
-2015, when Tor 0.2.6 was the most recent stable version, and Tor 0.2.7
-was under development. If you're reading this far in the future, some
-things may have changed. Caveat haxxor!
-
-This document is not an overview of the Tor protocol. For that, see the
-design paper and the specifications at https://spec.torproject.org/ .
-
-For more information about Tor's coding standards and some helpful
-development tools, see doc/HACKING in the Tor repository.
-
-For more information about writing tests, see doc/HACKING/WritingTests.txt
-in the Tor repository.
-
-### The very high level ###
-
-Ultimately, Tor runs as an event-driven network daemon: it responds to
-network events, signals, and timers by sending and receiving things over
-the network. Clients, relays, and directory authorities all use the
-same codebase: the Tor process will run as a client, relay, or authority
-depending on its configuration.
-
-Tor has a few major dependencies, including Libevent (used to tell which
-sockets are readable and writable), OpenSSL (used for many encryption
-functions, and to implement the TLS protocol), and zlib (used to
-compress and uncompress directory information).
-
-Most of Tor's work today is done in a single event-driven main thread.
-Tor also spawns one or more worker threads to handle CPU-intensive
-tasks. (Right now, this only includes circuit encryption.)
-
-On startup, Tor initializes its libraries, reads and responds to its
-configuration files, and launches a main event loop. At first, the only
-events that Tor listens for are a few signals (like TERM and HUP), and
-one or more listener sockets (for different kinds of incoming
-connections). Tor also configures a timer function to run once per
-second to handle periodic events. As Tor runs over time, other events
-will open, and new events will be scheduled.
-
-The codebase is divided into a few main subdirectories:
-
- src/common -- utility functions, not necessarily tor-specific.
-
- src/or -- implements the Tor protocols.
-
- src/test -- unit and regression tests
-
- src/ext -- Code maintained elsewhere that we include in the Tor
- source distribution.
-
- src/trunnel -- automatically generated code (from the Trunnel)
- tool: used to parse and encode binary formats.
-
-### Some key high-level abstractions ###
-
-The most important abstractions at Tor's high-level are Connections,
-Channels, Circuits, and Nodes.
-
-A 'Connection' represents a stream-based information flow. Most
-connections are TCP connections to remote Tor servers and clients. (But
-as a shortcut, a relay will sometimes make a connection to itself
-without actually using a TCP connection. More details later on.)
-Connections exist in different varieties, depending on what
-functionality they provide. The principle types of connection are
-"edge" (eg a socks connection or a connection from an exit relay to a
-destination), "OR" (a TLS stream connecting to a relay), "Directory" (an
-HTTP connection to learn about the network), and "Control" (a connection
-from a controller).
-
-A 'Circuit' is persistent tunnel through the Tor network, established
-with public-key cryptography, and used to send cells one or more hops.
-Clients keep track of multi-hop circuits, and the cryptography
-associated with each hop. Relays, on the other hand, keep track only of
-their hop of each circuit.
-
-A 'Channel' is an abstract view of sending cells to and from a Tor
-relay. Currently, all channels are implemented using OR connections.
-If we switch to other strategies in the future, we'll have more
-connection types.
-
-A 'Node' is a view of a Tor instance's current knowledge and opinions
-about a Tor relay orbridge.
-
-### The rest of this document. ###
-
-> **Note**: This section describes the eventual organization of this
-> document, which is not yet complete.
-
-We'll begin with an overview of the various utility functions available
-in Tor's 'common' directory. Knowing about these is key to writing
-portable, simple code in Tor.
-
-Then we'll go on and talk about the main data-flow of the Tor network:
-how Tor generates and responds to network traffic. This will occupy a
-chapter for the main overview, with other chapters for special topics.
-
-After that, we'll mention the main modules in Tor, and describe the
-function of each.
-
-We'll cover the directory subsystem next: how Tor learns about other
-relays, and how relays advertise themselves.
-
-Then we'll cover a few specialized modules, such as hidden services,
-sandboxing, hibernation, accounting, statistics, guards, path
-generation, pluggable transports, and how they integrate with the rest of Tor.
-
-We'll close with a meandering overview of important pending issues in
-the Tor codebase, and how they affect the future of the Tor software.
-
diff --git a/doc/HACKING/design/01-common-utils.md b/doc/HACKING/design/01-common-utils.md
deleted file mode 100644
index 79a6a7b7d3..0000000000
--- a/doc/HACKING/design/01-common-utils.md
+++ /dev/null
@@ -1,121 +0,0 @@
-
-## Utility code in Tor
-
-Most of Tor's utility code is in modules in the src/common subdirectory.
-
-These are divided, broadly, into _compatibility_ functions, _utility_
-functions, _containers_, and _cryptography_. (Someday in the future, it
-would be great to split these modules into separate directories. Also, some
-functions are probably put in the wrong modules)
-
-### Compatibility code
-
-These functions live in src/common/compat\*.c; some corresponding macros live
-in src/common/compat\*.h. They serve as wrappers around platform-specific or
-compiler-specific logic functionality.
-
-In general, the rest of the Tor code *should not* be calling platform-specific
-or otherwise non-portable functions. Instead, they should call wrappers from
-compat.c, which implement a common cross-platform API. (If you don't know
-whether a function is portable, it's usually good enough to see whether it
-exists on OSX, Linux, and Windows.)
-
-Other compatibility modules include backtrace.c, which generates stack traces
-for crash reporting; sandbox.c, which implements the Linux seccomp2 sandbox;
-and procmon.c, which handles monitoring a child process.
-
-Parts of address.c are compatibility code for handling network addressing
-issues; other parts are in util.c.
-
-Notable compatibility areas are:
-
- * mmap support for mapping files into the address space (read-only)
-
- * Code to work around the intricacies
-
- * Workaround code for Windows's horrible winsock incompatibilities and
- Linux's intricate socket extensions.
-
- * Helpful string functions like memmem, memstr, asprintf, strlcpy, and
- strlcat that not all platforms have.
-
- * Locale-ignoring variants of the ctypes functions.
-
- * Time-manipulation functions
-
- * File locking function
-
- * IPv6 functions for platforms that don't have enough IPv6 support
-
- * Endianness functions
-
- * OS functions
-
- * Threading and locking functions.
-
-=== Utility functions
-
-General-purpose utilities are in util.c; they include higher-level wrappers
-around many of the compatibility functions to provide things like
-file-at-once access, memory management functions, math, string manipulation,
-time manipulation, filesystem manipulation, etc.
-
-(Some functionality, like daemon-launching, would be better off in a
-compatibility module.)
-
-In util_format.c, we have code to implement stuff like base-32 and base-64
-encoding.
-
-The address.c module interfaces with the system resolver and implements
-address parsing and formatting functions. It converts sockaddrs to and from
-a more compact tor_addr_t type.
-
-The di_ops.c module provides constant-time comparison and associative-array
-operations, for side-channel avoidance.
-
-The logging subsystem in log.c supports logging to files, to controllers, to
-stdout/stderr, or to the system log.
-
-The abstraction in memarea.c is used in cases when a large amount of
-temporary objects need to be allocated, and they can all be freed at the same
-time.
-
-The torgzip.c module wraps the zlib library to implement compression.
-
-Workqueue.c provides a simple multithreaded work-queue implementation.
-
-### Containers
-
-The container.c module defines these container types, used throughout the Tor
-codebase.
-
-There is a dynamic array called **smartlist**, used as our general resizeable
-array type. It supports sorting, searching, common set operations, and so
-on. It has specialized functions for smartlists of strings, and for
-heap-based priority queues.
-
-There's a bit-array type.
-
-A set of mapping types to map strings, 160-bit digests, and 256-bit digests
-to void \*. These are what we generally use when we want O(1) lookup.
-
-Additionally, for containers, we use the ht.h and tor_queue.h headers, in
-src/ext. These provide intrusive hashtable and linked-list macros.
-
-### Cryptography
-
-Once, we tried to keep our cryptography code in a single "crypto.c" file,
-with an "aes.c" module containing an AES implementation for use with older
-OpenSSLs.
-
-Now, our practice has become to introduce crypto_\*.c modules when adding new
-cryptography backend code. We have modules for Ed25519, Curve25519,
-secret-to-key algorithms, and password-based boxed encryption.
-
-Our various TLS compatibility code, wrappers, and hacks are kept in
-tortls.c, which is probably too full of Tor-specific kludges. I'm
-hoping we can eliminate most of those kludges when we finally remove
-support for older versions of our TLS handshake.
-
-
-
diff --git a/doc/HACKING/design/01a-memory.md b/doc/HACKING/design/01a-memory.md
deleted file mode 100644
index 9a20782962..0000000000
--- a/doc/HACKING/design/01a-memory.md
+++ /dev/null
@@ -1,93 +0,0 @@
-
-## Memory management
-
-### Heap-allocation functions
-
-Tor imposes a few light wrappers over C's native malloc and free
-functions, to improve convenience, and to allow wholescale replacement
-of malloc and free as needed.
-
-You should never use 'malloc', 'calloc', 'realloc, or 'free' on their
-own; always use the variants prefixed with 'tor_'.
-They are the same as the standard C functions, with the following
-exceptions:
-
- * tor_free(NULL) is a no-op.
- * tor_free() is a macro that takes an lvalue as an argument and sets it to
- NULL after freeing it. To avoid this behavior, you can use tor_free_()
- instead.
- * tor_malloc() and friends fail with an assertion if they are asked to
- allocate a value so large that it is probably an underflow.
- * It is always safe to tor_malloc(0), regardless of whether your libc
- allows it.
- * tor_malloc(), tor_realloc(), and friends are never allowed to fail.
- Instead, Tor will die with an assertion. This means that you never
- need to check their return values. See the next subsection for
- information on why we think this is a good idea.
-
-We define additional general-purpose memory allocation functions as well:
-
- * tor_malloc_zero(x) behaves as calloc(1, x), except the it makes clear
- the intent to allocate a single zeroed-out value.
- * tor_reallocarray(x,y) behaves as the OpenBSD reallocarray function.
- Use it for cases when you need to realloc() in a multiplication-safe
- way.
-
-And specific-purpose functions as well:
-
- * tor_strdup() and tor_strndup() behaves as the underlying libc functions,
- but use tor_malloc() instead of the underlying function.
- * tor_memdup() copies a chunk of memory of a given size.
- * tor_memdup_nulterm() copies a chunk of memory of a given size, then
- NUL-terminates it just to be safe.
-
-#### Why assert on failure?
-
-Why don't we allow tor_malloc() and its allies to return NULL?
-
-First, it's error-prone. Many programmers forget to check for NULL return
-values, and testing for malloc() failures is a major pain.
-
-Second, it's not necessarily a great way to handle OOM conditions. It's
-probably better (we think) to have a memory target where we dynamically free
-things ahead of time in order to stay under the target. Trying to respond to
-an OOM at the point of tor_malloc() failure, on the other hand, would involve
-a rare operation invoked from deep in the call stack. (Again, that's
-error-prone and hard to debug.)
-
-Third, thanks to the rise of Linux and other operating systems that allow
-memory to be overcommitted, you can't actually ever rely on getting a NULL
-from malloc() when you're out of memory; instead you have to use an approach
-closer to tracking the total memory usage.
-
-#### Conventions for your own allocation functions.
-
-Whenever you create a new type, the convention is to give it a pair of
-x_new() and x_free() functions, named after the type.
-
-Calling x_free(NULL) should always be a no-op.
-
-
-### Grow-only memory allocation: memarea.c
-
-It's often handy to allocate a large number of tiny objects, all of which
-need to disappear at the same time. You can do this in tor using the
-memarea.c abstraction, which uses a set of grow-only buffers for allocation,
-and only supports a single "free" operation at the end.
-
-Using memareas also helps you avoid memory fragmentation. You see, some libc
-malloc implementations perform badly on the case where a large number of
-small temporary objects are allocated at the same time as a few long-lived
-objects of similar size. But if you use tor_malloc() for the long-lived ones
-and a memarea for the temporary object, the malloc implementation is likelier
-to do better.
-
-To create a new memarea, use memarea_new(). To drop all the storage from a
-memarea, and invalidate its pointers, use memarea_drop_all().
-
-The allocation functions memarea_alloc(), memarea_alloc_zero(),
-memarea_memdup(), memarea_strdup(), and memarea_strndup() are analogous to
-the similarly-named malloc() functions. There is intentionally no
-memarea_free() or memarea_realloc().
-
-
diff --git a/doc/HACKING/design/01e-os-compat.md b/doc/HACKING/design/01e-os-compat.md
deleted file mode 100644
index 072e95bc8a..0000000000
--- a/doc/HACKING/design/01e-os-compat.md
+++ /dev/null
@@ -1,50 +0,0 @@
-
-## OS compatibility functions ##
-
-We've got a bunch of functions to wrap differences between various
-operating systems where we run.
-
-### The filesystem ###
-
-We wrap the most important filesystem functions with load-file,
-save-file, and map-file abstractions declared in util.c or compat.c. If
-you're messing about with file descriptors yourself, you might be doing
-things wrong. Most of the time, write_str_to_file() and
-read_str_from_file() are all you need.
-
-Use the check_private_directory() function to create or verify the
-presence of directories, and tor_listdir() to list the files in a
-directory.
-
-Those modules also have functions for manipulating paths a bit.
-
-### Networking ###
-
-Nearly all the world is on a Berkeley sockets API, except for
-windows, whose version of the Berkeley API was corrupted by late-90s
-insistence on backward compatibility with the
-sort-of-berkeley-sort-of-not add-on *thing* that was WinSocks.
-
-What's more, everybody who implemented sockets realized that select()
-wasn't a very good way to do nonblocking IO... and then the various
-implementations all decided to so something different.
-
-You can forget about most of these differences, fortunately: We use
-libevent to hide most of the differences between the various networking
-backends, and we add a few of our own functions to hide the differences
-that Libevent doesn't.
-
-To create a network connection, the right level of abstraction to look
-at is probably the connection_t system in connection.c. Most of the
-lower level work has already been done for you. If you need to
-instantiate something that doesn't fit well with connection_t, you
-should see whether you can instantiate it with connection_t anyway -- or
-you might need to refactor connection.c a little.
-
-Whenever possible, represent network addresses as tor_addr_t.
-
-### Process launch and monitoring ###
-
-Launching and/or monitoring a process is tricky business. You can use
-the mechanisms in procmon.c and tor_spawn_background(), but they're both
-a bit wonky. A refactoring would not be out of order.
diff --git a/doc/HACKING/design/03-modules.md b/doc/HACKING/design/03-modules.md
deleted file mode 100644
index 93eb9d3089..0000000000
--- a/doc/HACKING/design/03-modules.md
+++ /dev/null
@@ -1,247 +0,0 @@
-
-## Tor's modules ##
-
-### Generic modules ###
-
-`buffers.c`
-: Implements the `buf_t` buffered data type for connections, and several
-low-level data handling functions to handle network protocols on it.
-
-`channel.c`
-: Generic channel implementation. Channels handle sending and receiving cells
-among tor nodes.
-
-`channeltls.c`
-: Channel implementation for TLS-based OR connections. Uses `connection_or.c`.
-
-`circuitbuild.c`
-: Code for constructing circuits and choosing their paths. (*Note*:
-this module could plausibly be split into handling the client side,
-the server side, and the path generation aspects of circuit building.)
-
-`circuitlist.c`
-: Code for maintaining and navigating the global list of circuits.
-
-`circuitmux.c`
-: Generic circuitmux implementation. A circuitmux handles deciding, for a
-particular channel, which circuit should write next.
-
-`circuitmux_ewma.c`
-: A circuitmux implementation based on the EWMA (exponentially
-weighted moving average) algorithm.
-
-`circuituse.c`
-: Code to actually send and receive data on circuits.
-
-`command.c`
-: Handles incoming cells on channels.
-
-`config.c`
-: Parses options from torrc, and uses them to configure the rest of Tor.
-
-`confparse.c`
-: Generic torrc-style parser. Used to parse torrc and state files.
-
-`connection.c`
-: Generic and common connection tools, and implementation for the simpler
-connection types.
-
-`connection_edge.c`
-: Implementation for entry and exit connections.
-
-`connection_or.c`
-: Implementation for OR connections (the ones that send cells over TLS).
-
-`main.c`
-: Principal entry point, main loops, scheduled events, and network
-management for Tor.
-
-`ntmain.c`
-: Implements Tor as a Windows service. (Not very well.)
-
-`onion.c`
-: Generic code for generating and responding to CREATE and CREATED
-cells, and performing the appropriate onion handshakes. Also contains
-code to manage the server-side onion queue.
-
-`onion_fast.c`
-: Implements the old SHA1-based CREATE_FAST/CREATED_FAST circuit
-creation handshake. (Now deprecated.)
-
-`onion_ntor.c`
-: Implements the Curve25519-based NTOR circuit creation handshake.
-
-`onion_tap.c`
-: Implements the old RSA1024/DH1024-based TAP circuit creation handshake. (Now
-deprecated.)
-
-`relay.c`
-: Handles particular types of relay cells, and provides code to receive,
-encrypt, route, and interpret relay cells.
-
-`scheduler.c`
-: Decides which channel/circuit pair is ready to receive the next cell.
-
-`statefile.c`
-: Handles loading and storing Tor's state file.
-
-`tor_main.c`
-: Contains the actual `main()` function. (This is placed in a separate
-file so that the unit tests can have their own `main()`.)
-
-
-### Node-status modules ###
-
-`directory.c`
-: Implements the HTTP-based directory protocol, including sending,
-receiving, and handling most request types. (*Note*: The client parts
-of this, and the generic-HTTP parts of this, could plausibly be split
-off.)
-
-`microdesc.c`
-: Implements the compact "microdescriptor" format for keeping track of
-what we know about a router.
-
-`networkstatus.c`
-: Code for fetching, storing, and interpreting consensus vote documents.
-
-`nodelist.c`
-: Higher-level view of our knowledge of which Tor servers exist. Each
-`node_t` corresponds to a router we know about.
-
-`routerlist.c`
-: Code for storing and retrieving router descriptors and extrainfo
-documents.
-
-`routerparse.c`
-: Generic and specific code for parsing all Tor directory information
-types.
-
-`routerset.c`
-: Parses and interprets a specification for a set of routers (by IP
-range, fingerprint, nickname (deprecated), or country).
-
-
-### Client modules ###
-
-`addressmap.c`
-: Handles client-side associations between one address and another.
-These are used to implement client-side DNS caching (NOT RECOMMENDED),
-MapAddress directives, Automapping, and more.
-
-`circpathbias.c`
-: Path bias attack detection for circuits: tracks whether
-connections made through a particular guard have an unusually high failure rate.
-
-`circuitstats.c`
-: Code to track circuit performance statistics in order to adapt our behavior.
-Notably includes an algorithm to track circuit build times.
-
-`dnsserv.c`
-: Implements DNSPort for clients. (Note that in spite of the word
-"server" in this module's name, it is used for Tor clients. It
-implements a DNS server, not DNS for servers.)
-
-`entrynodes.c`
-: Chooses, monitors, and remembers guard nodes. Also contains some
-bridge-related code.
-
-`torcert.c`
-: Code to interpret and generate Ed25519-based certificates.
-
-### Server modules ###
-
-`dns.c`
-: Server-side DNS code. Handles sending and receiving DNS requests on
-exit nodes, and implements the server-side DNS cache.
-
-`dirserv.c`
-: Implements part of directory caches that handles responding to
-client requests.
-
-`ext_orport.c`
-: Implements the extended ORPort protocol for communication between
-server-side pluggable transports and Tor servers.
-
-`hibernate.c`
-: Performs bandwidth accounting, and puts Tor relays into hibernation
-when their bandwidth is exhausted.
-
-`router.c`
-: Management code for running a Tor server. In charge of RSA key
-maintenance, descriptor generation and uploading.
-
-`routerkeys.c`
-: Key handling code for a Tor server. (Currently handles only the
-Ed25519 keys, but the RSA keys could be moved here too.)
-
-
-### Onion service modules ###
-
-`rendcache.c`
-: Stores onion service descriptors.
-
-`rendclient.c`
-: Client-side implementation of the onion service protocol.
-
-`rendcommon.c`
-: Parts of the onion service protocol that are shared by clients,
-services, and/or Tor servers.
-
-`rendmid.c`
-: Tor-server-side implementation of the onion service protocol. (Handles
-acting as an introduction point or a rendezvous point.)
-
-`rendservice.c`
-: Service-side implementation of the onion service protocol.
-
-`replaycache.c`
-: Backend to check introduce2 requests for replay attempts.
-
-
-### Authority modules ###
-
-`dircollate.c`
-: Helper for `dirvote.c`: Given a set of votes, each containing a list
-of Tor nodes, determines which entries across all the votes correspond
-to the same nodes, and yields them in a useful order.
-
-`dirvote.c`
-: Implements the directory voting algorithms that authorities use.
-
-`keypin.c`
-: Implements a persistent key-pinning mechanism to tie RSA1024
-identities to ed25519 identities.
-
-### Miscellaneous modules ###
-
-`control.c`
-: Implements the Tor controller protocol.
-
-`cpuworker.c`
-: Implements the inner work queue function. We use this to move the
-work of circuit creation (on server-side) to other CPUs.
-
-`fp_pair.c`
-: Types for handling 2-tuples of 20-byte fingerprints.
-
-`geoip.c`
-: Parses geoip files (which map IP addresses to country codes), and
-performs lookups on the internal geoip table. Also stores some
-geoip-related statistics.
-
-`policies.c`
-: Parses and implements Tor exit policies.
-
-`reasons.c`
-: Maps internal reason-codes to human-readable strings.
-
-`rephist.c`
-: Tracks Tor servers' performance over time.
-
-`status.c`
-: Writes periodic "heartbeat" status messages about the state of the Tor
-process.
-
-`transports.c`
-: Implements management for the pluggable transports subsystem.
diff --git a/doc/HACKING/design/Makefile b/doc/HACKING/design/Makefile
deleted file mode 100644
index e126130970..0000000000
--- a/doc/HACKING/design/Makefile
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-HTML= \
- 00-overview.html \
- 01-common-utils.html \
- 01a-memory.html \
- 01b-collections.html \
- 01c-time.html \
- 01d-crypto.html \
- 01e-os-compat.html \
- 01f-threads.html \
- 01g-strings.html \
- 02-dataflow.html \
- 03-modules.html \
- this-not-that.html
-
-PNG = \
- diagrams/02/02-dataflow.png \
- diagrams/02/02-connection-types.png
-
-all: generated
-
-generated: $(HTML) $(PNG)
-
-%.html: %.md
- maruku $< -o $@
-
-%.png: %.dia
- dia $< --export=$@
-
-clean:
- rm -f $(HTML)
- rm -f $(PNG)
diff --git a/doc/HACKING/design/this-not-that.md b/doc/HACKING/design/this-not-that.md
deleted file mode 100644
index 815c7b2fbc..0000000000
--- a/doc/HACKING/design/this-not-that.md
+++ /dev/null
@@ -1,51 +0,0 @@
-
-Don't use memcmp. Use {tor,fast}_{memeq,memneq,memcmp}.
-
-Don't use assert. Use tor_assert or tor_assert_nonfatal or BUG. Prefer
-nonfatal assertions or BUG()s.
-
-Don't use sprintf or snprintf. Use tor_asprintf or tor_snprintf.
-
-Don't write hand-written binary parsers. Use trunnel.
-
-Don't use malloc, realloc, calloc, free, strdup, etc. Use tor_malloc,
-tor_realloc, tor_calloc, tor_free, tor_strdup, etc.
-
-Don't use tor_realloc(x, y\*z). Use tor_reallocarray(x, y, z);
-
-Don't say "if (x) foo_free(x)". Just foo_free(x) and make sure that
-foo_free(NULL) is a no-op.
-
-Don't use toupper or tolower; use TOR_TOUPPER and TOR_TOLOWER.
-
-Don't use isalpha, isalnum, etc. Instead use TOR_ISALPHA, TOR_ISALNUM, etc.
-
-Don't use strcat, strcpy, strncat, or strncpy. Use strlcat and strlcpy
-instead.
-
-Don't use tor_asprintf then smartlist_add; use smartlist_add_asprintf.
-
-Don't use any of these functions: they aren't portable. Use the
-version prefixed with `tor_` instead: strtok_r, memmem, memstr,
-asprintf, localtime_r, gmtime_r, inet_aton, inet_ntop, inet_pton,
-getpass, ntohll, htonll, strdup, (This list is incomplete.)
-
-Don't create or close sockets directly. Instead use the wrappers in
-compat.h.
-
-When creating new APIs, only use 'char \*' to represent 'pointer to a
-nul-terminated string'. Represent 'pointer to a chunk of memory' as
-'uint8_t \*'. (Many older Tor APIs ignore this rule.)
-
-Don't encode/decode u32, u64, or u16 to byte arrays by casting
-pointers. That can crash if the pointers aren't aligned, and can cause
-endianness problems. Instead say something more like set_uint32(ptr,
-htonl(foo)) to encode, and ntohl(get_uint32(ptr)) to decode.
-
-Don't declare a 0-argument function with "void foo()". That's C++
-syntax. In C you say "void foo(void)".
-
-When creating new APIs, use const everywhere you reasonably can.
-
-Sockets should have type tor_socket_t, not int.
-
diff --git a/doc/include.am b/doc/include.am
index a9d3fa1c98..8651f845eb 100644
--- a/doc/include.am
+++ b/doc/include.am
@@ -47,6 +47,7 @@ EXTRA_DIST+= doc/asciidoc-helper.sh \
$(html_in) $(man_in) $(txt_in) \
doc/state-contents.txt \
doc/torrc_format.txt \
+ doc/tor-doxygen.css \
doc/TUNING \
doc/HACKING/README.1st.md \
doc/HACKING/CodingStandards.md \
diff --git a/doc/tor-doxygen.css b/doc/tor-doxygen.css
new file mode 100644
index 0000000000..97cd1886db
--- /dev/null
+++ b/doc/tor-doxygen.css
@@ -0,0 +1,10 @@
+
+p.definition {
+ font-size: small;
+ padding-left: 1.5em;
+}
+
+p.reference {
+ font-size: small;
+ padding-left: 1.5em;
+}
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index c7c41e7841..88cf47f2fe 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -4,161 +4,190 @@
// Learn asciidoc on http://www.methods.co.nz/asciidoc/userguide.html
:man source: Tor
:man manual: Tor Manual
-TOR(1)
-======
+// compat-mode tells Asciidoctor tools to process this as legacy AsciiDoc
+:compat-mode:
+// attribute to make it easier to write names containing double underscores
+:dbl_: __
+= TOR(1)
+
+== NAME
-NAME
-----
tor - The second-generation onion router
-SYNOPSIS
---------
+== SYNOPSIS
+
**tor** [__OPTION__ __value__]...
-DESCRIPTION
------------
-Tor is a connection-oriented anonymizing communication
-service. Users choose a source-routed path through a set of nodes, and
-negotiate a "virtual circuit" through the network, in which each node
-knows its predecessor and successor, but no others. Traffic flowing down
-the circuit is unwrapped by a symmetric key at each node, which reveals
-the downstream node. +
-
-Basically, Tor provides a distributed network of servers or relays ("onion routers").
-Users bounce their TCP streams -- web traffic, ftp, ssh, etc. -- around the
-network, and recipients, observers, and even the relays themselves have
-difficulty tracking the source of the stream.
-
-By default, **tor** will act as a client only. To help the network
-by providing bandwidth as a relay, change the **ORPort** configuration
-option -- see below. Please also consult the documentation on the Tor
-Project's website.
-
-COMMAND-LINE OPTIONS
---------------------
-[[opt-h]] **-h**, **--help**::
+== DESCRIPTION
+
+Tor is a connection-oriented anonymizing communication service. Users
+choose a source-routed path through a set of nodes, and negotiate a
+"virtual circuit" through the network. Each node in a virtual circuit
+knows its predecessor and successor nodes, but no other nodes. Traffic
+flowing down the circuit is unwrapped by a symmetric key at each node,
+which reveals the downstream node. +
+
+Basically, Tor provides a distributed network of servers or relays
+("onion routers"). Users bounce their TCP streams, including web
+traffic, ftp, ssh, etc., around the network, so that recipients,
+observers, and even the relays themselves have difficulty tracking the
+source of the stream.
+
+[NOTE]
+By default, **tor** acts as a client only. To help the network by
+providing bandwidth as a relay, change the **ORPort** configuration
+option as mentioned below. Please also consult the documentation on
+the Tor Project's website.
+
+== COMMAND-LINE OPTIONS
+
+Tor has a powerful command-line interface. This section lists optional
+arguments you can specify at the command line using the **`tor`**
+command.
+
+Configuration options can be specified on the command line in the
+format **`--`**_OptionName_ _OptionValue_, on the command line in the
+format _OptionName_ _OptionValue_, or in a configuration file. For
+instance, you can tell Tor to start listening for SOCKS connections on
+port 9999 by passing either **`--SocksPort 9999`** or **`SocksPort
+9999`** on the command line, or by specifying **`SocksPort 9999`** in
+the configuration file. On the command line, quote option values that
+contain spaces. For instance, if you want Tor to log all debugging
+messages to **`debug.log`**, you must specify **`--Log "debug file
+debug.log"`**.
+
+NOTE: Configuration options on the command line override those in
+configuration files. See **<<conf-format,THE CONFIGURATION FILE
+FORMAT>>** for more information.
+
+The following options in this section are only recognized on the
+**`tor`** command line, not in a configuration file.
+
+[[opt-h]] **`-h`**, **`--help`**::
Display a short help message and exit.
-[[opt-f]] **-f** __FILE__::
+[[opt-f]] **`-f`** __FILE__::
Specify a new configuration file to contain further Tor configuration
- options OR pass *-* to make Tor read its configuration from standard
- input. (Default: @CONFDIR@/torrc, or $HOME/.torrc if that file is not
- found)
+ options, or pass *-* to make Tor read its configuration from standard
+ input. (Default: **`@CONFDIR@/torrc`**, or **`$HOME/.torrc`** if
+ that file is not found)
-[[opt-allow-missing-torrc]] **--allow-missing-torrc**::
- Do not require that configuration file specified by **-f** exist if
- default torrc can be accessed.
+[[opt-allow-missing-torrc]] **`--allow-missing-torrc`**::
+ Allow the configuration file specified by **`-f`** to be missing,
+ if the defaults-torrc file (see below) is accessible.
-[[opt-defaults-torrc]] **--defaults-torrc** __FILE__::
+[[opt-defaults-torrc]] **`--defaults-torrc`** __FILE__::
Specify a file in which to find default values for Tor options. The
contents of this file are overridden by those in the regular
configuration file, and by those on the command line. (Default:
- @CONFDIR@/torrc-defaults.)
+ **`@CONFDIR@/torrc-defaults`**.)
-[[opt-ignore-missing-torrc]] **--ignore-missing-torrc**::
- Specifies that Tor should treat a missing torrc file as though it
+[[opt-ignore-missing-torrc]] **`--ignore-missing-torrc`**::
+ Specify that Tor should treat a missing torrc file as though it
were empty. Ordinarily, Tor does this for missing default torrc files,
but not for those specified on the command line.
-[[opt-hash-password]] **--hash-password** __PASSWORD__::
- Generates a hashed password for control port access.
+[[opt-hash-password]] **`--hash-password`** __PASSWORD__::
+ Generate a hashed password for control port access.
-[[opt-list-fingerprint]] **--list-fingerprint**::
+[[opt-list-fingerprint]] **`--list-fingerprint`**::
Generate your keys and output your nickname and fingerprint.
-[[opt-verify-config]] **--verify-config**::
- Verify the configuration file is valid.
+[[opt-verify-config]] **`--verify-config`**::
+ Verify whether the configuration file is valid.
+
+[[opt-dump-config]] **`--dump-config`** **`short`**|**`full`**|**`non-builtin`**::
+ Write a complete list of Tor's configured options to standard output.
+ When the `short` flag is selected, only write the options that
+ are different from their default values. When `non-builtin` is selected,
+ write options that are not zero or the empty string.
+ When `full` is selected, write every option.
-[[opt-serviceinstall]] **--service install** [**--options** __command-line options__]::
+[[opt-serviceinstall]] **`--service install`** [**`--options`** __command-line options__]::
Install an instance of Tor as a Windows service, with the provided
command-line options. Current instructions can be found at
https://www.torproject.org/docs/faq#NTService
-[[opt-service]] **--service** **remove**|**start**|**stop**::
+[[opt-service]] **`--service`** **`remove`**|**`start`**|**`stop`**::
Remove, start, or stop a configured Tor Windows service.
-[[opt-nt-service]] **--nt-service**::
+[[opt-nt-service]] **`--nt-service`**::
Used internally to implement a Windows service.
-[[opt-list-torrc-options]] **--list-torrc-options**::
+[[opt-list-torrc-options]] **`--list-torrc-options`**::
List all valid options.
-[[opt-list-deprecated-options]] **--list-deprecated-options**::
+[[opt-list-deprecated-options]] **`--list-deprecated-options`**::
List all valid options that are scheduled to become obsolete in a
future version. (This is a warning, not a promise.)
-[[opt-list-modules]] **--list-modules**::
- For each optional module, list whether or not it has been compiled
- into Tor. (Any module not listed is not optional in this version of Tor.)
+[[opt-list-modules]] **`--list-modules`**::
+ List whether each optional module has been compiled into Tor.
+ (Any module not listed is not optional in this version of Tor.)
-[[opt-version]] **--version**::
+[[opt-version]] **`--version`**::
Display Tor version and exit. The output is a single line of the format
"Tor version [version number]." (The version number format
is as specified in version-spec.txt.)
-[[opt-quiet]] **--quiet**|**--hush**::
- Override the default console log. By default, Tor starts out logging
- messages at level "notice" and higher to the console. It stops doing so
- after it parses its configuration, if the configuration tells it to log
- anywhere else. You can override this behavior with the **--hush** option,
- which tells Tor to only send warnings and errors to the console, or with
- the **--quiet** option, which tells Tor not to log to the console at all.
-
-[[opt-keygen]] **--keygen** [**--newpass**]::
- Running "tor --keygen" creates a new ed25519 master identity key for a
- relay, or only a fresh temporary signing key and certificate, if you
- already have a master key. Optionally you can encrypt the master identity
- key with a passphrase: Tor will ask you for one. If you don't want to
- encrypt the master key, just don't enter any passphrase when asked. +
- +
- The **--newpass** option should be used with --keygen only when you need
- to add, change, or remove a passphrase on an existing ed25519 master
- identity key. You will be prompted for the old passphase (if any),
- and the new passphrase (if any). +
- +
- When generating a master key, you will probably want to use
- **--DataDirectory** to control where the keys
- and certificates will be stored, and **--SigningKeyLifetime** to
- control their lifetimes. Their behavior is as documented in the
- server options section below. (You must have write access to the specified
- DataDirectory.) +
- +
- To use the generated files, you must copy them to the DataDirectory/keys
- directory of your Tor daemon, and make sure that they are owned by the
- user actually running the Tor daemon on your system.
-
-**--passphrase-fd** __FILEDES__::
- Filedescriptor to read the passphrase from. Note that unlike with the
+[[opt-quiet]] **`--quiet`**|**`--hush`**::
+ Override the default console logging behavior. By default, Tor
+ starts out logging messages at level "notice" and higher to the
+ console. It stops doing so after it parses its configuration, if
+ the configuration tells it to log anywhere else. These options
+ override the default console logging behavior. Use the
+ **`--hush`** option if you want Tor to log only warnings and
+ errors to the console, or use the **`--quiet`** option if you want
+ Tor not to log to the console at all.
+
+[[opt-keygen]] **`--keygen`** [**`--newpass`**]::
+ Running **`tor --keygen`** creates a new ed25519 master identity key
+ for a relay, or only a fresh temporary signing key and
+ certificate, if you already have a master key. Optionally, you
+ can encrypt the master identity key with a passphrase. When Tor
+ asks you for a passphrase and you don't want to encrypt the master
+ key, just don't enter any passphrase when asked. +
+ +
+ Use the **`--newpass`** option with **`--keygen`** only when you
+ need to add, change, or remove a passphrase on an existing ed25519
+ master identity key. You will be prompted for the old passphase
+ (if any), and the new passphrase (if any).
++
+[NOTE]
+ When generating a master key, you may want to use
+ **`--DataDirectory`** to control where the keys and certificates
+ will be stored, and **`--SigningKeyLifetime`** to control their
+ lifetimes. See the server options section to learn more about the
+ behavior of these options. You must have write access to the
+ specified DataDirectory.
++
+[normal]
+ To use the generated files, you must copy them to the
+ __DataDirectory__/**`keys`** directory of your Tor daemon, and
+ make sure that they are owned by the user actually running the Tor
+ daemon on your system.
+
+**`--passphrase-fd`** __FILEDES__::
+ File descriptor to read the passphrase from. Note that unlike with the
tor-gencert program, the entire file contents are read and used as
the passphrase, including any trailing newlines.
- Default: read from the terminal.
+ If the file descriptor is not specified, the passphrase is read
+ from the terminal by default.
-[[opt-key-expiration]] **--key-expiration** [**purpose**]::
- The **purpose** specifies which type of key certificate to determine
- the expiration of. The only currently recognised **purpose** is
+[[opt-key-expiration]] **`--key-expiration`** [__purpose__]::
+ The __purpose__ specifies which type of key certificate to determine
+ the expiration of. The only currently recognised __purpose__ is
"sign". +
- +
- Running "tor --key-expiration sign" will attempt to find your signing
- key certificate and will output, both in the logs as well as to stdout,
- the signing key certificate's expiration time in ISO-8601 format.
- For example, the output sent to stdout will be of the form:
- "signing-cert-expiry: 2017-07-25 08:30:15 UTC"
-
-Other options can be specified on the command-line in the format "--option
-value", in the format "option value", or in a configuration file. For
-instance, you can tell Tor to start listening for SOCKS connections on port
-9999 by passing --SocksPort 9999 or SocksPort 9999 to it on the command line,
-or by putting "SocksPort 9999" in the configuration file. You will need to
-quote options with spaces in them: if you want Tor to log all debugging
-messages to debug.log, you will probably need to say **--Log** `"debug file
-debug.log"`.
-
-Options on the command line override those in configuration files. See the
-next section for more information.
-
-THE CONFIGURATION FILE FORMAT
------------------------------
+ +
+ Running **`tor --key-expiration sign`** will attempt to find your
+ signing key certificate and will output, both in the logs as well
+ as to stdout, the signing key certificate's expiration time in
+ ISO-8601 format. For example, the output sent to stdout will be
+ of the form: "signing-cert-expiry: 2017-07-25 08:30:15 UTC"
+
+[[conf-format]]
+== THE CONFIGURATION FILE FORMAT
All configuration options in a configuration are written on a single line by
default. They take the form of an option name and a value, or an option name
@@ -196,8 +225,48 @@ command line that you want no SocksPorts at all. To do that, prefix the
option name with a forward slash (/). You can use the plus sign (+) and the
forward slash (/) in the configuration file and on the command line.
-GENERAL OPTIONS
----------------
+== GENERAL OPTIONS
+
+// These options are in alphabetical order, with exceptions as noted.
+// Please keep them that way!
+
+[[AccelDir]] **AccelDir** __DIR__::
+ Specify this option if using dynamic hardware acceleration and the engine
+ implementation library resides somewhere other than the OpenSSL default.
+ Can not be changed while tor is running.
+
+[[AccelName]] **AccelName** __NAME__::
+ When using OpenSSL hardware crypto acceleration attempt to load the dynamic
+ engine of this name. This must be used for any dynamic hardware engine.
+ Names can be verified with the openssl engine command. Can not be changed
+ while tor is running. +
+ +
+ If the engine name is prefixed with a "!", then Tor will exit if the
+ engine cannot be loaded.
+
+[[AlternateBridgeAuthority]] **AlternateBridgeAuthority** [__nickname__] [**flags**] __ipv4address__:__port__ __ fingerprint__::
+[[AlternateDirAuthority]] **AlternateDirAuthority** [__nickname__] [**flags**] __ipv4address__:__port__ __fingerprint__::
+ These options behave as DirAuthority, but they replace fewer of the
+ default directory authorities. Using
+ AlternateDirAuthority replaces the default Tor directory authorities, but
+ leaves the default bridge authorities in
+ place. Similarly,
+ AlternateBridgeAuthority replaces the default bridge authority,
+ but leaves the directory authorities alone.
+
+[[AndroidIdentityTag]] **AndroidIdentityTag** __tag__::
+ When logging to Android's logging subsystem, adds a tag to the log identity
+ such that log entries are marked with "Tor-__tag__". Can not be changed while
+ tor is running. (Default: none)
+
+[[AvoidDiskWrites]] **AvoidDiskWrites** **0**|**1**::
+ If non-zero, try to write to disk less frequently than we would otherwise.
+ This is useful when running on flash memory or other media that support
+ only a limited number of writes. (Default: 0)
+
+[[BandwidthBurst]] **BandwidthBurst** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**TBytes**|**KBits**|**MBits**|**GBits**|**TBits**::
+ Limit the maximum token bucket size (also known as the burst) to the given
+ number of bytes in each direction. (Default: 1 GByte)
[[BandwidthRate]] **BandwidthRate** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**TBytes**|**KBits**|**MBits**|**GBits**|**TBits**::
A token bucket limits the average incoming bandwidth usage on this node
@@ -207,13 +276,13 @@ GENERAL OPTIONS
relay (that is, 600 kbits) or 50 KBytes for a bridge (400 kbits) -- but of
course, more is better; we recommend at least 250 KBytes (2 mbits) if
possible. (Default: 1 GByte) +
- +
+ +
Note that this option, and other bandwidth-limiting options, apply to TCP
data only: They do not count TCP headers or DNS traffic. +
- +
+ +
Tor uses powers of two, not powers of ten, so 1 GByte is
1024*1024*1024 bytes as opposed to 1 billion bytes. +
- +
+ +
With this option, and in other options that take arguments in bytes,
KBytes, and so on, other formats are also supported. Notably, "KBytes" can
also be written as "kilobytes" or "kb"; "MBytes" can be written as
@@ -225,41 +294,27 @@ GENERAL OPTIONS
To avoid confusion, we recommend writing "bytes" or "bits" explicitly,
since it's easy to forget that "B" means bytes, not bits.
-[[BandwidthBurst]] **BandwidthBurst** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**TBytes**|**KBits**|**MBits**|**GBits**|**TBits**::
- Limit the maximum token bucket size (also known as the burst) to the given
- number of bytes in each direction. (Default: 1 GByte)
-
-[[MaxAdvertisedBandwidth]] **MaxAdvertisedBandwidth** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**TBytes**|**KBits**|**MBits**|**GBits**|**TBits**::
- If set, we will not advertise more than this amount of bandwidth for our
- BandwidthRate. Server operators who want to reduce the number of clients
- who ask to build circuits through them (since this is proportional to
- advertised bandwidth rate) can thus reduce the CPU demands on their server
- without impacting network performance.
-
-[[RelayBandwidthRate]] **RelayBandwidthRate** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**TBytes**|**KBits**|**MBits**|**GBits**|**TBits**::
- If not 0, a separate token bucket limits the average incoming bandwidth
- usage for \_relayed traffic_ on this node to the specified number of bytes
- per second, and the average outgoing bandwidth usage to that same value.
- Relayed traffic currently is calculated to include answers to directory
- requests, but that may change in future versions. They do not include directory
- fetches by the relay (from authority or other relays), because that is considered
- "client" activity. (Default: 0)
-
-[[RelayBandwidthBurst]] **RelayBandwidthBurst** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**TBytes**|**KBits**|**MBits**|**GBits**|**TBits**::
- If not 0, limit the maximum token bucket size (also known as the burst) for
- \_relayed traffic_ to the given number of bytes in each direction.
- They do not include directory fetches by the relay (from authority
- or other relays), because that is considered "client" activity. (Default: 0)
+[[CacheDirectory]] **CacheDirectory** __DIR__::
+ Store cached directory data in DIR. Can not be changed while tor is
+ running.
+ (Default: uses the value of DataDirectory.)
-[[PerConnBWRate]] **PerConnBWRate** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**TBytes**|**KBits**|**MBits**|**GBits**|**TBits**::
- If this option is set manually, or via the "perconnbwrate" consensus
- field, Tor will use it for separate rate limiting for each connection
- from a non-relay. (Default: 0)
+[[CacheDirectoryGroupReadable]] **CacheDirectoryGroupReadable** **0**|**1**|**auto**::
+ If this option is set to 0, don't allow the filesystem group to read the
+ CacheDirectory. If the option is set to 1, make the CacheDirectory readable
+ by the default GID. If the option is "auto", then we use the
+ setting for DataDirectoryGroupReadable when the CacheDirectory is the
+ same as the DataDirectory, and 0 otherwise. (Default: auto)
-[[PerConnBWBurst]] **PerConnBWBurst** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**TBytes**|**KBits**|**MBits**|**GBits**|**TBits**::
- If this option is set manually, or via the "perconnbwburst" consensus
- field, Tor will use it for separate rate limiting for each connection
- from a non-relay. (Default: 0)
+[[CircuitPriorityHalflife]] **CircuitPriorityHalflife** __NUM__::
+ If this value is set, we override the default algorithm for choosing which
+ circuit's cell to deliver or relay next. It is delivered first to the
+ circuit that has the lowest weighted cell count, where cells are weighted
+ exponentially according to this value (in seconds). If the value is -1, it
+ is taken from the consensus if possible else it will fallback to the
+ default value of 30. Minimum: 1, Maximum: 2147483647. This can be defined
+ as a float value. This is an advanced option; you generally shouldn't have
+ to mess with it. (Default: -1)
[[ClientTransportPlugin]] **ClientTransportPlugin** __transport__ socks4|socks5 __IP__:__PORT__::
**ClientTransportPlugin** __transport__ exec __path-to-binary__ [options]::
@@ -268,70 +323,29 @@ GENERAL OPTIONS
(IPv4 addresses should written as-is; IPv6 addresses should be wrapped in
square brackets.) It's the
duty of that proxy to properly forward the traffic to the bridge. +
- +
+ +
In its second form, when set along with a corresponding Bridge line, the Tor
client launches the pluggable transport proxy executable in
__path-to-binary__ using __options__ as its command-line options, and
forwards its traffic to it. It's the duty of that proxy to properly forward
- the traffic to the bridge.
-
-[[ServerTransportPlugin]] **ServerTransportPlugin** __transport__ exec __path-to-binary__ [options]::
- The Tor relay launches the pluggable transport proxy in __path-to-binary__
- using __options__ as its command-line options, and expects to receive
- proxied client traffic from it.
-
-[[ServerTransportListenAddr]] **ServerTransportListenAddr** __transport__ __IP__:__PORT__::
- When this option is set, Tor will suggest __IP__:__PORT__ as the
- listening address of any pluggable transport proxy that tries to
- launch __transport__. (IPv4 addresses should written as-is; IPv6
- addresses should be wrapped in square brackets.)
-
-[[ServerTransportOptions]] **ServerTransportOptions** __transport__ __k=v__ __k=v__ ...::
- When this option is set, Tor will pass the __k=v__ parameters to
- any pluggable transport proxy that tries to launch __transport__. +
- (Example: ServerTransportOptions obfs45 shared-secret=bridgepasswd cache=/var/lib/tor/cache)
-
-[[ExtORPort]] **ExtORPort** \['address':]__port__|**auto**::
- Open this port to listen for Extended ORPort connections from your
- pluggable transports.
-
-[[ExtORPortCookieAuthFile]] **ExtORPortCookieAuthFile** __Path__::
- If set, this option overrides the default location and file name
- for the Extended ORPort's cookie file -- the cookie file is needed
- for pluggable transports to communicate through the Extended ORPort.
-
-[[ExtORPortCookieAuthFileGroupReadable]] **ExtORPortCookieAuthFileGroupReadable** **0**|**1**::
- If this option is set to 0, don't allow the filesystem group to read the
- Extended OR Port cookie file. If the option is set to 1, make the cookie
- file readable by the default GID. [Making the file readable by other
- groups is not yet implemented; let us know if you need this for some
- reason.] (Default: 0)
+ the traffic to the bridge. (Default: none)
[[ConnLimit]] **ConnLimit** __NUM__::
The minimum number of file descriptors that must be available to the Tor
process before it will start. Tor will ask the OS for as many file
descriptors as the OS will allow (you can find this by "ulimit -H -n").
If this number is less than ConnLimit, then Tor will refuse to start. +
- +
+ +
Tor relays need thousands of sockets, to connect to every other relay.
If you are running a private bridge, you can reduce the number of sockets
that Tor uses. For example, to limit Tor to 500 sockets, run
"ulimit -n 500" in a shell. Then start tor in the same shell, with
**ConnLimit 500**. You may also need to set **DisableOOSCheck 0**. +
- +
+ +
Unless you have severely limited sockets, you probably don't need to
adjust **ConnLimit** itself. It has no effect on Windows, since that
platform lacks getrlimit(). (Default: 1000)
-[[DisableNetwork]] **DisableNetwork** **0**|**1**::
- When this option is set, we don't listen for or accept any connections
- other than controller connections, and we close (and don't reattempt)
- any outbound
- connections. Controllers sometimes use this option to avoid using
- the network until Tor is fully configured. Tor will make still certain
- network-related calls (like DNS lookups) as a part of its configuration
- process, even if DisableNetwork is set. (Default: 0)
-
[[ConstrainedSockets]] **ConstrainedSockets** **0**|**1**::
If set, Tor will tell the kernel to attempt to shrink the buffers for all
sockets to the size specified in **ConstrainedSockSize**. This is useful for
@@ -339,15 +353,15 @@ GENERAL OPTIONS
be limited. If you're on a virtual server, and you encounter the "Error
creating network socket: No buffer space available" message, you are
likely experiencing this problem. +
- +
+ +
The preferred solution is to have the admin increase the buffer pool for
the host itself via /proc/sys/net/ipv4/tcp_mem or equivalent facility;
this configuration option is a second-resort. +
- +
+ +
The DirPort option should also not be used if TCP buffers are scarce. The
cached directory requests consume additional sockets which exacerbates
the problem. +
- +
+ +
You should **not** enable this feature unless you encounter the "no buffer
space available" issue. Reducing the TCP buffers affects window size for
the TCP stream and will reduce throughput in proportion to round trip
@@ -358,7 +372,7 @@ GENERAL OPTIONS
all sockets will be set to this limit. Must be a value between 2048 and
262144, in 1024 byte increments. Default of 8192 is recommended.
-[[ControlPort]] **ControlPort** \['address':]__port__|**unix:**__path__|**auto** [__flags__]::
+[[ControlPort]] **ControlPort** ['address'**:**]{empty}__port__|**unix:**__path__|**auto** [__flags__]::
If set, Tor will accept connections on this port and allow those
connections to control the Tor process using the Tor Control Protocol
(described in control-spec.txt in
@@ -372,8 +386,8 @@ GENERAL OPTIONS
C escape sequences. You can specify this directive multiple times, to
bind to multiple address/port pairs.
Set it to "auto" to have Tor pick a port for you. (Default: 0) +
- +
- Recognized flags are...
+ +
+ Recognized flags are:
**GroupWritable**;;
Unix domain sockets only: makes the socket get created as
group-writable.
@@ -384,6 +398,16 @@ GENERAL OPTIONS
Unix domain sockets only: Do not insist that the directory
that holds the socket be read-restricted.
+[[ControlPortFileGroupReadable]] **ControlPortFileGroupReadable** **0**|**1**::
+ If this option is set to 0, don't allow the filesystem group to read the
+ control port file. If the option is set to 1, make the control port
+ file readable by the default GID. (Default: 0)
+
+[[ControlPortWriteToFile]] **ControlPortWriteToFile** __Path__::
+ If set, Tor writes the address and port of any control port it opens to
+ this address. Usable by controllers to learn the actual control port
+ when ControlPort is set to "auto".
+
[[ControlSocket]] **ControlSocket** __Path__::
Like ControlPort, but listens on a Unix domain socket, rather than a TCP
socket. '0' disables ControlSocket. (Unix and Unix-like systems only.)
@@ -394,13 +418,6 @@ GENERAL OPTIONS
write unix sockets (e.g. ControlSocket). If the option is set to 1, make
the control socket readable and writable by the default GID. (Default: 0)
-[[HashedControlPassword]] **HashedControlPassword** __hashed_password__::
- Allow connections on the control port if they present
- the password whose one-way hash is __hashed_password__. You
- can compute the hash of a password by running "tor --hash-password
- __password__". You can provide several acceptable passwords by using more
- than one HashedControlPassword line.
-
[[CookieAuthentication]] **CookieAuthentication** **0**|**1**::
If this option is set to 1, allow connections on the control port
when the connecting process knows the contents of a file named
@@ -418,15 +435,11 @@ GENERAL OPTIONS
the default GID. [Making the file readable by other groups is not yet
implemented; let us know if you need this for some reason.] (Default: 0)
-[[ControlPortWriteToFile]] **ControlPortWriteToFile** __Path__::
- If set, Tor writes the address and port of any control port it opens to
- this address. Usable by controllers to learn the actual control port
- when ControlPort is set to "auto".
-
-[[ControlPortFileGroupReadable]] **ControlPortFileGroupReadable** **0**|**1**::
- If this option is set to 0, don't allow the filesystem group to read the
- control port file. If the option is set to 1, make the control port
- file readable by the default GID. (Default: 0)
+[[CountPrivateBandwidth]] **CountPrivateBandwidth** **0**|**1**::
+ If this option is set, then Tor's rate-limiting applies not only to
+ remote connections, but also to connections to private addresses like
+ 127.0.0.1 or 10.0.0.1. This is mostly useful for debugging
+ rate-limiting. (Default: 0)
[[DataDirectory]] **DataDirectory** __DIR__::
Store working data in DIR. Can not be changed while tor is running.
@@ -439,39 +452,6 @@ GENERAL OPTIONS
DataDirectory. If the option is set to 1, make the DataDirectory readable
by the default GID. (Default: 0)
-[[CacheDirectory]] **CacheDirectory** __DIR__::
- Store cached directory data in DIR. Can not be changed while tor is
- running.
- (Default: uses the value of DataDirectory.)
-
-[[CacheDirectoryGroupReadable]] **CacheDirectoryGroupReadable** **0**|**1**|**auto**::
- If this option is set to 0, don't allow the filesystem group to read the
- CacheDirectory. If the option is set to 1, make the CacheDirectory readable
- by the default GID. If the option is "auto", then we use the
- setting for DataDirectoryGroupReadable when the CacheDirectory is the
- same as the DataDirectory, and 0 otherwise. (Default: auto)
-
-[[FallbackDir]] **FallbackDir** __ipv4address__:__dirport__ orport=__orport__ id=__fingerprint__ [weight=__num__] [ipv6=**[**__ipv6address__**]**:__orport__]::
- When tor is unable to connect to any directory cache for directory info
- (usually because it doesn't know about any yet) it tries a hard-coded
- directory. Relays try one directory authority at a time. Clients try
- multiple directory authorities and FallbackDirs, to avoid hangs on
- startup if a hard-coded directory is down. Clients wait for a few seconds
- between each attempt, and retry FallbackDirs more often than directory
- authorities, to reduce the load on the directory authorities. +
- +
- FallbackDirs should be stable relays with stable IP addresses, ports,
- and identity keys. They must have a DirPort. +
- +
- By default, the directory authorities are also FallbackDirs. Specifying a
- FallbackDir replaces Tor's default hard-coded FallbackDirs (if any).
- (See the **DirAuthority** entry for an explanation of each flag.)
-
-[[UseDefaultFallbackDirs]] **UseDefaultFallbackDirs** **0**|**1**::
- Use Tor's default hard-coded FallbackDirs (if any). (When a
- FallbackDir line is present, it replaces the hard-coded FallbackDirs,
- regardless of the value of UseDefaultFallbackDirs.) (Default: 1)
-
[[DirAuthority]] **DirAuthority** [__nickname__] [**flags**] __ipv4address__:__dirport__ __fingerprint__::
Use a nonstandard authoritative directory server at the provided address
and port, with the specified key fingerprint. This option can be repeated
@@ -479,7 +459,7 @@ GENERAL OPTIONS
separated by spaces, and determine what kind of an authority this directory
is. By default, an authority is not authoritative for any directory style
or version unless an appropriate flag is given. +
- +
+ +
Tor will use this authority as a bridge authoritative directory if the
"bridge" flag is set. If a flag "orport=**orport**" is given, Tor will
use the given port when opening encrypted tunnels to the dirserver. If a
@@ -490,13 +470,13 @@ GENERAL OPTIONS
if an "ipv6=**[**__ipv6address__**]**:__orport__" flag is present, then
the directory authority is listening for IPv6 connections on the
indicated IPv6 address and OR Port. +
- +
+ +
Tor will contact the authority at __ipv4address__ to
download directory documents. Clients always use the ORPort. Relays
usually use the DirPort, but will use the ORPort in some circumstances.
If an IPv6 ORPort is supplied, clients will also download directory
documents at the IPv6 ORPort, if they are configured to use IPv6. +
- +
+ +
If no **DirAuthority** line is given, Tor will use the default directory
authorities. NOTE: this option is intended for setting up a private Tor
network with its own directory authorities. If you use it, you will be
@@ -510,17 +490,6 @@ GENERAL OPTIONS
should be 1.0 or less. The default is less than 1, to reduce load on
authorities. (Default: 0.1)
-[[AlternateDirAuthority]] **AlternateDirAuthority** [__nickname__] [**flags**] __ipv4address__:__port__ __fingerprint__ +
-
-[[AlternateBridgeAuthority]] **AlternateBridgeAuthority** [__nickname__] [**flags**] __ipv4address__:__port__ __ fingerprint__::
- These options behave as DirAuthority, but they replace fewer of the
- default directory authorities. Using
- AlternateDirAuthority replaces the default Tor directory authorities, but
- leaves the default bridge authorities in
- place. Similarly,
- AlternateBridgeAuthority replaces the default bridge authority,
- but leaves the directory authorities alone.
-
[[DisableAllSwap]] **DisableAllSwap** **0**|**1**::
If set to 1, Tor will attempt to lock all current and future memory pages,
so that memory cannot be paged out. Windows, OS X and Solaris are currently
@@ -545,6 +514,55 @@ GENERAL OPTIONS
this to 0 for the duration of your debugging. Normal users should leave it
on. Disabling this option while Tor is running is prohibited. (Default: 1)
+[[DisableNetwork]] **DisableNetwork** **0**|**1**::
+ When this option is set, we don't listen for or accept any connections
+ other than controller connections, and we close (and don't reattempt)
+ any outbound
+ connections. Controllers sometimes use this option to avoid using
+ the network until Tor is fully configured. Tor will make still certain
+ network-related calls (like DNS lookups) as a part of its configuration
+ process, even if DisableNetwork is set. (Default: 0)
+
+[[ExtendByEd25519ID]] **ExtendByEd25519ID** **0**|**1**|**auto**::
+ If this option is set to 1, we always try to include a relay's Ed25519 ID
+ when telling the preceding relay in a circuit to extend to it.
+ If this option is set to 0, we never include Ed25519 IDs when extending
+ circuits. If the option is set to "auto", we obey a
+ parameter in the consensus document. (Default: auto)
+
+[[ExtORPort]] **ExtORPort** ['address'**:**]{empty}__port__|**auto**::
+ Open this port to listen for Extended ORPort connections from your
+ pluggable transports. +
+ (Default: **DataDirectory**/extended_orport_auth_cookie)
+
+[[ExtORPortCookieAuthFile]] **ExtORPortCookieAuthFile** __Path__::
+ If set, this option overrides the default location and file name
+ for the Extended ORPort's cookie file -- the cookie file is needed
+ for pluggable transports to communicate through the Extended ORPort.
+
+[[ExtORPortCookieAuthFileGroupReadable]] **ExtORPortCookieAuthFileGroupReadable** **0**|**1**::
+ If this option is set to 0, don't allow the filesystem group to read the
+ Extended OR Port cookie file. If the option is set to 1, make the cookie
+ file readable by the default GID. [Making the file readable by other
+ groups is not yet implemented; let us know if you need this for some
+ reason.] (Default: 0)
+
+[[FallbackDir]] **FallbackDir** __ipv4address__:__dirport__ orport=__orport__ id=__fingerprint__ [weight=__num__] [ipv6=**[**__ipv6address__**]**:__orport__]::
+ When tor is unable to connect to any directory cache for directory info
+ (usually because it doesn't know about any yet) it tries a hard-coded
+ directory. Relays try one directory authority at a time. Clients try
+ multiple directory authorities and FallbackDirs, to avoid hangs on
+ startup if a hard-coded directory is down. Clients wait for a few seconds
+ between each attempt, and retry FallbackDirs more often than directory
+ authorities, to reduce the load on the directory authorities. +
+ +
+ FallbackDirs should be stable relays with stable IP addresses, ports,
+ and identity keys. They must have a DirPort. +
+ +
+ By default, the directory authorities are also FallbackDirs. Specifying a
+ FallbackDir replaces Tor's default hard-coded FallbackDirs (if any).
+ (See the **DirAuthority** entry for an explanation of each flag.)
+
[[FetchDirInfoEarly]] **FetchDirInfoEarly** **0**|**1**::
If set to 1, Tor will always fetch directory information like other
directory caches, even if you don't meet the normal criteria for fetching
@@ -584,6 +602,17 @@ GENERAL OPTIONS
flavour of consensues and descriptors that is fetched and used for
building circuits. (Default: 0)
+[[HardwareAccel]] **HardwareAccel** **0**|**1**::
+ If non-zero, try to use built-in (static) crypto hardware acceleration when
+ available. Can not be changed while tor is running. (Default: 0)
+
+[[HashedControlPassword]] **HashedControlPassword** __hashed_password__::
+ Allow connections on the control port if they present
+ the password whose one-way hash is __hashed_password__. You
+ can compute the hash of a password by running "tor --hash-password
+ __password__". You can provide several acceptable passwords by using more
+ than one HashedControlPassword line.
+
[[HTTPProxy]] **HTTPProxy** __host__[:__port__]::
Tor will make all its directory requests through this host:port (or host:80
if port is not specified), rather than connecting directly to any directory
@@ -609,57 +638,19 @@ GENERAL OPTIONS
proxy authentication that Tor supports; feel free to submit a patch if you
want it to support others.
-[[Sandbox]] **Sandbox** **0**|**1**::
- If set to 1, Tor will run securely through the use of a syscall sandbox.
- Otherwise the sandbox will be disabled. The option is currently an
- experimental feature. It only works on Linux-based operating systems,
- and only when Tor has been built with the libseccomp library. This option
- can not be changed while tor is running. +
- +
- When the **Sandbox** is 1, the following options can not be changed when tor
- is running:
- **Address**,
- **ConnLimit**,
- **CookieAuthFile**,
- **DirPortFrontPage**,
- **ExtORPortCookieAuthFile**,
- **Logs**,
- **ServerDNSResolvConfFile**,
- **ClientOnionAuthDir** (and any files in it won't reload on HUP signal).
- +
- Launching new Onion Services through the control port is not supported
- with current syscall sandboxing implementation.
- +
- Tor must remain in client or server mode (some changes to **ClientOnly**
- and **ORPort** are not allowed). Currently, if **Sandbox** is 1,
- **ControlPort** command "GETINFO address" will not work.
- +
- (Default: 0)
-
-[[Socks4Proxy]] **Socks4Proxy** __host__[:__port__]::
- Tor will make all OR connections through the SOCKS 4 proxy at host:port
- (or host:1080 if port is not specified).
-
-[[Socks5Proxy]] **Socks5Proxy** __host__[:__port__]::
- Tor will make all OR connections through the SOCKS 5 proxy at host:port
- (or host:1080 if port is not specified).
-
-[[Socks5ProxyUsername]] **Socks5ProxyUsername** __username__ +
-
-[[Socks5ProxyPassword]] **Socks5ProxyPassword** __password__::
- If defined, authenticate to the SOCKS 5 server using username and password
- in accordance to RFC 1929. Both username and password must be between 1 and
- 255 characters.
-
-[[UnixSocksGroupWritable]] **UnixSocksGroupWritable** **0**|**1**::
- If this option is set to 0, don't allow the filesystem group to read and
- write unix sockets (e.g. SocksPort unix:). If the option is set to 1, make
- the Unix socket readable and writable by the default GID. (Default: 0)
-
[[KeepalivePeriod]] **KeepalivePeriod** __NUM__::
To keep firewalls from expiring connections, send a padding keepalive cell
every NUM seconds on open connections that are in use. (Default: 5 minutes)
+[[KeepBindCapabilities]] **KeepBindCapabilities** **0**|**1**|**auto**::
+ On Linux, when we are started as root and we switch our identity using
+ the **User** option, the **KeepBindCapabilities** option tells us whether to
+ try to retain our ability to bind to low ports. If this value is 1, we
+ try to keep the capability; if it is 0 we do not; and if it is **auto**,
+ we keep the capability only if we are configured to listen on a low port.
+ Can not be changed while tor is running.
+ (Default: auto.)
+
[[Log]] **Log** __minSeverity__[-__maxSeverity__] **stderr**|**stdout**|**syslog**::
Send all messages between __minSeverity__ and __maxSeverity__ to the standard
output stream, the standard error stream, or to the system log. (The
@@ -668,7 +659,7 @@ GENERAL OPTIONS
since anything more verbose may provide sensitive information to an
attacker who obtains the logs. If only one severity level is given, all
messages of that level or higher will be sent to the listed destination. +
- +
+ +
Some low-level logs may be sent from signal handlers, so their destination
logs must be signal-safe. These low-level logs include backtraces,
logging function errors, and errors in code called by logging functions.
@@ -694,16 +685,16 @@ GENERAL OPTIONS
list of logging domains. You can prefix a domain with $$~$$ to indicate
negation, and use * to indicate "all domains". If you specify a severity
range without a list of domains, it matches all domains. +
- +
+ +
This is an advanced feature which is most useful for debugging one or two
of Tor's subsystems at a time. +
- +
+ +
The currently recognized domains are: general, crypto, net, config, fs,
protocol, mm, http, app, control, circ, rend, bug, dir, dirserv, or, edge,
acct, hist, handshake, heartbeat, channel, sched, guard, consdiff, dos,
process, pt, btrack, and mesg.
Domain names are case-insensitive. +
- +
+ +
For example, "`Log [handshake]debug [~net,~mm]info notice stdout`" sends
to stdout: all handshake messages of any severity, all info-and-higher
messages from domains other than networking and memory management, and all
@@ -714,12 +705,33 @@ GENERAL OPTIONS
message currently has at least one domain; most currently have exactly
one. This doesn't affect controller log messages. (Default: 0)
+[[LogTimeGranularity]] **LogTimeGranularity** __NUM__::
+ Set the resolution of timestamps in Tor's logs to NUM milliseconds.
+ NUM must be positive and either a divisor or a multiple of 1 second.
+ Note that this option only controls the granularity written by Tor to
+ a file or console log. Tor does not (for example) "batch up" log
+ messages to affect times logged by a controller, times attached to
+ syslog messages, or the mtime fields on log files. (Default: 1 second)
+
+[[MaxAdvertisedBandwidth]] **MaxAdvertisedBandwidth** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**TBytes**|**KBits**|**MBits**|**GBits**|**TBits**::
+ If set, we will not advertise more than this amount of bandwidth for our
+ BandwidthRate. Server operators who want to reduce the number of clients
+ who ask to build circuits through them (since this is proportional to
+ advertised bandwidth rate) can thus reduce the CPU demands on their server
+ without impacting network performance.
+
[[MaxUnparseableDescSizeToLog]] **MaxUnparseableDescSizeToLog** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**TBytes**::
Unparseable descriptors (e.g. for votes, consensuses, routers) are logged
in separate files by hash, up to the specified size in total. Note that
only files logged during the lifetime of this Tor process count toward the
total; this is intended to be used to debug problems without opening live
- servers to resource exhaustion attacks. (Default: 10 MB)
+ servers to resource exhaustion attacks. (Default: 10 MBytes)
+
+[[NoExec]] **NoExec** **0**|**1**::
+ If this option is set to 1, then Tor will never launch another
+ executable, regardless of the settings of ClientTransportPlugin
+ or ServerTransportPlugin. Once this option has been set to 1,
+ it cannot be set back to 0 without restarting Tor. (Default: 0)
[[OutboundBindAddress]] **OutboundBindAddress** __IP__::
Make all outbound connections originate from the IP address specified. This
@@ -730,6 +742,15 @@ GENERAL OPTIONS
This setting will be ignored for connections to the loopback addresses
(127.0.0.0/8 and ::1), and is not used for DNS requests as well.
+[[OutboundBindAddressExit]] **OutboundBindAddressExit** __IP__::
+ Make all outbound exit connections originate from the IP address
+ specified. This option overrides **OutboundBindAddress** for the
+ same IP version. This option may be used twice, once with an IPv4
+ address and once with an IPv6 address.
+ IPv6 addresses should be wrapped in square brackets.
+ This setting will be ignored
+ for connections to the loopback addresses (127.0.0.0/8 and ::1).
+
[[OutboundBindAddressOR]] **OutboundBindAddressOR** __IP__::
Make all outbound non-exit (relay and other) connections
originate from the IP address specified. This option overrides
@@ -739,14 +760,20 @@ GENERAL OPTIONS
This setting will be ignored for connections to the loopback
addresses (127.0.0.0/8 and ::1).
-[[OutboundBindAddressExit]] **OutboundBindAddressExit** __IP__::
- Make all outbound exit connections originate from the IP address
- specified. This option overrides **OutboundBindAddress** for the
- same IP version. This option may be used twice, once with an IPv4
- address and once with an IPv6 address.
- IPv6 addresses should be wrapped in square brackets.
- This setting will be ignored
- for connections to the loopback addresses (127.0.0.0/8 and ::1).
+[[OwningControllerProcess]] **{dbl_}OwningControllerProcess** __PID__::
+ Make Tor instance periodically check for presence of a controller process
+ with given PID and terminate itself if this process is no longer alive.
+ Polling interval is 15 seconds.
+
+[[PerConnBWBurst]] **PerConnBWBurst** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**TBytes**|**KBits**|**MBits**|**GBits**|**TBits**::
+ If this option is set manually, or via the "perconnbwburst" consensus
+ field, Tor will use it for separate rate limiting for each connection
+ from a non-relay. (Default: 0)
+
+[[PerConnBWRate]] **PerConnBWRate** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**TBytes**|**KBits**|**MBits**|**GBits**|**TBits**::
+ If this option is set manually, or via the "perconnbwrate" consensus
+ field, Tor will use it for separate rate limiting for each connection
+ from a non-relay. (Default: 0)
[[PidFile]] **PidFile** __FILE__::
On startup, write our PID to FILE. On clean shutdown, remove
@@ -757,40 +784,38 @@ GENERAL OPTIONS
following the Tor specification. Otherwise, they are logged with severity
\'info'. (Default: 0)
+[[RelayBandwidthBurst]] **RelayBandwidthBurst** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**TBytes**|**KBits**|**MBits**|**GBits**|**TBits**::
+ If not 0, limit the maximum token bucket size (also known as the burst) for
+ \_relayed traffic_ to the given number of bytes in each direction.
+ They do not include directory fetches by the relay (from authority
+ or other relays), because that is considered "client" activity. (Default: 0)
+
+[[RelayBandwidthRate]] **RelayBandwidthRate** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**TBytes**|**KBits**|**MBits**|**GBits**|**TBits**::
+ If not 0, a separate token bucket limits the average incoming bandwidth
+ usage for \_relayed traffic_ on this node to the specified number of bytes
+ per second, and the average outgoing bandwidth usage to that same value.
+ Relayed traffic currently is calculated to include answers to directory
+ requests, but that may change in future versions. They do not include directory
+ fetches by the relay (from authority or other relays), because that is considered
+ "client" activity. (Default: 0)
+
+[[RephistTrackTime]] **RephistTrackTime** __N__ **seconds**|**minutes**|**hours**|**days**|**weeks**::
+ Tells an authority, or other node tracking node reliability and history,
+ that fine-grained information about nodes can be discarded when it hasn't
+ changed for a given amount of time. (Default: 24 hours)
+
[[RunAsDaemon]] **RunAsDaemon** **0**|**1**::
If 1, Tor forks and daemonizes to the background. This option has no effect
on Windows; instead you should use the --service command-line option.
Can not be changed while tor is running.
(Default: 0)
-[[LogTimeGranularity]] **LogTimeGranularity** __NUM__::
- Set the resolution of timestamps in Tor's logs to NUM milliseconds.
- NUM must be positive and either a divisor or a multiple of 1 second.
- Note that this option only controls the granularity written by Tor to
- a file or console log. Tor does not (for example) "batch up" log
- messages to affect times logged by a controller, times attached to
- syslog messages, or the mtime fields on log files. (Default: 1 second)
-
-[[TruncateLogFile]] **TruncateLogFile** **0**|**1**::
- If 1, Tor will overwrite logs at startup and in response to a HUP signal,
- instead of appending to them. (Default: 0)
-
-[[SyslogIdentityTag]] **SyslogIdentityTag** __tag__::
- When logging to syslog, adds a tag to the syslog identity such that
- log entries are marked with "Tor-__tag__". Can not be changed while tor is
- running. (Default: none)
-
-[[AndroidIdentityTag]] **AndroidIdentityTag** __tag__::
- When logging to Android's logging subsystem, adds a tag to the log identity
- such that log entries are marked with "Tor-__tag__". Can not be changed while
- tor is running. (Default: none)
-
[[SafeLogging]] **SafeLogging** **0**|**1**|**relay**::
Tor can scrub potentially sensitive strings from log messages (e.g.
addresses) by replacing them with the string [scrubbed]. This way logs can
still be useful, but they don't leave behind personally identifying
information about what sites a user might have visited. +
- +
+ +
If this option is set to 0, Tor will not perform any scrubbing, if it is
set to 1, all potentially sensitive strings are replaced. If it is set to
relay, all log messages generated when acting as a relay are sanitized, but
@@ -798,67 +823,32 @@ GENERAL OPTIONS
Note: Tor may not heed this option when logging at log levels below Notice.
(Default: 1)
-[[User]] **User** __Username__::
- On startup, setuid to this user and setgid to their primary group.
- Can not be changed while tor is running.
-
-[[KeepBindCapabilities]] **KeepBindCapabilities** **0**|**1**|**auto**::
- On Linux, when we are started as root and we switch our identity using
- the **User** option, the **KeepBindCapabilities** option tells us whether to
- try to retain our ability to bind to low ports. If this value is 1, we
- try to keep the capability; if it is 0 we do not; and if it is **auto**,
- we keep the capability only if we are configured to listen on a low port.
- Can not be changed while tor is running.
- (Default: auto.)
-
-[[HardwareAccel]] **HardwareAccel** **0**|**1**::
- If non-zero, try to use built-in (static) crypto hardware acceleration when
- available. Can not be changed while tor is running. (Default: 0)
-
-[[AccelName]] **AccelName** __NAME__::
- When using OpenSSL hardware crypto acceleration attempt to load the dynamic
- engine of this name. This must be used for any dynamic hardware engine.
- Names can be verified with the openssl engine command. Can not be changed
- while tor is running.
-
-[[AccelDir]] **AccelDir** __DIR__::
- Specify this option if using dynamic hardware acceleration and the engine
- implementation library resides somewhere other than the OpenSSL default.
- Can not be changed while tor is running.
-
-[[AvoidDiskWrites]] **AvoidDiskWrites** **0**|**1**::
- If non-zero, try to write to disk less frequently than we would otherwise.
- This is useful when running on flash memory or other media that support
- only a limited number of writes. (Default: 0)
-
-[[CircuitPriorityHalflife]] **CircuitPriorityHalflife** __NUM__::
- If this value is set, we override the default algorithm for choosing which
- circuit's cell to deliver or relay next. It is delivered first to the
- circuit that has the lowest weighted cell count, where cells are weighted
- exponentially according to this value (in seconds). If the value is -1, it
- is taken from the consensus if possible else it will fallback to the
- default value of 30. Minimum: 1, Maximum: 2147483647. This can be defined
- as a float value. This is an advanced option; you generally shouldn't have
- to mess with it. (Default: -1)
-
-[[CountPrivateBandwidth]] **CountPrivateBandwidth** **0**|**1**::
- If this option is set, then Tor's rate-limiting applies not only to
- remote connections, but also to connections to private addresses like
- 127.0.0.1 or 10.0.0.1. This is mostly useful for debugging
- rate-limiting. (Default: 0)
-
-[[ExtendByEd25519ID]] **ExtendByEd25519ID** **0**|**1**|**auto**::
- If this option is set to 1, we always try to include a relay's Ed25519 ID
- when telling the proceeding relay in a circuit to extend to it.
- If this option is set to 0, we never include Ed25519 IDs when extending
- circuits. If the option is set to "default", we obey a
- parameter in the consensus document. (Default: auto)
-
-[[NoExec]] **NoExec** **0**|**1**::
- If this option is set to 1, then Tor will never launch another
- executable, regardless of the settings of ClientTransportPlugin
- or ServerTransportPlugin. Once this option has been set to 1,
- it cannot be set back to 0 without restarting Tor. (Default: 0)
+[[Sandbox]] **Sandbox** **0**|**1**::
+ If set to 1, Tor will run securely through the use of a syscall sandbox.
+ Otherwise the sandbox will be disabled. The option is currently an
+ experimental feature. It only works on Linux-based operating systems,
+ and only when Tor has been built with the libseccomp library. This option
+ can not be changed while tor is running. +
+ +
+ When the **Sandbox** is 1, the following options can not be changed when tor
+ is running:
+ **Address**,
+ **ConnLimit**,
+ **CookieAuthFile**,
+ **DirPortFrontPage**,
+ **ExtORPortCookieAuthFile**,
+ **Logs**,
+ **ServerDNSResolvConfFile**,
+ **ClientOnionAuthDir** (and any files in it won't reload on HUP signal). +
+ +
+ Launching new Onion Services through the control port is not supported
+ with current syscall sandboxing implementation. +
+ +
+ Tor must remain in client or server mode (some changes to **ClientOnly**
+ and **ORPort** are not allowed). Currently, if **Sandbox** is 1,
+ **ControlPort** command "GETINFO address" will not work. +
+ +
+ (Default: 0)
[[Schedulers]] **Schedulers** **KIST**|**KISTLite**|**Vanilla**::
Specify the scheduler type that tor should use. The scheduler is
@@ -867,44 +857,137 @@ GENERAL OPTIONS
unavailable, the second one is tried and so on. It is possible to change
these values at runtime. This option mostly effects relays, and most
operators should leave it set to its default value.
- (Default: KIST,KISTLite,Vanilla)
- +
+ (Default: KIST,KISTLite,Vanilla) +
+ +
The possible scheduler types are:
- +
+ +
**KIST**: Kernel-Informed Socket Transport. Tor will use TCP information
from the kernel to make informed decisions regarding how much data to send
and when to send it. KIST also handles traffic in batches (see
KISTSchedRunInterval) in order to improve traffic prioritization decisions.
As implemented, KIST will only work on Linux kernel version 2.6.39 or
- higher.
- +
+ higher. +
+ +
**KISTLite**: Same as KIST but without kernel support. Tor will use all
the same mechanics as with KIST, including the batching, but its decisions
regarding how much data to send will not be as good. KISTLite will work on
all kernels and operating systems, and the majority of the benefits of KIST
- are still realized with KISTLite.
- +
+ are still realized with KISTLite. +
+ +
**Vanilla**: The scheduler that Tor used before KIST was implemented. It
sends as much data as possible, as soon as possible. Vanilla will work on
all kernels and operating systems.
+// Out of order because it logically belongs near the Schedulers option
[[KISTSchedRunInterval]] **KISTSchedRunInterval** __NUM__ **msec**::
If KIST or KISTLite is used in the Schedulers option, this controls at which
interval the scheduler tick is. If the value is 0 msec, the value is taken
from the consensus if possible else it will fallback to the default 10
msec. Maximum possible value is 100 msec. (Default: 0 msec)
+// Out of order because it logically belongs near the Schedulers option
[[KISTSockBufSizeFactor]] **KISTSockBufSizeFactor** __NUM__::
If KIST is used in Schedulers, this is a multiplier of the per-socket
limit calculation of the KIST algorithm. (Default: 1.0)
-CLIENT OPTIONS
---------------
+
+[[ServerTransportListenAddr]] **ServerTransportListenAddr** __transport__ __IP__:__PORT__::
+ When this option is set, Tor will suggest __IP__:__PORT__ as the
+ listening address of any pluggable transport proxy that tries to
+ launch __transport__. (IPv4 addresses should written as-is; IPv6
+ addresses should be wrapped in square brackets.) (Default: none)
+
+[[ServerTransportOptions]] **ServerTransportOptions** __transport__ __k=v__ __k=v__ ...::
+ When this option is set, Tor will pass the __k=v__ parameters to
+ any pluggable transport proxy that tries to launch __transport__. +
+ (Example: ServerTransportOptions obfs45 shared-secret=bridgepasswd cache=/var/lib/tor/cache) (Default: none)
+
+[[ServerTransportPlugin]] **ServerTransportPlugin** __transport__ exec __path-to-binary__ [options]::
+ The Tor relay launches the pluggable transport proxy in __path-to-binary__
+ using __options__ as its command-line options, and expects to receive
+ proxied client traffic from it. (Default: none)
+
+[[Socks4Proxy]] **Socks4Proxy** __host__[:__port__]::
+ Tor will make all OR connections through the SOCKS 4 proxy at host:port
+ (or host:1080 if port is not specified).
+
+[[Socks5Proxy]] **Socks5Proxy** __host__[:__port__]::
+ Tor will make all OR connections through the SOCKS 5 proxy at host:port
+ (or host:1080 if port is not specified).
+
+// Out of order because Username logically precedes Password
+[[Socks5ProxyUsername]] **Socks5ProxyUsername** __username__ +
+
+[[Socks5ProxyPassword]] **Socks5ProxyPassword** __password__::
+ If defined, authenticate to the SOCKS 5 server using username and password
+ in accordance to RFC 1929. Both username and password must be between 1 and
+ 255 characters.
+
+[[SyslogIdentityTag]] **SyslogIdentityTag** __tag__::
+ When logging to syslog, adds a tag to the syslog identity such that
+ log entries are marked with "Tor-__tag__". Can not be changed while tor is
+ running. (Default: none)
+
+[[TCPProxy]] **TCPProxy** __protocol__ __host__:__port__::
+ Tor will use the given protocol to make all its OR (SSL) connections through
+ a TCP proxy on host:port, rather than connecting directly to servers. You may
+ want to set **FascistFirewall** to restrict the set of ports you might try to
+ connect to, if your proxy only allows connecting to certain ports. There is no
+ equivalent option for directory connections, because all Tor client versions
+ that support this option download directory documents via OR connections. +
++
+ The only protocol supported right now 'haproxy'. This option is only for
+ clients. (Default: none) +
++
+ The HAProxy version 1 proxy protocol is described in detail at
+ https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt +
++
+ Both source IP address and source port will be set to zero.
+
+[[TruncateLogFile]] **TruncateLogFile** **0**|**1**::
+ If 1, Tor will overwrite logs at startup and in response to a HUP signal,
+ instead of appending to them. (Default: 0)
+
+[[UnixSocksGroupWritable]] **UnixSocksGroupWritable** **0**|**1**::
+ If this option is set to 0, don't allow the filesystem group to read and
+ write unix sockets (e.g. SocksPort unix:). If the option is set to 1, make
+ the Unix socket readable and writable by the default GID. (Default: 0)
+
+[[UseDefaultFallbackDirs]] **UseDefaultFallbackDirs** **0**|**1**::
+ Use Tor's default hard-coded FallbackDirs (if any). (When a
+ FallbackDir line is present, it replaces the hard-coded FallbackDirs,
+ regardless of the value of UseDefaultFallbackDirs.) (Default: 1)
+
+[[User]] **User** __Username__::
+ On startup, setuid to this user and setgid to their primary group.
+ Can not be changed while tor is running.
+
+== CLIENT OPTIONS
+
+// These options are in alphabetical order, with exceptions as noted.
+// Please keep them that way!
The following options are useful only for clients (that is, if
**SocksPort**, **HTTPTunnelPort**, **TransPort**, **DNSPort**, or
**NATDPort** is non-zero):
+[[AllowNonRFC953Hostnames]] **AllowNonRFC953Hostnames** **0**|**1**::
+ When this option is disabled, Tor blocks hostnames containing illegal
+ characters (like @ and :) rather than sending them to an exit node to be
+ resolved. This helps trap accidental attempts to resolve URLs and so on.
+ (Default: 0)
+
+[[AutomapHostsOnResolve]] **AutomapHostsOnResolve** **0**|**1**::
+ When this option is enabled, and we get a request to resolve an address
+ that ends with one of the suffixes in **AutomapHostsSuffixes**, we map an
+ unused virtual address to that address, and return the new virtual address.
+ This is handy for making ".onion" addresses work with applications that
+ resolve an address and then connect to it. (Default: 0)
+
+[[AutomapHostsSuffixes]] **AutomapHostsSuffixes** __SUFFIX__,__SUFFIX__,__...__::
+ A comma-separated list of suffixes to use with **AutomapHostsOnResolve**.
+ The "." suffix is equivalent to "all addresses." (Default: .exit,.onion).
+
[[Bridge]] **Bridge** [__transport__] __IP__:__ORPort__ [__fingerprint__]::
When set along with UseBridges, instructs Tor to use the relay at
"IP:ORPort" as a "bridge" relaying into the Tor network. If "fingerprint"
@@ -912,45 +995,86 @@ The following options are useful only for clients (that is, if
the relay running at that location has the right fingerprint. We also use
fingerprint to look up the bridge descriptor at the bridge authority, if
it's provided and if UpdateBridgesFromAuthority is set too. +
- +
+ +
If "transport" is provided, it must match a ClientTransportPlugin line. We
then use that pluggable transport's proxy to transfer data to the bridge,
rather than connecting to the bridge directly. Some transports use a
transport-specific method to work out the remote address to connect to.
These transports typically ignore the "IP:ORPort" specified in the bridge
line. +
- +
+ +
Tor passes any "key=val" settings to the pluggable transport proxy as
per-connection arguments when connecting to the bridge. Consult
the documentation of the pluggable transport for details of what
arguments it supports.
-[[LearnCircuitBuildTimeout]] **LearnCircuitBuildTimeout** **0**|**1**::
- If 0, CircuitBuildTimeout adaptive learning is disabled. (Default: 1)
+[[CircuitPadding]] **CircuitPadding** **0**|**1**::
+ If set to 0, Tor will not pad client circuits with additional cover
+ traffic. Only clients may set this option. This option should be offered
+ via the UI to mobile users for use where bandwidth may be expensive. If
+ set to 1, padding will be negotiated as per the consensus and relay
+ support (unlike ConnectionPadding, CircuitPadding cannot be force-enabled).
+ (Default: 1)
-[[CircuitBuildTimeout]] **CircuitBuildTimeout** __NUM__::
+// Out of order because it logically belongs after CircuitPadding
+[[ReducedCircuitPadding]] **ReducedCircuitPadding** **0**|**1**::
+ If set to 1, Tor will only use circuit padding algorithms that have low
+ overhead. Only clients may set this option. This option should be offered
+ via the UI to mobile users for use where bandwidth may be expensive.
+ (Default: 0)
- Try for at most NUM seconds when building circuits. If the circuit isn't
- open in that time, give up on it. If LearnCircuitBuildTimeout is 1, this
- value serves as the initial value to use before a timeout is learned. If
- LearnCircuitBuildTimeout is 0, this value is the only value used.
- (Default: 60 seconds)
+[[ClientAutoIPv6ORPort]] **ClientAutoIPv6ORPort** **0**|**1**::
+ If this option is set to 1, Tor clients randomly prefer a node's IPv4 or
+ IPv6 ORPort. The random preference is set every time a node is loaded
+ from a new consensus or bridge config. When this option is set to 1,
+ **ClientPreferIPv6ORPort** is ignored. (Default: 0) (DEPRECATED: This
+ option is unreliable if a connection isn't reliably dual-stack.)
-[[CircuitsAvailableTimeout]] **CircuitsAvailableTimeout** __NUM__::
- Tor will attempt to keep at least one open, unused circuit available for
- this amount of time. This option governs how long idle circuits are kept
- open, as well as the amount of time Tor will keep a circuit open to each
- of the recently used ports. This way when the Tor client is entirely
- idle, it can expire all of its circuits, and then expire its TLS
- connections. Note that the actual timeout value is uniformly randomized
- from the specified value to twice that amount. (Default: 30 minutes;
- Max: 24 hours)
+[[ClientBootstrapConsensusAuthorityDownloadInitialDelay]] **ClientBootstrapConsensusAuthorityDownloadInitialDelay** __N__::
+ Initial delay in seconds for when clients should download consensuses from authorities
+ if they are bootstrapping (that is, they don't have a usable, reasonably
+ live consensus). Only used by clients fetching from a list of fallback
+ directory mirrors. This schedule is advanced by (potentially concurrent)
+ connection attempts, unlike other schedules, which are advanced by
+ connection failures. (Default: 6)
-[[CircuitStreamTimeout]] **CircuitStreamTimeout** __NUM__::
- If non-zero, this option overrides our internal timeout schedule for how
- many seconds until we detach a stream from a circuit and try a new circuit.
- If your network is particularly slow, you might want to set this to a
- number like 60. (Default: 0)
+[[ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay]] **ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay** __N__::
+ Initial delay in seconds for when clients should download consensuses from authorities
+ if they are bootstrapping (that is, they don't have a usable, reasonably
+ live consensus). Only used by clients which don't have or won't fetch
+ from a list of fallback directory mirrors. This schedule is advanced by
+ (potentially concurrent) connection attempts, unlike other schedules,
+ which are advanced by connection failures. (Default: 0)
+
+[[ClientBootstrapConsensusFallbackDownloadInitialDelay]] **ClientBootstrapConsensusFallbackDownloadInitialDelay** __N__::
+ Initial delay in seconds for when clients should download consensuses from fallback
+ directory mirrors if they are bootstrapping (that is, they don't have a
+ usable, reasonably live consensus). Only used by clients fetching from a
+ list of fallback directory mirrors. This schedule is advanced by
+ (potentially concurrent) connection attempts, unlike other schedules,
+ which are advanced by connection failures. (Default: 0)
+
+[[ClientBootstrapConsensusMaxInProgressTries]] **ClientBootstrapConsensusMaxInProgressTries** __NUM__::
+ Try this many simultaneous connections to download a consensus before
+ waiting for one to complete, timeout, or error out. (Default: 3)
+
+[[ClientDNSRejectInternalAddresses]] **ClientDNSRejectInternalAddresses** **0**|**1**::
+ If true, Tor does not believe any anonymously retrieved DNS answer that
+ tells it that an address resolves to an internal address (like 127.0.0.1 or
+ 192.168.0.1). This option prevents certain browser-based attacks; it
+ is not allowed to be set on the default network. (Default: 1)
+
+[[ClientOnionAuthDir]] **ClientOnionAuthDir** __path__::
+ Path to the directory containing v3 hidden service authorization files.
+ Each file is for a single onion address, and the files MUST have the suffix
+ ".auth_private" (i.e. "bob_onion.auth_private"). The content format MUST be:
+ +
+ <onion-address>:descriptor:x25519:<base32-encoded-privkey>
+ +
+ The <onion-address> MUST NOT have the ".onion" suffix. The
+ <base32-encoded-privkey> is the base32 representation of the raw key bytes
+ only (32 bytes for x25519). See Appendix G in the rend-spec-v3.txt file of
+ https://spec.torproject.org/[torspec] for more information.
[[ClientOnly]] **ClientOnly** **0**|**1**::
If set to 1, Tor will not run as a relay or serve
@@ -961,6 +1085,43 @@ The following options are useful only for clients (that is, if
and fast enough. The current behavior is simply that Tor is a client
unless ORPort, ExtORPort, or DirPort are configured.) (Default: 0)
+[[ClientPreferIPv6DirPort]] **ClientPreferIPv6DirPort** **0**|**1**|**auto**::
+ If this option is set to 1, Tor prefers a directory port with an IPv6
+ address over one with IPv4, for direct connections, if a given directory
+ server has both. (Tor also prefers an IPv6 DirPort if IPv4Client is set to
+ 0.) If this option is set to auto, clients prefer IPv4. Other things may
+ influence the choice. This option breaks a tie to the favor of IPv6.
+ (Default: auto) (DEPRECATED: This option has had no effect for some
+ time.)
+
+[[ClientPreferIPv6ORPort]] **ClientPreferIPv6ORPort** **0**|**1**|**auto**::
+ If this option is set to 1, Tor prefers an OR port with an IPv6
+ address over one with IPv4 if a given entry node has both. (Tor also
+ prefers an IPv6 ORPort if IPv4Client is set to 0.) If this option is set
+ to auto, Tor bridge clients prefer the configured bridge address, and
+ other clients prefer IPv4. Other things may influence the choice. This
+ option breaks a tie to the favor of IPv6. (Default: auto)
+
+[[ClientRejectInternalAddresses]] **ClientRejectInternalAddresses** **0**|**1**::
+ If true, Tor does not try to fulfill requests to connect to an internal
+ address (like 127.0.0.1 or 192.168.0.1) __unless an exit node is
+ specifically requested__ (for example, via a .exit hostname, or a
+ controller request). If true, multicast DNS hostnames for machines on the
+ local network (of the form *.local) are also rejected. (Default: 1)
+
+[[ClientUseIPv4]] **ClientUseIPv4** **0**|**1**::
+ If this option is set to 0, Tor will avoid connecting to directory servers
+ and entry nodes over IPv4. Note that clients with an IPv4
+ address in a **Bridge**, proxy, or pluggable transport line will try
+ connecting over IPv4 even if **ClientUseIPv4** is set to 0. (Default: 1)
+
+[[ClientUseIPv6]] **ClientUseIPv6** **0**|**1**::
+ If this option is set to 1, Tor might connect to directory servers or
+ entry nodes over IPv6. For IPv6 only hosts, you need to also set
+ **ClientUseIPv4** to 0 to disable IPv4. Note that clients configured with
+ an IPv6 address in a **Bridge**, proxy, or pluggable transportline will
+ try connecting over IPv6 even if **ClientUseIPv6** is set to 0. (Default: 0)
+
[[ConnectionPadding]] **ConnectionPadding** **0**|**1**|**auto**::
This option governs Tor's use of padding to defend against some forms of
traffic analysis. If it is set to 'auto', Tor will send padding only
@@ -971,136 +1132,32 @@ The following options are useful only for clients (that is, if
for use where bandwidth may be expensive.
(Default: auto)
+// Out of order because it logically belongs after ConnectionPadding
[[ReducedConnectionPadding]] **ReducedConnectionPadding** **0**|**1**::
If set to 1, Tor will not not hold OR connections open for very long,
and will send less padding on these connections. Only clients may set
this option. This option should be offered via the UI to mobile users
for use where bandwidth may be expensive. (Default: 0)
-[[CircuitPadding]] **CircuitPadding** **0**|**1**::
- If set to 0, Tor will not pad client circuits with additional cover
- traffic. Only clients may set this option. This option should be offered
- via the UI to mobile users for use where bandwidth may be expensive. If
- set to 1, padding will be negotiated as per the consensus and relay
- support (unlike ConnectionPadding, CircuitPadding cannot be force-enabled).
- (Default: 1)
-
-[[ReducedCircuitPadding]] **ReducedCircuitPadding** **0**|**1**::
- If set to 1, Tor will only use circuit padding algorithms that have low
- overhead. Only clients may set this option. This option should be offered
- via the UI to mobile users for use where bandwidth may be expensive.
- (Default: 0)
-
-[[ExcludeNodes]] **ExcludeNodes** __node__,__node__,__...__::
- A list of identity fingerprints, country codes, and address
- patterns of nodes to avoid when building a circuit. Country codes are
- 2-letter ISO3166 codes, and must
- be wrapped in braces; fingerprints may be preceded by a dollar sign.
- (Example:
- ExcludeNodes ABCD1234CDEF5678ABCD1234CDEF5678ABCD1234, \{cc}, 255.254.0.0/8) +
- +
- By default, this option is treated as a preference that Tor is allowed
- to override in order to keep working.
- For example, if you try to connect to a hidden service,
- but you have excluded all of the hidden service's introduction points,
- Tor will connect to one of them anyway. If you do not want this
- behavior, set the StrictNodes option (documented below). +
- +
- Note also that if you are a relay, this (and the other node selection
- options below) only affects your own circuits that Tor builds for you.
- Clients can still build circuits through you to any node. Controllers
- can tell Tor to build circuits through any node. +
- +
- Country codes are case-insensitive. The code "\{??}" refers to nodes whose
- country can't be identified. No country code, including \{??}, works if
- no GeoIPFile can be loaded. See also the GeoIPExcludeUnknown option below.
-
-
-[[ExcludeExitNodes]] **ExcludeExitNodes** __node__,__node__,__...__::
- A list of identity fingerprints, country codes, and address
- patterns of nodes to never use when picking an exit node---that is, a
- node that delivers traffic for you *outside* the Tor network. Note that any
- node listed in ExcludeNodes is automatically considered to be part of this
- list too. See
- the **ExcludeNodes** option for more information on how to specify
- nodes. See also the caveats on the "ExitNodes" option below.
-
-[[GeoIPExcludeUnknown]] **GeoIPExcludeUnknown** **0**|**1**|**auto**::
- If this option is set to 'auto', then whenever any country code is set in
- ExcludeNodes or ExcludeExitNodes, all nodes with unknown country (\{??} and
- possibly \{A1}) are treated as excluded as well. If this option is set to
- '1', then all unknown countries are treated as excluded in ExcludeNodes
- and ExcludeExitNodes. This option has no effect when a GeoIP file isn't
- configured or can't be found. (Default: auto)
-
-[[ExitNodes]] **ExitNodes** __node__,__node__,__...__::
- A list of identity fingerprints, country codes, and address
- patterns of nodes to use as exit node---that is, a
- node that delivers traffic for you *outside* the Tor network. See
- the **ExcludeNodes** option for more information on how to specify nodes. +
- +
- Note that if you list too few nodes here, or if you exclude too many exit
- nodes with ExcludeExitNodes, you can degrade functionality. For example,
- if none of the exits you list allows traffic on port 80 or 443, you won't
- be able to browse the web. +
- +
- Note also that not every circuit is used to deliver traffic *outside* of
- the Tor network. It is normal to see non-exit circuits (such as those
- used to connect to hidden services, those that do directory fetches,
- those used for relay reachability self-tests, and so on) that end
- at a non-exit node. To
- keep a node from being used entirely, see ExcludeNodes and StrictNodes. +
- +
- The ExcludeNodes option overrides this option: any node listed in both
- ExitNodes and ExcludeNodes is treated as excluded. +
- +
- The .exit address notation, if enabled via MapAddress, overrides
- this option.
-
-[[MiddleNodes]] **MiddleNodes** __node__,__node__,__...__::
- A list of identity fingerprints and country codes of nodes
- to use for "middle" hops in your normal circuits.
- Normal circuits include all circuits except for direct connections
- to directory servers. Middle hops are all hops other than exit and entry. +
-+
- This is an **experimental** feature that is meant to be used by researchers
- and developers to test new features in the Tor network safely. Using it
- without care will strongly influence your anonymity. This feature might get
- removed in the future.
-+
- The HSLayer2Node and HSLayer3Node options override this option for onion
- service circuits, if they are set. The vanguards addon will read this
- option, and if set, it will set HSLayer2Nodes and HSLayer3Nodes to nodes
- from this set.
-+
- The ExcludeNodes option overrides this option: any node listed in both
- MiddleNodes and ExcludeNodes is treated as excluded. See
- the **ExcludeNodes** option for more information on how to specify nodes.
+[[DNSPort]] **DNSPort** ['address'**:**]{empty}__port__|**auto** [_isolation flags_]::
+ If non-zero, open this port to listen for UDP DNS requests, and resolve
+ them anonymously. This port only handles A, AAAA, and PTR requests---it
+ doesn't handle arbitrary DNS request types. Set the port to "auto" to
+ have Tor pick a port for
+ you. This directive can be specified multiple times to bind to multiple
+ addresses/ports. See SocksPort for an explanation of isolation
+ flags. (Default: 0)
-[[EntryNodes]] **EntryNodes** __node__,__node__,__...__::
- A list of identity fingerprints and country codes of nodes
- to use for the first hop in your normal circuits.
- Normal circuits include all
- circuits except for direct connections to directory servers. The Bridge
- option overrides this option; if you have configured bridges and
- UseBridges is 1, the Bridges are used as your entry nodes. +
- +
- The ExcludeNodes option overrides this option: any node listed in both
- EntryNodes and ExcludeNodes is treated as excluded. See
- the **ExcludeNodes** option for more information on how to specify nodes.
+[[DownloadExtraInfo]] **DownloadExtraInfo** **0**|**1**::
+ If true, Tor downloads and caches "extra-info" documents. These documents
+ contain information about servers other than the information in their
+ regular server descriptors. Tor does not use this information for anything
+ itself; to save bandwidth, leave this option turned off. (Default: 0)
-[[StrictNodes]] **StrictNodes** **0**|**1**::
- If StrictNodes is set to 1, Tor will treat solely the ExcludeNodes option
- as a requirement to follow for all the circuits you generate, even if
- doing so will break functionality for you (StrictNodes does not apply to
- ExcludeExitNodes, ExitNodes, MiddleNodes, or MapAddress). If StrictNodes
- is set to 0, Tor will still try to avoid nodes in the ExcludeNodes list,
- but it will err on the side of avoiding unexpected errors.
- Specifically, StrictNodes 0 tells Tor that it is okay to use an excluded
- node when it is *necessary* to perform relay reachability self-tests,
- connect to a hidden service, provide a hidden service to a client,
- fulfill a .exit request, upload directory information, or download
- directory information. (Default: 0)
+[[EnforceDistinctSubnets]] **EnforceDistinctSubnets** **0**|**1**::
+ If 1, Tor will not put two servers whose IP addresses are "too close" on
+ the same circuit. Currently, two addresses are "too close" if they lie in
+ the same /16 range. (Default: 1)
[[FascistFirewall]] **FascistFirewall** **0**|**1**::
If 1, Tor will only create outgoing connections to ORs running on ports
@@ -1115,36 +1172,6 @@ The following options are useful only for clients (that is, if
**FascistFirewall** is set. This option is deprecated; use ReachableAddresses
instead. (Default: 80, 443)
-[[ReachableAddresses]] **ReachableAddresses** __IP__[/__MASK__][:__PORT__]...::
- A comma-separated list of IP addresses and ports that your firewall allows
- you to connect to. The format is as for the addresses in ExitPolicy, except
- that "accept" is understood unless "reject" is explicitly provided. For
- example, \'ReachableAddresses 99.0.0.0/8, reject 18.0.0.0/8:80, accept
- \*:80' means that your firewall allows connections to everything inside net
- 99, rejects port 80 connections to net 18, and accepts connections to port
- 80 otherwise. (Default: \'accept \*:*'.)
-
-[[ReachableDirAddresses]] **ReachableDirAddresses** __IP__[/__MASK__][:__PORT__]...::
- Like **ReachableAddresses**, 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
- **ReachableAddresses** is used. If **HTTPProxy** is set then these
- connections will go through that proxy. (DEPRECATED: This option has
- had no effect for some time.)
-
-[[ReachableORAddresses]] **ReachableORAddresses** __IP__[/__MASK__][:__PORT__]...::
- Like **ReachableAddresses**, 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 **ReachableAddresses** is used. If
- **HTTPSProxy** is set then these connections will go through that proxy. +
- +
- The separation between **ReachableORAddresses** and
- **ReachableDirAddresses** is only interesting when you are connecting
- through proxies (see **HTTPProxy** and **HTTPSProxy**). Most proxies limit
- TLS connections (which Tor uses to connect to Onion Routers) to port 443,
- and some limit HTTP GET requests (which Tor uses for fetching directory
- information) to port 80.
-
[[HidServAuth]] **HidServAuth** __onion-address__ __auth-cookie__ [__service-name__]::
Client authorization for a v2 hidden service. Valid onion addresses contain 16
characters in a-z2-7 plus ".onion", and valid auth cookies contain 22
@@ -1155,17 +1182,15 @@ The following options are useful only for clients (that is, if
services can be configured to require authorization using the
**HiddenServiceAuthorizeClient** option.
-[[ClientOnionAuthDir]] **ClientOnionAuthDir** __path__::
- Path to the directory containing v3 hidden service authorization files.
- Each file is for a single onion address, and the files MUST have the suffix
- ".auth_private" (i.e. "bob_onion.auth_private"). The content format MUST be:
- +
- <onion-address>:descriptor:x25519:<base32-encoded-privkey>
- +
- The <onion-address> MUST NOT have the ".onion" suffix. The
- <base32-encoded-privkey> is the base32 representation of the raw key bytes
- only (32 bytes for x25519). See Appendix G in the rend-spec-v3.txt file of
- https://spec.torproject.org/[torspec] for more information.
+[[HTTPTunnelPort]] **HTTPTunnelPort** ['address'**:**]{empty}__port__|**auto** [_isolation flags_]::
+ Open this port to listen for proxy connections using the "HTTP CONNECT"
+ protocol instead of SOCKS. Set this to
+ 0 if you don't want to allow "HTTP CONNECT" connections. Set the port
+ to "auto" to have Tor pick a port for you. This directive can be
+ specified multiple times to bind to multiple addresses/ports. If multiple
+ entries of this option are present in your configuration file, Tor will
+ perform stream isolation between listeners by default. See
+ SOCKSPort for an explanation of isolation flags. (Default: 0)
[[LongLivedPorts]] **LongLivedPorts** __PORTS__::
A list of ports for services that tend to have long-running connections
@@ -1192,7 +1217,7 @@ The following options are useful only for clients (that is, if
*.example.com www.example.com". If the specified exit is not available,
or the exit can not connect to the site, Tor will fail any connections
to the mapped address.+
- +
+ +
NOTES:
1. When evaluating MapAddress expressions Tor stops when it hits the most
@@ -1228,10 +1253,6 @@ The following options are useful only for clients (that is, if
for the original address. You can use a wildcard mapping to handle
redirects within the same site.
-[[NewCircuitPeriod]] **NewCircuitPeriod** __NUM__::
- Every NUM seconds consider whether to build a new circuit. (Default: 30
- seconds)
-
[[MaxCircuitDirtiness]] **MaxCircuitDirtiness** __NUM__::
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. For hidden
@@ -1246,37 +1267,181 @@ The following options are useful only for clients (that is, if
client streams. A circuit is pending if we have begun constructing it,
but it has not yet been completely constructed. (Default: 32)
-[[NodeFamily]] **NodeFamily** __node__,__node__,__...__::
- The Tor servers, defined by their identity fingerprints,
- constitute a "family" of similar or co-administered servers, so never use
- any two of them in the same circuit. Defining a NodeFamily is only needed
- when a server doesn't list the family itself (with MyFamily). This option
- can be used multiple times; each instance defines a separate family. In
- addition to nodes, you can also list IP address and ranges and country
- codes in {curly braces}. See the **ExcludeNodes** option for more
- information on how to specify nodes.
+[[NATDPort]] **NATDPort** ['address'**:**]{empty}__port__|**auto** [_isolation flags_]::
+ Open this port to listen for connections from old versions of ipfw (as
+ included in old versions of FreeBSD, etc) using the NATD protocol.
+ Use 0 if you don't want to allow NATD connections. Set the port
+ to "auto" to have Tor pick a port for you. This directive can be
+ specified multiple times to bind to multiple addresses/ports. If multiple
+ entries of this option are present in your configuration file, Tor will
+ perform stream isolation between listeners by default. See
+ SocksPort for an explanation of isolation flags. +
+ +
+ This option is only for people who cannot use TransPort. (Default: 0)
-[[EnforceDistinctSubnets]] **EnforceDistinctSubnets** **0**|**1**::
- If 1, Tor will not put two servers whose IP addresses are "too close" on
- the same circuit. Currently, two addresses are "too close" if they lie in
- the same /16 range. (Default: 1)
+[[NewCircuitPeriod]] **NewCircuitPeriod** __NUM__::
+ Every NUM seconds consider whether to build a new circuit. (Default: 30
+ seconds)
+
+[[OptimisticData]] **OptimisticData** **0**|**1**|**auto**::
+ When this option is set, and Tor is using an exit node that supports
+ the feature, it will try optimistically to send data to the exit node
+ without waiting for the exit node to report whether the connection
+ succeeded. This can save a round-trip time for protocols like HTTP
+ where the client talks first. If OptimisticData is set to **auto**,
+ Tor will look at the UseOptimisticData parameter in the networkstatus.
+ (Default: auto)
+
+// These are out of order because they logically belong together
+[[PathBiasCircThreshold]] **PathBiasCircThreshold** __NUM__ +
+
+[[PathBiasDropGuards]] **PathBiasDropGuards** __NUM__ +
+
+[[PathBiasExtremeRate]] **PathBiasExtremeRate** __NUM__ +
+
+[[PathBiasNoticeRate]] **PathBiasNoticeRate** __NUM__ +
+
+[[PathBiasWarnRate]] **PathBiasWarnRate** __NUM__ +
+
+[[PathBiasScaleThreshold]] **PathBiasScaleThreshold** __NUM__::
+ These options override the default behavior of Tor's (**currently
+ experimental**) path bias detection algorithm. To try to find broken or
+ misbehaving guard nodes, Tor looks for nodes where more than a certain
+ fraction of circuits through that guard fail to get built. +
+ +
+ The PathBiasCircThreshold option controls how many circuits we need to build
+ through a guard before we make these checks. The PathBiasNoticeRate,
+ PathBiasWarnRate and PathBiasExtremeRate options control what fraction of
+ circuits must succeed through a guard so we won't write log messages.
+ If less than PathBiasExtremeRate circuits succeed *and* PathBiasDropGuards
+ is set to 1, we disable use of that guard. +
+ +
+ When we have seen more than PathBiasScaleThreshold
+ circuits through a guard, we scale our observations by 0.5 (governed by
+ the consensus) so that new observations don't get swamped by old ones. +
+ +
+ By default, or if a negative value is provided for one of these options,
+ Tor uses reasonable defaults from the networkstatus consensus document.
+ If no defaults are available there, these options default to 150, .70,
+ .50, .30, 0, and 300 respectively.
+
+// These are out of order because they logically belong together
+[[PathBiasUseThreshold]] **PathBiasUseThreshold** __NUM__ +
+
+[[PathBiasNoticeUseRate]] **PathBiasNoticeUseRate** __NUM__ +
+
+[[PathBiasExtremeUseRate]] **PathBiasExtremeUseRate** __NUM__ +
+
+[[PathBiasScaleUseThreshold]] **PathBiasScaleUseThreshold** __NUM__::
+ Similar to the above options, these options override the default behavior
+ of Tor's (**currently experimental**) path use bias detection algorithm. +
+ +
+ Where as the path bias parameters govern thresholds for successfully
+ building circuits, these four path use bias parameters govern thresholds
+ only for circuit usage. Circuits which receive no stream usage
+ are not counted by this detection algorithm. A used circuit is considered
+ successful if it is capable of carrying streams or otherwise receiving
+ well-formed responses to RELAY cells. +
+ +
+ By default, or if a negative value is provided for one of these options,
+ Tor uses reasonable defaults from the networkstatus consensus document.
+ If no defaults are available there, these options default to 20, .80,
+ .60, and 100, respectively.
+
+[[PathsNeededToBuildCircuits]] **PathsNeededToBuildCircuits** __NUM__::
+ Tor clients don't build circuits for user traffic until they know
+ about enough of the network so that they could potentially construct
+ enough of the possible paths through the network. If this option
+ is set to a fraction between 0.25 and 0.95, Tor won't build circuits
+ until it has enough descriptors or microdescriptors to construct
+ that fraction of possible paths. Note that setting this option too low
+ can make your Tor client less anonymous, and setting it too high can
+ prevent your Tor client from bootstrapping. If this option is negative,
+ Tor will use a default value chosen by the directory authorities. If the
+ directory authorities do not choose a value, Tor will default to 0.6.
+ (Default: -1)
+
+[[ReachableAddresses]] **ReachableAddresses** __IP__[/__MASK__][:__PORT__]...::
+ A comma-separated list of IP addresses and ports that your firewall allows
+ you to connect to. The format is as for the addresses in ExitPolicy, except
+ that "accept" is understood unless "reject" is explicitly provided. For
+ example, \'ReachableAddresses 99.0.0.0/8, reject 18.0.0.0/8:80, accept
+ \*:80' means that your firewall allows connections to everything inside net
+ 99, rejects port 80 connections to net 18, and accepts connections to port
+ 80 otherwise. (Default: \'accept \*:*'.)
+
+[[ReachableDirAddresses]] **ReachableDirAddresses** __IP__[/__MASK__][:__PORT__]...::
+ Like **ReachableAddresses**, 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
+ **ReachableAddresses** is used. If **HTTPProxy** is set then these
+ connections will go through that proxy. (DEPRECATED: This option has
+ had no effect for some time.)
+
+[[ReachableORAddresses]] **ReachableORAddresses** __IP__[/__MASK__][:__PORT__]...::
+ Like **ReachableAddresses**, 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 **ReachableAddresses** is used. If
+ **HTTPSProxy** is set then these connections will go through that proxy. +
+ +
+ The separation between **ReachableORAddresses** and
+ **ReachableDirAddresses** is only interesting when you are connecting
+ through proxies (see **HTTPProxy** and **HTTPSProxy**). Most proxies limit
+ TLS connections (which Tor uses to connect to Onion Routers) to port 443,
+ and some limit HTTP GET requests (which Tor uses for fetching directory
+ information) to port 80.
+
+[[SafeSocks]] **SafeSocks** **0**|**1**::
+ 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.
+ Specifically, these are socks4 and socks5 when not doing remote DNS.
+ (Default: 0)
+
+// Out of order because it logically belongs after SafeSocks
+[[TestSocks]] **TestSocks** **0**|**1**::
+ When this option is enabled, Tor will make a notice-level log entry for
+ each connection to the Socks port indicating whether the request used a
+ safe socks protocol or an unsafe one (see above entry on SafeSocks). This
+ helps to determine whether an application using Tor is possibly leaking
+ DNS requests. (Default: 0)
+
+// Out of order because it logically belongs with SafeSocks
+[[WarnPlaintextPorts]] **WarnPlaintextPorts** __port__,__port__,__...__::
+ Tells Tor to issue a warnings whenever the user tries to make an anonymous
+ connection to one of these ports. This option is designed to alert users
+ to services that risk sending passwords in the clear. (Default:
+ 23,109,110,143)
+
+// Out of order because it logically belongs with SafeSocks
+[[RejectPlaintextPorts]] **RejectPlaintextPorts** __port__,__port__,__...__::
+ Like WarnPlaintextPorts, but instead of warning about risky port uses, Tor
+ will instead refuse to make the connection. (Default: None)
+
+[[SocksPolicy]] **SocksPolicy** __policy__,__policy__,__...__::
+ Set an entrance policy for this server, to limit who can connect to the
+ SocksPort and DNSPort ports. The policies have the same form as exit
+ policies below, except that port specifiers are ignored. Any address
+ not matched by some entry in the policy is accepted.
-[[SocksPort]] **SocksPort** \['address':]__port__|**unix:**__path__|**auto** [_flags_] [_isolation flags_]::
+[[SocksPort]] **SocksPort** ['address'**:**]{empty}__port__|**unix:**__path__|**auto** [_flags_] [_isolation flags_]::
Open this port to listen for connections from SOCKS-speaking
applications. Set this to 0 if you don't want to allow application
connections via SOCKS. Set it to "auto" to have Tor pick a port for
you. This directive can be specified multiple times to bind
to multiple addresses/ports. If a unix domain socket is used, you may
- quote the path using standard C escape sequences.
+ quote the path using standard C escape sequences. Most flags are off by
+ default, except where specified. Flags that are on by default can be
+ disabled by putting "No" before the flag name.
(Default: 9050) +
- +
+ +
NOTE: Although this option allows you to specify an IP address
other than localhost, you should do so only with extreme caution.
The SOCKS protocol is unencrypted and (as we use it)
unauthenticated, so exposing it in this way could leak your
information to anybody watching your network, and allow anybody
to use your computer as an open proxy. +
- +
+ +
If multiple entries of this option are present in your configuration
file, Tor will perform stream isolation between listeners by default.
The _isolation flags_ arguments give Tor rules for which streams
@@ -1295,8 +1460,9 @@ The following options are useful only for clients (that is, if
you can disable it with **NoIsolateSOCKSAuth**.)
**IsolateClientProtocol**;;
Don't share circuits with streams using a different protocol.
- (SOCKS 4, SOCKS 5, TransPort connections, NATDPort connections,
- and DNSPort requests are all considered to be different protocols.)
+ (SOCKS 4, SOCKS 5, HTTPTunnelPort connections, TransPort connections,
+ NATDPort connections, and DNSPort requests are all considered to be
+ different protocols.)
**IsolateDestPort**;;
Don't share circuits with streams targeting a different
destination port.
@@ -1305,8 +1471,9 @@ The following options are useful only for clients (that is, if
destination address.
**KeepAliveIsolateSOCKSAuth**;;
If **IsolateSOCKSAuth** is enabled, keep alive circuits while they have
- at least one stream with SOCKS authentication active. After such a circuit
- is idle for more than MaxCircuitDirtiness seconds, it can be closed.
+ at least one stream with SOCKS authentication active. After such a
+ circuit is idle for more than MaxCircuitDirtiness seconds, it can be
+ closed.
**SessionGroup=**__INT__;;
If no other isolation rules would prevent it, allow streams
on this port to share circuits with streams from every other
@@ -1319,11 +1486,12 @@ The following options are useful only for clients (that is, if
Other recognized __flags__ for a SocksPort are:
**NoIPv4Traffic**;;
Tell exits to not connect to IPv4 addresses in response to SOCKS
- requests on this connection.
- **IPv6Traffic**;;
- Tell exits to allow IPv6 addresses in response to SOCKS requests on
- this connection, so long as SOCKS5 is in use. (SOCKS4 can't handle
- IPv6.)
+ requests on this connection. (Allowing IPv4 is the default.)
+ **NoIPv6Traffic**;;
+ Tell exits to not connect to IPv6 addresses in response to SOCKS
+ requests on this connection. This option is only relevant when SOCKS5
+ is in use, because SOCKS4 can't handle IPv6. (Allowing IPv6 is the
+ default.)
**PreferIPv6**;;
Tells exits that, if a host has both an IPv4 and an IPv6 address,
we would prefer to connect to it via IPv6. (IPv4 is the default.)
@@ -1364,11 +1532,11 @@ The following options are useful only for clients (that is, if
**UseDNSCache**;;
Tells the client to use any cached DNS answers we have when making
requests via this connection.
- **PreferIPv6Automap**;;
+ **NoPreferIPv6Automap**;;
When serving a hostname lookup request on this port that
should get automapped (according to AutomapHostsOnResolve),
if we could return either an IPv4 or an IPv6 answer, prefer
- an IPv6 answer. (On by default.)
+ an IPv4 answer. (Tor prefers IPv4 by default.)
**PreferSOCKSNoAuth**;;
Ordinarily, when an application offers both "username/password
authentication" and "no authentication" to Tor via SOCKS5, Tor
@@ -1378,6 +1546,50 @@ The following options are useful only for clients (that is, if
one. You can disable this behavior, so that Tor will select "No
authentication" when IsolateSOCKSAuth is disabled, or when this
option is set.
+ **ExtendedErrors**;;
+ Return extended error code in the SOCKS reply. So far, the possible
+ errors are:
+
+ X'F0' Onion Service Descriptor Can Not be Found
+
+ The requested onion service descriptor can't be found on the
+ hashring and thus not reachable by the client. (v3 only)
+
+ X'F1' Onion Service Descriptor Is Invalid
+
+ The requested onion service descriptor can't be parsed or
+ signature validation failed. (v3 only)
+
+ X'F2' Onion Service Introduction Failed
+
+ Client failed to introduce to the service meaning the descriptor
+ was found but the service is not connected anymore to the
+ introduction point. The service has likely changed its descriptor
+ or is not running. (v3 only)
+
+ X'F3' Onion Service Rendezvous Failed
+
+ Client failed to rendezvous with the service which means that the
+ client is unable to finalize the connection. (v3 only)
+
+ X'F4' Onion Service Missing Client Authorization
+
+ Client was able to download the requested onion service descriptor
+ but is unable to decrypt its content because it is missing client
+ authorization information. (v3 only)
+
+ X'F5' Onion Service Wrong Client Authorization
+
+ Client was able to download the requested onion service descriptor
+ but is unable to decrypt its content using the client
+ authorization information it has. This means the client access
+ were revoked. (v3 only)
+
+ X'F6' Onion Service Invalid Address
+
+ The given .onion address is invalid. In one of these cases this
+ error is returned: address checksum doesn't match, ed25519 public
+ key is invalid or the encoding is invalid. (v3 only)
// Anchor only for formatting, not visible in the man page.
[[SocksPortFlagsMisc]]::
@@ -1385,17 +1597,6 @@ The following options are useful only for clients (that is, if
line is used, and all earlier flags are ignored. No error is issued for
conflicting flags.
-[[SocksPolicy]] **SocksPolicy** __policy__,__policy__,__...__::
- Set an entrance policy for this server, to limit who can connect to the
- SocksPort and DNSPort ports. The policies have the same form as exit
- policies below, except that port specifiers are ignored. Any address
- not matched by some entry in the policy is accepted.
-
-[[SocksTimeout]] **SocksTimeout** __NUM__::
- Let a socks connection wait NUM seconds handshaking, and NUM seconds
- unattached waiting for an appropriate circuit, before we fail it. (Default:
- 2 minutes)
-
[[TokenBucketRefillInterval]] **TokenBucketRefillInterval** __NUM__ [**msec**|**second**]::
Set the refill delay interval of Tor's token bucket to NUM milliseconds.
NUM must be between 1 and 1000, inclusive. When Tor is out of bandwidth,
@@ -1423,6 +1624,44 @@ The following options are useful only for clients (that is, if
association between host and exit server after NUM seconds. The default is
1800 seconds (30 minutes).
+[[TransPort]] **TransPort** ['address'**:**]{empty}__port__|**auto** [_isolation flags_]::
+ Open this port to listen for transparent proxy connections. Set this to
+ 0 if you don't want to allow transparent proxy connections. Set the port
+ to "auto" to have Tor pick a port for you. This directive can be
+ specified multiple times to bind to multiple addresses/ports. If multiple
+ entries of this option are present in your configuration file, Tor will
+ perform stream isolation between listeners by default. See
+ SOCKSPort for an explanation of isolation flags. +
+ +
+ TransPort requires OS support for transparent proxies, such as BSDs' pf or
+ Linux's IPTables. If you're planning to use Tor as a transparent proxy for
+ a network, you'll want to examine and change VirtualAddrNetwork from the
+ default setting. (Default: 0)
+
+[[TransProxyType]] **TransProxyType** **default**|**TPROXY**|**ipfw**|**pf-divert**::
+ TransProxyType may only be enabled when there is transparent proxy listener
+ enabled. +
+ +
+ Set this to "TPROXY" if you wish to be able to use the TPROXY Linux module
+ to transparently proxy connections that are configured using the TransPort
+ option. Detailed information on how to configure the TPROXY
+ feature can be found in the Linux kernel source tree in the file
+ Documentation/networking/tproxy.txt. +
+ +
+ Set this option to "ipfw" to use the FreeBSD ipfw interface. +
+ +
+ On *BSD operating systems when using pf, set this to "pf-divert" to take
+ advantage of +divert-to+ rules, which do not modify the packets like
+ +rdr-to+ rules do. Detailed information on how to configure pf to use
+ +divert-to+ rules can be found in the pf.conf(5) manual page. On OpenBSD,
+ +divert-to+ is available to use on versions greater than or equal to
+ OpenBSD 4.4. +
+ +
+ Set this to "default", or leave it unconfigured, to use regular IPTables
+ on Linux, or to use pf +rdr-to+ rules on *BSD systems. +
+ +
+ (Default: "default")
+
[[UpdateBridgesFromAuthority]] **UpdateBridgesFromAuthority** **0**|**1**::
When set (along with UseBridges), Tor will try to fetch bridge descriptors
from the configured bridge authorities when feasible. It will fall back to
@@ -1441,23 +1680,33 @@ The following options are useful only for clients (that is, if
Authorities or Single Onion Services. In these cases,
this option is ignored. (Default: 1)
-[[GuardfractionFile]] **GuardfractionFile** __FILENAME__::
- V3 authoritative directories only. Configures the location of the
- guardfraction file which contains information about how long relays
- have been guards. (Default: unset)
-
[[UseGuardFraction]] **UseGuardFraction** **0**|**1**|**auto**::
This option specifies whether clients should use the
guardfraction information found in the consensus during path
selection. If it's set to 'auto', clients will do what the
UseGuardFraction consensus parameter tells them to do. (Default: auto)
+//Out of order because it logically belongs after the UseEntryGuards option
+[[GuardLifetime]] **GuardLifetime** __N__ **days**|**weeks**|**months**::
+ If UseEntryGuards is set, minimum time to keep a guard on our guard list
+ before picking a new one. If less than one day, we use defaults from the
+ consensus directory. (Default: 0)
+
+//Out of order because it logically belongs after the UseEntryGuards option
+[[NumDirectoryGuards]] **NumDirectoryGuards** __NUM__::
+ If UseEntryGuards is set to 1, we try to make sure we have at least NUM
+ routers to use as directory guards. If this option is set to 0, use the
+ value from the guard-n-primary-dir-guards-to-use consensus parameter, and
+ default to 3 if the consensus parameter isn't set. (Default: 0)
+
+//Out of order because it logically belongs after the UseEntryGuards option
[[NumEntryGuards]] **NumEntryGuards** __NUM__::
If UseEntryGuards is set to 1, we will try to pick a total of NUM routers
as long-term entries for our circuits. If NUM is 0, we try to learn the
number from the guard-n-primary-guards-to-use consensus parameter, and
default to 1 if the consensus parameter isn't set. (Default: 0)
+//Out of order because it logically belongs after the UseEntryGuards option
[[NumPrimaryGuards]] **NumPrimaryGuards** __NUM__::
If UseEntryGuards is set to 1, we will try to pick NUM routers for our
primary guard list, which is the set of routers we strongly prefer when
@@ -1465,30 +1714,13 @@ The following options are useful only for clients (that is, if
the guard-n-primary-guards consensus parameter, and default to 3 if the
consensus parameter isn't set. (Default: 0)
-[[NumDirectoryGuards]] **NumDirectoryGuards** __NUM__::
- If UseEntryGuards is set to 1, we try to make sure we have at least NUM
- routers to use as directory guards. If this option is set to 0, use the
- value from the guard-n-primary-dir-guards-to-use consensus parameter, and
- default to 3 if the consensus parameter isn't set. (Default: 0)
-
-[[GuardLifetime]] **GuardLifetime** __N__ **days**|**weeks**|**months**::
- If UseEntryGuards is set, minimum time to keep a guard on our guard list
- before picking a new one. If less than one day, we use defaults from the
- consensus directory. (Default: 0)
-
-[[SafeSocks]] **SafeSocks** **0**|**1**::
- 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.
- Specifically, these are socks4 and socks5 when not doing remote DNS.
- (Default: 0)
-
-[[TestSocks]] **TestSocks** **0**|**1**::
- When this option is enabled, Tor will make a notice-level log entry for
- each connection to the Socks port indicating whether the request used a
- safe socks protocol or an unsafe one (see above entry on SafeSocks). This
- helps to determine whether an application using Tor is possibly leaking
- DNS requests. (Default: 0)
+[[UseMicrodescriptors]] **UseMicrodescriptors** **0**|**1**|**auto**::
+ Microdescriptors are a smaller version of the information that Tor needs
+ in order to build its circuits. Using microdescriptors makes Tor clients
+ download less directory information, thus saving bandwidth. Directory
+ caches need to fetch regular descriptors and microdescriptors, so this
+ option doesn't save any bandwidth for them. For legacy reasons, auto is
+ accepted, but it has the same effect as 1. (Default: auto)
[[VirtualAddrNetworkIPv4]] **VirtualAddrNetworkIPv4** __IPv4Address__/__bits__ +
@@ -1497,7 +1729,7 @@ The following options are useful only for clients (that is, if
command from the controller or the AutomapHostsOnResolve feature, Tor
picks an unassigned address from this range. (Defaults:
127.192.0.0/10 and [FE80::]/10 respectively.) +
- +
+ +
When providing proxy server service to a network of computers using a tool
like dns-proxy-tor, change the IPv4 network to "10.192.0.0/10" or
"172.16.0.0/12" and change the IPv6 network to "[FC00::]/7".
@@ -1509,129 +1741,178 @@ The following options are useful only for clients (that is, if
used IP. For local use, no change to the default VirtualAddrNetwork setting
is needed.
-[[AllowNonRFC953Hostnames]] **AllowNonRFC953Hostnames** **0**|**1**::
- When this option is disabled, Tor blocks hostnames containing illegal
- characters (like @ and :) rather than sending them to an exit node to be
- resolved. This helps trap accidental attempts to resolve URLs and so on.
- (Default: 0)
+== CIRCUIT TIMEOUT OPTIONS
-[[HTTPTunnelPort]] **HTTPTunnelPort** \['address':]__port__|**auto** [_isolation flags_]::
- Open this port to listen for proxy connections using the "HTTP CONNECT"
- protocol instead of SOCKS. Set this to
- 0 if you don't want to allow "HTTP CONNECT" connections. Set the port
- to "auto" to have Tor pick a port for you. This directive can be
- specified multiple times to bind to multiple addresses/ports. If multiple
- entries of this option are present in your configuration file, Tor will
- perform stream isolation between listeners by default. See
- SOCKSPort for an explanation of isolation flags. (Default: 0)
+// These options are in alphabetical order, with exceptions as noted.
+// Please keep them that way!
-[[TransPort]] **TransPort** \['address':]__port__|**auto** [_isolation flags_]::
- Open this port to listen for transparent proxy connections. Set this to
- 0 if you don't want to allow transparent proxy connections. Set the port
- to "auto" to have Tor pick a port for you. This directive can be
- specified multiple times to bind to multiple addresses/ports. If multiple
- entries of this option are present in your configuration file, Tor will
- perform stream isolation between listeners by default. See
- SOCKSPort for an explanation of isolation flags. +
- +
- TransPort requires OS support for transparent proxies, such as BSDs' pf or
- Linux's IPTables. If you're planning to use Tor as a transparent proxy for
- a network, you'll want to examine and change VirtualAddrNetwork from the
- default setting. (Default: 0)
+The following options are useful for configuring timeouts related
+to building Tor circuits and using them:
-[[TransProxyType]] **TransProxyType** **default**|**TPROXY**|**ipfw**|**pf-divert**::
- TransProxyType may only be enabled when there is transparent proxy listener
- enabled. +
- +
- Set this to "TPROXY" if you wish to be able to use the TPROXY Linux module
- to transparently proxy connections that are configured using the TransPort
- option. Detailed information on how to configure the TPROXY
- feature can be found in the Linux kernel source tree in the file
- Documentation/networking/tproxy.txt. +
- +
- Set this option to "ipfw" to use the FreeBSD ipfw interface. +
- +
- On *BSD operating systems when using pf, set this to "pf-divert" to take
- advantage of +divert-to+ rules, which do not modify the packets like
- +rdr-to+ rules do. Detailed information on how to configure pf to use
- +divert-to+ rules can be found in the pf.conf(5) manual page. On OpenBSD,
- +divert-to+ is available to use on versions greater than or equal to
- OpenBSD 4.4. +
- +
- Set this to "default", or leave it unconfigured, to use regular IPTables
- on Linux, or to use pf +rdr-to+ rules on *BSD systems. +
- +
- (Default: "default")
+[[CircuitsAvailableTimeout]] **CircuitsAvailableTimeout** __NUM__::
+ Tor will attempt to keep at least one open, unused circuit available for
+ this amount of time. This option governs how long idle circuits are kept
+ open, as well as the amount of time Tor will keep a circuit open to each
+ of the recently used ports. This way when the Tor client is entirely
+ idle, it can expire all of its circuits, and then expire its TLS
+ connections. Note that the actual timeout value is uniformly randomized
+ from the specified value to twice that amount. (Default: 30 minutes;
+ Max: 24 hours)
-[[NATDPort]] **NATDPort** \['address':]__port__|**auto** [_isolation flags_]::
- Open this port to listen for connections from old versions of ipfw (as
- included in old versions of FreeBSD, etc) using the NATD protocol.
- Use 0 if you don't want to allow NATD connections. Set the port
- to "auto" to have Tor pick a port for you. This directive can be
- specified multiple times to bind to multiple addresses/ports. If multiple
- entries of this option are present in your configuration file, Tor will
- perform stream isolation between listeners by default. See
- SocksPort for an explanation of isolation flags. +
- +
- This option is only for people who cannot use TransPort. (Default: 0)
+// Out of order because it logically belongs before the CircuitBuildTimeout option
+[[LearnCircuitBuildTimeout]] **LearnCircuitBuildTimeout** **0**|**1**::
+ If 0, CircuitBuildTimeout adaptive learning is disabled. (Default: 1)
-[[AutomapHostsOnResolve]] **AutomapHostsOnResolve** **0**|**1**::
- When this option is enabled, and we get a request to resolve an address
- that ends with one of the suffixes in **AutomapHostsSuffixes**, we map an
- unused virtual address to that address, and return the new virtual address.
- This is handy for making ".onion" addresses work with applications that
- resolve an address and then connect to it. (Default: 0)
+[[CircuitBuildTimeout]] **CircuitBuildTimeout** __NUM__::
+ Try for at most NUM seconds when building circuits. If the circuit isn't
+ open in that time, give up on it. If LearnCircuitBuildTimeout is 1, this
+ value serves as the initial value to use before a timeout is learned. If
+ LearnCircuitBuildTimeout is 0, this value is the only value used.
+ (Default: 60 seconds)
-[[AutomapHostsSuffixes]] **AutomapHostsSuffixes** __SUFFIX__,__SUFFIX__,__...__::
- A comma-separated list of suffixes to use with **AutomapHostsOnResolve**.
- The "." suffix is equivalent to "all addresses." (Default: .exit,.onion).
+[[CircuitStreamTimeout]] **CircuitStreamTimeout** __NUM__::
+ If non-zero, this option overrides our internal timeout schedule for how
+ many seconds until we detach a stream from a circuit and try a new circuit.
+ If your network is particularly slow, you might want to set this to a
+ number like 60. (Default: 0)
-[[DNSPort]] **DNSPort** \['address':]__port__|**auto** [_isolation flags_]::
- If non-zero, open this port to listen for UDP DNS requests, and resolve
- them anonymously. This port only handles A, AAAA, and PTR requests---it
- doesn't handle arbitrary DNS request types. Set the port to "auto" to
- have Tor pick a port for
- you. This directive can be specified multiple times to bind to multiple
- addresses/ports. See SocksPort for an explanation of isolation
- flags. (Default: 0)
+[[SocksTimeout]] **SocksTimeout** __NUM__::
+ Let a socks connection wait NUM seconds handshaking, and NUM seconds
+ unattached waiting for an appropriate circuit, before we fail it. (Default:
+ 2 minutes)
-[[ClientDNSRejectInternalAddresses]] **ClientDNSRejectInternalAddresses** **0**|**1**::
- If true, Tor does not believe any anonymously retrieved DNS answer that
- tells it that an address resolves to an internal address (like 127.0.0.1 or
- 192.168.0.1). This option prevents certain browser-based attacks; it
- is not allowed to be set on the default network. (Default: 1)
+== DORMANT MODE OPTIONS
-[[ClientRejectInternalAddresses]] **ClientRejectInternalAddresses** **0**|**1**::
- If true, Tor does not try to fulfill requests to connect to an internal
- address (like 127.0.0.1 or 192.168.0.1) __unless an exit node is
- specifically requested__ (for example, via a .exit hostname, or a
- controller request). If true, multicast DNS hostnames for machines on the
- local network (of the form *.local) are also rejected. (Default: 1)
+// These options are in alphabetical order, with exceptions as noted.
+// Please keep them that way!
-[[DownloadExtraInfo]] **DownloadExtraInfo** **0**|**1**::
- If true, Tor downloads and caches "extra-info" documents. These documents
- contain information about servers other than the information in their
- regular server descriptors. Tor does not use this information for anything
- itself; to save bandwidth, leave this option turned off. (Default: 0)
+Tor can enter dormant mode to conserve power and network bandwidth.
+The following options control when Tor enters and leaves dormant mode:
-[[WarnPlaintextPorts]] **WarnPlaintextPorts** __port__,__port__,__...__::
- Tells Tor to issue a warnings whenever the user tries to make an anonymous
- connection to one of these ports. This option is designed to alert users
- to services that risk sending passwords in the clear. (Default:
- 23,109,110,143)
+[[DormantCanceledByStartup]] **DormantCanceledByStartup** **0**|**1**::
+ By default, Tor starts in active mode if it was active the last time
+ it was shut down, and in dormant mode if it was dormant. But if
+ this option is true, Tor treats every startup event as user
+ activity, and Tor will never start in Dormant mode, even if it has
+ been unused for a long time on previous runs. (Default: 0)
+ +
+ Note: Packagers and application developers should change the value of
+ this option only with great caution: it has the potential to
+ create spurious traffic on the network. This option should only
+ be used if Tor is started by an affirmative user activity (like
+ clicking on an applcation or running a command), and not if Tor
+ is launched for some other reason (for example, by a startup
+ process, or by an application that launches itself on every login.)
-[[RejectPlaintextPorts]] **RejectPlaintextPorts** __port__,__port__,__...__::
- Like WarnPlaintextPorts, but instead of warning about risky port uses, Tor
- will instead refuse to make the connection. (Default: None)
+[[DormantClientTimeout]] **DormantClientTimeout** __N__ **minutes**|**hours**|**days**|**weeks**::
+ If Tor spends this much time without any client activity,
+ enter a dormant state where automatic circuits are not built, and
+ directory information is not fetched.
+ Does not affect servers or onion services. Must be at least 10 minutes.
+ (Default: 24 hours)
-[[OptimisticData]] **OptimisticData** **0**|**1**|**auto**::
- When this option is set, and Tor is using an exit node that supports
- the feature, it will try optimistically to send data to the exit node
- without waiting for the exit node to report whether the connection
- succeeded. This can save a round-trip time for protocols like HTTP
- where the client talks first. If OptimisticData is set to **auto**,
- Tor will look at the UseOptimisticData parameter in the networkstatus.
- (Default: auto)
+[[DormantOnFirstStartup]] **DormantOnFirstStartup** **0**|**1**::
+ If true, then the first time Tor starts up with a fresh DataDirectory,
+ it starts in dormant mode, and takes no actions until the user has made
+ a request. (This mode is recommended if installing a Tor client for a
+ user who might not actually use it.) If false, Tor bootstraps the first
+ time it is started, whether it sees a user request or not.
+ +
+ After the first time Tor starts, it begins in dormant mode if it was
+ dormant before, and not otherwise. (Default: 0)
+
+[[DormantTimeoutDisabledByIdleStreams]] **DormantTimeoutDisabledByIdleStreams** **0**|**1**::
+ If true, then any open client stream (even one not reading or writing)
+ counts as client activity for the purpose of DormantClientTimeout.
+ If false, then only network activity counts. (Default: 1)
+
+== NODE SELECTION OPTIONS
+
+// These options are in alphabetical order, with exceptions as noted.
+// Please keep them that way!
+
+The following options restrict the nodes that a tor client
+(or onion service) can use while building a circuit.
+These options can weaken your anonymity by making your client behavior
+different from other Tor clients:
+
+[[EntryNodes]] **EntryNodes** __node__,__node__,__...__::
+ A list of identity fingerprints and country codes of nodes
+ to use for the first hop in your normal circuits.
+ Normal circuits include all
+ circuits except for direct connections to directory servers. The Bridge
+ option overrides this option; if you have configured bridges and
+ UseBridges is 1, the Bridges are used as your entry nodes. +
+ +
+ The ExcludeNodes option overrides this option: any node listed in both
+ EntryNodes and ExcludeNodes is treated as excluded. See
+ the **ExcludeNodes** option for more information on how to specify nodes.
+
+[[ExcludeNodes]] **ExcludeNodes** __node__,__node__,__...__::
+ A list of identity fingerprints, country codes, and address
+ patterns of nodes to avoid when building a circuit. Country codes are
+ 2-letter ISO3166 codes, and must
+ be wrapped in braces; fingerprints may be preceded by a dollar sign.
+ (Example:
+ ExcludeNodes ABCD1234CDEF5678ABCD1234CDEF5678ABCD1234, \{cc}, 255.254.0.0/8) +
+ +
+ By default, this option is treated as a preference that Tor is allowed
+ to override in order to keep working.
+ For example, if you try to connect to a hidden service,
+ but you have excluded all of the hidden service's introduction points,
+ Tor will connect to one of them anyway. If you do not want this
+ behavior, set the StrictNodes option (documented below). +
+ +
+ Note also that if you are a relay, this (and the other node selection
+ options below) only affects your own circuits that Tor builds for you.
+ Clients can still build circuits through you to any node. Controllers
+ can tell Tor to build circuits through any node. +
+ +
+ Country codes are case-insensitive. The code "\{??}" refers to nodes whose
+ country can't be identified. No country code, including \{??}, works if
+ no GeoIPFile can be loaded. See also the GeoIPExcludeUnknown option below.
+
+// Out of order because it logically belongs after the ExcludeNodes option
+[[ExcludeExitNodes]] **ExcludeExitNodes** __node__,__node__,__...__::
+ A list of identity fingerprints, country codes, and address
+ patterns of nodes to never use when picking an exit node---that is, a
+ node that delivers traffic for you *outside* the Tor network. Note that any
+ node listed in ExcludeNodes is automatically considered to be part of this
+ list too. See
+ the **ExcludeNodes** option for more information on how to specify
+ nodes. See also the caveats on the "ExitNodes" option below.
+
+[[ExitNodes]] **ExitNodes** __node__,__node__,__...__::
+ A list of identity fingerprints, country codes, and address
+ patterns of nodes to use as exit node---that is, a
+ node that delivers traffic for you *outside* the Tor network. See
+ the **ExcludeNodes** option for more information on how to specify nodes. +
+ +
+ Note that if you list too few nodes here, or if you exclude too many exit
+ nodes with ExcludeExitNodes, you can degrade functionality. For example,
+ if none of the exits you list allows traffic on port 80 or 443, you won't
+ be able to browse the web. +
+ +
+ Note also that not every circuit is used to deliver traffic *outside* of
+ the Tor network. It is normal to see non-exit circuits (such as those
+ used to connect to hidden services, those that do directory fetches,
+ those used for relay reachability self-tests, and so on) that end
+ at a non-exit node. To
+ keep a node from being used entirely, see ExcludeNodes and StrictNodes. +
+ +
+ The ExcludeNodes option overrides this option: any node listed in both
+ ExitNodes and ExcludeNodes is treated as excluded. +
+ +
+ The .exit address notation, if enabled via MapAddress, overrides
+ this option.
+
+[[GeoIPExcludeUnknown]] **GeoIPExcludeUnknown** **0**|**1**|**auto**::
+ If this option is set to 'auto', then whenever any country code is set in
+ ExcludeNodes or ExcludeExitNodes, all nodes with unknown country (\{??} and
+ possibly \{A1}) are treated as excluded as well. If this option is set to
+ '1', then all unknown countries are treated as excluded in ExcludeNodes
+ and ExcludeExitNodes. This option has no effect when a GeoIP file isn't
+ configured or can't be found. (Default: auto)
[[HSLayer2Nodes]] **HSLayer2Nodes** __node__,__node__,__...__::
A list of identity fingerprints, nicknames, country codes, and
@@ -1641,39 +1922,39 @@ The following options are useful only for clients (that is, if
and induces your client or service to create many circuits, in order
to discover your primary guard node.
(Default: Any node in the network may be used in the second hop.)
- +
+ +
(Example:
HSLayer2Nodes ABCD1234CDEF5678ABCD1234CDEF5678ABCD1234, \{cc}, 255.254.0.0/8) +
- +
+ +
When this is set, the resulting hidden service paths will
look like:
- +
+ +
C - G - L2 - M - Rend +
C - G - L2 - M - HSDir +
C - G - L2 - M - Intro +
S - G - L2 - M - Rend +
S - G - L2 - M - HSDir +
S - G - L2 - M - Intro +
- +
+ +
where C is this client, S is the service, G is the Guard node,
L2 is a node from this option, and M is a random middle node.
Rend, HSDir, and Intro point selection is not affected by this
option.
- +
+ +
This option may be combined with HSLayer3Nodes to create
paths of the form:
- +
+ +
C - G - L2 - L3 - Rend +
C - G - L2 - L3 - M - HSDir +
C - G - L2 - L3 - M - Intro +
S - G - L2 - L3 - M - Rend +
S - G - L2 - L3 - HSDir +
S - G - L2 - L3 - Intro +
- +
+ +
ExcludeNodes have higher priority than HSLayer2Nodes,
which means that nodes specified in ExcludeNodes will not be
picked.
- +
+ +
When either this option or HSLayer3Nodes are set, the /16 subnet
and node family restrictions are removed for hidden service
circuits. Additionally, we allow the guard node to be present
@@ -1681,7 +1962,7 @@ The following options are useful only for clients (that is, if
is done to prevent the adversary from inferring information
about our guard, layer2, and layer3 node choices at later points
in the path.
- +
+ +
This option is meant to be managed by a Tor controller such as
https://github.com/mikeperry-tor/vanguards that selects and
updates this set of nodes for you. Hence it does not do load
@@ -1697,10 +1978,10 @@ The following options are useful only for clients (that is, if
and induces your client or service to create many circuits, in order
to discover your primary or Layer2 guard nodes.
(Default: Any node in the network may be used in the third hop.)
- +
+ +
(Example:
HSLayer3Nodes ABCD1234CDEF5678ABCD1234CDEF5678ABCD1234, \{cc}, 255.254.0.0/8) +
- +
+ +
When this is set by itself, the resulting hidden service paths
will look like: +
C - G - M - L3 - Rend +
@@ -1713,21 +1994,21 @@ The following options are useful only for clients (that is, if
L2 is a node from this option, and M is a random middle node.
Rend, HSDir, and Intro point selection is not affected by this
option.
- +
+ +
While it is possible to use this option by itself, it should be
combined with HSLayer2Nodes to create paths of the form:
- +
+ +
C - G - L2 - L3 - Rend +
C - G - L2 - L3 - M - HSDir +
C - G - L2 - L3 - M - Intro +
S - G - L2 - L3 - M - Rend +
S - G - L2 - L3 - HSDir +
S - G - L2 - L3 - Intro +
- +
+ +
ExcludeNodes have higher priority than HSLayer3Nodes,
which means that nodes specified in ExcludeNodes will not be
picked.
- +
+ +
When either this option or HSLayer2Nodes are set, the /16 subnet
and node family restrictions are removed for hidden service
circuits. Additionally, we allow the guard node to be present
@@ -1743,187 +2024,102 @@ The following options are useful only for clients (that is, if
HSLayer3Nodes are currently available for use, Tor will not work.
Please use extreme care if you are setting this option manually.
-[[UseMicrodescriptors]] **UseMicrodescriptors** **0**|**1**|**auto**::
- Microdescriptors are a smaller version of the information that Tor needs
- in order to build its circuits. Using microdescriptors makes Tor clients
- download less directory information, thus saving bandwidth. Directory
- caches need to fetch regular descriptors and microdescriptors, so this
- option doesn't save any bandwidth for them. For legacy reasons, auto is
- accepted, but it has the same effect as 1. (Default: auto)
-
-[[PathBiasCircThreshold]] **PathBiasCircThreshold** __NUM__ +
-
-[[PathBiasNoticeRate]] **PathBiasNoticeRate** __NUM__ +
-
-[[PathBiasWarnRate]] **PathBiasWarnRate** __NUM__ +
-
-[[PathBiasExtremeRate]] **PathBiasExtremeRate** __NUM__ +
-
-[[PathBiasDropGuards]] **PathBiasDropGuards** __NUM__ +
-
-[[PathBiasScaleThreshold]] **PathBiasScaleThreshold** __NUM__::
- These options override the default behavior of Tor's (**currently
- experimental**) path bias detection algorithm. To try to find broken or
- misbehaving guard nodes, Tor looks for nodes where more than a certain
- fraction of circuits through that guard fail to get built. +
- +
- The PathBiasCircThreshold option controls how many circuits we need to build
- through a guard before we make these checks. The PathBiasNoticeRate,
- PathBiasWarnRate and PathBiasExtremeRate options control what fraction of
- circuits must succeed through a guard so we won't write log messages.
- If less than PathBiasExtremeRate circuits succeed *and* PathBiasDropGuards
- is set to 1, we disable use of that guard. +
- +
- When we have seen more than PathBiasScaleThreshold
- circuits through a guard, we scale our observations by 0.5 (governed by
- the consensus) so that new observations don't get swamped by old ones. +
- +
- By default, or if a negative value is provided for one of these options,
- Tor uses reasonable defaults from the networkstatus consensus document.
- If no defaults are available there, these options default to 150, .70,
- .50, .30, 0, and 300 respectively.
-
-[[PathBiasUseThreshold]] **PathBiasUseThreshold** __NUM__ +
-
-[[PathBiasNoticeUseRate]] **PathBiasNoticeUseRate** __NUM__ +
-
-[[PathBiasExtremeUseRate]] **PathBiasExtremeUseRate** __NUM__ +
-
-[[PathBiasScaleUseThreshold]] **PathBiasScaleUseThreshold** __NUM__::
- Similar to the above options, these options override the default behavior
- of Tor's (**currently experimental**) path use bias detection algorithm. +
- +
- Where as the path bias parameters govern thresholds for successfully
- building circuits, these four path use bias parameters govern thresholds
- only for circuit usage. Circuits which receive no stream usage
- are not counted by this detection algorithm. A used circuit is considered
- successful if it is capable of carrying streams or otherwise receiving
- well-formed responses to RELAY cells. +
- +
- By default, or if a negative value is provided for one of these options,
- Tor uses reasonable defaults from the networkstatus consensus document.
- If no defaults are available there, these options default to 20, .80,
- .60, and 100, respectively.
-
-[[ClientUseIPv4]] **ClientUseIPv4** **0**|**1**::
- If this option is set to 0, Tor will avoid connecting to directory servers
- and entry nodes over IPv4. Note that clients with an IPv4
- address in a **Bridge**, proxy, or pluggable transport line will try
- connecting over IPv4 even if **ClientUseIPv4** is set to 0. (Default: 1)
-
-[[ClientUseIPv6]] **ClientUseIPv6** **0**|**1**::
- If this option is set to 1, Tor might connect to directory servers or
- entry nodes over IPv6. For IPv6 only hosts, you need to also set
- **ClientUseIPv4** to 0 to disable IPv4. Note that clients configured with
- an IPv6 address in a **Bridge**, proxy, or pluggable transportline will
- try connecting over IPv6 even if **ClientUseIPv6** is set to 0. (Default: 0)
-
-[[ClientPreferIPv6DirPort]] **ClientPreferIPv6DirPort** **0**|**1**|**auto**::
- If this option is set to 1, Tor prefers a directory port with an IPv6
- address over one with IPv4, for direct connections, if a given directory
- server has both. (Tor also prefers an IPv6 DirPort if IPv4Client is set to
- 0.) If this option is set to auto, clients prefer IPv4. Other things may
- influence the choice. This option breaks a tie to the favor of IPv6.
- (Default: auto) (DEPRECATED: This option has had no effect for some
- time.)
-
-[[ClientPreferIPv6ORPort]] **ClientPreferIPv6ORPort** **0**|**1**|**auto**::
- If this option is set to 1, Tor prefers an OR port with an IPv6
- address over one with IPv4 if a given entry node has both. (Tor also
- prefers an IPv6 ORPort if IPv4Client is set to 0.) If this option is set
- to auto, Tor bridge clients prefer the configured bridge address, and
- other clients prefer IPv4. Other things may influence the choice. This
- option breaks a tie to the favor of IPv6. (Default: auto)
-
-[[ClientAutoIPv6ORPort]] **ClientAutoIPv6ORPort** **0**|**1**::
- If this option is set to 1, Tor clients randomly prefer a node's IPv4 or
- IPv6 ORPort. The random preference is set every time a node is loaded
- from a new consensus or bridge config. When this option is set to 1,
- **ClientPreferIPv6ORPort** is ignored. (Default: 0)
-
-[[PathsNeededToBuildCircuits]] **PathsNeededToBuildCircuits** __NUM__::
- Tor clients don't build circuits for user traffic until they know
- about enough of the network so that they could potentially construct
- enough of the possible paths through the network. If this option
- is set to a fraction between 0.25 and 0.95, Tor won't build circuits
- until it has enough descriptors or microdescriptors to construct
- that fraction of possible paths. Note that setting this option too low
- can make your Tor client less anonymous, and setting it too high can
- prevent your Tor client from bootstrapping. If this option is negative,
- Tor will use a default value chosen by the directory authorities. If the
- directory authorities do not choose a value, Tor will default to 0.6.
- (Default: -1)
-
-[[ClientBootstrapConsensusAuthorityDownloadInitialDelay]] **ClientBootstrapConsensusAuthorityDownloadInitialDelay** __N__::
- Initial delay in seconds for when clients should download consensuses from authorities
- if they are bootstrapping (that is, they don't have a usable, reasonably
- live consensus). Only used by clients fetching from a list of fallback
- directory mirrors. This schedule is advanced by (potentially concurrent)
- connection attempts, unlike other schedules, which are advanced by
- connection failures. (Default: 6)
-
-[[ClientBootstrapConsensusFallbackDownloadInitialDelay]] **ClientBootstrapConsensusFallbackDownloadInitialDelay** __N__::
- Initial delay in seconds for when clients should download consensuses from fallback
- directory mirrors if they are bootstrapping (that is, they don't have a
- usable, reasonably live consensus). Only used by clients fetching from a
- list of fallback directory mirrors. This schedule is advanced by
- (potentially concurrent) connection attempts, unlike other schedules,
- which are advanced by connection failures. (Default: 0)
+[[MiddleNodes]] **MiddleNodes** __node__,__node__,__...__::
+ A list of identity fingerprints and country codes of nodes
+ to use for "middle" hops in your normal circuits.
+ Normal circuits include all circuits except for direct connections
+ to directory servers. Middle hops are all hops other than exit and entry. +
++
+ This is an **experimental** feature that is meant to be used by researchers
+ and developers to test new features in the Tor network safely. Using it
+ without care will strongly influence your anonymity. This feature might get
+ removed in the future.
++
+ The HSLayer2Node and HSLayer3Node options override this option for onion
+ service circuits, if they are set. The vanguards addon will read this
+ option, and if set, it will set HSLayer2Nodes and HSLayer3Nodes to nodes
+ from this set.
++
+ The ExcludeNodes option overrides this option: any node listed in both
+ MiddleNodes and ExcludeNodes is treated as excluded. See
+ the **ExcludeNodes** option for more information on how to specify nodes.
-[[ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay]] **ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay** __N__::
- Initial delay in seconds for when clients should download consensuses from authorities
- if they are bootstrapping (that is, they don't have a usable, reasonably
- live consensus). Only used by clients which don't have or won't fetch
- from a list of fallback directory mirrors. This schedule is advanced by
- (potentially concurrent) connection attempts, unlike other schedules,
- which are advanced by connection failures. (Default: 0)
+[[NodeFamily]] **NodeFamily** __node__,__node__,__...__::
+ The Tor servers, defined by their identity fingerprints,
+ constitute a "family" of similar or co-administered servers, so never use
+ any two of them in the same circuit. Defining a NodeFamily is only needed
+ when a server doesn't list the family itself (with MyFamily). This option
+ can be used multiple times; each instance defines a separate family. In
+ addition to nodes, you can also list IP address and ranges and country
+ codes in {curly braces}. See the **ExcludeNodes** option for more
+ information on how to specify nodes.
-[[ClientBootstrapConsensusMaxInProgressTries]] **ClientBootstrapConsensusMaxInProgressTries** __NUM__::
- Try this many simultaneous connections to download a consensus before
- waiting for one to complete, timeout, or error out. (Default: 3)
+[[StrictNodes]] **StrictNodes** **0**|**1**::
+ If StrictNodes is set to 1, Tor will treat solely the ExcludeNodes option
+ as a requirement to follow for all the circuits you generate, even if
+ doing so will break functionality for you (StrictNodes does not apply to
+ ExcludeExitNodes, ExitNodes, MiddleNodes, or MapAddress). If StrictNodes
+ is set to 0, Tor will still try to avoid nodes in the ExcludeNodes list,
+ but it will err on the side of avoiding unexpected errors.
+ Specifically, StrictNodes 0 tells Tor that it is okay to use an excluded
+ node when it is *necessary* to perform relay reachability self-tests,
+ connect to a hidden service, provide a hidden service to a client,
+ fulfill a .exit request, upload directory information, or download
+ directory information. (Default: 0)
-[[DormantClientTimeout]] **DormantClientTimeout** __N__ **minutes**|**hours**|**days**|**weeks**::
- If Tor spends this much time without any client activity,
- enter a dormant state where automatic circuits are not built, and
- directory information is not fetched.
- Does not affect servers or onion services. Must be at least 10 minutes.
- (Default: 24 hours)
+== SERVER OPTIONS
-[[DormantTimeoutDisabledByIdleStreams]] **DormantTimeoutDisabledByIdleStreams** **0**|**1**::
- If true, then any open client stream (even one not reading or writing)
- counts as client activity for the purpose of DormantClientTimeout.
- If false, then only network activity counts. (Default: 1)
+// These options are in alphabetical order, with exceptions as noted.
+// Please keep them that way!
-[[DormantOnFirstStartup]] **DormantOnFirstStartup** **0**|**1**::
- If true, then the first time Tor starts up with a fresh DataDirectory,
- it starts in dormant mode, and takes no actions until the user has made
- a request. (This mode is recommended if installing a Tor client for a
- user who might not actually use it.) If false, Tor bootstraps the first
- time it is started, whether it sees a user request or not.
- +
- After the first time Tor starts, it begins in dormant mode if it was
- dormant before, and not otherwise. (Default: 0)
+The following options are useful only for servers (that is, if ORPort
+is non-zero):
-[[DormantCanceledByStartup]] **DormantCanceledByStartup** **0**|**1**::
- By default, Tor starts in active mode if it was active the last time
- it was shut down, and in dormant mode if it was dormant. But if
- this option is true, Tor treats every startup event as user
- activity, and Tor will never start in Dormant mode, even if it has
- been unused for a long time on previous runs. (Default: 0)
- +
- Note: Packagers and application developers should change the value of
- this option only with great caution: it has the potential to
- create spurious traffic on the network. This option should only
- be used if Tor is started by an affirmative user activity (like
- clicking on an applcation or running a command), and not if Tor
- is launched for some other reason (for example, by a startup
- process, or by an application that launches itself on every login.)
+[[AccountingMax]] **AccountingMax** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**TBytes**|**KBits**|**MBits**|**GBits**|**TBits**::
+ Limits the max number of bytes sent and received within a set time period
+ using a given calculation rule (see: AccountingStart, AccountingRule).
+ Useful if you need to stay under a specific bandwidth. By default, the
+ number used for calculation is the max of either the bytes sent or
+ received. For example, with AccountingMax set to 1 TByte, a server
+ could send 900 GBytes and receive 800 GBytes and continue running.
+ It will only hibernate once one of the two reaches 1 TByte. This can
+ be changed to use the sum of the both bytes received and sent by setting
+ the AccountingRule option to "sum" (total bandwidth in/out). When the
+ number of bytes remaining gets low, Tor will stop accepting new connections
+ and circuits. When the number of bytes is exhausted, Tor will hibernate
+ until some time in the next accounting period. To prevent all servers
+ from waking at the same time, Tor will also wait until a random point
+ in each period before waking up. If you have bandwidth cost issues,
+ enabling hibernation is preferable to setting a low bandwidth, since
+ it provides users with a collection of fast servers that are up some
+ of the time, which is more useful than a set of slow servers that are
+ always "available". +
+ +
+ Note that (as also described in the Bandwidth section) Tor uses
+ powers of two, not powers of ten: 1 GByte is 1024*1024*1024, not
+ one billion. Be careful: some internet service providers might count
+ GBytes differently.
-SERVER OPTIONS
---------------
+[[AccountingRule]] **AccountingRule** **sum**|**max**|**in**|**out**::
+ How we determine when our AccountingMax has been reached (when we
+ should hibernate) during a time interval. Set to "max" to calculate
+ using the higher of either the sent or received bytes (this is the
+ default functionality). Set to "sum" to calculate using the sent
+ plus received bytes. Set to "in" to calculate using only the
+ received bytes. Set to "out" to calculate using only the sent bytes.
+ (Default: max)
-The following options are useful only for servers (that is, if ORPort
-is non-zero):
+[[AccountingStart]] **AccountingStart** **day**|**week**|**month** [__day__] __HH:MM__::
+ Specify how long accounting periods last. If **month** is given,
+ each accounting period runs from the time __HH:MM__ on the __dayth__ day of one
+ month to the same day and time of the next. The relay will go at full speed,
+ use all the quota you specify, then hibernate for the rest of the period. (The
+ day must be between 1 and 28.) If **week** is given, each accounting period
+ runs from the time __HH:MM__ of the __dayth__ day of one week to the same day
+ and time of the next week, with Monday as day 1 and Sunday as day 7. If **day**
+ is given, each accounting period runs from the time __HH:MM__ each day to the
+ same time on the next day. All times are local, and given in 24-hour time.
+ (Default: "month 1 0:00")
[[Address]] **Address** __address__::
The IPv4 address of this server, or a fully qualified domain name of
@@ -1946,10 +2142,20 @@ is non-zero):
from bridge users to the Tor network. It mainly causes Tor to publish a
server descriptor to the bridge database, rather than
to the public directory authorities. +
- +
+ +
Note: make sure that no MyFamily lines are present in your torrc when
relay is configured in bridge mode.
+//Out of order because it logically belongs after BridgeRelay.
+[[BridgeRecordUsageByCountry]] **BridgeRecordUsageByCountry** **0**|**1**::
+ When this option is enabled and BridgeRelay is also enabled, and we have
+ GeoIP data, Tor keeps a per-country count of how many client
+ addresses have contacted it so that it can help the bridge authority guess
+ which countries have blocked access to it. If ExtraInfoStatistics is
+ enabled, it will be published as part of the extra-info document.
+ (Default: 1)
+
+//Out of order because it logically belongs after BridgeRelay.
[[BridgeDistribution]] **BridgeDistribution** __string__::
If set along with BridgeRelay, Tor will include a new line in its
bridge descriptor which indicates to the BridgeDB service how it
@@ -1965,26 +2171,16 @@ is non-zero):
spammers might also collect them. You may want to obscure the fact
that it's an email address and/or generate a new address for this
purpose. +
- +
+ +
ContactInfo **must** be set to a working address if you run more than one
relay or bridge. (Really, everybody running a relay or bridge should set
it.)
-
-[[ExitRelay]] **ExitRelay** **0**|**1**|**auto**::
- Tells Tor whether to run as an exit relay. If Tor is running as a
- non-bridge server, and ExitRelay is set to 1, then Tor allows traffic to
- exit according to the ExitPolicy option, the ReducedExitPolicy option,
- or the default ExitPolicy (if no other exit policy option is specified). +
- +
- If ExitRelay is set to 0, no traffic is allowed to exit, and the
- ExitPolicy, ReducedExitPolicy, and IPv6Exit options are ignored. +
- +
- If ExitRelay is set to "auto", then Tor checks the ExitPolicy,
- ReducedExitPolicy, and IPv6Exit options. If at least one of these options
- is set, Tor behaves as if ExitRelay were set to 1. If none of these exit
- policy options are set, Tor behaves as if ExitRelay were set to 0.
- (Default: auto)
+[[DisableOOSCheck]] **DisableOOSCheck** **0**|**1**::
+ This option disables the code that closes connections when Tor notices
+ that it is running low on sockets. Right now, it is on by default,
+ since the existing out-of-sockets mechanism tends to kill OR connections
+ more than it should. (Default: 1)
[[ExitPolicy]] **ExitPolicy** __policy__,__policy__,__...__::
Set an exit policy for this server. Each policy is of the form
@@ -1996,29 +2192,29 @@ is non-zero):
__PORT__ can be a single port number, an interval of ports
"__FROM_PORT__-__TO_PORT__", or "\*". If __PORT__ is omitted, that means
"\*". +
- +
+ +
For example, "accept 18.7.22.69:\*,reject 18.0.0.0/8:\*,accept \*:\*" would
reject any IPv4 traffic destined for MIT except for web.mit.edu, and accept
any other IPv4 or IPv6 traffic. +
- +
+ +
Tor also allows IPv6 exit policy entries. For instance, "reject6 [FC00::]/7:\*"
rejects all destinations that share 7 most significant bit prefix with
address FC00::. Respectively, "accept6 [C000::]/3:\*" accepts all destinations
that share 3 most significant bit prefix with address C000::. +
- +
+ +
accept6 and reject6 only produce IPv6 exit policy entries. Using an IPv4
address with accept6 or reject6 is ignored and generates a warning.
accept/reject allows either IPv4 or IPv6 addresses. Use \*4 as an IPv4
wildcard address, and \*6 as an IPv6 wildcard address. accept/reject *
expands to matching IPv4 and IPv6 wildcard address rules. +
- +
+ +
To specify all IPv4 and IPv6 internal and link-local networks (including
0.0.0.0/8, 169.254.0.0/16, 127.0.0.0/8, 192.168.0.0/16, 10.0.0.0/8,
172.16.0.0/12, [::]/8, [FC00::]/7, [FE80::]/10, [FEC0::]/10, [FF00::]/8,
and [::]/127), you can use the "private" alias instead of an address.
("private" always produces rules for IPv4 and IPv6 addresses, even when
used with accept6/reject6.) +
- +
+ +
Private addresses are rejected by default (at the beginning of your exit
policy), along with any configured primary public IPv4 and IPv6 addresses.
These private addresses are rejected unless you set the
@@ -2030,10 +2226,10 @@ is non-zero):
about internal and reserved IP address space. See
ExitPolicyRejectLocalInterfaces if you want to block every address on the
relay, even those that aren't advertised in the descriptor. +
- +
+ +
This directive can be specified multiple times so you don't have to put it
all on one line. +
- +
+ +
Policies are considered first to last, and the first match wins. If you
want to allow the same ports on IPv4 and IPv6, write your rules using
accept/reject \*. If you want to allow different ports on IPv4 and IPv6,
@@ -2041,13 +2237,13 @@ is non-zero):
accept/reject \*4. If you want to \_replace_ the default exit policy, end
your exit policy with either a reject \*:* or an accept \*:*. Otherwise,
you're \_augmenting_ (prepending to) the default exit policy. +
- +
+ +
If you want to use a reduced exit policy rather than the default exit
policy, set "ReducedExitPolicy 1". If you want to _replace_ the default
exit policy with your custom exit policy, end your exit policy with either
a reject *:* or an accept *:*. Otherwise, you're _augmenting_ (prepending
to) the default or reduced exit policy. +
- +
+ +
The default exit policy is:
reject *:25
@@ -2067,12 +2263,6 @@ is non-zero):
Since the default exit policy uses accept/reject *, it applies to both
IPv4 and IPv6 addresses.
-[[ExitPolicyRejectPrivate]] **ExitPolicyRejectPrivate** **0**|**1**::
- Reject all private (local) networks, along with the relay's advertised
- public IPv4 and IPv6 addresses, at the beginning of your exit policy.
- See above entry on ExitPolicy.
- (Default: 1)
-
[[ExitPolicyRejectLocalInterfaces]] **ExitPolicyRejectLocalInterfaces** **0**|**1**::
Reject all IPv4 and IPv6 addresses that the relay knows about, at the
beginning of your exit policy. This includes any OutboundBindAddress, the
@@ -2085,15 +2275,177 @@ is non-zero):
to disclose.
(Default: 0)
+[[ExitPolicyRejectPrivate]] **ExitPolicyRejectPrivate** **0**|**1**::
+ Reject all private (local) networks, along with the relay's advertised
+ public IPv4 and IPv6 addresses, at the beginning of your exit policy.
+ See above entry on ExitPolicy.
+ (Default: 1)
+
+[[ExitRelay]] **ExitRelay** **0**|**1**|**auto**::
+ Tells Tor whether to run as an exit relay. If Tor is running as a
+ non-bridge server, and ExitRelay is set to 1, then Tor allows traffic to
+ exit according to the ExitPolicy option, the ReducedExitPolicy option,
+ or the default ExitPolicy (if no other exit policy option is specified). +
+ +
+ If ExitRelay is set to 0, no traffic is allowed to exit, and the
+ ExitPolicy, ReducedExitPolicy, and IPv6Exit options are ignored. +
+ +
+ If ExitRelay is set to "auto", then Tor checks the ExitPolicy,
+ ReducedExitPolicy, and IPv6Exit options. If at least one of these options
+ is set, Tor behaves as if ExitRelay were set to 1. If none of these exit
+ policy options are set, Tor behaves as if ExitRelay were set to 0.
+ (Default: auto)
+
+[[ExtendAllowPrivateAddresses]] **ExtendAllowPrivateAddresses** **0**|**1**::
+ When this option is enabled, Tor will connect to relays on localhost,
+ RFC1918 addresses, and so on. In particular, Tor will make direct OR
+ connections, and Tor routers allow EXTEND requests, to these private
+ addresses. (Tor will always allow connections to bridges, proxies, and
+ pluggable transports configured on private addresses.) Enabling this
+ option can create security issues; you should probably leave it off.
+ (Default: 0)
+
+[[GeoIPFile]] **GeoIPFile** __filename__::
+ A filename containing IPv4 GeoIP data, for use with by-country statistics.
+
+[[GeoIPv6File]] **GeoIPv6File** __filename__::
+ A filename containing IPv6 GeoIP data, for use with by-country statistics.
+
+[[HeartbeatPeriod]] **HeartbeatPeriod** __N__ **minutes**|**hours**|**days**|**weeks**::
+ Log a heartbeat message every **HeartbeatPeriod** seconds. This is
+ a log level __notice__ message, designed to let you know your Tor
+ server is still alive and doing useful things. Settings this
+ to 0 will disable the heartbeat. Otherwise, it must be at least 30
+ minutes. (Default: 6 hours)
+
+[[IPv6Exit]] **IPv6Exit** **0**|**1**::
+ If set, and we are an exit node, allow clients to use us for IPv6 traffic.
+ When this option is set and ExitRelay is auto, we act as if ExitRelay
+ is 1. (Default: 0)
+
+[[KeyDirectory]] **KeyDirectory** __DIR__::
+ Store secret keys in DIR. Can not be changed while tor is
+ running.
+ (Default: the "keys" subdirectory of DataDirectory.)
+
+[[KeyDirectoryGroupReadable]] **KeyDirectoryGroupReadable** **0**|**1**|**auto**::
+ If this option is set to 0, don't allow the filesystem group to read the
+ KeyDirectory. If the option is set to 1, make the KeyDirectory readable
+ by the default GID. If the option is "auto", then we use the
+ setting for DataDirectoryGroupReadable when the KeyDirectory is the
+ same as the DataDirectory, and 0 otherwise. (Default: auto)
+
+[[MainloopStats]] **MainloopStats** **0**|**1**::
+ Log main loop statistics every **HeartbeatPeriod** seconds. This is a log
+ level __notice__ message designed to help developers instrumenting Tor's
+ main event loop. (Default: 0)
+
+[[MaxMemInQueues]] **MaxMemInQueues** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**::
+ This option configures a threshold above which Tor will assume that it
+ needs to stop queueing or buffering data because it's about to run out of
+ memory. If it hits this threshold, it will begin killing circuits until
+ it has recovered at least 10% of this memory. Do not set this option too
+ low, or your relay may be unreliable under load. This option only
+ affects some queues, so the actual process size will be larger than
+ this. If this option is set to 0, Tor will try to pick a reasonable
+ default based on your system's physical memory. (Default: 0)
+
+[[MaxOnionQueueDelay]] **MaxOnionQueueDelay** __NUM__ [**msec**|**second**]::
+ If we have more onionskins queued for processing than we can process in
+ this amount of time, reject new ones. (Default: 1750 msec)
+
+[[MyFamily]] **MyFamily** __fingerprint__,__fingerprint__,...::
+ Declare that this Tor relay is controlled or administered by a group or
+ organization identical or similar to that of the other relays, defined by
+ their (possibly $-prefixed) identity fingerprints.
+ This option can be repeated many times, for
+ convenience in defining large families: all fingerprints in all MyFamily
+ lines are merged into one list.
+ When two relays both declare that they are in the
+ same \'family', Tor clients will not use them in the same circuit. (Each
+ relay only needs to list the other servers in its family; it doesn't need to
+ list itself, but it won't hurt if it does.) Do not list any bridge relay as it would
+ compromise its concealment. +
+ +
+ When listing a node, it's better to list it by fingerprint than by
+ nickname: fingerprints are more reliable. +
+ +
+ If you run more than one relay, the MyFamily option on each relay
+ **must** list all other relays, as described above. +
+ +
+ Note: do not use MyFamily when configuring your Tor instance as a
+ brigde.
+
+[[Nickname]] **Nickname** __name__::
+ Set the server's nickname to \'name'. Nicknames must be between 1 and 19
+ characters inclusive, and must contain only the characters [a-zA-Z0-9].
+ If not set, **Unnamed** will be used. Relays can always be uniquely identified
+ by their identity fingerprints.
+
+[[NumCPUs]] **NumCPUs** __num__::
+ How many processes to use at once for decrypting onionskins and other
+ parallelizable operations. If this is set to 0, Tor will try to detect
+ how many CPUs you have, defaulting to 1 if it can't tell. (Default: 0)
+
+[[OfflineMasterKey]] **OfflineMasterKey** **0**|**1**::
+ If non-zero, the Tor relay will never generate or load its master secret
+ key. Instead, you'll have to use "tor --keygen" to manage the permanent
+ ed25519 master identity key, as well as the corresponding temporary
+ signing keys and certificates. (Default: 0)
+
+[[ORPort]] **ORPort** ['address'**:**]{empty}__PORT__|**auto** [_flags_]::
+ Advertise this port to listen for connections from Tor clients and
+ servers. This option is required to be a Tor server.
+ Set it to "auto" to have Tor pick a port for you. Set it to 0 to not
+ run an ORPort at all. This option can occur more than once. (Default: 0) +
+ +
+ Tor recognizes these flags on each ORPort:
+ **NoAdvertise**;;
+ By default, we bind to a port and tell our users about it. If
+ NoAdvertise is specified, we don't advertise, but listen anyway. This
+ can be useful if the port everybody will be connecting to (for
+ example, one that's opened on our firewall) is somewhere else.
+ **NoListen**;;
+ By default, we bind to a port and tell our users about it. If
+ NoListen is specified, we don't bind, but advertise anyway. This
+ can be useful if something else (for example, a firewall's port
+ forwarding configuration) is causing connections to reach us.
+ **IPv4Only**;;
+ If the address is absent, or resolves to both an IPv4 and an IPv6
+ address, only listen to the IPv4 address.
+ **IPv6Only**;;
+ If the address is absent, or resolves to both an IPv4 and an IPv6
+ address, only listen to the IPv6 address.
+
+// Anchor only for formatting, not visible in the man page.
+[[ORPortFlagsExclusive]]::
+ For obvious reasons, NoAdvertise and NoListen are mutually exclusive, and
+ IPv4Only and IPv6Only are mutually exclusive.
+
+[[PublishServerDescriptor]] **PublishServerDescriptor** **0**|**1**|**v3**|**bridge**,**...**::
+ This option specifies which descriptors Tor will publish when acting as
+ a relay. You can
+ choose multiple arguments, separated by commas. +
+ +
+ If this option is set to 0, Tor will not publish its
+ descriptors to any directories. (This is useful if you're testing
+ out your server, or if you're using a Tor controller that handles
+ directory publishing for you.) Otherwise, Tor will publish its
+ descriptors of all type(s) specified. The default is "1", which
+ means "if running as a relay or bridge, publish descriptors to the
+ appropriate authorities". Other possibilities are "v3", meaning
+ "publish as if you're a relay", and "bridge", meaning "publish as
+ if you're a bridge".
+
[[ReducedExitPolicy]] **ReducedExitPolicy** **0**|**1**::
If set, use a reduced exit policy rather than the default one. +
- +
+ +
The reduced exit policy is an alternative to the default exit policy. It
allows as many Internet services as possible while still blocking the
majority of TCP ports. Currently, the policy allows approximately 65 ports.
This reduces the odds that your node will be used for peer-to-peer
applications. +
- +
+ +
The reduced exit policy is:
accept *:20-21
@@ -2178,161 +2530,6 @@ is non-zero):
(Default: 0)
-[[IPv6Exit]] **IPv6Exit** **0**|**1**::
- If set, and we are an exit node, allow clients to use us for IPv6 traffic.
- When this option is set and ExitRelay is auto, we act as if ExitRelay
- is 1. (Default: 0)
-
-[[MaxOnionQueueDelay]] **MaxOnionQueueDelay** __NUM__ [**msec**|**second**]::
- If we have more onionskins queued for processing than we can process in
- this amount of time, reject new ones. (Default: 1750 msec)
-
-[[MyFamily]] **MyFamily** __fingerprint__,__fingerprint__,...::
- Declare that this Tor relay is controlled or administered by a group or
- organization identical or similar to that of the other relays, defined by
- their (possibly $-prefixed) identity fingerprints.
- This option can be repeated many times, for
- convenience in defining large families: all fingerprints in all MyFamily
- lines are merged into one list.
- When two relays both declare that they are in the
- same \'family', Tor clients will not use them in the same circuit. (Each
- relay only needs to list the other servers in its family; it doesn't need to
- list itself, but it won't hurt if it does.) Do not list any bridge relay as it would
- compromise its concealment. +
- +
- When listing a node, it's better to list it by fingerprint than by
- nickname: fingerprints are more reliable. +
- +
- If you run more than one relay, the MyFamily option on each relay
- **must** list all other relays, as described above. +
- +
- Note: do not use MyFamily when configuring your Tor instance as a
- brigde.
-
-[[Nickname]] **Nickname** __name__::
- Set the server's nickname to \'name'. Nicknames must be between 1 and 19
- characters inclusive, and must contain only the characters [a-zA-Z0-9].
- If not set, **Unnamed** will be used. Relays can always be uniquely identified
- by their identity fingerprints.
-
-[[NumCPUs]] **NumCPUs** __num__::
- How many processes to use at once for decrypting onionskins and other
- parallelizable operations. If this is set to 0, Tor will try to detect
- how many CPUs you have, defaulting to 1 if it can't tell. (Default: 0)
-
-[[ORPort]] **ORPort** \['address':]__PORT__|**auto** [_flags_]::
- Advertise this port to listen for connections from Tor clients and
- servers. This option is required to be a Tor server.
- Set it to "auto" to have Tor pick a port for you. Set it to 0 to not
- run an ORPort at all. This option can occur more than once. (Default: 0) +
- +
- Tor recognizes these flags on each ORPort:
- **NoAdvertise**;;
- By default, we bind to a port and tell our users about it. If
- NoAdvertise is specified, we don't advertise, but listen anyway. This
- can be useful if the port everybody will be connecting to (for
- example, one that's opened on our firewall) is somewhere else.
- **NoListen**;;
- By default, we bind to a port and tell our users about it. If
- NoListen is specified, we don't bind, but advertise anyway. This
- can be useful if something else (for example, a firewall's port
- forwarding configuration) is causing connections to reach us.
- **IPv4Only**;;
- If the address is absent, or resolves to both an IPv4 and an IPv6
- address, only listen to the IPv4 address.
- **IPv6Only**;;
- If the address is absent, or resolves to both an IPv4 and an IPv6
- address, only listen to the IPv6 address.
-
-// Anchor only for formatting, not visible in the man page.
-[[ORPortFlagsExclusive]]::
- For obvious reasons, NoAdvertise and NoListen are mutually exclusive, and
- IPv4Only and IPv6Only are mutually exclusive.
-
-[[PublishServerDescriptor]] **PublishServerDescriptor** **0**|**1**|**v3**|**bridge**,**...**::
- This option specifies which descriptors Tor will publish when acting as
- a relay. You can
- choose multiple arguments, separated by commas. +
- +
- If this option is set to 0, Tor will not publish its
- descriptors to any directories. (This is useful if you're testing
- out your server, or if you're using a Tor controller that handles
- directory publishing for you.) Otherwise, Tor will publish its
- descriptors of all type(s) specified. The default is "1", which
- means "if running as a relay or bridge, publish descriptors to the
- appropriate authorities". Other possibilities are "v3", meaning
- "publish as if you're a relay", and "bridge", meaning "publish as
- if you're a bridge".
-
-[[ShutdownWaitLength]] **ShutdownWaitLength** __NUM__::
- When we get a SIGINT and we're a server, we begin shutting down:
- we close listeners and start refusing new circuits. After **NUM**
- seconds, we exit. If we get a second SIGINT, we exit immediately.
- (Default: 30 seconds)
-
-[[SSLKeyLifetime]] **SSLKeyLifetime** __N__ **minutes**|**hours**|**days**|**weeks**::
- When creating a link certificate for our outermost SSL handshake,
- set its lifetime to this amount of time. If set to 0, Tor will choose
- some reasonable random defaults. (Default: 0)
-
-[[HeartbeatPeriod]] **HeartbeatPeriod** __N__ **minutes**|**hours**|**days**|**weeks**::
- Log a heartbeat message every **HeartbeatPeriod** seconds. This is
- a log level __notice__ message, designed to let you know your Tor
- server is still alive and doing useful things. Settings this
- to 0 will disable the heartbeat. Otherwise, it must be at least 30
- minutes. (Default: 6 hours)
-
-[[MainloopStats]] **MainloopStats** **0**|**1**::
- Log main loop statistics every **HeartbeatPeriod** seconds. This is a log
- level __notice__ message designed to help developers instrumenting Tor's
- main event loop. (Default: 0)
-
-[[AccountingMax]] **AccountingMax** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**TBytes**|**KBits**|**MBits**|**GBits**|**TBits**::
- Limits the max number of bytes sent and received within a set time period
- using a given calculation rule (see: AccountingStart, AccountingRule).
- Useful if you need to stay under a specific bandwidth. By default, the
- number used for calculation is the max of either the bytes sent or
- received. For example, with AccountingMax set to 1 TByte, a server
- could send 900 GBytes and receive 800 GBytes and continue running.
- It will only hibernate once one of the two reaches 1 TByte. This can
- be changed to use the sum of the both bytes received and sent by setting
- the AccountingRule option to "sum" (total bandwidth in/out). When the
- number of bytes remaining gets low, Tor will stop accepting new connections
- and circuits. When the number of bytes is exhausted, Tor will hibernate
- until some time in the next accounting period. To prevent all servers
- from waking at the same time, Tor will also wait until a random point
- in each period before waking up. If you have bandwidth cost issues,
- enabling hibernation is preferable to setting a low bandwidth, since
- it provides users with a collection of fast servers that are up some
- of the time, which is more useful than a set of slow servers that are
- always "available". +
- +
- Note that (as also described in the Bandwidth section) Tor uses
- powers of two, not powers of ten: 1 GByte is 1024*1024*1024, not
- one billion. Be careful: some internet service providers might count
- GBytes differently.
-
-[[AccountingRule]] **AccountingRule** **sum**|**max**|**in**|**out**::
- How we determine when our AccountingMax has been reached (when we
- should hibernate) during a time interval. Set to "max" to calculate
- using the higher of either the sent or received bytes (this is the
- default functionality). Set to "sum" to calculate using the sent
- plus received bytes. Set to "in" to calculate using only the
- received bytes. Set to "out" to calculate using only the sent bytes.
- (Default: max)
-
-[[AccountingStart]] **AccountingStart** **day**|**week**|**month** [__day__] __HH:MM__::
- Specify how long accounting periods last. If **month** is given,
- each accounting period runs from the time __HH:MM__ on the __dayth__ day of one
- month to the same day and time of the next. The relay will go at full speed,
- use all the quota you specify, then hibernate for the rest of the period. (The
- day must be between 1 and 28.) If **week** is given, each accounting period
- runs from the time __HH:MM__ of the __dayth__ day of one week to the same day
- and time of the next week, with Monday as day 1 and Sunday as day 7. If **day**
- is given, each accounting period runs from the time __HH:MM__ each day to the
- same time on the next day. All times are local, and given in 24-hour time.
- (Default: "month 1 0:00")
-
[[RefuseUnknownExits]] **RefuseUnknownExits** **0**|**1**|**auto**::
Prevent nodes that don't appear in the consensus from exiting using this
relay. If the option is 1, we always block exit attempts from such
@@ -2340,6 +2537,34 @@ is non-zero):
whatever the authorities suggest in the consensus (and block if the consensus
is quiet on the issue). (Default: auto)
+[[ServerDNSAllowBrokenConfig]] **ServerDNSAllowBrokenConfig** **0**|**1**::
+ If this option is false, Tor exits immediately if there are problems
+ parsing the system DNS configuration or connecting to nameservers.
+ Otherwise, Tor continues to periodically retry the system nameservers until
+ it eventually succeeds. (Default: 1)
+
+[[ServerDNSAllowNonRFC953Hostnames]] **ServerDNSAllowNonRFC953Hostnames** **0**|**1**::
+ When this option is disabled, Tor does not try to resolve hostnames
+ containing illegal characters (like @ and :) rather than sending them to an
+ exit node to be resolved. This helps trap accidental attempts to resolve
+ URLs and so on. This option only affects name lookups that your server does
+ on behalf of clients. (Default: 0)
+
+[[ServerDNSDetectHijacking]] **ServerDNSDetectHijacking** **0**|**1**::
+ 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 affects name lookups that your server does
+ on behalf of clients. (Default: 1)
+
+[[ServerDNSRandomizeCase]] **ServerDNSRandomizeCase** **0**|**1**::
+ When this option is set, Tor sets the case of each character randomly in
+ outgoing DNS requests, and makes sure that the case matches in DNS replies.
+ This so-called "0x20 hack" helps resist some types of DNS poisoning attack.
+ For more information, see "Increased DNS Forgery Resistance through
+ 0x20-Bit Encoding". This option only affects name lookups that your server
+ does on behalf of clients. (Default: 1)
+
[[ServerDNSResolvConfFile]] **ServerDNSResolvConfFile** __filename__::
Overrides the default DNS configuration with the configuration in
__filename__. The file format is the same as the standard Unix
@@ -2348,12 +2573,6 @@ is non-zero):
(Defaults to use the system DNS configuration or a localhost DNS service
in case no nameservers are found in a given configuration.)
-[[ServerDNSAllowBrokenConfig]] **ServerDNSAllowBrokenConfig** **0**|**1**::
- If this option is false, Tor exits immediately if there are problems
- parsing the system DNS configuration or connecting to nameservers.
- Otherwise, Tor continues to periodically retry the system nameservers until
- it eventually succeeds. (Default: 1)
-
[[ServerDNSSearchDomains]] **ServerDNSSearchDomains** **0**|**1**::
If set to 1, then we will search for addresses in the local search domain.
For example, if this system is configured to believe it is in
@@ -2361,13 +2580,6 @@ is non-zero):
connected to "www.example.com". This option only affects name lookups that
your server does on behalf of clients. (Default: 0)
-[[ServerDNSDetectHijacking]] **ServerDNSDetectHijacking** **0**|**1**::
- 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 affects name lookups that your server does
- on behalf of clients. (Default: 1)
-
[[ServerDNSTestAddresses]] **ServerDNSTestAddresses** __hostname__,__hostname__,__...__::
When we're detecting DNS hijacking, make sure that these __valid__ addresses
aren't getting redirected. If they are, then our DNS is completely useless,
@@ -2375,33 +2587,32 @@ is non-zero):
name lookups that your server does on behalf of clients. (Default:
"www.google.com, www.mit.edu, www.yahoo.com, www.slashdot.org")
-[[ServerDNSAllowNonRFC953Hostnames]] **ServerDNSAllowNonRFC953Hostnames** **0**|**1**::
- When this option is disabled, Tor does not try to resolve hostnames
- containing illegal characters (like @ and :) rather than sending them to an
- exit node to be resolved. This helps trap accidental attempts to resolve
- URLs and so on. This option only affects name lookups that your server does
- on behalf of clients. (Default: 0)
+[[ShutdownWaitLength]] **ShutdownWaitLength** __NUM__::
+ When we get a SIGINT and we're a server, we begin shutting down:
+ we close listeners and start refusing new circuits. After **NUM**
+ seconds, we exit. If we get a second SIGINT, we exit immediately.
+ (Default: 30 seconds)
-[[BridgeRecordUsageByCountry]] **BridgeRecordUsageByCountry** **0**|**1**::
- When this option is enabled and BridgeRelay is also enabled, and we have
- GeoIP data, Tor keeps a per-country count of how many client
- addresses have contacted it so that it can help the bridge authority guess
- which countries have blocked access to it. If ExtraInfoStatistics is
- enabled, it will be published as part of extra-info document. (Default: 1)
+[[SigningKeyLifetime]] **SigningKeyLifetime** __N__ **days**|**weeks**|**months**::
+ For how long should each Ed25519 signing key be valid? Tor uses a
+ permanent master identity key that can be kept offline, and periodically
+ generates new "signing" keys that it uses online. This option
+ configures their lifetime.
+ (Default: 30 days)
-[[ServerDNSRandomizeCase]] **ServerDNSRandomizeCase** **0**|**1**::
- When this option is set, Tor sets the case of each character randomly in
- outgoing DNS requests, and makes sure that the case matches in DNS replies.
- This so-called "0x20 hack" helps resist some types of DNS poisoning attack.
- For more information, see "Increased DNS Forgery Resistance through
- 0x20-Bit Encoding". This option only affects name lookups that your server
- does on behalf of clients. (Default: 1)
+[[SSLKeyLifetime]] **SSLKeyLifetime** __N__ **minutes**|**hours**|**days**|**weeks**::
+ When creating a link certificate for our outermost SSL handshake,
+ set its lifetime to this amount of time. If set to 0, Tor will choose
+ some reasonable random defaults. (Default: 0)
-[[GeoIPFile]] **GeoIPFile** __filename__::
- A filename containing IPv4 GeoIP data, for use with by-country statistics.
+== STATISTICS OPTIONS
-[[GeoIPv6File]] **GeoIPv6File** __filename__::
- A filename containing IPv6 GeoIP data, for use with by-country statistics.
+// These options are in alphabetical order, with exceptions as noted.
+// Please keep them that way!
+
+Relays publish most statistics in a document called the
+extra-info document. The following options affect the different
+types of statistics that Tor relays collect and publish:
[[CellStatistics]] **CellStatistics** **0**|**1**::
Relays only.
@@ -2411,16 +2622,16 @@ is non-zero):
circuit) and writes them into disk every 24 hours. Onion router
operators may use the statistics for performance monitoring.
If ExtraInfoStatistics is enabled, it will published as part of
- extra-info document. (Default: 0)
+ the extra-info document. (Default: 0)
-[[PaddingStatistics]] **PaddingStatistics** **0**|**1**::
- Relays and bridges only.
- When this option is enabled, Tor collects statistics for padding cells
- sent and received by this relay, in addition to total cell counts.
- These statistics are rounded, and omitted if traffic is low. This
- information is important for load balancing decisions related to padding.
- If ExtraInfoStatistics is enabled, it will be published
- as a part of extra-info document. (Default: 1)
+[[ConnDirectionStatistics]] **ConnDirectionStatistics** **0**|**1**::
+ Relays only.
+ When this option is enabled, Tor writes statistics on the amounts of
+ traffic it passes between itself and other relays to disk every 24
+ hours. Enables relay operators to monitor how much their relay is
+ being used as middle node in the circuit. If ExtraInfoStatistics is
+ enabled, it will be published as part of the extra-info document.
+ (Default: 0)
[[DirReqStatistics]] **DirReqStatistics** **0**|**1**::
Relays and bridges only.
@@ -2429,7 +2640,7 @@ is non-zero):
hours. Enables relay and bridge operators to monitor how much their
server is being used by clients to learn about Tor network.
If ExtraInfoStatistics is enabled, it will published as part of
- extra-info document. (Default: 1)
+ the extra-info document. (Default: 1)
[[EntryStatistics]] **EntryStatistics** **0**|**1**::
Relays only.
@@ -2438,7 +2649,7 @@ is non-zero):
operators to monitor how much inbound traffic that originates from
Tor clients passes through their server to go further down the
Tor network. If ExtraInfoStatistics is enabled, it will be published
- as part of extra-info document. (Default: 0)
+ as part of the extra-info document. (Default: 0)
[[ExitPortStatistics]] **ExitPortStatistics** **0**|**1**::
Exit relays only.
@@ -2446,116 +2657,41 @@ is non-zero):
relayed bytes and opened stream per exit port to disk every 24 hours.
Enables exit relay operators to measure and monitor amounts of traffic
that leaves Tor network through their exit node. If ExtraInfoStatistics
- is enabled, it will be published as part of extra-info document.
+ is enabled, it will be published as part of the extra-info document.
(Default: 0)
-[[ConnDirectionStatistics]] **ConnDirectionStatistics** **0**|**1**::
- Relays only.
- When this option is enabled, Tor writes statistics on the amounts of
- traffic it passes between itself and other relays to disk every 24
- hours. Enables relay operators to monitor how much their relay is
- being used as middle node in the circuit. If ExtraInfoStatistics is
- enabled, it will be published as part of extra-info document.
- (Default: 0)
-
-[[HiddenServiceStatistics]] **HiddenServiceStatistics** **0**|**1**::
- Relays only.
- When this option is enabled, a Tor relay writes obfuscated
- statistics on its role as hidden-service directory, introduction
- point, or rendezvous point to disk every 24 hours. If
- ExtraInfoStatistics is also enabled, these statistics are further
- published to the directory authorities. (Default: 1)
-
[[ExtraInfoStatistics]] **ExtraInfoStatistics** **0**|**1**::
When this option is enabled, Tor includes previously gathered statistics in
its extra-info documents that it uploads to the directory authorities.
Disabling this option also removes bandwidth usage statistics, and
GeoIPFile and GeoIPv6File hashes from the extra-info file. Bridge
- ServerTransportPlugin lines are always includes in the extra-info file,
+ ServerTransportPlugin lines are always included in the extra-info file,
because they are required by BridgeDB.
(Default: 1)
-[[ExtendAllowPrivateAddresses]] **ExtendAllowPrivateAddresses** **0**|**1**::
- When this option is enabled, Tor will connect to relays on localhost,
- RFC1918 addresses, and so on. In particular, Tor will make direct OR
- connections, and Tor routers allow EXTEND requests, to these private
- addresses. (Tor will always allow connections to bridges, proxies, and
- pluggable transports configured on private addresses.) Enabling this
- option can create security issues; you should probably leave it off.
- (Default: 0)
-
-[[MaxMemInQueues]] **MaxMemInQueues** __N__ **bytes**|**KB**|**MB**|**GB**::
- This option configures a threshold above which Tor will assume that it
- needs to stop queueing or buffering data because it's about to run out of
- memory. If it hits this threshold, it will begin killing circuits until
- it has recovered at least 10% of this memory. Do not set this option too
- low, or your relay may be unreliable under load. This option only
- affects some queues, so the actual process size will be larger than
- this. If this option is set to 0, Tor will try to pick a reasonable
- default based on your system's physical memory. (Default: 0)
-
-[[DisableOOSCheck]] **DisableOOSCheck** **0**|**1**::
- This option disables the code that closes connections when Tor notices
- that it is running low on sockets. Right now, it is on by default,
- since the existing out-of-sockets mechanism tends to kill OR connections
- more than it should. (Default: 1)
-
-[[SigningKeyLifetime]] **SigningKeyLifetime** __N__ **days**|**weeks**|**months**::
- For how long should each Ed25519 signing key be valid? Tor uses a
- permanent master identity key that can be kept offline, and periodically
- generates new "signing" keys that it uses online. This option
- configures their lifetime.
- (Default: 30 days)
-
-[[OfflineMasterKey]] **OfflineMasterKey** **0**|**1**::
- If non-zero, the Tor relay will never generate or load its master secret
- key. Instead, you'll have to use "tor --keygen" to manage the permanent
- ed25519 master identity key, as well as the corresponding temporary
- signing keys and certificates. (Default: 0)
-
-[[KeyDirectory]] **KeyDirectory** __DIR__::
- Store secret keys in DIR. Can not be changed while tor is
- running.
- (Default: the "keys" subdirectory of DataDirectory.)
-
-[[KeyDirectoryGroupReadable]] **KeyDirectoryGroupReadable** **0**|**1**::
- If this option is set to 0, don't allow the filesystem group to read the
- KeywDirectory. If the option is set to 1, make the KeyDirectory readable
- by the default GID. (Default: 0)
-
-[[RephistTrackTime]] **RephistTrackTime** __N__ **seconds**|**minutes**|**hours**|**days**|**weeks**::
- Tells an authority, or other node tracking node reliability and history,
- that fine-grained information about nodes can be discarded when it hasn't
- changed for a given amount of time. (Default: 24 hours)
+[[HiddenServiceStatistics]] **HiddenServiceStatistics** **0**|**1**::
+ Relays only.
+ When this option is enabled, a Tor relay writes obfuscated
+ statistics on its role as hidden-service directory, introduction
+ point, or rendezvous point to disk every 24 hours. If ExtraInfoStatistics
+ is enabled, it will be published as part of the extra-info document.
+ (Default: 1)
+[[PaddingStatistics]] **PaddingStatistics** **0**|**1**::
+ Relays and bridges only.
+ When this option is enabled, Tor collects statistics for padding cells
+ sent and received by this relay, in addition to total cell counts.
+ These statistics are rounded, and omitted if traffic is low. This
+ information is important for load balancing decisions related to padding.
+ If ExtraInfoStatistics is enabled, it will be published
+ as a part of the extra-info document. (Default: 1)
-DIRECTORY SERVER OPTIONS
-------------------------
+== DIRECTORY SERVER OPTIONS
The following options are useful only for directory servers. (Relays with
enough bandwidth automatically become directory servers; see DirCache for
details.)
-[[DirPortFrontPage]] **DirPortFrontPage** __FILENAME__::
- When this option is set, it takes an HTML file and publishes it as "/" on
- the DirPort. Now relay operators can provide a disclaimer without needing
- to set up a separate webserver. There's a sample disclaimer in
- contrib/operator-tools/tor-exit-notice.html.
-
-[[DirPort]] **DirPort** \['address':]__PORT__|**auto** [_flags_]::
- If this option is nonzero, advertise the directory service on this port.
- Set it to "auto" to have Tor pick a port for you. This option can occur
- more than once, but only one advertised DirPort is supported: all
- but one DirPort must have the **NoAdvertise** flag set. (Default: 0) +
- +
- The same flags are supported here as are supported by ORPort.
-
-[[DirPolicy]] **DirPolicy** __policy__,__policy__,__...__::
- 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,
- except that port specifiers are ignored. Any address not matched by
- some entry in the policy is accepted.
-
[[DirCache]] **DirCache** **0**|**1**::
When this option is set, Tor caches all current directory documents except
extra info documents, and accepts client requests for them. If
@@ -2564,6 +2700,26 @@ details.)
connect via the ORPort by default. Setting either DirPort or BridgeRelay
and setting DirCache to 0 is not supported. (Default: 1)
+[[DirPolicy]] **DirPolicy** __policy__,__policy__,__...__::
+ 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,
+ except that port specifiers are ignored. Any address not matched by
+ some entry in the policy is accepted.
+
+[[DirPort]] **DirPort** ['address'**:**]{empty}__PORT__|**auto** [_flags_]::
+ If this option is nonzero, advertise the directory service on this port.
+ Set it to "auto" to have Tor pick a port for you. This option can occur
+ more than once, but only one advertised DirPort is supported: all
+ but one DirPort must have the **NoAdvertise** flag set. (Default: 0) +
+ +
+ The same flags are supported here as are supported by ORPort.
+
+[[DirPortFrontPage]] **DirPortFrontPage** __FILENAME__::
+ When this option is set, it takes an HTML file and publishes it as "/" on
+ the DirPort. Now relay operators can provide a disclaimer without needing
+ to set up a separate webserver. There's a sample disclaimer in
+ contrib/operator-tools/tor-exit-notice.html.
+
[[MaxConsensusAgeForDiffs]] **MaxConsensusAgeForDiffs** __N__ **minutes**|**hours**|**days**|**weeks**::
When this option is nonzero, Tor caches will not try to generate
consensus diffs for any consensus older than this amount of time.
@@ -2575,8 +2731,7 @@ details.)
(Default: 0)
-DENIAL OF SERVICE MITIGATION OPTIONS
-------------------------------------
+== DENIAL OF SERVICE MITIGATION OPTIONS
Tor has three built-in mitigation options that can be individually
enabled/disabled and fine-tuned, but by default Tor directory authorities will
@@ -2587,14 +2742,14 @@ and are as follows:
1. If a single client address makes too many concurrent connections (this is
configurable via DoSConnectionMaxConcurrentCount), hang up on further
connections.
- +
+ +
2. If a single client IP address (v4 or v6) makes circuits too quickly
(default values are more than 3 per second, with an allowed burst of 90,
see DoSCircuitCreationRate and DoSCircuitCreationBurst) while also having
too many connections open (default is 3, see
DoSCircuitCreationMinConnections), tor will refuse any new circuit (CREATE
cells) for the next while (random value between 1 and 2 hours).
- +
+ +
3. If a client asks to establish a rendezvous point to you directly (ex:
Tor2Web client), ignore the request.
@@ -2652,11 +2807,11 @@ Denial of Service mitigation subsystem described above.
This is the type of defense applied to a detected client address. The
possible values are:
- +
+ +
1: No defense.
- +
+ +
2: Refuse circuit creation for the DoSCircuitCreationDefenseTimePeriod period of time.
- +
+ +
"0" means use the consensus parameter. If not defined in the consensus, the value is 2.
(Default: 0)
@@ -2688,11 +2843,11 @@ Denial of Service mitigation subsystem described above.
This is the type of defense applied to a detected client address for the
connection mitigation. The possible values are:
- +
+ +
1: No defense.
- +
+ +
2: Immediately close new connections.
- +
+ +
"0" means use the consensus parameter. If not defined in the consensus, the value is 2.
(Default: 0)
@@ -2705,8 +2860,7 @@ Denial of Service mitigation subsystem described above.
(Default: auto)
-DIRECTORY AUTHORITY SERVER OPTIONS
-----------------------------------
+== DIRECTORY AUTHORITY SERVER OPTIONS
The following options enable operation as a directory authority, and
control how Tor behaves as a directory authority. You should not need
@@ -2753,8 +2907,8 @@ on the public Tor network.
networkstatus documents rather than generating its own. (Default: 0)
[[MinUptimeHidServDirectoryV2]] **MinUptimeHidServDirectoryV2** __N__ **seconds**|**minutes**|**hours**|**days**|**weeks**::
- Minimum uptime of a v2 hidden service directory to be accepted as such by
- authoritative directories. (Default: 25 hours)
+ Minimum uptime of a relay to be accepted as a hidden service directory
+ by directory authorities. (Default: 96 hours)
[[RecommendedServerVersions]] **RecommendedServerVersions** __STRING__::
STRING is a comma-separated list of Tor versions currently believed to be
@@ -2778,7 +2932,7 @@ on the public Tor network.
Authoritative directories only. A set of address patterns for servers that
will be listed as bad exits in any network status document this authority
publishes, if **AuthDirListBadExits** is set. +
- +
+ +
(The address pattern syntax here and in the options below
is the same as for exit policies, except that you don't need to say
"accept" or "reject", and ports are not needed.)
@@ -2887,6 +3041,11 @@ on the public Tor network.
be written to temporary file, then renamed to the configured filename.
(Default: unset)
+[[GuardfractionFile]] **GuardfractionFile** __FILENAME__::
+ V3 authoritative directories only. Configures the location of the
+ guardfraction file which contains information about how long relays
+ have been guards. (Default: unset)
+
[[V3AuthUseLegacyKey]] **V3AuthUseLegacyKey** **0**|**1**::
If set, the directory authority will sign consensuses not only with its
own signing key, but also with a "legacy" key and certificate with a
@@ -2996,25 +3155,25 @@ The next section describes the per service options that can only be set
identifier of each inbound client circuit. The only
protocol supported right now \'haproxy'. This option is only for v3
services. (Default: none) +
- +
+ +
The haproxy option works in the following way: when the feature is
enabled, the Tor process will write a header line when a client is connecting
to the onion service. The header will look like this: +
- +
+ +
"PROXY TCP6 fc00:dead:beef:4dad::ffff:ffff ::1 65535 42\r\n" +
- +
+ +
We encode the "global circuit identifier" as the last 32-bits of the first
IPv6 address. All other values in the header can safely be ignored. You can
compute the global circuit identifier using the following formula given the
IPv6 address "fc00:dead:beef:4dad::AABB:CCDD": +
- +
+ +
global_circuit_id = (0xAA << 24) + (0xBB << 16) + (0xCC << 8) + 0xDD; +
- +
+ +
In the case above, where the last 32-bits are 0xffffffff, the global circuit
identifier would be 4294967295. You can use this value together with Tor's
control port to terminate particular circuits using their global
circuit identifiers. For more information about this see control-spec.txt. +
- +
+ +
The HAProxy version 1 protocol is described in detail at
https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt
@@ -3088,7 +3247,7 @@ The next section describes the per service options that can only be set
locatable, but clients remain location-anonymous. However, the fact that a
client is accessing a Single Onion rather than a Hidden Service may be
statistically distinguishable. +
- +
+ +
**WARNING:** Once a hidden service directory has been used by a tor
instance in HiddenServiceSingleHopMode, it can **NEVER** be used again for
a hidden service. It is best practice to create a new hidden service
@@ -3096,7 +3255,7 @@ The next section describes the per service options that can only be set
Service. It is not possible to run Single Onion Services and Hidden
Services from the same tor instance: they should be run on different
servers with different IP addresses. +
- +
+ +
HiddenServiceSingleHopMode requires HiddenServiceNonAnonymousMode to be set
to 1. Since a Single Onion service is non-anonymous, you can not configure
a SOCKSPort on a tor instance that is running in
@@ -3111,8 +3270,7 @@ The next section describes the per service options that can only be set
including setting SOCKSPort to "0". Can not be changed while tor is
running. (Default: 0)
-Client Authorization
---------------------
+== Client Authorization
(Version 3 only)
@@ -3153,8 +3311,7 @@ Client side:
For more information, please see https://2019.www.torproject.org/docs/tor-onion-service.html.en#ClientAuthorization .
-TESTING NETWORK OPTIONS
------------------------
+== TESTING NETWORK OPTIONS
The following options are used for running a testing Tor network.
@@ -3187,7 +3344,6 @@ The following options are used for running a testing Tor network.
TestingV3AuthInitialVoteDelay 20 seconds
TestingV3AuthInitialDistDelay 20 seconds
TestingAuthDirTimeToLearnReachability 0 minutes
- TestingEstimatedDescriptorPropagationTime 0 minutes
TestingServerDownloadInitialDelay 0
TestingClientDownloadInitialDelay 0
TestingServerConsensusDownloadInitialDelay 0
@@ -3223,11 +3379,6 @@ The following options are used for running a testing Tor network.
are Running until this much time has passed. Changing this requires
that **TestingTorNetwork** is set. (Default: 30 minutes)
-[[TestingEstimatedDescriptorPropagationTime]] **TestingEstimatedDescriptorPropagationTime** __N__ **minutes**|**hours**::
- Clients try downloading server descriptors from directory caches after this
- time. Changing this requires that **TestingTorNetwork** is set. (Default:
- 10 minutes)
-
[[TestingMinFastFlagThreshold]] **TestingMinFastFlagThreshold** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**TBytes**|**KBits**|**MBits**|**GBits**|**TBits**::
Minimum value for the Fast flag. Overrides the ordinary minimum taken
from the consensus when TestingTorNetwork is set. (Default: 0.)
@@ -3274,7 +3425,7 @@ The following options are used for running a testing Tor network.
address patterns of nodes to vote Exit for regardless of their
uptime, bandwidth, or exit policy. See the **ExcludeNodes**
option for more information on how to specify nodes. +
- +
+ +
In order for this option to have any effect, **TestingTorNetwork**
has to be set. See the **ExcludeNodes** option for more
information on how to specify nodes.
@@ -3283,7 +3434,7 @@ The following options are used for running a testing Tor network.
If True (1), a node will never receive the Exit flag unless it is specified
in the **TestingDirAuthVoteExit** list, regardless of its uptime, bandwidth,
or exit policy. +
- +
+ +
In order for this option to have any effect, **TestingTorNetwork**
has to be set.
@@ -3292,14 +3443,14 @@ The following options are used for running a testing Tor network.
address patterns of nodes to vote Guard for regardless of their
uptime and bandwidth. See the **ExcludeNodes** option for more
information on how to specify nodes. +
- +
+ +
In order for this option to have any effect, **TestingTorNetwork**
has to be set.
[[TestingDirAuthVoteGuardIsStrict]] **TestingDirAuthVoteGuardIsStrict** **0**|**1** ::
If True (1), a node will never receive the Guard flag unless it is specified
in the **TestingDirAuthVoteGuard** list, regardless of its uptime and bandwidth. +
- +
+ +
In order for this option to have any effect, **TestingTorNetwork**
has to be set.
@@ -3308,14 +3459,14 @@ The following options are used for running a testing Tor network.
address patterns of nodes to vote HSDir for regardless of their
uptime and DirPort. See the **ExcludeNodes** option for more
information on how to specify nodes. +
- +
+ +
In order for this option to have any effect, **TestingTorNetwork**
must be set.
[[TestingDirAuthVoteHSDirIsStrict]] **TestingDirAuthVoteHSDirIsStrict** **0**|**1** ::
If True (1), a node will never receive the HSDir flag unless it is specified
in the **TestingDirAuthVoteHSDir** list, regardless of its uptime and DirPort. +
- +
+ +
In order for this option to have any effect, **TestingTorNetwork**
has to be set.
@@ -3332,7 +3483,7 @@ The following options are used for running a testing Tor network.
[[TestingMinExitFlagThreshold]] **TestingMinExitFlagThreshold** __N__ **KBytes**|**MBytes**|**GBytes**|**TBytes**|**KBits**|**MBits**|**GBits**|**TBits**::
Sets a lower-bound for assigning an exit flag when running as an
authority on a testing network. Overrides the usual default lower bound
- of 4 KB. (Default: 0)
+ of 4 KBytes. (Default: 0)
[[TestingLinkCertLifetime]] **TestingLinkCertLifetime** __N__ **seconds**|**minutes**|**hours**|**days**|**weeks**|**months**::
Overrides the default lifetime for the certificates used to authenticate
@@ -3353,21 +3504,19 @@ The following options are used for running a testing Tor network.
we replace it and issue a new key?
(Default: 3 hours for link and auth; 1 day for signing.)
-NON-PERSISTENT OPTIONS
-----------------------
+== NON-PERSISTENT OPTIONS
These options are not saved to the torrc file by the "SAVECONF" controller
command. Other options of this type are documented in control-spec.txt,
section 5.4. End-users should mostly ignore them.
-[[UnderscorePorts]] **\_\_ControlPort**, **\_\_DirPort**, **\_\_DNSPort**, **\_\_ExtORPort**, **\_\_NATDPort**, **\_\_ORPort**, **\_\_SocksPort**, **\_\_TransPort**::
+[[UnderscorePorts]] **{dbl_}ControlPort**, **{dbl_}DirPort**, **{dbl_}DNSPort**, **{dbl_}ExtORPort**, **{dbl_}NATDPort**, **{dbl_}ORPort**, **{dbl_}SocksPort**, **{dbl_}TransPort**::
These underscore-prefixed options are variants of the regular Port
options. They behave the same, except they are not saved to the
torrc file by the controller's SAVECONF command.
-SIGNALS
--------
+== SIGNALS
Tor catches the following signals:
@@ -3400,260 +3549,251 @@ Tor catches the following signals:
[[SIGXFSZ]] **SIGXFSZ**::
If this signal exists on your platform, Tor catches and ignores it.
-FILES
------
+== FILES
-**@CONFDIR@/torrc**::
- The configuration file, which contains "option value" pairs.
+**`@CONFDIR@/torrc`**::
+ Default location of the configuration file.
-**$HOME/.torrc**::
+**`$HOME/.torrc`**::
Fallback location for torrc, if @CONFDIR@/torrc is not found.
-**@LOCALSTATEDIR@/lib/tor/**::
+**`@LOCALSTATEDIR@/lib/tor/`**::
The tor process stores keys and other data here.
+__CacheDirectory__/**`cached-certs`**::
+ Contains downloaded directory key certificates that are used to verify
+ authenticity of documents generated by the Tor directory authorities.
-__CacheDirectory__**/cached-certs**::
- This file holds downloaded directory key certificates that are used to
- verify authenticity of documents generated by Tor directory authorities.
-
-__CacheDirectory__**/cached-consensus** and/or **cached-microdesc-consensus**::
+__CacheDirectory__/**`cached-consensus`** and/or **`cached-microdesc-consensus`**::
The most recent consensus network status document we've downloaded.
-__CacheDirectory__**/cached-descriptors** and **cached-descriptors.new**::
- These files hold downloaded router statuses. Some routers may appear more
- than once; if so, the most recently published descriptor is used. Lines
- beginning with @-signs are annotations that contain more information about
- a given router. The ".new" file is an append-only journal; when it gets
- too large, all entries are merged into a new cached-descriptors file.
-
-__CacheDirectory__**/cached-extrainfo** and **cached-extrainfo.new**::
- As "cached-descriptors", but holds optionally-downloaded "extra-info"
- documents. Relays use these documents to send inessential information
- about statistics, bandwidth history, and network health to the
- authorities. They aren't fetched by default; see the DownloadExtraInfo
- option for more info.
-
-__CacheDirectory__**/cached-microdescs** and **cached-microdescs.new**::
+__CacheDirectory__/**`cached-descriptors`** and **`cached-descriptors.new`**::
+ These files contain the downloaded router statuses. Some routers may appear
+ more than once; if so, the most recently published descriptor is
+ used. Lines beginning with **`@`**-signs are annotations that contain more
+ information about a given router. The **`.new`** file is an append-only
+ journal; when it gets too large, all entries are merged into a new
+ cached-descriptors file.
+
+__CacheDirectory__/**`cached-extrainfo`** and **`cached-extrainfo.new`**::
+ Similar to **cached-descriptors**, but holds optionally-downloaded
+ "extra-info" documents. Relays use these documents to send inessential
+ information about statistics, bandwidth history, and network health to the
+ authorities. They aren't fetched by default. See the DownloadExtraInfo
+ option for more information.
+
+__CacheDirectory__/**`cached-microdescs`** and **`cached-microdescs.new`**::
These files hold downloaded microdescriptors. Lines beginning with
- @-signs are annotations that contain more information about a given
- router. The ".new" file is an append-only journal; when it gets too
+ **`@`**-signs are annotations that contain more information about a given
+ router. The **`.new`** file is an append-only journal; when it gets too
large, all entries are merged into a new cached-microdescs file.
-__DataDirectory__**/state**::
- A set of persistent key-value mappings. These are documented in
- the file. These include:
- - The current entry guards and their status.
- - The current bandwidth accounting values.
- - When the file was last written
- - What version of Tor generated the state file
- - A short history of bandwidth usage, as produced in the server
- descriptors.
-
-__DataDirectory__**/sr-state**::
- Authority only. State file used to record information about the current
+__DataDirectory__/**`state`**::
+ Contains a set of persistent key-value mappings. These include:
+ - the current entry guards and their status.
+ - the current bandwidth accounting values.
+ - when the file was last written
+ - what version of Tor generated the state file
+ - a short history of bandwidth usage, as produced in the server
+ descriptors.
+
+__DataDirectory__/**`sr-state`**::
+ _Authority only_. This file is used to record information about the current
status of the shared-random-value voting state.
-__CacheDirectory__**/diff-cache**::
- Directory cache only. Holds older consensuses, and diffs from older
- consensuses to the most recent consensus of each type, compressed
- in various ways. Each file contains a set of key-value arguments
- describing its contents, followed by a single NUL byte, followed by the
- main file contents.
-
-__DataDirectory__**/bw_accounting**::
- Used to track bandwidth accounting values (when the current period starts
- and ends; how much has been read and written so far this period). This file
- is obsolete, and the data is now stored in the \'state' file instead.
-
-__DataDirectory__**/control_auth_cookie**::
- Used for cookie authentication with the controller. Location can be
- overridden by the CookieAuthFile config option. Regenerated on startup. See
+__CacheDirectory__/**`diff-cache`**::
+ _Directory cache only_. Holds older consensuses and diffs from oldest to
+ the most recent consensus of each type compressed in various ways. Each
+ file contains a set of key-value arguments describing its contents,
+ followed by a single NUL byte, followed by the main file contents.
+
+__DataDirectory__/**`bw_accounting`**::
+ This file is obsolete and the data is now stored in the **`state`** file
+ instead. Used to track bandwidth accounting values (when the current period
+ starts and ends; how much has been read and written so far this period).
+
+__DataDirectory__/**`control_auth_cookie`**::
+ This file can be used only when cookie authentication is enabled. Used for
+ cookie authentication with the controller. Location can be overridden by
+ the `CookieAuthFile` configuration option. Regenerated on startup. See
control-spec.txt in https://spec.torproject.org/[torspec] for details.
- Only used when cookie authentication is enabled.
-__DataDirectory__**/lock**::
- This file is used to prevent two Tor instances from using same data
- directory. If access to this file is locked, data directory is already
- in use by Tor.
+__DataDirectory__/**`lock`**::
+ This file is used to prevent two Tor instances from using the same data
+ directory. If access to this file is locked, data directory is already in
+ use by Tor.
-__DataDirectory__**/key-pinning-journal**::
+__DataDirectory__/**`key-pinning-journal`**::
Used by authorities. A line-based file that records mappings between
- RSA1024 identity keys and Ed25519 identity keys. Authorities enforce
- these mappings, so that once a relay has picked an Ed25519 key, stealing
- or factoring the RSA1024 key will no longer let an attacker impersonate
- the relay.
+ RSA1024 and Ed25519 identity keys. Authorities enforce these mappings, so
+ that once a relay has picked an Ed25519 key, stealing or factoring the
+ RSA1024 key will no longer let an attacker impersonate the relay.
-__KeyDirectory__**/authority_identity_key**::
+__KeyDirectory__/**`authority_identity_key`**::
A v3 directory authority's master identity key, used to authenticate its
signing key. Tor doesn't use this while it's running. The tor-gencert
- program uses this. If you're running an authority, you should keep this
- key offline, and not actually put it here.
+ program uses this. If you're running an authority, you should keep this key
+ offline, and not put it in this file.
-__KeyDirectory__**/authority_certificate**::
- A v3 directory authority's certificate, which authenticates the authority's
- current vote- and consensus-signing key using its master identity key.
- Only directory authorities use this file.
+__KeyDirectory__/**`authority_certificate`**::
+ Only directory authorities use this file. A v3 directory authority's
+ certificate which authenticates the authority's current vote- and
+ consensus-signing key using its master identity key.
-__KeyDirectory__**/authority_signing_key**::
- A v3 directory authority's signing key, used to sign votes and consensuses.
- Only directory authorities use this file. Corresponds to the
+__KeyDirectory__/**`authority_signing_key`**::
+ Only directory authorities use this file. A v3 directory authority's
+ signing key that is used to sign votes and consensuses. Corresponds to the
**authority_certificate** cert.
-__KeyDirectory__**/legacy_certificate**::
- As authority_certificate: used only when V3AuthUseLegacyKey is set.
- See documentation for V3AuthUseLegacyKey.
+__KeyDirectory__/**`legacy_certificate`**::
+ As authority_certificate; used only when `V3AuthUseLegacyKey` is set. See
+ documentation for V3AuthUseLegacyKey.
-__KeyDirectory__**/legacy_signing_key**::
- As authority_signing_key: used only when V3AuthUseLegacyKey is set.
- See documentation for V3AuthUseLegacyKey.
+__KeyDirectory__/**`legacy_signing_key`**::
+ As authority_signing_key: used only when `V3AuthUseLegacyKey` is set. See
+ documentation for V3AuthUseLegacyKey.
-__KeyDirectory__**/secret_id_key**::
+__KeyDirectory__/**`secret_id_key`**::
A relay's RSA1024 permanent identity key, including private and public
- components. Used to sign router descriptors, and to sign other keys.
+ components. Used to sign router descriptors, and to sign other keys.
-__KeyDirectory__**/ed25519_master_id_public_key**::
+__KeyDirectory__/**`ed25519_master_id_public_key`**::
The public part of a relay's Ed25519 permanent identity key.
-__KeyDirectory__**/ed25519_master_id_secret_key**::
- The private part of a relay's Ed25519 permanent identity key. This key
- is used to sign the medium-term ed25519 signing key. This file can be
- kept offline, or kept encrypted. If so, Tor will not be able to generate
- new signing keys itself; you'll need to use tor --keygen yourself to do
- so.
+__KeyDirectory__/**`ed25519_master_id_secret_key`**::
+ The private part of a relay's Ed25519 permanent identity key. This key is
+ used to sign the medium-term ed25519 signing key. This file can be kept
+ offline or encrypted. If so, Tor will not be able to generate new signing
+ keys automatically; you'll need to use `tor --keygen` to do so.
-__KeyDirectory__**/ed25519_signing_secret_key**::
+__KeyDirectory__/**`ed25519_signing_secret_key`**::
The private and public components of a relay's medium-term Ed25519 signing
- key. This key is authenticated by the Ed25519 master key, in turn
+ key. This key is authenticated by the Ed25519 master key, which in turn
authenticates other keys (and router descriptors).
-__KeyDirectory__**/ed25519_signing_cert**::
- The certificate which authenticates "ed25519_signing_secret_key" as
- having been signed by the Ed25519 master key.
+__KeyDirectory__/**`ed25519_signing_cert`**::
+ The certificate which authenticates "ed25519_signing_secret_key" as having
+ been signed by the Ed25519 master key.
-__KeyDirectory__**/secret_onion_key** and **secret_onion_key.old**::
+__KeyDirectory__/**`secret_onion_key`** and **`secret_onion_key.old`**::
A relay's RSA1024 short-term onion key. Used to decrypt old-style ("TAP")
- circuit extension requests. The ".old" file holds the previously
- generated key, which the relay uses to handle any requests that were
- made by clients that didn't have the new one.
+ circuit extension requests. The **`.old`** file holds the previously
+ generated key, which the relay uses to handle any requests that were made
+ by clients that didn't have the new one.
-__KeyDirectory__**/secret_onion_key_ntor** and **secret_onion_key_ntor.old**::
+__KeyDirectory__/**`secret_onion_key_ntor`** and **`secret_onion_key_ntor.old`**::
A relay's Curve25519 short-term onion key. Used to handle modern ("ntor")
- circuit extension requests. The ".old" file holds the previously
- generated key, which the relay uses to handle any requests that were
- made by clients that didn't have the new one.
+ circuit extension requests. The **`.old`** file holds the previously
+ generated key, which the relay uses to handle any requests that were made
+ by clients that didn't have the new one.
-__DataDirectory__**/fingerprint**::
- Only used by servers. Holds the fingerprint of the server's identity key.
+__DataDirectory__/**`fingerprint`**::
+ Only used by servers. Contains the fingerprint of the server's identity key.
-__DataDirectory__**/hashed-fingerprint**::
- Only used by bridges. Holds the hashed fingerprint of the bridge's
+__DataDirectory__/**`hashed-fingerprint`**::
+ Only used by bridges. Contains the hashed fingerprint of the bridge's
identity key. (That is, the hash of the hash of the identity key.)
-__DataDirectory__**/approved-routers**::
- Only used by authoritative directory servers. This file lists
- the status of routers by their identity fingerprint.
- Each line lists a status and a fingerprint separated by
- whitespace. See your **fingerprint** file in the __DataDirectory__ for an
- example line. If the status is **!reject** then descriptors from the
- given identity (fingerprint) are rejected by this server. If it is
- **!invalid** then descriptors are accepted but marked in the directory as
- not valid, that is, not recommended.
-
-__DataDirectory__**/v3-status-votes**::
- Only for v3 authoritative directory servers. This file contains
- status votes from all the authoritative directory servers.
-
-__CacheDirectory__**/unverified-consensus**::
- This file contains a network consensus document that has been downloaded,
- but which we didn't have the right certificates to check yet.
-
-__CacheDirectory__**/unverified-microdesc-consensus**::
- This file contains a microdescriptor-flavored network consensus document
- that has been downloaded, but which we didn't have the right certificates
- to check yet.
-
-__DataDirectory__**/unparseable-desc**::
+__DataDirectory__/**`approved-routers`**::
+ Only used by authoritative directory servers. Each line lists a status and
+ an identity, separated by whitespace. Identities can be hex-encoded RSA
+ fingerprints, or base-64 encoded ed25519 public keys. See the
+ **fingerprint** file in a tor relay's __DataDirectory__ for an example
+ fingerprint line. If the status is **!reject**, then descriptors from the
+ given identity are rejected by this server. If it is **!invalid** then
+ descriptors are accepted, but marked in the directory as not valid, that
+ is, not recommended. In either case, the corresponding relays are not
+ included in the consensus.
+
+__DataDirectory__/**`v3-status-votes`**::
+ Only for v3 authoritative directory servers. This file contains status
+ votes from all the authoritative directory servers.
+
+__CacheDirectory__/**`unverified-consensus`**::
+ Contains a network consensus document that has been downloaded, but which
+ we didn't have the right certificates to check yet.
+
+__CacheDirectory__/**`unverified-microdesc-consensus`**::
+ Contains a microdescriptor-flavored network consensus document that has
+ been downloaded, but which we didn't have the right certificates to check
+ yet.
+
+__DataDirectory__/**`unparseable-desc`**::
Onion server descriptors that Tor was unable to parse are dumped to this
file. Only used for debugging.
-__DataDirectory__**/router-stability**::
+__DataDirectory__/**`router-stability`**::
Only used by authoritative directory servers. Tracks measurements for
- router mean-time-between-failures so that authorities have a good idea of
+ router mean-time-between-failures so that authorities have a fair idea of
how to set their Stable flags.
-__DataDirectory__**/stats/dirreq-stats**::
+__DataDirectory__/**`stats/dirreq-stats`**::
Only used by directory caches and authorities. This file is used to
collect directory request statistics.
-__DataDirectory__**/stats/entry-stats**::
+__DataDirectory__/**`stats/entry-stats`**::
Only used by servers. This file is used to collect incoming connection
statistics by Tor entry nodes.
-__DataDirectory__**/stats/bridge-stats**::
+__DataDirectory__/**`stats/bridge-stats`**::
Only used by servers. This file is used to collect incoming connection
statistics by Tor bridges.
-__DataDirectory__**/stats/exit-stats**::
+__DataDirectory__/**`stats/exit-stats`**::
Only used by servers. This file is used to collect outgoing connection
statistics by Tor exit routers.
-__DataDirectory__**/stats/buffer-stats**::
+__DataDirectory__/**`stats/buffer-stats`**::
Only used by servers. This file is used to collect buffer usage
history.
-__DataDirectory__**/stats/conn-stats**::
+__DataDirectory__/**`stats/conn-stats`**::
Only used by servers. This file is used to collect approximate connection
history (number of active connections over time).
-__DataDirectory__**/stats/hidserv-stats**::
+__DataDirectory__/**`stats/hidserv-stats`**::
Only used by servers. This file is used to collect approximate counts
of what fraction of the traffic is hidden service rendezvous traffic, and
approximately how many hidden services the relay has seen.
-__DataDirectory__**/networkstatus-bridges**::
+__DataDirectory__/**networkstatus-bridges`**::
Only used by authoritative bridge directories. Contains information
about bridges that have self-reported themselves to the bridge
authority.
-__DataDirectory__**/approved-routers**::
- Authorities only. This file is used to configure which relays are
- known to be valid, invalid, and so forth.
-
-__HiddenServiceDirectory__**/hostname**::
+__HiddenServiceDirectory__/**`hostname`**::
The <base32-encoded-fingerprint>.onion domain name for this hidden service.
If the hidden service is restricted to authorized clients only, this file
also contains authorization data for all clients.
- +
- Note that clients will ignore any extra subdomains prepended to a hidden
- service hostname. So if you have "xyz.onion" as your hostname, you
- can tell clients to connect to "www.xyz.onion" or "irc.xyz.onion"
++
+[NOTE]
+ The clients will ignore any extra subdomains prepended to a hidden
+ service hostname. Supposing you have "xyz.onion" as your hostname, you
+ can ask your clients to connect to "www.xyz.onion" or "irc.xyz.onion"
for virtual-hosting purposes.
-__HiddenServiceDirectory__**/private_key**::
- The private key for this hidden service.
+__HiddenServiceDirectory__/**`private_key`**::
+ Contains the private key for this hidden service.
-__HiddenServiceDirectory__**/client_keys**::
- Authorization data for a hidden service that is only accessible by
+__HiddenServiceDirectory__/**`client_keys`**::
+ Contains authorization data for a hidden service that is only accessible by
authorized clients.
-__HiddenServiceDirectory__**/onion_service_non_anonymous**::
+__HiddenServiceDirectory__/**`onion_service_non_anonymous`**::
This file is present if a hidden service key was created in
**HiddenServiceNonAnonymousMode**.
-SEE ALSO
---------
-**torsocks**(1), **torify**(1) +
+== SEE ALSO
-**https://www.torproject.org/**
+For more information, refer to the Tor Project website at
+https://www.torproject.org/ and the Tor specifications at
+https://spec.torproject.org. See also **torsocks**(1) and **torify**(1).
-**torspec: https://spec.torproject.org **
+== BUGS
-BUGS
-----
+Because Tor is still under development, there may be plenty of bugs. Please
+report them at https://trac.torproject.org/.
-Plenty, probably. Tor is still in development. Please report them at https://trac.torproject.org/.
+== AUTHORS
-AUTHORS
--------
Roger Dingledine [arma at mit.edu], Nick Mathewson [nickm at alum.mit.edu].
diff --git a/m4/pprint.m4 b/m4/pprint.m4
new file mode 100644
index 0000000000..4e8a71c876
--- /dev/null
+++ b/m4/pprint.m4
@@ -0,0 +1,228 @@
+# Pretty printing macros.
+#
+# Copyright (C) 2019 - Philippe Proulx <pproulx@efficios.com>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License, version 2 only, as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# As a special exception to the GNU General Public License, if you distribute
+# this file as part of a program that contains a configuration script
+# generated by Autoconf, you may include it under the same distribution terms
+# that you use for the rest of that program.
+
+#serial 1
+
+# PPRINT_INIT(): initializes the pretty printing system.
+#
+# Use this macro before using any other PPRINT_* macro.
+AC_DEFUN([PPRINT_INIT], [
+ m4_define([PPRINT_CONFIG_TS], [50])
+ m4_define([PPRINT_CONFIG_INDENT], [2])
+ PPRINT_YES_MSG=yes
+ PPRINT_NO_MSG=no
+
+ # find tput, which tells us if colors are supported and gives us color codes
+ AC_PATH_PROG([pprint_tput], [tput])
+
+ AS_IF([test -n "$pprint_tput"], [
+ AS_IF([test -n "$PS1" && test `"$pprint_tput" colors` -ge 8 && test -t 1], [
+ # interactive shell and colors supported and standard output
+ # file descriptor is opened on a terminal
+ PPRINT_COLOR_TXTBLK="`"$pprint_tput" setaf 0`"
+ PPRINT_COLOR_TXTBLU="`"$pprint_tput" setaf 4`"
+ PPRINT_COLOR_TXTGRN="`"$pprint_tput" setaf 2`"
+ PPRINT_COLOR_TXTCYN="`"$pprint_tput" setaf 6`"
+ PPRINT_COLOR_TXTRED="`"$pprint_tput" setaf 1`"
+ PPRINT_COLOR_TXTPUR="`"$pprint_tput" setaf 5`"
+ PPRINT_COLOR_TXTYLW="`"$pprint_tput" setaf 3`"
+ PPRINT_COLOR_TXTWHT="`"$pprint_tput" setaf 7`"
+ PPRINT_COLOR_BLD=`"$pprint_tput" bold`
+ PPRINT_COLOR_BLDBLK="$PPRINT_COLOR_BLD$PPRINT_COLOR_TXTBLK"
+ PPRINT_COLOR_BLDBLU="$PPRINT_COLOR_BLD$PPRINT_COLOR_TXTBLU"
+ PPRINT_COLOR_BLDGRN="$PPRINT_COLOR_BLD$PPRINT_COLOR_TXTGRN"
+ PPRINT_COLOR_BLDCYN="$PPRINT_COLOR_BLD$PPRINT_COLOR_TXTCYN"
+ PPRINT_COLOR_BLDRED="$PPRINT_COLOR_BLD$PPRINT_COLOR_TXTRED"
+ PPRINT_COLOR_BLDPUR="$PPRINT_COLOR_BLD$PPRINT_COLOR_TXTPUR"
+ PPRINT_COLOR_BLDYLW="$PPRINT_COLOR_BLD$PPRINT_COLOR_TXTYLW"
+ PPRINT_COLOR_BLDWHT="$PPRINT_COLOR_BLD$PPRINT_COLOR_TXTWHT"
+ PPRINT_COLOR_RST="`"$pprint_tput" sgr0`"
+
+ # colored yes and no
+ PPRINT_YES_MSG="$PPRINT_COLOR_BLDGRN$PPRINT_YES_MSG$PPRINT_COLOR_RST"
+ PPRINT_NO_MSG="$PPRINT_COLOR_BLDRED$PPRINT_NO_MSG$PPRINT_COLOR_RST"
+
+ # subtitle color
+ PPRINT_COLOR_SUBTITLE="$PPRINT_COLOR_BLDCYN"
+ ])
+ ])
+])
+
+# PPRINT_SET_INDENT(indent): sets the current indentation.
+#
+# Use PPRINT_INIT() before using this macro.
+AC_DEFUN([PPRINT_SET_INDENT], [
+ m4_define([PPRINT_CONFIG_INDENT], [$1])
+])
+
+# PPRINT_SET_TS(ts): sets the current tab stop.
+#
+# Use PPRINT_INIT() before using this macro.
+AC_DEFUN([PPRINT_SET_TS], [
+ m4_define([PPRINT_CONFIG_TS], [$1])
+])
+
+# PPRINT_SUBTITLE(subtitle): pretty prints a subtitle.
+#
+# The subtitle is put as is in a double-quoted shell string so the user
+# needs to escape ".
+#
+# Use PPRINT_INIT() before using this macro.
+AC_DEFUN([PPRINT_SUBTITLE], [
+ AS_ECHO(["${PPRINT_COLOR_SUBTITLE}$1$PPRINT_COLOR_RST"])
+])
+
+AC_DEFUN([_PPRINT_INDENT], [
+ m4_if(PPRINT_CONFIG_INDENT, 0, [
+ ], [
+ m4_for([pprint_i], [0], m4_eval(PPRINT_CONFIG_INDENT * 2 - 1), [1], [
+ AS_ECHO_N([" "])
+ ])
+ ])
+])
+
+# PPRINT_PROP_STRING(title, value, title_color?): pretty prints a
+# string property.
+#
+# The title is put as is in a double-quoted shell string so the user
+# needs to escape ".
+#
+# The $PPRINT_CONFIG_INDENT variable must be set to the desired indentation
+# level.
+#
+# Use PPRINT_INIT() before using this macro.
+AC_DEFUN([PPRINT_PROP_STRING], [
+ m4_pushdef([pprint_title], [$1])
+ m4_pushdef([pprint_value], [$2])
+ m4_pushdef([pprint_title_color], m4_default([$3], []))
+ m4_pushdef([pprint_title_len], m4_len(pprint_title))
+ m4_pushdef([pprint_spaces_cnt], m4_eval(PPRINT_CONFIG_TS - pprint_title_len - (PPRINT_CONFIG_INDENT * 2) - 1))
+
+ m4_if(m4_eval(pprint_spaces_cnt <= 0), [1], [
+ m4_define([pprint_spaces_cnt], [1])
+ ])
+
+ m4_pushdef([pprint_spaces], [])
+
+ m4_for([pprint_i], 0, m4_eval(pprint_spaces_cnt - 1), [1], [
+ m4_append([pprint_spaces], [ ])
+ ])
+
+ _PPRINT_INDENT
+
+ AS_ECHO_N(["pprint_title_color""pprint_title$PPRINT_COLOR_RST:pprint_spaces"])
+ AS_ECHO(["${PPRINT_COLOR_BLD}pprint_value$PPRINT_COLOR_RST"])
+
+ m4_popdef([pprint_spaces])
+ m4_popdef([pprint_spaces_cnt])
+ m4_popdef([pprint_title_len])
+ m4_popdef([pprint_title_color])
+ m4_popdef([pprint_value])
+ m4_popdef([pprint_title])
+])
+
+# PPRINT_PROP_BOOL(title, value, title_color?): pretty prints a boolean
+# property.
+#
+# The title is put as is in a double-quoted shell string so the user
+# needs to escape ".
+#
+# The value is evaluated at shell runtime. Its evaluation must be
+# 0 (false) or 1 (true).
+#
+# Uses the PPRINT_PROP_STRING() with the "yes" or "no" string.
+#
+# Use PPRINT_INIT() before using this macro.
+AC_DEFUN([PPRINT_PROP_BOOL], [
+ m4_pushdef([pprint_title], [$1])
+ m4_pushdef([pprint_value], [$2])
+
+ test pprint_value -eq 0 && pprint_msg="$PPRINT_NO_MSG" || pprint_msg="$PPRINT_YES_MSG"
+
+ m4_if([$#], [3], [
+ PPRINT_PROP_STRING(pprint_title, [$pprint_msg], $3)
+ ], [
+ PPRINT_PROP_STRING(pprint_title, [$pprint_msg])
+ ])
+
+ m4_popdef([pprint_value])
+ m4_popdef([pprint_title])
+])
+
+# PPRINT_PROP_BOOL_CUSTOM(title, value, no_msg, title_color?): pretty prints a boolean
+# property.
+#
+# The title is put as is in a double-quoted shell string so the user
+# needs to escape ".
+#
+# The value is evaluated at shell runtime. Its evaluation must be
+# 0 (false) or 1 (true).
+#
+# Uses the PPRINT_PROP_STRING() with the "yes" or "no" string.
+#
+# Use PPRINT_INIT() before using this macro.
+AC_DEFUN([PPRINT_PROP_BOOL_CUSTOM], [
+ m4_pushdef([pprint_title], [$1])
+ m4_pushdef([pprint_value], [$2])
+ m4_pushdef([pprint_value_no_msg], [$3])
+
+ test pprint_value -eq 0 && pprint_msg="$PPRINT_NO_MSG (pprint_value_no_msg)" || pprint_msg="$PPRINT_YES_MSG"
+
+ m4_if([$#], [4], [
+ PPRINT_PROP_STRING(pprint_title, [$pprint_msg], $4)
+ ], [
+ PPRINT_PROP_STRING(pprint_title, [$pprint_msg])
+ ])
+
+ m4_popdef([pprint_value_no_msg])
+ m4_popdef([pprint_value])
+ m4_popdef([pprint_title])
+])
+
+# PPRINT_WARN(msg): pretty prints a warning message.
+#
+# The message is put as is in a double-quoted shell string so the user
+# needs to escape ".
+#
+# Use PPRINT_INIT() before using this macro.
+AC_DEFUN([PPRINT_WARN], [
+ m4_pushdef([pprint_msg], [$1])
+
+ _PPRINT_INDENT
+ AS_ECHO(["${PPRINT_COLOR_TXTYLW}WARNING:$PPRINT_COLOR_RST ${PPRINT_COLOR_BLDYLW}pprint_msg$PPRINT_COLOR_RST"])
+
+ m4_popdef([pprint_msg])
+])
+
+# PPRINT_ERROR(msg): pretty prints an error message and exits.
+#
+# The message is put as is in a double-quoted shell string so the user
+# needs to escape ".
+#
+# Use PPRINT_INIT() before using this macro.
+AC_DEFUN([PPRINT_ERROR], [
+ m4_pushdef([pprint_msg], [$1])
+
+ AC_MSG_ERROR([${PPRINT_COLOR_BLDRED}pprint_msg$PPRINT_COLOR_RST])
+
+ m4_popdef([pprint_msg])
+])
diff --git a/scripts/coccinelle/apply.sh b/scripts/coccinelle/apply.sh
new file mode 100755
index 0000000000..f531d7fa32
--- /dev/null
+++ b/scripts/coccinelle/apply.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# apply.sh:
+# run spatch with appropriate includes and builtins for the Tor source code
+
+top="$(dirname "$0")/../.."
+
+spatch -macro_file_builtins "$top"/scripts/coccinelle/tor-coccinelle.h \
+ -I "$top" -I "$top"/src -I "$top"/ext --defined COCCI "$@"
diff --git a/scripts/coccinelle/check_cocci_parse.sh b/scripts/coccinelle/check_cocci_parse.sh
new file mode 100755
index 0000000000..aaa586c093
--- /dev/null
+++ b/scripts/coccinelle/check_cocci_parse.sh
@@ -0,0 +1,98 @@
+#!/bin/sh
+
+# If we have coccinelle installed, run try_parse.sh on every filename passed
+# as an argument. If no filenames are supplied, scan a standard Tor 0.3.5 or
+# later directory layout.
+#
+# Uses the default coccinelle exceptions file, or $TOR_COCCI_EXCEPTIONS_FILE,
+# if it is set.
+#
+# Use TOR_COCCI_EXCEPTIONS_FILE=/dev/null check_cocci_parse.sh to disable
+# the default exception file.
+#
+# If spatch is not installed, remind the user to install it, but exit with
+# a success error status.
+
+scripts_cocci="$(dirname "$0")"
+top="$scripts_cocci/../.."
+try_parse="$scripts_cocci/try_parse.sh"
+
+exitcode=0
+
+export TOR_COCCI_EXCEPTIONS_FILE="${TOR_COCCI_EXCEPTIONS_FILE:-$scripts_cocci/exceptions.txt}"
+
+PURPOSE="cocci C parsing"
+
+echo "Checking spatch:"
+
+if ! command -v spatch ; then
+ echo "Install coccinelle's spatch to check $PURPOSE."
+ exit "$exitcode"
+fi
+
+# Returns true if $1 is greater than or equal to $2
+version_ge()
+{
+ if test "$1" = "$2" ; then
+ # return true
+ return 0
+ fi
+ LOWER_VERSION="$(printf '%s\n' "$1" "$2" | $SORT_V | head -n 1)"
+ # implicit return
+ test "$LOWER_VERSION" != "$1"
+}
+
+# 'sort -V' is a gnu extension
+SORT_V="sort -V"
+# Use 'sort -n' if 'sort -V' doesn't work
+if ! version_ge "1" "0" ; then
+ echo "Your 'sort -V' command appears broken. Falling back to 'sort -n'."
+ echo "Some spatch version checks may give the wrong result."
+ SORT_V="sort -n"
+fi
+
+# Print the full spatch version, for diagnostics
+spatch --version
+
+MIN_SPATCH_V="1.0.4"
+# This pattern needs to handle version strings like:
+# spatch version 1.0.0-rc19
+# spatch version 1.0.6 compiled with OCaml version 4.05.0
+SPATCH_V=$(spatch --version | head -1 | \
+ sed 's/spatch version \([0-9][^ ]*\).*/\1/')
+
+if ! version_ge "$SPATCH_V" "$MIN_SPATCH_V" ; then
+ echo "Tor requires coccinelle spatch >= $MIN_SPATCH_V to check $PURPOSE."
+ echo "But you have $SPATCH_V. Please install a newer version."
+ exit "$exitcode"
+fi
+
+if test $# -ge 1 ; then
+ "$try_parse" "$@"
+ exitcode=$?
+else
+ cd "$top" || exit 1
+ # This is the layout in 0.3.5
+ # Keep these lists consistent:
+ # - OWNED_TOR_C_FILES in Makefile.am
+ # - CHECK_FILES in pre-commit.git-hook and pre-push.git-hook
+ # - try_parse in check_cocci_parse.sh
+ "$try_parse" \
+ src/lib/*/*.[ch] \
+ src/core/*/*.[ch] \
+ src/feature/*/*.[ch] \
+ src/app/*/*.[ch] \
+ src/test/*.[ch] \
+ src/test/*/*.[ch] \
+ src/tools/*.[ch]
+ exitcode=$?
+fi
+
+if test "$exitcode" != 0 ; then
+ echo "Please fix these $PURPOSE errors in the above files"
+ echo "Set VERBOSE=1 for more details"
+ echo "Try running test-operator-cleanup or 'make autostyle-operators'"
+ echo "As a last resort, you can modify scripts/coccinelle/exceptions.txt"
+fi
+
+exit "$exitcode"
diff --git a/scripts/coccinelle/exceptions.txt b/scripts/coccinelle/exceptions.txt
new file mode 100644
index 0000000000..473f4b22c5
--- /dev/null
+++ b/scripts/coccinelle/exceptions.txt
@@ -0,0 +1,24 @@
+# A list of exception patterns for check_cocci_parse.sh
+# Passed to 'grep -f'
+src/lib/cc/compat_compiler.h
+src/lib/container/handles.h
+src/lib/container/map.c
+src/lib/container/map.h
+src/lib/container/order.c
+src/lib/crypt_ops/crypto_rand.c
+src/lib/fs/files.h
+src/lib/log/util_bug.c
+src/lib/pubsub/pubsub_macros.h
+src/lib/smartlist_core/smartlist_foreach.h
+src/lib/testsupport/testsupport.h
+src/lib/tls/tortls.h
+src/lib/tls/tortls_openssl.c
+src/lib/tls/x509.h
+src/lib/version/version.c
+src/core/mainloop/connection.c
+src/core/or/reasons.c
+src/feature/dirclient/dirclient.c
+src/feature/nodelist/networkstatus.c
+src/test/test_address.c
+src/test/test_hs_cache.c
+src/test/test_hs_descriptor.c
diff --git a/scripts/coccinelle/test-operator-cleanup b/scripts/coccinelle/test-operator-cleanup
index e7822542a4..28b4d4f588 100755
--- a/scripts/coccinelle/test-operator-cleanup
+++ b/scripts/coccinelle/test-operator-cleanup
@@ -1,4 +1,17 @@
#!/usr/bin/perl -w -p -i
+#
+# Copyright (c) 2001 Matej Pfajfar.
+# Copyright (c) 2001-2004, Roger Dingledine.
+# Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+# Copyright (c) 2007-2019, The Tor Project, Inc.
+# See LICENSE for licensing information
+
+# This script looks for instances of C comparison operators as macro arguments,
+# and replaces them with our OP_* equivalents.
+#
+# Some macros that take operators are our tt_int_op() testing macro, and the
+# standard timercmp() macro. Coccinelle can't handle their syntax, however,
+# unless we give them their operators as a macro too.
next if m#^ */\*# or m#^ *\* #;
diff --git a/scripts/coccinelle/tor-coccinelle.h b/scripts/coccinelle/tor-coccinelle.h
index 8f625dcee4..44d79325eb 100644
--- a/scripts/coccinelle/tor-coccinelle.h
+++ b/scripts/coccinelle/tor-coccinelle.h
@@ -1,3 +1,63 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/*
+ * This file looks like a C header, but its purpose is a bit different.
+ *
+ * We never include it from our real C files; we only tell Coccinelle
+ * about it in apply.sh.
+ *
+ * It tells the Coccinelle semantic patching tool how to understand
+ * things that would otherwise not be good C syntax, or which would
+ * otherwise not make sense to it as C. It doesn't need to produce
+ * semantically equivalent C, or even correct C: it only has to produce
+ * syntactically valid C.
+ */
+
+#define MOCK_DECL(a, b, c) a b c
#define MOCK_IMPL(a, b, c) a b c
#define CHECK_PRINTF(a, b)
+#define CHECK_SCANF(a, b)
#define STATIC static
+#define EXTERN(a,b) extern a b;
+
+#define STMT_BEGIN do {
+#define STMT_END } while (0)
+
+#define BUG(x) (x)
+#define IF_BUG_ONCE(x) if (x)
+
+#define ATTR_NORETURN
+#define ATTR_UNUSED
+#define ATTR_CONST
+#define ATTR_MALLOC
+#define ATTR_WUR
+#define DISABLE_GCC_WARNING(x)
+#define ENABLE_GCC_WARNING(x)
+
+#define HANDLE_DECL(a,b,c)
+#define HANDLE_IMPL(a,b,c)
+#define HT_ENTRY(x) void *
+#define HT_HEAD(a,b) struct ht_head
+#define HT_INITIALIZER() { }
+#define X509 struct x509_st
+#define STACK_OF(x) struct foo_stack_t
+#define TOR_TAILQ_HEAD(a,b) struct tailq_head
+#define TOR_TAILQ_ENTRY(a) struct tailq_entry
+#define TOR_SIMPLEQ_HEAD(a,b) struct simpleq_entry
+#define TOR_SIMPLEQ_ENTRY(a) struct simpleq_entry
+#define TOR_LIST_HEAD(a,b) struct list_head
+#define TOR_LIST_ENTRY(a) struct list_entry
+#define TOR_SLIST_HEAD(a,b) struct slist_head
+#define TOR_SLIST_ENTRY(a) struct slist_entry
+
+#define NS_DECL(a, b, c) a b c
+#define NS(a) a
+
+#define CONF_TEST_MEMBERS(a,b,c)
+#define DUMMY_CONF_TEST_MEMBERS
+
+#define EAT_SEMICOLON extern int dummy__;
diff --git a/scripts/coccinelle/try_parse.sh b/scripts/coccinelle/try_parse.sh
new file mode 100755
index 0000000000..a90e51b4aa
--- /dev/null
+++ b/scripts/coccinelle/try_parse.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+# Echo the name of every argument of this script that is not "perfect"
+# according to coccinelle's --parse-c.
+#
+# If $TOR_COCCI_EXCEPTIONS_FILE is non-empty, skip any files that match the
+# patterns in the exception file, according to "grep -f"
+#
+# If VERBOSE is non-empty, log spatch errors and skipped files.
+
+top="$(dirname "$0")/../.."
+
+exitcode=0
+
+for fn in "$@"; do
+
+ if test "${TOR_COCCI_EXCEPTIONS_FILE}" ; then
+ skip_fn=$(echo "$fn" | grep -f "${TOR_COCCI_EXCEPTIONS_FILE}")
+ if test "${skip_fn}" ; then
+ if test "${VERBOSE}" != ""; then
+ echo "Skipping '${skip_fn}'"
+ fi
+ continue
+ fi
+ fi
+
+ if spatch --macro-file-builtins \
+ "$top"/scripts/coccinelle/tor-coccinelle.h \
+ --defined COCCI \
+ --parse-c "$fn" \
+ 2>/dev/null | grep "perfect = 1" > /dev/null; then
+ : # it's perfect
+ else
+ echo "$fn"
+ if test "${VERBOSE}" != ""; then
+ spatch --macro-file-builtins \
+ "$top"/scripts/coccinelle/tor-coccinelle.h \
+ --defined COCCI \
+ --parse-c "$fn"
+ fi
+ exitcode=1
+ fi
+
+done
+
+exit "$exitcode"
diff --git a/scripts/codegen/fuzzing_include_am.py b/scripts/codegen/fuzzing_include_am.py
index a944584453..aa3ba49a73 100755
--- a/scripts/codegen/fuzzing_include_am.py
+++ b/scripts/codegen/fuzzing_include_am.py
@@ -1,5 +1,10 @@
#!/usr/bin/python
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
FUZZERS = """
consensus
descriptor
diff --git a/scripts/codegen/gen_server_ciphers.py b/scripts/codegen/gen_server_ciphers.py
index 5d326f8b9e..3b77952243 100755
--- a/scripts/codegen/gen_server_ciphers.py
+++ b/scripts/codegen/gen_server_ciphers.py
@@ -8,6 +8,11 @@
#
# Run it on all the files in your openssl include directory.
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import re
import sys
@@ -96,7 +101,7 @@ def parse_cipher(ciph):
fwsec, = m.groups()
return Ciphersuite(ciph, fwsec, "CHACHA20", "256", "POLY1305", "n/a")
- print "/* Couldn't parse %s ! */"%ciph
+ print("/* Couldn't parse %s ! */"%ciph)
return None
@@ -120,12 +125,12 @@ for c in ALL_CIPHERS:
colon = ' ":"'
if c.name in MANDATORY:
- print "%s/* Required */"%indent
- print '%s%s%s'%(indent,c.name,colon)
+ print("%s/* Required */"%indent)
+ print('%s%s%s'%(indent,c.name,colon))
else:
- print "#ifdef %s"%c.name
- print '%s%s%s'%(indent,c.name,colon)
- print "#endif"
+ print("#ifdef %s"%c.name)
+ print('%s%s%s'%(indent,c.name,colon))
+ print("#endif")
-print '%s;'%indent
+print('%s;'%indent)
diff --git a/scripts/codegen/get_mozilla_ciphers.py b/scripts/codegen/get_mozilla_ciphers.py
index f23f2f1e6f..165105736a 100755
--- a/scripts/codegen/get_mozilla_ciphers.py
+++ b/scripts/codegen/get_mozilla_ciphers.py
@@ -10,12 +10,17 @@
# It takes two arguments: the location of a firefox source directory, and the
# location of an openssl source directory.
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import os
import re
import sys
if len(sys.argv) != 3:
- print >>sys.stderr, "Syntax: get_mozilla_ciphers.py <firefox-source-dir> <openssl-source-dir>"
+ print("Syntax: get_mozilla_ciphers.py <firefox-source-dir> <openssl-source-dir>", file=sys.stderr)
sys.exit(1)
ff_root = sys.argv[1]
@@ -171,13 +176,13 @@ for fl in oSSLinclude:
fp.close()
# Now generate the output.
-print """\
+print("""\
/* This is an include file used to define the list of ciphers clients should
* advertise. Before including it, you should define the CIPHER and XCIPHER
* macros.
*
* This file was automatically generated by get_mozilla_ciphers.py.
- */"""
+ */""")
# Go in order by the order in CipherPrefs
for firefox_macro in firefox_ciphers:
@@ -210,4 +215,4 @@ for firefox_macro in firefox_ciphers:
#else
XCIPHER(%(hex)s, %(macro)s)
#endif""" % format
- print res
+ print(res)
diff --git a/scripts/codegen/makedesc.py b/scripts/codegen/makedesc.py
index efca4dda9a..af926a6438 100644
--- a/scripts/codegen/makedesc.py
+++ b/scripts/codegen/makedesc.py
@@ -9,6 +9,11 @@
# I've used this to make inputs for unit tests. I wouldn't suggest
# using it for anything else.
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import base64
import binascii
import ctypes
@@ -19,12 +24,16 @@ import os
import re
import struct
import time
-import UserDict
import slow_ed25519
import slownacl_curve25519
import ed25519_exts_ref
+try:
+ xrange # Python 2
+except NameError:
+ xrange = range # Python 3
+
# Pull in the openssl stuff we need.
crypt = ctypes.CDLL(ctypes.util.find_library('crypto'))
@@ -247,8 +256,8 @@ class OnDemandKeys(object):
def signdesc(body, args_out=None):
- rsa, ident_pem, id_digest = make_key()
- _, onion_pem, _ = make_key()
+ rsa, ident_pem, id_digest = make_rsa_key()
+ _, onion_pem, _ = make_rsa_key()
need_ed = '{ED25519-CERT}' in body or '{ED25519-SIGNATURE}' in body
if need_ed:
@@ -298,10 +307,10 @@ def signdesc(body, args_out=None):
return body.rstrip()
def print_c_string(ident, body):
- print "static const char %s[] =" % ident
+ print("static const char %s[] =" % ident)
for line in body.split("\n"):
- print ' "%s\\n"' %(line)
- print " ;"
+ print(' "%s\\n"' %(line))
+ print(" ;")
def emit_ri(name, body):
info = OnDemandKeys()
@@ -315,8 +324,8 @@ def emit_ei(name, body):
body = info.sign_desc(body)
print_c_string("EX_EI_%s"%name.upper(), body)
- print 'const char EX_EI_{NAME}_FP[] = "{d.RSA_FINGERPRINT_NOSPACE}";'.format(
- d=info, NAME=name.upper())
+ print('const char EX_EI_{NAME}_FP[] = "{d.RSA_FINGERPRINT_NOSPACE}";'.format(
+ d=info, NAME=name.upper()))
print_c_string("EX_EI_%s_KEY"%name.upper(), info.RSA_IDENTITY)
def analyze(s):
diff --git a/scripts/git/git-merge-forward.sh b/scripts/git/git-merge-forward.sh
index bdd0da5b75..bbc5047cb7 100755
--- a/scripts/git/git-merge-forward.sh
+++ b/scripts/git/git-merge-forward.sh
@@ -11,8 +11,8 @@ function usage()
echo " -n: dry run mode"
echo " (default: run commands)"
echo " -t: test branch mode: create new branches from the commits checked"
- echo " out in each maint directory. Call these branches prefix_029,"
- echo " prefix_035, ... , prefix_master."
+ echo " out in each maint directory. Call these branches prefix_035,"
+ echo " prefix_040, ... , prefix_master."
echo " (default: merge forward maint-*, release-*, and master)"
echo " -u: in test branch mode, if a prefix_* branch already exists,"
echo " skip creating that branch. Use after a merge error, to"
@@ -87,24 +87,26 @@ TOR_WKT_NAME=${TOR_WKT_NAME:-"tor-wkt"}
# New arrays need to be in the WORKTREE= array else they aren't considered.
#
# Only used in test branch mode
-# There is no previous branch to merge forward, so the second and fifth items
-# must be blank ("")
-MAINT_029_TB=( "maint-0.2.9" "" "$GIT_PATH/$TOR_WKT_NAME/maint-0.2.9" \
- "_029" "")
+# We create a test branch for the earliest maint branch.
+# But it's the earliest maint branch, so we don't merge forward into it.
+# Since we don't merge forward into it, the second and fifth items must be
+# blank ("").
+MAINT_035_TB=( "maint-0.3.5" "" "$GIT_PATH/$TOR_WKT_NAME/maint-0.3.5" \
+ "_035" "")
# Used in maint/release merge and test branch modes
-MAINT_035=( "maint-0.3.5" "maint-0.2.9" "$GIT_PATH/$TOR_WKT_NAME/maint-0.3.5" \
- "_035" "_029")
MAINT_040=( "maint-0.4.0" "maint-0.3.5" "$GIT_PATH/$TOR_WKT_NAME/maint-0.4.0" \
"_040" "_035")
MAINT_041=( "maint-0.4.1" "maint-0.4.0" "$GIT_PATH/$TOR_WKT_NAME/maint-0.4.1" \
"_041" "_040")
-MAINT_MASTER=( "master" "maint-0.4.1" "$GIT_PATH/$TOR_MASTER_NAME" \
- "_master" "_041")
+MAINT_042=( "maint-0.4.2" "maint-0.4.1" "$GIT_PATH/$TOR_WKT_NAME/maint-0.4.2" \
+ "_042" "_041")
+MAINT_MASTER=( "master" "maint-0.4.2" "$GIT_PATH/$TOR_MASTER_NAME" \
+ "_master" "_042")
-RELEASE_029=( "release-0.2.9" "maint-0.2.9" "$GIT_PATH/$TOR_WKT_NAME/release-0.2.9" )
RELEASE_035=( "release-0.3.5" "maint-0.3.5" "$GIT_PATH/$TOR_WKT_NAME/release-0.3.5" )
RELEASE_040=( "release-0.4.0" "maint-0.4.0" "$GIT_PATH/$TOR_WKT_NAME/release-0.4.0" )
RELEASE_041=( "release-0.4.1" "maint-0.4.1" "$GIT_PATH/$TOR_WKT_NAME/release-0.4.1" )
+RELEASE_042=( "release-0.4.2" "maint-0.4.2" "$GIT_PATH/$TOR_WKT_NAME/release-0.4.2" )
# The master branch path has to be the main repository thus contains the
# origin that will be used to fetch the updates. All the worktrees are created
@@ -113,15 +115,15 @@ ORIGIN_PATH="$GIT_PATH/$TOR_MASTER_NAME"
# SC2034 -- shellcheck thinks that these are unused. We know better.
ACTUALLY_THESE_ARE_USED=<<EOF
-${MAINT_029_TB[0]}
-${MAINT_035[0]}
+${MAINT_035_TB[0]}
${MAINT_040[0]}
${MAINT_041[0]}
+${MAINT_042[0]}
${MAINT_MASTER[0]}
-${RELEASE_029[0]}
${RELEASE_035[0]}
${RELEASE_040[0]}
${RELEASE_041[0]}
+${RELEASE_042[0]}
EOF
#######################
@@ -134,7 +136,7 @@ DRY_RUN=0
# Controlled by the -t <test-branch-prefix> option. The test branch base
# name option makes git-merge-forward.sh create new test branches:
-# <tbbn>_029, <tbbn>_035, ... , <tbbn>_master, and merge forward.
+# <tbbn>_035, <tbbn>_040, ... , <tbbn>_master, and merge forward.
TEST_BRANCH_PREFIX=
# Controlled by the -u option. The use existing option checks for existing
@@ -172,12 +174,11 @@ if [ -z "$TEST_BRANCH_PREFIX" ]; then
# maint/release merge mode
#
- # List of all worktrees to work on. All defined above. Ordering is important.
- # Always the maint-* branch BEFORE then the release-*.
+ # List of all worktrees to merge forward into. All defined above.
+ # Ordering is important. Always the maint-* branch BEFORE the release-*.
WORKTREE=(
- RELEASE_029[@]
-
- MAINT_035[@]
+ # We don't merge forward into MAINT_035_TB[@], because it's the earliest
+ # maint branch
RELEASE_035[@]
MAINT_040[@]
@@ -186,21 +187,28 @@ if [ -z "$TEST_BRANCH_PREFIX" ]; then
MAINT_041[@]
RELEASE_041[@]
+ MAINT_042[@]
+ RELEASE_042[@]
+
MAINT_MASTER[@]
)
else
- # Test branch mode: merge to maint only, and create a new branch for 0.2.9
+ # Test branch mode: base test branches on maint branches only
+ #
+ # List of all worktrees to create test branches from. All defined above.
+ # Ordering is important. All maint-* branches, including the earliest one.
WORKTREE=(
- MAINT_029_TB[@]
-
- MAINT_035[@]
+ # We want a test branch based on the earliest maint branch
+ MAINT_035_TB[@]
MAINT_040[@]
MAINT_041[@]
+ MAINT_042[@]
+
MAINT_MASTER[@]
)
@@ -323,7 +331,7 @@ function merge_branch
fi
}
-# Pull the given branch name.
+# Merge origin/(branch name) into the current branch.
function merge_branch_origin
{
local cmd="git merge --ff-only 'origin/$1'"
@@ -417,9 +425,9 @@ for ((i=0; i<COUNT; i++)); do
fi
# Merge the previous branch into the target branch
# Merge Forward Example:
- # merge maint-0.2.9 into maint-0.3.5.
+ # merge maint-0.3.5 into maint-0.4.0.
# Test Branch Example:
- # merge bug99999_029 into bug99999_035.
+ # merge bug99999_035 into bug99999_040.
# Skip the merge if the previous branch does not exist
# (there's nothing to merge forward into the oldest test branch)
if [ "$target_previous" ]; then
diff --git a/scripts/git/git-pull-all.sh b/scripts/git/git-pull-all.sh
index dc16066388..c8d115da01 100755
--- a/scripts/git/git-pull-all.sh
+++ b/scripts/git/git-pull-all.sh
@@ -58,16 +58,16 @@ TOR_WKT_NAME=${TOR_WKT_NAME:-"tor-wkt"}
#
# First set of arrays are the maint-* branch and then the release-* branch.
# New arrays need to be in the WORKTREE= array else they aren't considered.
-MAINT_029=( "maint-0.2.9" "$GIT_PATH/$TOR_WKT_NAME/maint-0.2.9" )
MAINT_035=( "maint-0.3.5" "$GIT_PATH/$TOR_WKT_NAME/maint-0.3.5" )
MAINT_040=( "maint-0.4.0" "$GIT_PATH/$TOR_WKT_NAME/maint-0.4.0" )
MAINT_041=( "maint-0.4.1" "$GIT_PATH/$TOR_WKT_NAME/maint-0.4.1" )
+MAINT_042=( "maint-0.4.2" "$GIT_PATH/$TOR_WKT_NAME/maint-0.4.2" )
MAINT_MASTER=( "master" "$GIT_PATH/$TOR_MASTER_NAME" )
-RELEASE_029=( "release-0.2.9" "$GIT_PATH/$TOR_WKT_NAME/release-0.2.9" )
RELEASE_035=( "release-0.3.5" "$GIT_PATH/$TOR_WKT_NAME/release-0.3.5" )
RELEASE_040=( "release-0.4.0" "$GIT_PATH/$TOR_WKT_NAME/release-0.4.0" )
RELEASE_041=( "release-0.4.1" "$GIT_PATH/$TOR_WKT_NAME/release-0.4.1" )
+RELEASE_042=( "release-0.4.2" "$GIT_PATH/$TOR_WKT_NAME/release-0.4.2" )
# The master branch path has to be the main repository thus contains the
# origin that will be used to fetch the updates. All the worktrees are created
@@ -76,27 +76,23 @@ ORIGIN_PATH="$GIT_PATH/$TOR_MASTER_NAME"
# SC2034 -- shellcheck thinks that these are unused. We know better.
ACTUALLY_THESE_ARE_USED=<<EOF
-${MAINT_029[0]}
${MAINT_035[0]}
${MAINT_040[0]}
${MAINT_041[0]}
+${MAINT_042[0]}
${MAINT_MASTER[0]}
-${RELEASE_029[0]}
${RELEASE_035[0]}
${RELEASE_040[0]}
${RELEASE_041[0]}
+${RELEASE_042[0]}
EOF
###########################
# Git worktrees to manage #
###########################
-# List of all worktrees to work on. All defined above. Ordering is important.
-# Always the maint-* branch first then the release-*.
+# List of all worktrees to pull. All defined above. Ordering is not important.
WORKTREE=(
- MAINT_029[@]
- RELEASE_029[@]
-
MAINT_035[@]
RELEASE_035[@]
@@ -106,6 +102,9 @@ WORKTREE=(
MAINT_041[@]
RELEASE_041[@]
+ MAINT_042[@]
+ RELEASE_042[@]
+
MAINT_MASTER[@]
)
COUNT=${#WORKTREE[@]}
diff --git a/scripts/git/git-push-all.sh b/scripts/git/git-push-all.sh
index 7c43fe24d8..0abddc8023 100755
--- a/scripts/git/git-push-all.sh
+++ b/scripts/git/git-push-all.sh
@@ -21,7 +21,7 @@ function usage()
echo " -r: push to remote-name, rather than the default upstream remote."
echo " (default: $DEFAULT_UPSTREAM_REMOTE, current: $UPSTREAM_REMOTE)"
echo " -t: test branch mode: push test branches to remote-name. Pushes"
- echo " branches prefix_029, prefix_035, ... , prefix_master."
+ echo " branches prefix_035, prefix_040, ... , prefix_master."
echo " (default: push maint-*, release-*, and master)"
echo " -s: push branches whose tips match upstream maint, release, or"
echo " master branches. The default is to skip these branches,"
@@ -29,6 +29,8 @@ function usage()
echo " CI environment failures, using code that previously passed CI."
echo " (default: skip; current: $CURRENT_PUSH_SAME matching branches)"
echo " --: pass further arguments to git push."
+ echo " All unrecognised arguments are passed to git push, but complex"
+ echo " arguments before -- may be mangled by getopt."
echo " (default: git push --atomic, current: $GIT_PUSH)"
echo
echo " env vars:"
@@ -95,9 +97,10 @@ PUSH_SAME=${TOR_PUSH_SAME:-0}
# Argument processing #
#######################
-# Controlled by the -t <test-branch-prefix> option. The test branch base
-# name option makes git-merge-forward.sh create new test branches:
-# <tbbn>_029, <tbbn>_035, ... , <tbbn>_master, and merge forward.
+# Controlled by the -t <test-branch-prefix> option. The test branch prefix
+# option makes git-merge-forward.sh create new test branches:
+# <tbp>_035, <tbp>_040, ... , <tbp>_master, and merge each branch forward into
+# the next one.
TEST_BRANCH_PREFIX=
while getopts ":hr:st:" opt; do
@@ -127,9 +130,11 @@ while getopts ":hr:st:" opt; do
OPTIND=$((OPTIND - 2))
;;
*)
- # Assume we're done with script arguments,
- # and git push will handle the option
- break
+ # Make git push handle the option
+ # This might mangle options with spaces, use -- for complex options
+ GIT_PUSH="$GIT_PUSH $1"
+ shift
+ OPTIND=$((OPTIND - 1))
;;
esac
done
@@ -151,7 +156,7 @@ if [ "$TEST_BRANCH_PREFIX" ]; then
fi
if [ "$TOR_GIT_PUSH_PATH" ]; then
- echo "Changing to $GIT_PUSH_PATH before pushing"
+ echo "Changing to $TOR_GIT_PUSH_PATH before pushing"
cd "$TOR_GIT_PUSH_PATH"
else
echo "Pushing from the current directory"
@@ -167,19 +172,19 @@ DEFAULT_UPSTREAM_BRANCHES=
if [ "$DEFAULT_UPSTREAM_REMOTE" != "$UPSTREAM_REMOTE" ]; then
DEFAULT_UPSTREAM_BRANCHES=$(echo \
"$DEFAULT_UPSTREAM_REMOTE"/master \
+ "$DEFAULT_UPSTREAM_REMOTE"/{release,maint}-0.4.2 \
"$DEFAULT_UPSTREAM_REMOTE"/{release,maint}-0.4.1 \
"$DEFAULT_UPSTREAM_REMOTE"/{release,maint}-0.4.0 \
"$DEFAULT_UPSTREAM_REMOTE"/{release,maint}-0.3.5 \
- "$DEFAULT_UPSTREAM_REMOTE"/{release,maint}-0.2.9 \
)
fi
UPSTREAM_BRANCHES=$(echo \
"$UPSTREAM_REMOTE"/master \
+ "$UPSTREAM_REMOTE"/{release,maint}-0.4.2 \
"$UPSTREAM_REMOTE"/{release,maint}-0.4.1 \
"$UPSTREAM_REMOTE"/{release,maint}-0.4.0 \
"$UPSTREAM_REMOTE"/{release,maint}-0.3.5 \
- "$UPSTREAM_REMOTE"/{release,maint}-0.2.9 \
)
########################
@@ -188,35 +193,35 @@ UPSTREAM_BRANCHES=$(echo \
PUSH_BRANCHES=$(echo \
master \
+ {release,maint}-0.4.2 \
{release,maint}-0.4.1 \
{release,maint}-0.4.0 \
{release,maint}-0.3.5 \
- {release,maint}-0.2.9 \
)
if [ -z "$TEST_BRANCH_PREFIX" ]; then
- # maint/release push mode
+ # maint/release push mode: push all branches.
#
# List of branches to push. Ordering is not important.
PUSH_BRANCHES=$(echo \
master \
+ {release,maint}-0.4.2 \
{release,maint}-0.4.1 \
{release,maint}-0.4.0 \
{release,maint}-0.3.5 \
- {release,maint}-0.2.9 \
)
else
- # Test branch mode: merge to maint only, and create a new branch for 0.2.9
+ # Test branch push mode: push test branches, based on each maint branch.
#
# List of branches to push. Ordering is not important.
PUSH_BRANCHES=" \
${TEST_BRANCH_PREFIX}_master \
+ ${TEST_BRANCH_PREFIX}_042 \
${TEST_BRANCH_PREFIX}_041 \
${TEST_BRANCH_PREFIX}_040 \
${TEST_BRANCH_PREFIX}_035 \
- ${TEST_BRANCH_PREFIX}_029 \
"
fi
@@ -224,20 +229,32 @@ fi
# Entry point #
###############
-# Skip the test branches that are the same as the upstream branches
-if [ "$PUSH_SAME" -eq 0 ] && [ "$TEST_BRANCH_PREFIX" ]; then
+if [ "$TEST_BRANCH_PREFIX" ]; then
+ # Skip the test branches that are the same as the default or current
+ # upstream branches (they have already been tested)
+ UPSTREAM_SKIP_SAME_AS="$UPSTREAM_BRANCHES $DEFAULT_UPSTREAM_BRANCHES"
+else
+ # Skip the local maint-*, release-*, master branches that are the same as the
+ # current upstream branches, but ignore the default upstream
+ # (we want to update a non-default remote, even if it matches the default)
+ UPSTREAM_SKIP_SAME_AS="$UPSTREAM_BRANCHES"
+fi
+
+# Skip branches that match the relevant upstream(s)
+if [ "$PUSH_SAME" -eq 0 ]; then
NEW_PUSH_BRANCHES=
for b in $PUSH_BRANCHES; do
PUSH_COMMIT=$(git rev-parse "$b")
SKIP_UPSTREAM=
- for u in $DEFAULT_UPSTREAM_BRANCHES $UPSTREAM_BRANCHES; do
- UPSTREAM_COMMIT=$(git rev-parse "$u")
+ for u in $UPSTREAM_SKIP_SAME_AS; do
+ # Skip the branch check on error
+ UPSTREAM_COMMIT=$(git rev-parse "$u" 2>/dev/null) || continue
if [ "$PUSH_COMMIT" = "$UPSTREAM_COMMIT" ]; then
SKIP_UPSTREAM="$u"
fi
done
if [ "$SKIP_UPSTREAM" ]; then
- printf "Skipping unchanged: %s remote: %s\\n" \
+ printf "Skipping unchanged: %s matching remote: %s\\n" \
"$b" "$SKIP_UPSTREAM"
else
if [ "$NEW_PUSH_BRANCHES" ]; then
@@ -250,6 +267,12 @@ if [ "$PUSH_SAME" -eq 0 ] && [ "$TEST_BRANCH_PREFIX" ]; then
PUSH_BRANCHES=${NEW_PUSH_BRANCHES}
fi
+if [ ! "$PUSH_BRANCHES" ]; then
+ echo "No branches to push!"
+ # We expect the rest of the script to run without errors, even if there
+ # are no branches
+fi
+
if [ "$PUSH_DELAY" -le 0 ]; then
echo "Pushing $PUSH_BRANCHES"
# We know that there are no spaces in any branch within $PUSH_BRANCHES, so
@@ -262,28 +285,43 @@ if [ "$PUSH_DELAY" -le 0 ]; then
else
# Push the branches in optimal CI order, with a delay between each push
PUSH_BRANCHES=$(echo "$PUSH_BRANCHES" | tr " " "\\n" | sort -V)
- MASTER_BRANCH=$(echo "$PUSH_BRANCHES" | tr " " "\\n" | grep master)
+ MASTER_BRANCH=$(echo "$PUSH_BRANCHES" | tr " " "\\n" | grep master) \
+ || true # Skipped master branch
if [ -z "$TEST_BRANCH_PREFIX" ]; then
- MAINT_BRANCHES=$(echo "$PUSH_BRANCHES" | tr " " "\\n" | grep maint)
+ MAINT_BRANCHES=$(echo "$PUSH_BRANCHES" | tr " " "\\n" | grep maint) \
+ || true # Skipped all maint branches
RELEASE_BRANCHES=$(echo "$PUSH_BRANCHES" | tr " " "\\n" | grep release | \
- tr "\\n" " ")
- printf \
- "Pushing with %ss delays, so CI runs in this order:\\n%s\\n%s\\n%s\\n" \
- "$PUSH_DELAY" "$MASTER_BRANCH" "$MAINT_BRANCHES" "$RELEASE_BRANCHES"
+ tr "\\n" " ") || true # Skipped all release branches
else
# Actually test branches based on maint branches
- MAINT_BRANCHES=$(echo "$PUSH_BRANCHES" | tr " " "\\n" | grep -v master)
- printf "Pushing with %ss delays, so CI runs in this order:\\n%s\\n%s\\n" \
- "$PUSH_DELAY" "$MASTER_BRANCH" "$MAINT_BRANCHES"
+ MAINT_BRANCHES=$(echo "$PUSH_BRANCHES" | tr " " "\\n" | grep -v master) \
+ || true # Skipped all maint test branches
# No release branches
RELEASE_BRANCHES=
fi
- $GIT_PUSH "$@" "$UPSTREAM_REMOTE" "$MASTER_BRANCH"
- sleep "$PUSH_DELAY"
+ if [ "$MASTER_BRANCH" ] || [ "$MAINT_BRANCHES" ] \
+ || [ "$RELEASE_BRANCHES" ]; then
+ printf "Pushing with %ss delays, so CI runs in this order:\\n" \
+ "$PUSH_DELAY"
+ if [ "$MASTER_BRANCH" ]; then
+ printf "%s\\n" "$MASTER_BRANCH"
+ fi
+ if [ "$MAINT_BRANCHES" ]; then
+ printf "%s\\n" "$MAINT_BRANCHES"
+ fi
+ if [ "$RELEASE_BRANCHES" ]; then
+ printf "%s\\n" "$RELEASE_BRANCHES"
+ fi
+ fi
# shellcheck disable=SC2086
- for b in $MAINT_BRANCHES; do
+ for b in $MASTER_BRANCH $MAINT_BRANCHES; do
$GIT_PUSH "$@" "$UPSTREAM_REMOTE" "$b"
- sleep "$PUSH_DELAY"
+ # If we are pushing more than one branch, delay.
+ # In the unlikely scenario where we are pushing maint without master,
+ # or maint without release, there may be an extra delay
+ if [ "$MAINT_BRANCHES" ] || [ "$RELEASE_BRANCHES" ]; then
+ sleep "$PUSH_DELAY"
+ fi
done
if [ "$RELEASE_BRANCHES" ]; then
# shellcheck disable=SC2086
diff --git a/scripts/git/git-setup-dirs.sh b/scripts/git/git-setup-dirs.sh
new file mode 100755
index 0000000000..20a148204a
--- /dev/null
+++ b/scripts/git/git-setup-dirs.sh
@@ -0,0 +1,550 @@
+#!/usr/bin/env bash
+
+SCRIPT_NAME=$(basename "$0")
+
+function usage()
+{
+ echo "$SCRIPT_NAME [-h] [-n] [-u]"
+ echo
+ echo " arguments:"
+ echo " -h: show this help text"
+ echo " -n: dry run mode"
+ echo " (default: run commands)"
+ echo " -u: if a directory or worktree already exists, use it"
+ echo " (default: fail and exit on existing directories)"
+ echo
+ echo " env vars:"
+ echo " required:"
+ echo " TOR_FULL_GIT_PATH: where the git repository directories reside."
+ echo " You must set this env var, we recommend \$HOME/git/"
+ echo " (default: fail if this env var is not set;"
+ echo " current: $GIT_PATH)"
+ echo
+ echo " optional:"
+ echo " TOR_MASTER: the name of the directory containing the tor.git clone"
+ echo " The tor master git directory is \$GIT_PATH/\$TOR_MASTER"
+ echo " (default: tor; current: $TOR_MASTER_NAME)"
+ echo " TOR_WKT_NAME: the name of the directory containing the tor"
+ echo " worktrees. The tor worktrees are:"
+ echo " \$GIT_PATH/\$TOR_WKT_NAME/{maint-*,release-*}"
+ echo " (default: tor-wkt; current: $TOR_WKT_NAME)"
+ echo " TOR_GIT_ORIGIN_PULL: the origin remote pull URL."
+ echo " (current: $GIT_ORIGIN_PULL)"
+ echo " TOR_GIT_ORIGIN_PUSH: the origin remote push URL"
+ echo " (current: $GIT_ORIGIN_PUSH)"
+ echo " TOR_UPSTREAM_REMOTE_NAME: the default upstream remote."
+ echo " If \$TOR_UPSTREAM_REMOTE_NAME is not 'origin', we have a"
+ echo " separate upstream remote, and we don't push to origin."
+ echo " (default: $DEFAULT_UPSTREAM_REMOTE)"
+ echo " TOR_GITHUB_PULL: the tor-github remote pull URL"
+ echo " (current: $GITHUB_PULL)"
+ echo " TOR_GITHUB_PUSH: the tor-github remote push URL"
+ echo " (current: $GITHUB_PUSH)"
+ echo " TOR_EXTRA_CLONE_ARGS: extra arguments to git clone"
+ echo " (current: $TOR_EXTRA_CLONE_ARGS)"
+ echo " TOR_EXTRA_REMOTE_NAME: the name of an extra remote"
+ echo " This remote is not pulled by this script or git-pull-all.sh."
+ echo " This remote is not pushed by git-push-all.sh."
+ echo " (current: $TOR_EXTRA_REMOTE_NAME)"
+ echo " TOR_EXTRA_REMOTE_PULL: the extra remote pull URL."
+ echo " (current: $TOR_EXTRA_REMOTE_PULL)"
+ echo " TOR_EXTRA_REMOTE_PUSH: the extra remote push URL"
+ echo " (current: $TOR_EXTRA_REMOTE_PUSH)"
+ echo " we recommend that you set these env vars in your ~/.profile"
+}
+
+#################
+# Configuration #
+#################
+
+# Don't change this configuration - set the env vars in your .profile
+
+# Where are all those git repositories?
+GIT_PATH=${TOR_FULL_GIT_PATH:-"FULL_PATH_TO_GIT_REPOSITORY_DIRECTORY"}
+# The tor master git repository directory from which all the worktree have
+# been created.
+TOR_MASTER_NAME=${TOR_MASTER_NAME:-"tor"}
+# The worktrees location (directory).
+TOR_WKT_NAME=${TOR_WKT_NAME:-"tor-wkt"}
+
+# Origin repositories
+GIT_ORIGIN_PULL=${TOR_GIT_ORIGIN_PULL:-"https://git.torproject.org/tor.git"}
+GIT_ORIGIN_PUSH=${TOR_GIT_ORIGIN_PUSH:-"git@git-rw.torproject.org:tor.git"}
+# The upstream remote which git.torproject.org/tor.git points to.
+DEFAULT_UPSTREAM_REMOTE=${TOR_UPSTREAM_REMOTE_NAME:-"upstream"}
+# Copy the URLs from origin
+GIT_UPSTREAM_PULL="$GIT_ORIGIN_PULL"
+GIT_UPSTREAM_PUSH="$GIT_ORIGIN_PUSH"
+# And avoid pushing to origin if we have an upstream
+if [ "$DEFAULT_UPSTREAM_REMOTE" != "origin" ]; then
+ GIT_ORIGIN_PUSH="No pushes to origin, if there is an upstream"
+fi
+# GitHub repositories
+GITHUB_PULL=${TOR_GITHUB_PULL:-"https://github.com/torproject/tor.git"}
+GITHUB_PUSH=${TOR_GITHUB_PUSH:-"No_Pushing_To_GitHub"}
+
+##########################
+# Git branches to manage #
+##########################
+
+# The branches and worktrees need to be modified when there is a new branch,
+# and when an old branch is no longer supported.
+
+# Configuration of the branches that needs merging. The values are in order:
+# (0) current maint/release branch name
+# (1) Full path of the git worktree
+#
+# First set of arrays are the maint-* branch and then the release-* branch.
+# New arrays need to be in the WORKTREE= array else they aren't considered.
+MAINT_035=( "maint-0.3.5" "$GIT_PATH/$TOR_WKT_NAME/maint-0.3.5" )
+MAINT_040=( "maint-0.4.0" "$GIT_PATH/$TOR_WKT_NAME/maint-0.4.0" )
+MAINT_041=( "maint-0.4.1" "$GIT_PATH/$TOR_WKT_NAME/maint-0.4.1" )
+MAINT_042=( "maint-0.4.2" "$GIT_PATH/$TOR_WKT_NAME/maint-0.4.2" )
+MAINT_MASTER=( "master" "$GIT_PATH/$TOR_MASTER_NAME" )
+
+RELEASE_035=( "release-0.3.5" "$GIT_PATH/$TOR_WKT_NAME/release-0.3.5" )
+RELEASE_040=( "release-0.4.0" "$GIT_PATH/$TOR_WKT_NAME/release-0.4.0" )
+RELEASE_041=( "release-0.4.1" "$GIT_PATH/$TOR_WKT_NAME/release-0.4.1" )
+RELEASE_042=( "release-0.4.2" "$GIT_PATH/$TOR_WKT_NAME/release-0.4.2" )
+
+# The master branch path has to be the main repository thus contains the
+# origin that will be used to fetch the updates. All the worktrees are created
+# from that repository.
+ORIGIN_PATH="$GIT_PATH/$TOR_MASTER_NAME"
+
+# SC2034 -- shellcheck thinks that these are unused. We know better.
+ACTUALLY_THESE_ARE_USED=<<EOF
+${MAINT_035[0]}
+${MAINT_040[0]}
+${MAINT_041[0]}
+${MAINT_042[0]}
+${MAINT_MASTER[0]}
+${RELEASE_035[0]}
+${RELEASE_040[0]}
+${RELEASE_041[0]}
+${RELEASE_042[0]}
+EOF
+
+#######################
+# Argument processing #
+#######################
+
+# Controlled by the -n option. The dry run option will just output the command
+# that would have been executed for each worktree.
+DRY_RUN=0
+
+# Controlled by the -s option. The use existing option checks for existing
+# directories, and re-uses them, rather than creating a new directory.
+USE_EXISTING=0
+USE_EXISTING_HINT="Use existing: '$SCRIPT_NAME -u'."
+
+while getopts "hnu" opt; do
+ case "$opt" in
+ h) usage
+ exit 0
+ ;;
+ n) DRY_RUN=1
+ echo " *** DRY RUN MODE ***"
+ ;;
+ u) USE_EXISTING=1
+ echo " *** USE EXISTING DIRECTORIES MODE ***"
+ ;;
+ *)
+ echo
+ usage
+ exit 1
+ ;;
+ esac
+done
+
+###########################
+# Git worktrees to manage #
+###########################
+
+WORKTREE=(
+ MAINT_035[@]
+ RELEASE_035[@]
+
+ MAINT_040[@]
+ RELEASE_040[@]
+
+ MAINT_041[@]
+ RELEASE_041[@]
+
+ MAINT_042[@]
+ RELEASE_042[@]
+
+ MAINT_MASTER[@]
+)
+
+COUNT=${#WORKTREE[@]}
+
+#############
+# Constants #
+#############
+
+# Control characters
+CNRM=$'\x1b[0;0m' # Clear color
+
+# Bright color
+BGRN=$'\x1b[1;32m'
+BBLU=$'\x1b[1;34m'
+BRED=$'\x1b[1;31m'
+BYEL=$'\x1b[1;33m'
+IWTH=$'\x1b[3;37m'
+
+# Strings for the pretty print.
+MARKER="${BBLU}[${BGRN}+${BBLU}]${CNRM}"
+SUCCESS="${BGRN}success${CNRM}"
+SKIPPED="${BYEL}skipped${CNRM}"
+FAILED="${BRED}failed${CNRM}"
+
+####################
+# Helper functions #
+####################
+
+# Validate the given returned value (error code), print success or failed. The
+# second argument is the error output in case of failure, it is printed out.
+# On failure, this function exits.
+function validate_ret
+{
+ if [ "$1" -eq 0 ]; then
+ printf "%s\\n" "$SUCCESS"
+ else
+ printf "%s\\n" "$FAILED"
+ printf " %s\\n" "$2"
+ exit 1
+ fi
+}
+
+# Validate the given returned value (error code), print success, skipped, or
+# failed. If $USE_EXISTING is 0, fail on error, otherwise, skip on error.
+# The second argument is the error output in case of failure, it is printed
+# out. On failure, this function exits.
+function validate_ret_skip
+{
+ if [ "$1" -ne 0 ]; then
+ if [ "$USE_EXISTING" -eq "0" ]; then
+ # Fail and exit with error
+ validate_ret "$1" "$2 $USE_EXISTING_HINT"
+ else
+ printf "%s\\n" "$SKIPPED"
+ printf " %s\\n" "${IWTH}$2${CNRM}"
+ # Tell the caller to skip the rest of the function
+ return 0
+ fi
+ fi
+ # Tell the caller to continue
+ return 1
+}
+
+# Create a directory, and any missing enclosing directories.
+# If the directory already exists: fail if $USE_EXISTING is 0, otherwise skip.
+function make_directory
+{
+ local cmd="mkdir -p '$1'"
+ printf " %s Creating directory %s..." "$MARKER" "$1"
+ local check_cmd="[ ! -d '$1' ]"
+ msg=$( eval "$check_cmd" 2>&1 )
+ if validate_ret_skip $? "Directory already exists."; then
+ return
+ fi
+ if [ $DRY_RUN -eq 0 ]; then
+ msg=$( eval "$cmd" 2>&1 )
+ validate_ret $? "$msg"
+ else
+ printf "\\n %s\\n" "${IWTH}$cmd${CNRM}"
+ fi
+}
+
+# Create a symlink from the first argument to the second argument
+# If the link already exists: fail if $USE_EXISTING is 0, otherwise skip.
+function make_symlink
+{
+ local cmd="ln -s '$1' '$2'"
+ printf " %s Creating symlink from %s to %s..." "$MARKER" "$1" "$2"
+ local check_cmd="[ ! -e '$2' ]"
+ msg=$( eval "$check_cmd" 2>&1 )
+ if validate_ret_skip $? "File already exists."; then
+ return
+ fi
+ if [ $DRY_RUN -eq 0 ]; then
+ msg=$( eval "$cmd" 2>&1 )
+ validate_ret $? "$msg"
+ else
+ printf "\\n %s\\n" "${IWTH}$cmd${CNRM}"
+ fi
+}
+
+# Go into the directory or repository, even if $DRY_RUN is non-zero.
+# If the directory does not exist, fail and log an error.
+# Otherwise, silently succeed.
+function goto_dir
+{
+ if ! cd "$1" 1>/dev/null 2>/dev/null ; then
+ printf " %s Changing to directory %s..." "$MARKER" "$1"
+ validate_ret 1 "$1: Not found. Stopping."
+ fi
+}
+
+# Clone a repository into a directory.
+# If the directory already exists: fail if $USE_EXISTING is 0, otherwise skip.
+function clone_repo
+{
+ local cmd="git clone $TOR_EXTRA_CLONE_ARGS '$1' '$2'"
+ printf " %s Cloning %s into %s..." "$MARKER" "$1" "$2"
+ local check_cmd="[ ! -d '$2' ]"
+ msg=$( eval "$check_cmd" 2>&1 )
+ if validate_ret_skip $? "Directory already exists."; then
+ # If we skip the clone, we need to do a fetch
+ goto_dir "$ORIGIN_PATH"
+ fetch_remote "origin"
+ return
+ fi
+ if [ $DRY_RUN -eq 0 ]; then
+ msg=$( eval "$cmd" 2>&1 )
+ validate_ret $? "$msg"
+ else
+ printf "\\n %s\\n" "${IWTH}$cmd${CNRM}"
+ fi
+}
+
+# Add a remote by name and URL.
+# If the remote already exists: fail if $USE_EXISTING is 0, otherwise skip.
+function add_remote
+{
+ local cmd="git remote add '$1' '$2'"
+ printf " %s Adding remote %s at %s..." "$MARKER" "$1" "$2"
+ local check_cmd="git remote get-url '$1'"
+ msg=$( eval "$check_cmd" 2>&1 )
+ ret=$?
+ # We don't want a remote, so we invert the exit status
+ if validate_ret_skip $(( ! ret )) \
+ "Remote already exists for $1 at $msg."; then
+ return
+ fi
+ if [ $DRY_RUN -eq 0 ]; then
+ msg=$( eval "$cmd" 2>&1 )
+ validate_ret $? "$msg"
+ else
+ printf "\\n %s\\n" "${IWTH}$cmd${CNRM}"
+ fi
+}
+
+# Set a remote's push URL by name and URL.
+function set_remote_push
+{
+ local cmd="git remote set-url --push '$1' '$2'"
+ printf " %s Setting remote %s push URL to '%s'..." "$MARKER" "$1" "$2"
+ if [ $DRY_RUN -eq 0 ]; then
+ msg=$( eval "$cmd" 2>&1 )
+ validate_ret $? "$msg"
+ else
+ printf "\\n %s\\n" "${IWTH}$cmd${CNRM}"
+ fi
+}
+
+# Fetch a remote by name.
+function fetch_remote
+{
+ local cmd="git fetch '$1'"
+ printf " %s Fetching %s..." "$MARKER" "$1"
+ if [ $DRY_RUN -eq 0 ]; then
+ msg=$( eval "$cmd" 2>&1 )
+ validate_ret $? "$msg"
+ else
+ printf "\\n %s\\n" "${IWTH}$cmd${CNRM}"
+ fi
+}
+
+# Replace the fetch configs for a remote with config if they match a pattern.
+function replace_fetch_config
+{
+ local cmd="git config --replace-all remote.'$1'.fetch '$2' '$3'"
+ printf " %s Replacing %s fetch configs for '%s'..." \
+ "$MARKER" "$1" "$3"
+ if [ $DRY_RUN -eq 0 ]; then
+ msg=$( eval "$cmd" 2>&1 )
+ validate_ret $? "$msg"
+ else
+ printf "\\n %s\\n" "${IWTH}$cmd${CNRM}"
+ fi
+}
+
+# Set up the tor-github PR config, so tor-github/pr/NNNN/head points to GitHub
+# PR NNNN. In some repositories, "/head" is optional.
+function set_tor_github_pr_fetch_config
+{
+ # Standard branches
+ replace_fetch_config tor-github \
+ "+refs/heads/*:refs/remotes/tor-github/*" \
+ "refs/heads"
+ # PRs
+ replace_fetch_config "tor-github" \
+ "+refs/pull/*:refs/remotes/tor-github/pr/*" \
+ "refs/pull.*pr"
+}
+
+# Add a new worktree for branch at path.
+# If the directory already exists: fail if $USE_EXISTING is 0, otherwise skip.
+function add_worktree
+{
+ local cmd="git worktree add '$2' '$1'"
+ printf " %s Adding worktree for %s at %s..." "$MARKER" "$1" "$2"
+ local check_cmd="[ ! -d '$2' ]"
+ msg=$( eval "$check_cmd" 2>&1 )
+ if validate_ret_skip $? "Directory already exists."; then
+ return
+ fi
+ if [ $DRY_RUN -eq 0 ]; then
+ msg=$( eval "$cmd" 2>&1 )
+ validate_ret $? "$msg"
+ else
+ printf "\\n %s\\n" "${IWTH}$cmd${CNRM}"
+ fi
+}
+
+# Switch to the given branch name.
+# If the branch does not exist: fail.
+function switch_branch
+{
+ local cmd="git checkout '$1'"
+ printf " %s Switching branch to %s..." "$MARKER" "$1"
+ if [ $DRY_RUN -eq 0 ]; then
+ msg=$( eval "$cmd" 2>&1 )
+ validate_ret $? "$msg"
+ else
+ printf "\\n %s\\n" "${IWTH}$cmd${CNRM}"
+ fi
+}
+
+# Checkout a new branch with the given branch name.
+# If the branch already exists: fail if $USE_EXISTING is 0, otherwise skip.
+function new_branch
+{
+ local cmd="git checkout -b '$1'"
+ printf " %s Creating new branch %s..." "$MARKER" "$1"
+ local check_cmd="git branch --list '$1'"
+ msg=$( eval "$check_cmd" 2>&1 )
+ if validate_ret_skip $? "Branch already exists."; then
+ return
+ fi
+ if [ $DRY_RUN -eq 0 ]; then
+ msg=$( eval "$cmd" 2>&1 )
+ validate_ret $? "$msg"
+ else
+ printf "\\n %s\\n" "${IWTH}$cmd${CNRM}"
+ fi
+}
+
+# Switch to an existing branch, or checkout a new branch with the given
+# branch name.
+function switch_or_new_branch
+{
+ local cmd="git rev-parse --verify '$1'"
+ if [ $DRY_RUN -eq 0 ]; then
+ # Call switch_branch if there is a branch, or new_branch if there is not
+ msg=$( eval "$cmd" 2>&1 )
+ RET=$?
+ if [ $RET -eq 0 ]; then
+ # Branch: (commit id)
+ switch_branch "$1"
+ elif [ $RET -eq 128 ]; then
+ # Not a branch: "fatal: Needed a single revision"
+ new_branch "$1"
+ else
+ # Unexpected return value
+ validate_ret $RET "$msg"
+ fi
+ else
+ printf "\\n %s\\n" "${IWTH}$cmd${CNRM}, then depending on the result:"
+ switch_branch "$1"
+ new_branch "$1"
+ fi
+}
+
+# Set the upstream for branch to upstream.
+function set_upstream
+{
+ # Note the argument order is swapped
+ local cmd="git branch --set-upstream-to='$2' '$1'"
+ printf " %s Setting upstream for %s to %s..." "$MARKER" "$1" "$2"
+ if [ $DRY_RUN -eq 0 ]; then
+ msg=$( eval "$cmd" 2>&1 )
+ validate_ret $? "$msg"
+ else
+ printf "\\n %s\\n" "${IWTH}$cmd${CNRM}"
+ fi
+}
+
+###############
+# Entry point #
+###############
+
+printf "%s Setting up the repository and remote %s\\n" "$MARKER" \
+ "${BYEL}origin${CNRM}"
+# First, fetch the origin.
+ORIGIN_PARENT=$(dirname "$ORIGIN_PATH")
+make_directory "$ORIGIN_PARENT"
+# This is just cd with an error check
+goto_dir "$ORIGIN_PARENT"
+
+# clone repository / origin remote
+clone_repo "$GIT_ORIGIN_PULL" "$TOR_MASTER_NAME"
+goto_dir "$ORIGIN_PATH"
+set_remote_push "origin" "$GIT_ORIGIN_PUSH"
+
+# upstream remote, if different to origin
+if [ "$DEFAULT_UPSTREAM_REMOTE" != "origin" ]; then
+ printf "%s Setting up remote %s\\n" "$MARKER" \
+ "${BYEL}$DEFAULT_UPSTREAM_REMOTE${CNRM}"
+ add_remote "$DEFAULT_UPSTREAM_REMOTE" "$GIT_UPSTREAM_PULL"
+ set_remote_push "$DEFAULT_UPSTREAM_REMOTE" "$GIT_UPSTREAM_PUSH"
+ fetch_remote "$DEFAULT_UPSTREAM_REMOTE"
+fi
+
+# GitHub remote
+printf "%s Setting up remote %s\\n" "$MARKER" "${BYEL}tor-github${CNRM}"
+# Add remote
+add_remote "tor-github" "$GITHUB_PULL"
+set_remote_push "tor-github" "$GITHUB_PUSH"
+# Add custom fetch for PRs
+set_tor_github_pr_fetch_config
+# Now fetch them all
+fetch_remote "tor-github"
+
+# Extra remote
+if [ "$TOR_EXTRA_REMOTE_NAME" ]; then
+ printf "%s Setting up remote %s\\n" "$MARKER" \
+ "${BYEL}$TOR_EXTRA_REMOTE_NAME${CNRM}"
+ # Add remote
+ add_remote "$TOR_EXTRA_REMOTE_NAME" "$TOR_EXTRA_REMOTE_PULL"
+ set_remote_push "$TOR_EXTRA_REMOTE_NAME" "$TOR_EXTRA_REMOTE_PUSH"
+ # But leave it to the user to decide if they want to fetch it
+ #fetch_remote "$TOR_EXTRA_REMOTE_NAME"
+fi
+
+# Go over all configured worktree.
+for ((i=0; i<COUNT; i++)); do
+ branch=${!WORKTREE[$i]:0:1}
+ repo_path=${!WORKTREE[$i]:1:1}
+
+ printf "%s Handling branch %s\\n" "$MARKER" "${BYEL}$branch${CNRM}"
+ # We cloned the repository, and master is the default branch
+ if [ "$branch" = "master" ]; then
+ if [ "$TOR_MASTER_NAME" != "master" ]; then
+ # Set up a master link in the worktree directory
+ make_symlink "$repo_path" "$GIT_PATH/$TOR_WKT_NAME/master"
+ fi
+ else
+ # git makes worktree directories if they don't exist
+ add_worktree "origin/$branch" "$repo_path"
+ fi
+ goto_dir "$repo_path"
+ switch_or_new_branch "$branch"
+ set_upstream "$branch" "origin/$branch"
+done
+
+echo
+echo "Remember to copy the git hooks from tor/scripts/git/*.git-hook to"
+echo "$ORIGIN_PATH/.git/hooks/*"
diff --git a/scripts/git/pre-commit.git-hook b/scripts/git/pre-commit.git-hook
index 1c381ec60a..f630a242bd 100755
--- a/scripts/git/pre-commit.git-hook
+++ b/scripts/git/pre-commit.git-hook
@@ -13,30 +13,67 @@ cd "$workdir" || exit 1
set -e
+if [ $# -eq 0 ]; then
+ # When called in pre-commit, check the files modified in this commit
+ CHECK_FILTER="git diff --cached --name-only --diff-filter=ACMR"
+ # Use the appropriate owned tor source list to filter the changed files
+
+ # This is the layout in 0.3.5 and later.
+
+ # Keep these lists consistent:
+ # - OWNED_TOR_C_FILES in Makefile.am
+ # - CHECK_FILES in pre-commit.git-hook and pre-push.git-hook
+ # - try_parse in check_cocci_parse.sh
+ CHECK_FILES="$($CHECK_FILTER \
+ src/lib/*/*.[ch] \
+ src/core/*/*.[ch] \
+ src/feature/*/*.[ch] \
+ src/app/*/*.[ch] \
+ src/test/*.[ch] \
+ src/test/*/*.[ch] \
+ src/tools/*.[ch] \
+ )"
+else
+ # When called in pre-push, concatenate the argument array
+ # Fails on special characters in file names
+ CHECK_FILES="$*"
+fi
+
+## General File Checks
+
if [ -n "$(ls ./changes/)" ]; then
python scripts/maint/lintChanges.py ./changes/*
fi
-if [ -d src/lib ]; then
- # This is the layout in 0.3.5
- perl scripts/maint/checkSpace.pl -C \
- src/lib/*/*.[ch] \
- src/core/*/*.[ch] \
- src/feature/*/*.[ch] \
- src/app/*/*.[ch] \
- src/test/*.[ch] \
- src/test/*/*.[ch] \
- src/tools/*.[ch]
-elif [ -d src/common ]; then
- # This was the layout before 0.3.5
- perl scripts/maint/checkSpace.pl -C \
- src/common/*/*.[ch] \
- src/or/*/*.[ch] \
- src/test/*.[ch] \
- src/test/*/*.[ch] \
- src/tools/*.[ch]
+if [ -e scripts/maint/checkShellScripts.sh ]; then
+ scripts/maint/checkShellScripts.sh
+fi
+
+# Always run the practracker unit tests
+PT_DIR=scripts/maint/practracker
+
+if [ -e "${PT_DIR}/test_practracker.sh" ]; then
+ "${PT_DIR}/test_practracker.sh"
fi
+if [ -e scripts/maint/checkSpaceTest.sh ]; then
+ scripts/maint/checkSpaceTest.sh
+fi
+
+if [ ! "$CHECK_FILES" ]; then
+ echo "No modified tor-owned source files, skipping further checks"
+ exit 0
+fi
+
+## Owned Source File Checks
+
+printf "Modified tor-owned source files:\\n%s\\n" "$CHECK_FILES"
+
+# We want word splitting here, because file names are space separated
+# shellcheck disable=SC2086
+perl scripts/maint/checkSpace.pl -C \
+ $CHECK_FILES
+
if test -e scripts/maint/practracker/includes.py; then
python scripts/maint/practracker/includes.py
fi
@@ -44,16 +81,19 @@ fi
# Only call practracker if ${PT_DIR}/.enable_practracker_in_hooks exists
# We do this check so that we can enable practracker in hooks in master, and
# disable it on maint branches
-PT_DIR=scripts/maint/practracker
-
if [ -e "${PT_DIR}/practracker.py" ]; then
if [ -e "${PT_DIR}/.enable_practracker_in_hooks" ]; then
- if ! python3 "${PT_DIR}/practracker.py" "$workdir"; then
- exit 1
- fi
+ python3 "${PT_DIR}/practracker.py" "$workdir"
fi
fi
-if [ -e scripts/maint/checkShellScripts.sh ]; then
- scripts/maint/checkShellScripts.sh
+if [ -e scripts/coccinelle/check_cocci_parse.sh ]; then
+
+ # Run a verbose cocci parse check on the changed files
+ # (spatch is slow, so we don't want to check all the files.)
+ #
+ # We want word splitting here, because file names are space separated
+ # shellcheck disable=SC2086
+ VERBOSE=1 scripts/coccinelle/check_cocci_parse.sh \
+ $CHECK_FILES
fi
diff --git a/scripts/git/pre-push.git-hook b/scripts/git/pre-push.git-hook
index f4504c4215..7b06f3734d 100755
--- a/scripts/git/pre-push.git-hook
+++ b/scripts/git/pre-push.git-hook
@@ -16,91 +16,109 @@
# The following sample script was used as starting point:
# https://github.com/git/git/blob/master/templates/hooks--pre-push.sample
+# Are you adding a new check to the git hooks?
+# - Common checks belong in the pre-commit hook
+# - Push-only checks belong in the pre-push hook
+
echo "Running pre-push hook"
z40=0000000000000000000000000000000000000000
upstream_name=${TOR_UPSTREAM_REMOTE_NAME:-"upstream"}
-# Are you adding a new check to the git hooks?
-# - Common checks belong in the pre-commit hook
-# - Push-only checks belong in the pre-push hook
-#
-# Call the pre-commit hook for the common checks, if it is executable.
workdir=$(git rev-parse --show-toplevel)
-if [ -x "$workdir/.git/hooks/pre-commit" ]; then
- if ! "$workdir"/.git/hooks/pre-commit; then
- exit 1
- fi
-fi
-remote="$1"
+cd "$workdir" || exit 1
+remote="$1"
remote_name=$(git remote --verbose | grep "$2" | awk '{print $1}' | head -n 1)
-if [[ "$remote_name" != "$upstream_name" ]]; then
- echo "Not pushing to upstream - refraining from further checks"
- exit 0
-fi
ref_is_upstream_branch() {
- if [ "$1" == "refs/heads/master" ] ||
- [[ "$1" == refs/heads/release-* ]] ||
- [[ "$1" == refs/heads/maint-* ]]
- then
- return 1
- fi
+ if [ "$1" == "refs/heads/master" ] ||
+ [[ "$1" == refs/heads/release-* ]] ||
+ [[ "$1" == refs/heads/maint-* ]]; then
+ return 1
+ fi
}
# shellcheck disable=SC2034
while read -r local_ref local_sha remote_ref remote_sha
do
- if [ "$local_sha" = $z40 ]
- then
- # Handle delete
- :
- else
- if [ "$remote_sha" = $z40 ]
- then
- # New branch, examine all commits
- range="$local_sha"
- else
- # Update to existing branch, examine new commits
- range="$remote_sha..$local_sha"
- fi
-
- if (ref_is_upstream_branch "$local_ref" == 0 ||
- ref_is_upstream_branch "$remote_ref" == 0) &&
- [ "$local_ref" != "$remote_ref" ]
- then
- if [ "$remote" == "origin" ]
- then
- echo >&2 "Not pushing: $local_ref to $remote_ref"
- echo >&2 "If you really want to push this, use --no-verify."
- exit 1
- else
- continue
- fi
- fi
-
- # Check for fixup! commit
- commit=$(git rev-list -n 1 --grep '^fixup!' "$range")
- if [ -n "$commit" ]
- then
- echo >&2 "Found fixup! commit in $local_ref, not pushing"
- echo >&2 "If you really want to push this, use --no-verify."
- exit 1
- fi
-
- # Check for squash! commit
- commit=$(git rev-list -n 1 --grep '^squash!' "$range")
- if [ -n "$commit" ]
- then
- echo >&2 "Found squash! commit in $local_ref, not pushing"
- echo >&2 "If you really want to push this, use --no-verify."
- exit 1
- fi
- fi
+ if [ "$local_sha" = $z40 ]; then
+ # Handle delete
+ :
+ else
+ if [ "$remote_sha" = $z40 ]; then
+ # New branch, examine commits not in master
+ range="master...$local_sha"
+ else
+ # Update to existing branch, examine new commits
+ range="$remote_sha..$local_sha"
+ fi
+
+ # Call the pre-commit hook for the common checks, if it is executable
+ if [ -x scripts/git/pre-commit.git-hook ]; then
+ # Only check the files newly modified in this branch
+ CHECK_FILTER="git diff --name-only --diff-filter=ACMR $range"
+ # Use the appropriate owned tor source list to filter the changed
+ # files
+ # This is the layout in 0.3.5
+ # Keep these lists consistent:
+ # - OWNED_TOR_C_FILES in Makefile.am
+ # - CHECK_FILES in pre-commit.git-hook and pre-push.git-hook
+ # - try_parse in check_cocci_parse.sh
+ CHECK_FILES="$($CHECK_FILTER \
+ src/lib/*/*.[ch] \
+ src/core/*/*.[ch] \
+ src/feature/*/*.[ch] \
+ src/app/*/*.[ch] \
+ src/test/*.[ch] \
+ src/test/*/*.[ch] \
+ src/tools/*.[ch] \
+ )"
+
+ # We want word splitting here, because file names are space
+ # separated
+ # shellcheck disable=SC2086
+ if ! scripts/git/pre-commit.git-hook $CHECK_FILES ; then
+ exit 1
+ fi
+ fi
+
+ if [[ "$remote_name" != "$upstream_name" ]]; then
+ echo "Not pushing to upstream - refraining from further checks"
+ continue
+ fi
+
+ if (ref_is_upstream_branch "$local_ref" == 0 ||
+ ref_is_upstream_branch "$remote_ref" == 0) &&
+ [ "$local_ref" != "$remote_ref" ]; then
+ if [ "$remote" == "origin" ]; then
+ echo >&2 "Not pushing: $local_ref to $remote_ref"
+ echo >&2 "If you really want to push this, use --no-verify."
+ exit 1
+ else
+ continue
+ fi
+ fi
+
+ # Check for fixup! commit
+ commit=$(git rev-list -n 1 --grep '^fixup!' "$range")
+ if [ -n "$commit" ]; then
+ echo >&2 "Found fixup! commit in $local_ref, not pushing"
+ echo >&2 "If you really want to push this, use --no-verify."
+ exit 1
+ fi
+
+ # Check for squash! commit
+ commit=$(git rev-list -n 1 --grep '^squash!' "$range")
+ if [ -n "$commit" ]; then
+ echo >&2 "Found squash! commit in $local_ref, not pushing"
+ echo >&2 "If you really want to push this, use --no-verify."
+ exit 1
+ fi
+ fi
done
exit 0
diff --git a/scripts/maint/add_c_file.py b/scripts/maint/add_c_file.py
index adf7ce79bb..e1e224d8d5 100755
--- a/scripts/maint/add_c_file.py
+++ b/scripts/maint/add_c_file.py
@@ -4,53 +4,89 @@
Add a C file with matching header to the Tor codebase. Creates
both files from templates, and adds them to the right include.am file.
+ This script takes paths relative to the top-level tor directory. It
+ expects to be run from that directory.
+
+ This script creates files, and inserts them into include.am, also
+ relative to the top-level tor directory.
+
+ But the template content in those files is relative to tor's src
+ directory. (This script strips "src" from the paths used to create
+ templated comments and macros.)
+
+ This script expects posix paths, so it should be run with a python
+ where os.path is posixpath. (Rather than ntpath.) This probably means
+ Linux, macOS, or BSD, although it might work on Windows if your python
+ was compiled with mingw, MSYS, or cygwin.
+
Example usage:
% add_c_file.py ./src/feature/dirauth/ocelot.c
"""
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import os
import re
import time
-def topdir_file(name):
- """Strip opening "src" from a filename"""
- if name.startswith("src/"):
- name = name[4:]
- return name
-
-def guard_macro(name):
- """Return the guard macro that should be used for the header file 'name'.
+def tordir_file(fname):
+ """Make fname relative to the current directory, which should be the
+ top-level tor directory. Also performs basic path simplifications."""
+ return os.path.normpath(os.path.relpath(fname))
+
+def srcdir_file(tor_fname):
+ """Make tor_fname relative to tor's "src" directory.
+ Also performs basic path simplifications.
+ (This function takes paths relative to the top-level tor directory,
+ but outputs a path that is relative to tor's src directory.)"""
+ return os.path.normpath(os.path.relpath(tor_fname, 'src'))
+
+def guard_macro(src_fname):
+ """Return the guard macro that should be used for the header file
+ 'src_fname'. This function takes paths relative to tor's src directory.
"""
- td = topdir_file(name).replace(".", "_").replace("/", "_").upper()
+ td = src_fname.replace(".", "_").replace("/", "_").upper()
return "TOR_{}".format(td)
-def makeext(name, new_extension):
- """Replace the extension for the file called 'name' with 'new_extension'.
+def makeext(fname, new_extension):
+ """Replace the extension for the file called 'fname' with 'new_extension'.
+ This function takes and returns paths relative to either the top-level
+ tor directory, or tor's src directory, and returns the same kind
+ of path.
"""
- base = os.path.splitext(name)[0]
+ base = os.path.splitext(fname)[0]
return base + "." + new_extension
-def instantiate_template(template, output_fname):
+def instantiate_template(template, tor_fname):
"""
Fill in a template with string using the fields that should be used
- for 'output_fname'.
+ for 'tor_fname'.
+
+ This function takes paths relative to the top-level tor directory,
+ but the paths in the completed template are relative to tor's src
+ directory. (Except for one of the fields, which is just a basename).
"""
+ src_fname = srcdir_file(tor_fname)
names = {
# The relative location of the header file.
- 'header_path' : makeext(topdir_file(output_fname), "h"),
+ 'header_path' : makeext(src_fname, "h"),
# The relative location of the C file file.
- 'c_file_path' : makeext(topdir_file(output_fname), "c"),
+ 'c_file_path' : makeext(src_fname, "c"),
# The truncated name of the file.
- 'short_name' : os.path.basename(output_fname),
+ 'short_name' : os.path.basename(src_fname),
# The current year, for the copyright notice
'this_year' : time.localtime().tm_year,
# An appropriate guard macro, for the header.
- 'guard_macro' : guard_macro(output_fname),
+ 'guard_macro' : guard_macro(src_fname),
}
return template.format(**names)
+# This template operates on paths relative to tor's src directory
HEADER_TEMPLATE = """\
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
@@ -69,6 +105,7 @@ HEADER_TEMPLATE = """\
#endif /* !defined({guard_macro}) */
"""
+# This template operates on paths relative to the tor's src directory
C_FILE_TEMPLATE = """\
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
@@ -90,16 +127,22 @@ class AutomakeChunk:
Represents part of an automake file. If it is decorated with
an ADD_C_FILE comment, it has a "kind" based on what to add to it.
Otherwise, it only has a bunch of lines in it.
+
+ This class operates on paths relative to the top-level tor directory.
"""
pat = re.compile(r'# ADD_C_FILE: INSERT (\S*) HERE', re.I)
def __init__(self):
self.lines = []
self.kind = ""
+ self.hasBlank = False # true if we end with a blank line.
def addLine(self, line):
"""
Insert a line into this chunk while parsing the automake file.
+
+ Return True if we have just read the last line in the chunk, and
+ False otherwise.
"""
m = self.pat.match(line)
if m:
@@ -107,23 +150,28 @@ class AutomakeChunk:
raise ValueError("control line not preceded by a blank line")
self.kind = m.group(1)
- self.lines.append(line)
if line.strip() == "":
+ self.hasBlank = True
return True
+ self.lines.append(line)
+
return False
- def insertMember(self, member):
+ def insertMember(self, new_tor_fname):
"""
- Add a new member to this chunk. Try to insert it in alphabetical
- order with matching indentation, but don't freak out too much if the
- source isn't consistent.
+ Add a new file name new_tor_fname to this chunk. Try to insert it in
+ alphabetical order with matching indentation, but don't freak out too
+ much if the source isn't consistent.
Assumes that this chunk is of the form:
FOOBAR = \
X \
Y \
Z
+
+ This function operates on paths relative to the top-level tor
+ directory.
"""
prespace = "\t"
postspace = "\t\t"
@@ -131,20 +179,21 @@ class AutomakeChunk:
m = re.match(r'(\s+)(\S+)(\s+)\\', line)
if not m:
continue
- prespace, fname, postspace = m.groups()
- if fname > member:
- self.insert_before(lineno, member, prespace, postspace)
+ prespace, cur_tor_fname, postspace = m.groups()
+ if cur_tor_fname > new_tor_fname:
+ self.insert_before(lineno, new_tor_fname, prespace, postspace)
return
- self.insert_at_end(member, prespace, postspace)
+ self.insert_at_end(new_tor_fname, prespace, postspace)
- def insert_before(self, lineno, member, prespace, postspace):
+ def insert_before(self, lineno, new_tor_fname, prespace, postspace):
self.lines.insert(lineno,
- "{}{}{}\\\n".format(prespace, member, postspace))
+ "{}{}{}\\\n".format(prespace, new_tor_fname,
+ postspace))
- def insert_at_end(self, member, prespace, postspace):
- lastline = self.lines[-1]
- self.lines[-1] += '{}\\\n'.format(postspace)
- self.lines.append("{}{}\n".format(prespace, member))
+ def insert_at_end(self, new_tor_fname, prespace, postspace):
+ lastline = self.lines[-1].strip()
+ self.lines[-1] = '{}{}{}\\\n'.format(prespace, lastline, postspace)
+ self.lines.append("{}{}\n".format(prespace, new_tor_fname))
def dump(self, f):
"""Write all the lines in this chunk to the file 'f'."""
@@ -153,9 +202,14 @@ class AutomakeChunk:
if not line.endswith("\n"):
f.write("\n")
+ if self.hasBlank:
+ f.write("\n")
+
class ParsedAutomake:
"""A sort-of-parsed automake file, with identified chunks into which
headers and c files can be inserted.
+
+ This class operates on paths relative to the top-level tor directory.
"""
def __init__(self):
self.chunks = []
@@ -166,12 +220,15 @@ class ParsedAutomake:
self.chunks.append(chunk)
self.by_type[chunk.kind.lower()] = chunk
- def add_file(self, fname, kind):
- """Insert a file of kind 'kind' to the appropriate section of this
- file. Return True if we added it.
+ def add_file(self, tor_fname, kind):
+ """Insert a file tor_fname of kind 'kind' to the appropriate
+ section of this file. Return True if we added it.
+
+ This function operates on paths relative to the top-level tor
+ directory.
"""
if kind.lower() in self.by_type:
- self.by_type[kind.lower()].insertMember(fname)
+ self.by_type[kind.lower()].insertMember(tor_fname)
return True
else:
return False
@@ -181,52 +238,77 @@ class ParsedAutomake:
for chunk in self.chunks:
chunk.dump(f)
-def get_include_am_location(fname):
- """Find the right include.am file for introducing a new file. Return None
- if we can't guess one.
+def get_include_am_location(tor_fname):
+ """Find the right include.am file for introducing a new file
+ tor_fname. Return None if we can't guess one.
Note that this function is imperfect because our include.am layout is
not (yet) consistent.
+
+ This function operates on paths relative to the top-level tor directory.
"""
- td = topdir_file(fname)
- m = re.match(r'^lib/([a-z0-9_]*)/', td)
+ # Strip src for pattern matching, but add it back when returning the path
+ src_fname = srcdir_file(tor_fname)
+ m = re.match(r'^(lib|core|feature|app)/([a-z0-9_]*)/', src_fname)
if m:
- return "src/lib/{}/include.am".format(m.group(1))
-
- if re.match(r'^(core|feature|app)/', td):
- return "src/core/include.am"
+ return "src/{}/{}/include.am".format(m.group(1),m.group(2))
- if re.match(r'^test/', td):
+ if re.match(r'^test/', src_fname):
return "src/test/include.am"
return None
-def run(fn):
- """
- Create a new C file and H file corresponding to the filename "fn", and
- add them to include.am.
+def run(fname):
"""
+ Create a new C file and H file corresponding to the filename "fname",
+ and add them to the corresponding include.am.
- cf = makeext(fn, "c")
- hf = makeext(fn, "h")
+ This function operates on paths relative to the top-level tor directory.
+ """
- if os.path.exists(cf):
- print("{} already exists".format(cf))
+ # Make sure we're in the top-level tor directory,
+ # which contains the src directory
+ if not os.path.isdir("src"):
+ raise RuntimeError("Could not find './src/'. "
+ "Run this script from the top-level tor source "
+ "directory.")
+
+ # And it looks like a tor/src directory
+ if not os.path.isfile("src/include.am"):
+ raise RuntimeError("Could not find './src/include.am'. "
+ "Run this script from the top-level tor source "
+ "directory.")
+
+ # Make the file name relative to the top-level tor directory
+ tor_fname = tordir_file(fname)
+ # And check that we're adding files to the "src" directory,
+ # with canonical paths
+ if tor_fname[:4] != "src/":
+ raise ValueError("Requested file path '{}' canonicalized to '{}', "
+ "but the canonical path did not start with 'src/'. "
+ "Please add files to the src directory."
+ .format(fname, tor_fname))
+
+ c_tor_fname = makeext(tor_fname, "c")
+ h_tor_fname = makeext(tor_fname, "h")
+
+ if os.path.exists(c_tor_fname):
+ print("{} already exists".format(c_tor_fname))
return 1
- if os.path.exists(hf):
- print("{} already exists".format(hf))
+ if os.path.exists(h_tor_fname):
+ print("{} already exists".format(h_tor_fname))
return 1
- with open(cf, 'w') as f:
- f.write(instantiate_template(C_FILE_TEMPLATE, cf))
+ with open(c_tor_fname, 'w') as f:
+ f.write(instantiate_template(C_FILE_TEMPLATE, c_tor_fname))
- with open(hf, 'w') as f:
- f.write(instantiate_template(HEADER_TEMPLATE, hf))
+ with open(h_tor_fname, 'w') as f:
+ f.write(instantiate_template(HEADER_TEMPLATE, h_tor_fname))
- iam = get_include_am_location(cf)
+ iam = get_include_am_location(c_tor_fname)
if iam is None or not os.path.exists(iam):
print("Made files successfully but couldn't identify include.am for {}"
- .format(cf))
+ .format(c_tor_fname))
return 1
amfile = ParsedAutomake()
@@ -238,8 +320,8 @@ def run(fn):
cur_chunk = AutomakeChunk()
amfile.addChunk(cur_chunk)
- amfile.add_file(cf, "sources")
- amfile.add_file(hf, "headers")
+ amfile.add_file(c_tor_fname, "sources")
+ amfile.add_file(h_tor_fname, "headers")
with open(iam+".tmp", 'w') as f:
amfile.dump(f)
diff --git a/scripts/maint/annotate_ifdef_directives.py b/scripts/maint/annotate_ifdef_directives.py
index 102128bfa0..cd70b55c8c 100755
--- a/scripts/maint/annotate_ifdef_directives.py
+++ b/scripts/maint/annotate_ifdef_directives.py
@@ -57,6 +57,11 @@ Note that only #else and #endif lines are annotated. Existing comments
on those lines are removed.
"""
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import re
# Any block with fewer than this many lines does not need annotations.
diff --git a/scripts/maint/checkIncludes.py b/scripts/maint/checkIncludes.py
index 926b201b35..2ca46347f0 100755
--- a/scripts/maint/checkIncludes.py
+++ b/scripts/maint/checkIncludes.py
@@ -5,6 +5,11 @@
# functionality. This is a stub file that exists so that older git
# hooks will know where to look.
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import sys, os
dirname = os.path.split(sys.argv[0])[0]
diff --git a/scripts/maint/checkSpace.pl b/scripts/maint/checkSpace.pl
index 9c9b68ff9d..f4e6f733c8 100755
--- a/scripts/maint/checkSpace.pl
+++ b/scripts/maint/checkSpace.pl
@@ -4,9 +4,16 @@ use strict;
use warnings;
my $found = 0;
+my $COLON_POS = 10;
+
sub msg {
$found = 1;
- print "$_[0]";
+ my $v = shift;
+ $v =~ /^\s*([^:]+):(.*)$/;
+ chomp(my $errtype = $1);
+ my $rest = $2;
+ my $padding = ' ' x ($COLON_POS - length $errtype);
+ print "$padding$errtype:$rest\n";
}
my $C = 0;
@@ -29,7 +36,7 @@ for my $fn (@ARGV) {
my $basename = $fn;
$basename =~ s#.*/##;
if ($basenames{$basename}) {
- msg "Duplicate fnames: $fn and $basenames{$basename}.\n";
+ msg "dup fname:$fn (same as $basenames{$basename}).\n";
} else {
$basenames{$basename} = $fn;
}
@@ -42,12 +49,12 @@ for my $fn (@ARGV) {
# (We insist on lines that end with a single LF character, not
# CR LF.)
if (/\r/) {
- msg " CR:$fn:$.\n";
+ msg "CR:$fn:$.\n";
}
## Warn about tabs.
# (We only use spaces)
if (/\t/) {
- msg " TAB:$fn:$.\n";
+ msg "TAB:$fn:$.\n";
}
## Warn about labels that don't have a space in front of them
# (We indent every label at least one space)
@@ -63,12 +70,12 @@ for my $fn (@ARGV) {
## Warn about control keywords without following space.
# (We put a space after every 'if', 'while', 'for', 'switch', etc)
if ($C && /\s(?:if|while|for|switch)\(/) {
- msg " KW(:$fn:$.\n";
+ msg "KW(:$fn:$.\n";
}
## Warn about #else #if instead of #elif.
# (We only allow #elif)
if (($lastline =~ /^\# *else/) and ($_ =~ /^\# *if/)) {
- msg " #else#if:$fn:$.\n";
+ msg "#else#if:$fn:$.\n";
}
## Warn about some K&R violations
# (We use K&R-style C, where open braces go on the same line as
@@ -83,19 +90,19 @@ for my $fn (@ARGV) {
msg "non-K&R {:$fn:$.\n";
}
if (/^\s*else/ and $lastline =~ /\}$/) {
- msg " }\\nelse:$fn:$.\n";
+ msg "}\\nelse:$fn:$.\n";
}
$lastline = $_;
## Warn about unnecessary empty lines.
# (Don't put an empty line before a line that contains nothing
# but a closing brace.)
if ($lastnil && /^\s*}\n/) {
- msg " UnnecNL:$fn:$.\n";
+ msg "UnnecNL:$fn:$.\n";
}
## Warn about multiple empty lines.
# (At most one blank line in a row.)
if ($lastnil && /^$/) {
- msg " DoubleNL:$fn:$.\n";
+ msg "DoubleNL:$fn:$.\n";
} elsif (/^$/) {
$lastnil = 1;
} else {
@@ -105,7 +112,7 @@ for my $fn (@ARGV) {
## accept double-line lines.
# (Don't make lines wider than 80 characters, including newline.)
if (/^.{80}/) {
- msg " Wide:$fn:$.\n";
+ msg "Wide:$fn:$.\n";
}
### Juju to skip over comments and strings, since the tests
### we're about to do are okay there.
@@ -144,29 +151,28 @@ for my $fn (@ARGV) {
}
s!"(?:[^\"]+|\\.)*"!"X"!g;
next if /^\#/;
- ## Warn about C++-style comments.
- # (Use C style comments only.)
+ ## Skip C++-style comments.
if (m!//!) {
- # msg " //:$fn:$.\n";
+ # msg "//:$fn:$.\n";
s!//.*!!;
}
## Warn about unquoted braces preceded by non-space.
# (No character except a space should come before a {)
if (/([^\s'])\{/) {
- msg " $1\{:$fn:$.\n";
+ msg "$1\{:$fn:$.\n";
}
## Warn about double semi-colons at the end of a line.
if (/;;$/) {
- msg " double semi-colons at the end of $. in $fn\n"
+ msg ";;:$fn:$.\n"
}
## Warn about multiple internal spaces.
#if (/[^\s,:]\s{2,}[^\s\\=]/) {
- # msg " X X:$fn:$.\n";
+ # msg "X X:$fn:$.\n";
#}
## Warn about { with stuff after.
#s/\s+$//;
#if (/\{[^\}\\]+$/) {
- # msg " {X:$fn:$.\n";
+ # msg "{X:$fn:$.\n";
#}
## Warn about function calls with space before parens.
# (Don't put a space between the name of a function and its
@@ -178,7 +184,7 @@ for my $fn (@ARGV) {
$1 ne "void" and $1 ne "__attribute__" and $1 ne "op" and
$1 ne "size_t" and $1 ne "double" and $1 ne "uint64_t" and
$1 ne "workqueue_reply_t" and $1 ne "bool") {
- msg " fn ():$fn:$.\n";
+ msg "fn ():$fn:$.\n";
}
}
## Warn about functions not declared at start of line.
@@ -207,28 +213,28 @@ for my $fn (@ARGV) {
## Check for forbidden functions except when they are
# explicitly permitted
if (/\bassert\(/ && not /assert OK/) {
- msg "assert :$fn:$. (use tor_assert)\n";
+ msg "assert:$fn:$. (use tor_assert)\n";
}
if (/\bmemcmp\(/ && not /memcmp OK/) {
- msg "memcmp :$fn:$. (use {tor,fast}_mem{eq,neq,cmp}\n";
+ msg "memcmp:$fn:$. (use {tor,fast}_mem{eq,neq,cmp}\n";
}
# always forbidden.
if (not /\ OVERRIDE\ /) {
if (/\bstrcat\(/ or /\bstrcpy\(/ or /\bsprintf\(/) {
- msg "$& :$fn:$.\n";
+ msg "$&:$fn:$.\n";
}
if (/\bmalloc\(/ or /\bfree\(/ or /\brealloc\(/ or
/\bstrdup\(/ or /\bstrndup\(/ or /\bcalloc\(/) {
- msg "$& :$fn:$. (use tor_malloc, tor_free, etc)\n";
+ msg "$&:$fn:$. (use tor_malloc, tor_free, etc)\n";
}
}
}
}
if ($isheader && $C) {
if ($seenguard < 2) {
- msg "$fn:No #ifndef/#define header guard pair found.\n";
+ msg "noguard:$fn (No #ifndef/#define header guard pair found)\n";
} elsif ($guardnames{$guardname}) {
- msg "$fn:Guard macro $guardname also used in $guardnames{$guardname}\n";
+ msg "dupguard:$fn (Guard macro $guardname also used in $guardnames{$guardname})\n";
} else {
$guardnames{$guardname} = $fn;
}
diff --git a/scripts/maint/checkSpaceTest.sh b/scripts/maint/checkSpaceTest.sh
new file mode 100755
index 0000000000..e1d207a1a8
--- /dev/null
+++ b/scripts/maint/checkSpaceTest.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+# Copyright 2019, The Tor Project, Inc.
+# See LICENSE for licensing information
+
+# Integration test for checkSpace.pl, which we want to rewrite.
+
+umask 077
+set -e
+
+# Skip this test if we're running on Windows; we expect line-ending
+# issues in that case.
+case "$(uname -s)" in
+ CYGWIN*) WINDOWS=1;;
+ MINGW*) WINDOWS=1;;
+ MSYS*) WINDOWS=1;;
+ *) WINDOWS=0;;
+esac
+if test "$WINDOWS" = 1; then
+ # This magic value tells automake that the test has been skipped.
+ exit 77
+fi
+
+# make a safe space for temporary files
+DATA_DIR=$(mktemp -d -t tor_checkspace_tests.XXXXXX)
+trap 'rm -rf "$DATA_DIR"' 0
+
+RECEIVED_FNAME="${DATA_DIR}/got.txt"
+
+cd "$(dirname "$0")/checkspace_tests"
+
+# we expect this to give an error code.
+../checkSpace.pl -C ./*.[ch] ./*/*.[ch] > "${RECEIVED_FNAME}" && exit 1
+
+diff -u expected.txt "${RECEIVED_FNAME}" || exit 1
+
+echo "OK"
diff --git a/scripts/maint/checkspace_tests/dubious.c b/scripts/maint/checkspace_tests/dubious.c
new file mode 100644
index 0000000000..59c5f8e4fe
--- /dev/null
+++ b/scripts/maint/checkspace_tests/dubious.c
@@ -0,0 +1,83 @@
+
+// The { coming up should be on its own line.
+int
+foo(void) {
+ // There should be a space before (1)
+ if(1) x += 1;
+
+ // The following empty line is unnecessary.
+
+}
+
+
+// There should be a newline between void and bar.
+void bar(void)
+{
+ // too wide:
+ testing("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
+}
+
+long
+bad_spacing()
+{
+ // here comes a tab
+ return 2;
+ // here comes a label without space:
+foo:
+ ;
+}
+
+// Here comes a CR:
+
+// Trailing space:
+
+int
+non_k_and_r(void)
+{
+ // non-k&r
+ if (foo)
+ {
+ // double-semi
+ return 1;;
+ }
+ else
+ {
+ return 2;
+ }
+}
+
+// #else #if causes a warning.
+#if 1
+#else
+#if 2
+#else
+#endif
+#endif
+
+// always space before a brace.
+foo{
+}
+
+void
+unexpected_space(void)
+{
+ // This space gives a warning.
+ foobar (77);
+}
+
+void
+bad_function_calls(long)
+{
+ // These are forbidden:
+ assert(1);
+ memcmp("a","b",1);
+ strcat(foo,x);
+ strcpy(foo,y);
+ sprintf(foo,"x");
+ malloc(7);
+ free(p);
+ realloc(p);
+ strdup(s);
+ strndup(s,10);
+ calloc(a,b);
+}
diff --git a/scripts/maint/checkspace_tests/dubious.h b/scripts/maint/checkspace_tests/dubious.h
new file mode 100644
index 0000000000..744ec33955
--- /dev/null
+++ b/scripts/maint/checkspace_tests/dubious.h
@@ -0,0 +1,4 @@
+
+// no guards.
+
+int foo(int);
diff --git a/scripts/maint/checkspace_tests/expected.txt b/scripts/maint/checkspace_tests/expected.txt
new file mode 100644
index 0000000000..935b750ef9
--- /dev/null
+++ b/scripts/maint/checkspace_tests/expected.txt
@@ -0,0 +1,31 @@
+ fn() {:./dubious.c:4
+ KW(:./dubious.c:6
+ UnnecNL:./dubious.c:10
+ DoubleNL:./dubious.c:12
+ tp fn():./dubious.c:15
+ Wide:./dubious.c:17
+ TAB:./dubious.c:24
+ nosplabel:./dubious.c:26
+ CR:./dubious.c:30
+ Space@EOL:./dubious.c:32
+ non-K&R {:./dubious.c:39
+ ;;:./dubious.c:41
+ }\nelse:./dubious.c:43
+ #else#if:./dubious.c:52
+ o{:./dubious.c:58
+ fn() {:./dubious.c:58
+ fn ():./dubious.c:65
+ assert:./dubious.c:72 (use tor_assert)
+ memcmp:./dubious.c:73 (use {tor,fast}_mem{eq,neq,cmp}
+ strcat(:./dubious.c:74
+ strcpy(:./dubious.c:75
+ sprintf(:./dubious.c:76
+ malloc(:./dubious.c:77 (use tor_malloc, tor_free, etc)
+ free(:./dubious.c:78 (use tor_malloc, tor_free, etc)
+ realloc(:./dubious.c:79 (use tor_malloc, tor_free, etc)
+ strdup(:./dubious.c:80 (use tor_malloc, tor_free, etc)
+ strndup(:./dubious.c:81 (use tor_malloc, tor_free, etc)
+ calloc(:./dubious.c:82 (use tor_malloc, tor_free, etc)
+ noguard:./dubious.h (No #ifndef/#define header guard pair found)
+ dupguard:./same_guard.h (Guard macro GUARD_MACRO_H also used in ./good_guard.h)
+ dup fname:./subdir/dubious.c (same as ./dubious.c).
diff --git a/scripts/maint/checkspace_tests/good_guard.h b/scripts/maint/checkspace_tests/good_guard.h
new file mode 100644
index 0000000000..b792912d90
--- /dev/null
+++ b/scripts/maint/checkspace_tests/good_guard.h
@@ -0,0 +1,6 @@
+#ifndef GUARD_MACRO_H
+#define GUARD_MACRO_H
+
+int bar(void);
+
+#endif
diff --git a/scripts/maint/checkspace_tests/same_guard.h b/scripts/maint/checkspace_tests/same_guard.h
new file mode 100644
index 0000000000..b792912d90
--- /dev/null
+++ b/scripts/maint/checkspace_tests/same_guard.h
@@ -0,0 +1,6 @@
+#ifndef GUARD_MACRO_H
+#define GUARD_MACRO_H
+
+int bar(void);
+
+#endif
diff --git a/scripts/maint/checkspace_tests/subdir/dubious.c b/scripts/maint/checkspace_tests/subdir/dubious.c
new file mode 100644
index 0000000000..7f22bf79bf
--- /dev/null
+++ b/scripts/maint/checkspace_tests/subdir/dubious.c
@@ -0,0 +1 @@
+// Nothing wrong with this file, but the name is a duplicate.
diff --git a/scripts/maint/format_changelog.py b/scripts/maint/format_changelog.py
index 08b2155fa3..32085c3602 100755
--- a/scripts/maint/format_changelog.py
+++ b/scripts/maint/format_changelog.py
@@ -9,6 +9,11 @@
# To run it, pipe a section of the changelog (starting with "Changes
# in Tor 0.x.y.z-alpha" through the script.)
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import os
import re
import sys
@@ -190,7 +195,7 @@ def body_parser(line):
elif re.match(r'^\s+\S', line):
return TP_HEADTEXT
else:
- print "Weird line %r"%line
+ print("Weird line %r"%line, file=sys.stderr)
def clean_head(head):
return head
@@ -198,7 +203,7 @@ def clean_head(head):
def head_score(s):
m = re.match(r'^ +o (.*)', s)
if not m:
- print >>sys.stderr, "Can't score %r"%s
+ print("Can't score %r"%s, file=sys.stderr)
return 99999
lw = m.group(1).lower()
if lw.startswith("security") and "feature" not in lw:
@@ -286,12 +291,12 @@ class ChangeLog(object):
self.curgraf.append(line)
else:
- assert "This" is "unreachable"
+ assert "This" is "unreachable" # noqa: F632
def lint_head(self, line, head):
m = re.match(r'^ *o ([^\(]+)((?:\([^\)]+\))?):', head)
if not m:
- print >>sys.stderr, "Weird header format on line %s"%line
+ print("Weird header format on line %s"%line, file=sys.stderr)
def lint_item(self, line, grafs, head_type):
pass
@@ -306,7 +311,7 @@ class ChangeLog(object):
def dumpGraf(self,par,indent1,indent2=-1):
if not self.wrapText:
for line in par:
- print line
+ print(line)
return
if indent2 == -1:
@@ -320,17 +325,17 @@ class ChangeLog(object):
def dumpPreheader(self, graf):
self.dumpGraf(graf, 0)
- print
+ print()
def dumpMainhead(self, head):
- print head
+ print(head)
def dumpHeadGraf(self, graf):
self.dumpGraf(graf, 2)
- print
+ print()
def dumpSectionHeader(self, header):
- print header
+ print(header)
def dumpStartOfSections(self):
pass
@@ -339,10 +344,10 @@ class ChangeLog(object):
pass
def dumpEndOfSection(self):
- print
+ print()
def dumpEndOfChangelog(self):
- print
+ print()
def dumpDrupalBreak(self):
pass
@@ -350,7 +355,7 @@ class ChangeLog(object):
def dumpItem(self, grafs):
self.dumpGraf(grafs[0],4,6)
for par in grafs[1:]:
- print
+ print()
self.dumpGraf(par,6,6)
def collateAndSortSections(self):
@@ -389,7 +394,7 @@ class ChangeLog(object):
self.dumpStartOfSections()
for _,head,items in self.sections:
if not head.endswith(':'):
- print >>sys.stderr, "adding : to %r"%head
+ print("adding : to %r"%head, file=sys.stderr)
head = head + ":"
self.dumpSectionHeader(head)
for _,grafs in items:
@@ -445,16 +450,16 @@ class HTMLChangeLog(ChangeLog):
pass
def dumpStartOfSections(self):
- print "<ul>\n"
+ print("<ul>\n")
def dumpEndOfSections(self):
- print "</ul>\n"
+ print("</ul>\n")
def dumpDrupalBreak(self):
- print "\n</ul>\n"
- print "<p>&nbsp;</p>"
- print "\n<!--break-->\n\n"
- print "<ul>"
+ print("\n</ul>\n")
+ print("<p>&nbsp;</p>")
+ print("\n<!--break-->\n\n")
+ print("<ul>")
def dumpItem(self, grafs):
grafs[0][0] = grafs[0][0].replace(" - ", "", 1).lstrip()
@@ -464,7 +469,7 @@ class HTMLChangeLog(ChangeLog):
self.htmlPar(par)
else:
self.htmlText(grafs[0])
- print
+ print()
op = optparse.OptionParser(usage="usage: %prog [options] [filename]")
op.add_option('-W', '--no-wrap', action='store_false',
@@ -560,7 +565,7 @@ if options.firstOnly:
sys.exit(0)
if nextline is not None:
- print nextline
+ print(nextline)
for line in sys.stdin:
sys.stdout.write(line)
diff --git a/scripts/maint/lintChanges.py b/scripts/maint/lintChanges.py
index 82c118f07e..88a865a572 100755
--- a/scripts/maint/lintChanges.py
+++ b/scripts/maint/lintChanges.py
@@ -1,7 +1,10 @@
#!/usr/bin/python
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
from __future__ import print_function
-from __future__ import with_statement
+from __future__ import unicode_literals
+
import sys
import re
import os
diff --git a/scripts/maint/locatemissingdoxygen.py b/scripts/maint/locatemissingdoxygen.py
index 797bf8176f..7733977359 100755
--- a/scripts/maint/locatemissingdoxygen.py
+++ b/scripts/maint/locatemissingdoxygen.py
@@ -7,6 +7,11 @@
to highlight the undocumented stuff.
"""
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import os
import re
import shutil
@@ -29,10 +34,10 @@ def buildWarnings():
def count(fn):
if os.path.abspath(fn) not in warnings:
- print "0\t%s"%fn
+ print("0\t%s"%fn)
else:
n = len(warnings[os.path.abspath(fn)])
- print "%d\t%s"%(n,fn)
+ print("%d\t%s"%(n,fn))
def getIndentation(line):
s = line.lstrip()
@@ -62,7 +67,7 @@ def annotate(filename):
if __name__ == '__main__':
if len(sys.argv) == 1:
- print "Usage: locatemissingdoxygen.py [-A] filename... <doxygen_log"
+ print("Usage: locatemissingdoxygen.py [-A] filename... <doxygen_log")
sys.exit(1)
buildWarnings()
if sys.argv[1] == '-A':
diff --git a/scripts/maint/practracker/exceptions.txt b/scripts/maint/practracker/exceptions.txt
index 7b15b37f8c..d89b80c1b3 100644
--- a/scripts/maint/practracker/exceptions.txt
+++ b/scripts/maint/practracker/exceptions.txt
@@ -6,8 +6,12 @@
#
# There are three kinds of problems that we recognize right now:
# function-size -- a function of more than 100 lines.
-# file-size -- a file of more than 3000 lines.
-# include-count -- a file with more than 50 #includes.
+# file-size -- a .c file of more than 3000 lines, or a .h
+# file with more than 500 lines.
+# include-count -- a .c file with more than 50 #includes,
+# or a .h file with more than 15 #includes.
+# dependency-violation -- a file includes a header that it should
+# not, according to an advisory .may_include file.
#
# Each line below represents a single exception that practracker should
# _ignore_. Each line has four parts:
@@ -29,34 +33,35 @@
#
# Remember: It is better to fix the problem than to add a new exception!
-problem file-size /src/app/config/config.c 8518
-problem include-count /src/app/config/config.c 89
-problem function-size /src/app/config/config.c:options_act_reversible() 296
-problem function-size /src/app/config/config.c:options_act() 589
+problem file-size /src/app/config/config.c 7400
+problem include-count /src/app/config/config.c 80
+problem function-size /src/app/config/config.c:options_act_reversible() 298
+problem function-size /src/app/config/config.c:options_act() 381
problem function-size /src/app/config/config.c:resolve_my_address() 190
-problem function-size /src/app/config/config.c:options_validate() 1209
-problem function-size /src/app/config/config.c:options_init_from_torrc() 207
-problem function-size /src/app/config/config.c:options_init_from_string() 171
-problem function-size /src/app/config/config.c:options_init_logs() 145
+problem function-size /src/app/config/config.c:options_validate_cb() 780
+problem function-size /src/app/config/config.c:options_init_from_torrc() 188
+problem function-size /src/app/config/config.c:options_init_from_string() 103
+problem function-size /src/app/config/config.c:options_init_logs() 125
problem function-size /src/app/config/config.c:parse_bridge_line() 104
-problem function-size /src/app/config/config.c:parse_transport_line() 189
+problem function-size /src/app/config/config.c:pt_parse_transport_line() 189
problem function-size /src/app/config/config.c:parse_dir_authority_line() 150
problem function-size /src/app/config/config.c:parse_dir_fallback_line() 101
-problem function-size /src/app/config/config.c:parse_port_config() 446
-problem function-size /src/app/config/config.c:parse_ports() 168
-problem file-size /src/app/config/or_options_st.h 1112
-problem include-count /src/app/main/main.c 68
+problem function-size /src/app/config/config.c:port_parse_config() 450
+problem function-size /src/app/config/config.c:parse_ports() 132
+problem file-size /src/app/config/or_options_st.h 1115
+problem include-count /src/app/main/main.c 69
problem function-size /src/app/main/main.c:dumpstats() 102
-problem function-size /src/app/main/main.c:tor_init() 137
+problem function-size /src/app/main/main.c:tor_init() 101
problem function-size /src/app/main/main.c:sandbox_init_filter() 291
problem function-size /src/app/main/main.c:run_tor_main_loop() 105
problem function-size /src/app/main/ntmain.c:nt_service_install() 126
problem dependency-violation /src/core/crypto/hs_ntor.c 1
+problem dependency-violation /src/core/crypto/hs_ntor.h 1
problem dependency-violation /src/core/crypto/onion_crypto.c 5
problem dependency-violation /src/core/crypto/onion_fast.c 1
problem dependency-violation /src/core/crypto/onion_tap.c 3
problem dependency-violation /src/core/crypto/relay_crypto.c 9
-problem file-size /src/core/mainloop/connection.c 5569
+problem file-size /src/core/mainloop/connection.c 5577
problem include-count /src/core/mainloop/connection.c 62
problem function-size /src/core/mainloop/connection.c:connection_free_minimal() 185
problem function-size /src/core/mainloop/connection.c:connection_listener_new() 324
@@ -68,20 +73,22 @@ problem function-size /src/core/mainloop/connection.c:connection_handle_read_imp
problem function-size /src/core/mainloop/connection.c:connection_buf_read_from_socket() 180
problem function-size /src/core/mainloop/connection.c:connection_handle_write_impl() 241
problem function-size /src/core/mainloop/connection.c:assert_connection_ok() 143
-problem dependency-violation /src/core/mainloop/connection.c 44
+problem dependency-violation /src/core/mainloop/connection.c 47
problem dependency-violation /src/core/mainloop/cpuworker.c 12
-problem include-count /src/core/mainloop/mainloop.c 63
+problem include-count /src/core/mainloop/mainloop.c 64
problem function-size /src/core/mainloop/mainloop.c:conn_close_if_marked() 108
problem function-size /src/core/mainloop/mainloop.c:run_connection_housekeeping() 123
-problem dependency-violation /src/core/mainloop/mainloop.c 49
+problem dependency-violation /src/core/mainloop/mainloop.c 50
problem dependency-violation /src/core/mainloop/mainloop_pubsub.c 1
problem dependency-violation /src/core/mainloop/mainloop_sys.c 1
problem dependency-violation /src/core/mainloop/netstatus.c 4
problem dependency-violation /src/core/mainloop/periodic.c 2
problem dependency-violation /src/core/or/address_set.c 1
+problem dependency-violation /src/core/or/cell_queue_st.h 1
problem file-size /src/core/or/channel.c 3487
problem dependency-violation /src/core/or/channel.c 9
-problem file-size /src/core/or/channel.h 780
+problem file-size /src/core/or/channel.h 781
+problem dependency-violation /src/core/or/channel.h 1
problem dependency-violation /src/core/or/channelpadding.c 6
problem function-size /src/core/or/channeltls.c:channel_tls_handle_var_cell() 160
problem function-size /src/core/or/channeltls.c:channel_tls_process_versions_cell() 170
@@ -96,15 +103,16 @@ problem function-size /src/core/or/circuitbuild.c:choose_good_exit_server_genera
problem dependency-violation /src/core/or/circuitbuild.c 25
problem include-count /src/core/or/circuitlist.c 55
problem function-size /src/core/or/circuitlist.c:HT_PROTOTYPE() 109
-problem function-size /src/core/or/circuitlist.c:circuit_free_() 143
+problem function-size /src/core/or/circuitlist.c:circuit_free_() 146
problem function-size /src/core/or/circuitlist.c:circuit_find_to_cannibalize() 101
problem function-size /src/core/or/circuitlist.c:circuit_about_to_free() 120
problem function-size /src/core/or/circuitlist.c:circuits_handle_oom() 117
problem dependency-violation /src/core/or/circuitlist.c 19
+problem dependency-violation /src/core/or/circuitlist.h 1
problem function-size /src/core/or/circuitmux.c:circuitmux_set_policy() 109
problem function-size /src/core/or/circuitmux.c:circuitmux_attach_circuit() 113
problem dependency-violation /src/core/or/circuitmux_ewma.c 2
-problem file-size /src/core/or/circuitpadding.c 3096
+problem file-size /src/core/or/circuitpadding.c 3098
problem function-size /src/core/or/circuitpadding.c:circpad_machine_schedule_padding() 113
problem dependency-violation /src/core/or/circuitpadding.c 6
problem file-size /src/core/or/circuitpadding.h 813
@@ -119,33 +127,35 @@ problem function-size /src/core/or/circuituse.c:circuit_expire_building() 394
problem function-size /src/core/or/circuituse.c:circuit_log_ancient_one_hop_circuits() 126
problem function-size /src/core/or/circuituse.c:circuit_build_failed() 149
problem function-size /src/core/or/circuituse.c:circuit_launch_by_extend_info() 108
-problem function-size /src/core/or/circuituse.c:circuit_get_open_circ_or_launch() 352
+problem function-size /src/core/or/circuituse.c:circuit_get_open_circ_or_launch() 351
problem function-size /src/core/or/circuituse.c:connection_ap_handshake_attach_circuit() 244
-problem dependency-violation /src/core/or/circuituse.c 23
+problem dependency-violation /src/core/or/circuituse.c 24
problem function-size /src/core/or/command.c:command_process_create_cell() 156
problem function-size /src/core/or/command.c:command_process_relay_cell() 132
problem dependency-violation /src/core/or/command.c 8
-problem file-size /src/core/or/connection_edge.c 4596
+problem file-size /src/core/or/connection_edge.c 4640
problem include-count /src/core/or/connection_edge.c 65
problem function-size /src/core/or/connection_edge.c:connection_ap_expire_beginning() 117
-problem function-size /src/core/or/connection_edge.c:connection_ap_handshake_rewrite() 191
+problem function-size /src/core/or/connection_edge.c:connection_ap_handshake_rewrite() 193
problem function-size /src/core/or/connection_edge.c:connection_ap_handle_onion() 185
-problem function-size /src/core/or/connection_edge.c:connection_ap_handshake_rewrite_and_attach() 421
+problem function-size /src/core/or/connection_edge.c:connection_ap_handshake_rewrite_and_attach() 420
problem function-size /src/core/or/connection_edge.c:connection_ap_handshake_send_begin() 111
problem function-size /src/core/or/connection_edge.c:connection_ap_handshake_socks_resolved() 101
problem function-size /src/core/or/connection_edge.c:connection_exit_begin_conn() 185
problem function-size /src/core/or/connection_edge.c:connection_exit_connect() 102
problem dependency-violation /src/core/or/connection_edge.c 27
+problem dependency-violation /src/core/or/connection_edge.h 1
problem file-size /src/core/or/connection_or.c 3122
problem include-count /src/core/or/connection_or.c 51
problem function-size /src/core/or/connection_or.c:connection_or_group_set_badness_() 105
problem function-size /src/core/or/connection_or.c:connection_or_client_learned_peer_id() 142
problem function-size /src/core/or/connection_or.c:connection_or_compute_authenticate_cell_body() 231
problem dependency-violation /src/core/or/connection_or.c 20
-problem dependency-violation /src/core/or/dos.c 5
+problem dependency-violation /src/core/or/dos.c 6
problem dependency-violation /src/core/or/onion.c 2
problem file-size /src/core/or/or.h 1107
problem include-count /src/core/or/or.h 49
+problem dependency-violation /src/core/or/or.h 1
problem dependency-violation /src/core/or/or_periodic.c 1
problem file-size /src/core/or/policies.c 3249
problem function-size /src/core/or/policies.c:policy_summarize() 107
@@ -179,7 +189,7 @@ problem function-size /src/feature/client/addressmap.c:addressmap_rewrite() 109
problem function-size /src/feature/client/bridges.c:rewrite_node_address_for_bridge() 126
problem function-size /src/feature/client/circpathbias.c:pathbias_measure_close_rate() 108
problem function-size /src/feature/client/dnsserv.c:evdns_server_callback() 153
-problem file-size /src/feature/client/entrynodes.c 3824
+problem file-size /src/feature/client/entrynodes.c 3825
problem function-size /src/feature/client/entrynodes.c:entry_guards_upgrade_waiting_circuits() 155
problem function-size /src/feature/client/entrynodes.c:entry_guard_parse_from_state() 246
problem file-size /src/feature/client/entrynodes.h 639
@@ -190,11 +200,11 @@ problem function-size /src/feature/control/control.c:connection_control_process_
problem function-size /src/feature/control/control_auth.c:handle_control_authenticate() 186
problem function-size /src/feature/control/control_cmd.c:handle_control_extendcircuit() 150
problem function-size /src/feature/control/control_cmd.c:handle_control_add_onion() 256
-problem function-size /src/feature/control/control_cmd.c:add_onion_helper_keyarg() 116
-problem function-size /src/feature/control/control_events.c:control_event_stream_status() 118
+problem function-size /src/feature/control/control_cmd.c:add_onion_helper_keyarg() 118
+problem function-size /src/feature/control/control_events.c:control_event_stream_status() 124
problem include-count /src/feature/control/control_getinfo.c 54
problem function-size /src/feature/control/control_getinfo.c:getinfo_helper_misc() 108
-problem function-size /src/feature/control/control_getinfo.c:getinfo_helper_dir() 302
+problem function-size /src/feature/control/control_getinfo.c:getinfo_helper_dir() 297
problem function-size /src/feature/control/control_getinfo.c:getinfo_helper_events() 234
problem function-size /src/feature/dirauth/bwauth.c:dirserv_read_measured_bandwidths() 121
problem file-size /src/feature/dirauth/dirvote.c 4700
@@ -215,8 +225,8 @@ problem function-size /src/feature/dircache/consdiffmgr.c:consdiffmgr_cleanup()
problem function-size /src/feature/dircache/consdiffmgr.c:consdiffmgr_rescan_flavor_() 111
problem function-size /src/feature/dircache/consdiffmgr.c:consensus_diff_worker_threadfn() 132
problem function-size /src/feature/dircache/dircache.c:handle_get_current_consensus() 165
-problem function-size /src/feature/dircache/dircache.c:directory_handle_command_post() 119
-problem file-size /src/feature/dirclient/dirclient.c 3215
+problem function-size /src/feature/dircache/dircache.c:directory_handle_command_post() 124
+problem file-size /src/feature/dirclient/dirclient.c 3165
problem include-count /src/feature/dirclient/dirclient.c 51
problem function-size /src/feature/dirclient/dirclient.c:directory_get_from_dirserver() 126
problem function-size /src/feature/dirclient/dirclient.c:directory_initiate_request() 201
@@ -246,8 +256,8 @@ problem function-size /src/feature/hs/hs_descriptor.c:desc_encode_v3() 101
problem function-size /src/feature/hs/hs_descriptor.c:decrypt_desc_layer() 111
problem function-size /src/feature/hs/hs_descriptor.c:decode_introduction_point() 122
problem function-size /src/feature/hs/hs_descriptor.c:desc_decode_superencrypted_v3() 107
-problem function-size /src/feature/hs/hs_descriptor.c:desc_decode_encrypted_v3() 107
-problem file-size /src/feature/hs/hs_service.c 4116
+problem function-size /src/feature/hs/hs_descriptor.c:desc_decode_encrypted_v3() 109
+problem file-size /src/feature/hs/hs_service.c 4172
problem function-size /src/feature/keymgt/loadkey.c:ed_key_init_from_file() 326
problem function-size /src/feature/nodelist/authcert.c:trusted_dirs_load_certs_from_string() 123
problem function-size /src/feature/nodelist/authcert.c:authority_certs_fetch_missing() 295
@@ -260,7 +270,7 @@ problem function-size /src/feature/nodelist/node_select.c:router_pick_directory_
problem function-size /src/feature/nodelist/node_select.c:compute_weighted_bandwidths() 203
problem function-size /src/feature/nodelist/node_select.c:router_pick_trusteddirserver_impl() 112
problem function-size /src/feature/nodelist/nodelist.c:compute_frac_paths_available() 190
-problem file-size /src/feature/nodelist/routerlist.c 3241
+problem file-size /src/feature/nodelist/routerlist.c 3239
problem function-size /src/feature/nodelist/routerlist.c:router_rebuild_store() 148
problem function-size /src/feature/nodelist/routerlist.c:router_add_to_routerlist() 168
problem function-size /src/feature/nodelist/routerlist.c:routerlist_remove_old_routers() 121
@@ -269,8 +279,8 @@ problem function-size /src/feature/nodelist/routerlist.c:update_extrainfo_downlo
problem function-size /src/feature/relay/dns.c:dns_resolve_impl() 131
problem function-size /src/feature/relay/dns.c:configure_nameservers() 161
problem function-size /src/feature/relay/dns.c:evdns_callback() 108
-problem file-size /src/feature/relay/router.c 3522
-problem include-count /src/feature/relay/router.c 56
+problem file-size /src/feature/relay/router.c 3520
+problem include-count /src/feature/relay/router.c 57
problem function-size /src/feature/relay/router.c:init_keys() 252
problem function-size /src/feature/relay/router.c:get_my_declared_family() 114
problem function-size /src/feature/relay/router.c:router_build_fresh_unsigned_routerinfo() 136
@@ -279,14 +289,14 @@ problem function-size /src/feature/relay/routerkeys.c:load_ed_keys() 294
problem function-size /src/feature/rend/rendcache.c:rend_cache_store_v2_desc_as_client() 190
problem function-size /src/feature/rend/rendclient.c:rend_client_send_introduction() 219
problem function-size /src/feature/rend/rendcommon.c:rend_encode_v2_descriptors() 221
-problem function-size /src/feature/rend/rendmid.c:rend_mid_establish_intro_legacy() 104
+problem function-size /src/feature/rend/rendmid.c:rend_mid_establish_intro_legacy() 105
problem function-size /src/feature/rend/rendparse.c:rend_parse_v2_service_descriptor() 181
problem function-size /src/feature/rend/rendparse.c:rend_parse_introduction_points() 129
-problem file-size /src/feature/rend/rendservice.c 4511
+problem file-size /src/feature/rend/rendservice.c 4522
problem function-size /src/feature/rend/rendservice.c:rend_service_prune_list_impl_() 107
problem function-size /src/feature/rend/rendservice.c:rend_config_service() 162
problem function-size /src/feature/rend/rendservice.c:rend_service_load_auth_keys() 178
-problem function-size /src/feature/rend/rendservice.c:rend_service_receive_introduction() 330
+problem function-size /src/feature/rend/rendservice.c:rend_service_receive_introduction() 334
problem function-size /src/feature/rend/rendservice.c:rend_service_parse_intro_for_v3() 111
problem function-size /src/feature/rend/rendservice.c:rend_service_decrypt_intro() 112
problem function-size /src/feature/rend/rendservice.c:rend_service_intro_has_opened() 126
@@ -310,7 +320,7 @@ problem function-size /src/lib/net/address.c:tor_addr_compare_masked() 110
problem function-size /src/lib/net/inaddr.c:tor_inet_pton() 107
problem function-size /src/lib/net/socketpair.c:tor_ersatz_socketpair() 102
problem function-size /src/lib/osinfo/uname.c:get_uname() 116
-problem function-size /src/lib/process/process_unix.c:process_unix_exec() 220
+problem function-size /src/lib/process/process_unix.c:process_unix_exec() 213
problem function-size /src/lib/process/process_win32.c:process_win32_exec() 151
problem function-size /src/lib/process/process_win32.c:process_win32_create_pipe() 109
problem function-size /src/lib/process/restrict.c:set_max_file_descriptors() 102
@@ -324,12 +334,3 @@ problem function-size /src/tools/tor-gencert.c:parse_commandline() 111
problem function-size /src/tools/tor-resolve.c:build_socks5_resolve_request() 102
problem function-size /src/tools/tor-resolve.c:do_resolve() 171
problem function-size /src/tools/tor-resolve.c:main() 112
-
-problem dependency-violation /scripts/maint/practracker/testdata/a.c 3
-problem dependency-violation /scripts/maint/practracker/testdata/header.h 3
-problem dependency-violation /src/core/crypto/hs_ntor.h 1
-problem dependency-violation /src/core/or/cell_queue_st.h 1
-problem dependency-violation /src/core/or/channel.h 1
-problem dependency-violation /src/core/or/circuitlist.h 1
-problem dependency-violation /src/core/or/connection_edge.h 1
-problem dependency-violation /src/core/or/or.h 1
diff --git a/scripts/maint/practracker/includes.py b/scripts/maint/practracker/includes.py
index 397439b4ef..fe0f32e253 100755
--- a/scripts/maint/practracker/includes.py
+++ b/scripts/maint/practracker/includes.py
@@ -13,10 +13,16 @@
file in each directory. This file contains empty lines, #-prefixed
comments, filenames (like "lib/foo/bar.h") and file globs (like lib/*/*.h)
for files that are permitted.
-"""
+ The script exits with an error if any non-permitted includes are found.
+ .may_include files that contain "!advisory" are considered advisory.
+ Advisory .may_include files only result in warnings, rather than errors.
+"""
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
from __future__ import print_function
+from __future__ import unicode_literals
import fnmatch
import os
@@ -36,7 +42,11 @@ def warn(msg):
def fname_is_c(fname):
""" Return true iff 'fname' is the name of a file that we should
search for possibly disallowed #include directives. """
- return fname.endswith(".h") or fname.endswith(".c")
+ if fname.endswith(".h") or fname.endswith(".c"):
+ bname = os.path.basename(fname)
+ return not (bname.startswith(".") or bname.startswith("#"))
+ else:
+ return False
INCLUDE_PATTERN = re.compile(r'\s*#\s*include\s+"([^"]*)"')
RULES_FNAME = ".may_include"
@@ -235,7 +245,7 @@ def run_check_includes(topdir, list_unused=False, log_sorted_levels=False,
trouble = True
if trouble:
- err(
+ warn(
"""To change which includes are allowed in a C file, edit the {}
files in its enclosing directory.""".format(RULES_FNAME))
sys.exit(1)
diff --git a/scripts/maint/practracker/metrics.py b/scripts/maint/practracker/metrics.py
index 4c62bc2425..ae88b84f31 100644
--- a/scripts/maint/practracker/metrics.py
+++ b/scripts/maint/practracker/metrics.py
@@ -4,6 +4,11 @@
# These are currently ad-hoc string operations and regexps.
# We might want to use a proper static analysis library in the future, if we want to get more advanced metrics.
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import re
def get_file_len(f):
diff --git a/scripts/maint/practracker/practracker.py b/scripts/maint/practracker/practracker.py
index 71741265f6..79b13cb056 100755
--- a/scripts/maint/practracker/practracker.py
+++ b/scripts/maint/practracker/practracker.py
@@ -19,14 +19,18 @@ problems in the Tor source, use the --regen flag:
$ python3 --regen ./scripts/maint/practracker/practracker.py .
"""
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
from __future__ import print_function
+from __future__ import unicode_literals
-import os, sys
+import codecs, os, sys
import metrics
import util
import problem
import includes
+import shutil
# The filename of the exceptions file (it should be placed in the practracker directory)
EXCEPTIONS_FNAME = "./exceptions.txt"
@@ -59,12 +63,8 @@ TOR_TOPDIR = None
#######################################################
-if sys.version_info[0] <= 2:
- def open_file(fname):
- return open(fname, 'r')
-else:
- def open_file(fname):
- return open(fname, 'r', encoding='utf-8')
+def open_file(fname):
+ return codecs.open(fname, 'r', encoding='utf-8')
def consider_file_size(fname, f):
"""Consider the size of 'f' and yield an FileSizeItem for it.
@@ -147,7 +147,7 @@ HEADER="""\
# file-size -- a .c file of more than {MAX_FILE_SIZE} lines, or a .h
# file with more than {MAX_H_FILE_SIZE} lines.
# include-count -- a .c file with more than {MAX_INCLUDE_COUNT} #includes,
- or a .h file with more than {MAX_H_INCLUDE_COUNT} #includes.
+# or a .h file with more than {MAX_H_INCLUDE_COUNT} #includes.
# dependency-violation -- a file includes a header that it should
# not, according to an advisory .may_include file.
#
@@ -182,6 +182,9 @@ def main(argv):
help="Regenerate the exceptions file")
parser.add_argument("--list-overbroad", action="store_true",
help="List over-broad exceptions")
+ parser.add_argument("--regen-overbroad", action="store_true",
+ help="Regenerate the exceptions file, "
+ "removing over-broad exceptions.")
parser.add_argument("--exceptions",
help="Override the location for the exceptions file")
parser.add_argument("--strict", action="store_true",
@@ -224,8 +227,9 @@ def main(argv):
filt.addThreshold(problem.DependencyViolationItem("*.c", int(args.max_dependency_violations)))
filt.addThreshold(problem.DependencyViolationItem("*.h", int(args.max_dependency_violations)))
- if args.list_overbroad and args.regen:
- print("Cannot use --regen with --list-overbroad",
+ if args.list_overbroad + args.regen + args.regen_overbroad > 1:
+ print("Cannot use more than one of --regen, --list-overbroad, and "
+ "--regen-overbroad.",
file=sys.stderr)
sys.exit(1)
@@ -244,13 +248,15 @@ def main(argv):
ProblemVault = problem.ProblemVault(exceptions_file)
problem_file = sys.stdout
- if args.list_overbroad:
- # If we're listing overbroad exceptions, don't list problems.
+ if args.list_overbroad or args.regen_overbroad:
+ # If we're looking for overbroad exceptions, don't list problems
+ # immediately to the problem file.
problem_file = util.NullFile()
# 2.1) Adjust the exceptions so that we warn only about small problems,
# and produce errors on big ones.
- if not (args.regen or args.list_overbroad or args.strict):
+ if not (args.regen or args.list_overbroad or args.regen_overbroad or
+ args.strict):
ProblemVault.set_tolerances(TOLERANCE_FNS)
# 3) Go through all the files and report problems if they are not exceptions
@@ -266,7 +272,17 @@ def main(argv):
if args.regen:
tmpfile.close()
- os.rename(tmpname, exceptions_file)
+ shutil.move(tmpname, exceptions_file)
+ sys.exit(0)
+
+ if args.regen_overbroad:
+ tmpname = exceptions_file + ".tmp"
+ tmpfile = open(tmpname, "w")
+ tmpfile.write(HEADER)
+ for item in ProblemVault.list_exceptions_without_overbroad():
+ print(item, file=tmpfile)
+ tmpfile.close()
+ shutil.move(tmpname, exceptions_file)
sys.exit(0)
# If new issues were found, try to give out some advice to the developer on how to resolve it.
@@ -293,6 +309,7 @@ variable.
else:
print(ex, "->", p.metric_value)
+
sys.exit(found_new_issues)
if __name__ == '__main__':
diff --git a/scripts/maint/practracker/practracker_tests.py b/scripts/maint/practracker/practracker_tests.py
index 45719d6cb7..8d0418880c 100755
--- a/scripts/maint/practracker/practracker_tests.py
+++ b/scripts/maint/practracker/practracker_tests.py
@@ -2,6 +2,11 @@
"""Some simple tests for practracker metrics"""
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import unittest
try:
diff --git a/scripts/maint/practracker/problem.py b/scripts/maint/practracker/problem.py
index d21840a213..a3255dcc80 100644
--- a/scripts/maint/practracker/problem.py
+++ b/scripts/maint/practracker/problem.py
@@ -7,7 +7,10 @@ problem is worse than a registered exception so that it only warns when things
get worse.
"""
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
from __future__ import print_function
+from __future__ import unicode_literals
import os.path
import re
@@ -26,6 +29,8 @@ class ProblemVault(object):
def __init__(self, exception_fname=None):
# Exception dictionary: { problem.key() : Problem object }
self.exceptions = {}
+ # Exception list: list of Problem objects, in the order added.
+ self.exception_list = []
# Exception dictionary: maps key to the problem it was used to
# suppress.
self.used_exception_for = {}
@@ -60,6 +65,7 @@ class ProblemVault(object):
sys.exit(1)
self.exceptions[problem.key()] = problem
+ self.exception_list.append(problem)
#print "Registering exception: %s" % problem
def register_problem(self, problem):
@@ -95,6 +101,24 @@ class ProblemVault(object):
if p is None or e.is_worse_than(p):
yield (e, p)
+ def list_exceptions_without_overbroad(self):
+ """Return an iterator of new problems, such that overbroad
+ exceptions are replaced with minimally broad versions, or removed.
+ """
+ for e in self.exception_list:
+ p = self.used_exception_for.get(e.key())
+ if p is None:
+ # This exception wasn't needed at all.
+ continue
+ if e.is_worse_than(p):
+ # The exception is worse than the problem we found.
+ # Yield the problem as the new exception value.
+ yield p
+ else:
+ # The problem is as bad as the exception, or worse.
+ # Yield the exception.
+ yield e
+
def set_tolerances(self, fns):
"""Adjust the tolerances for the exceptions in this vault. Takes
a map of problem type to a function that adjusts the permitted
diff --git a/scripts/maint/practracker/test_practracker.sh b/scripts/maint/practracker/test_practracker.sh
index 207a5ceded..e29b9106de 100755
--- a/scripts/maint/practracker/test_practracker.sh
+++ b/scripts/maint/practracker/test_practracker.sh
@@ -1,5 +1,8 @@
#!/bin/sh
+# Fail if any subprocess fails unexpectedly
+set -e
+
umask 077
unset TOR_DISABLE_PRACTRACKER
@@ -16,6 +19,11 @@ if test "${PRACTRACKER_DIR}" = "" ||
PRACTRACKER_DIR=$(dirname "$0")
fi
+# Change to the tor directory, and canonicalise PRACTRACKER_DIR,
+# so paths in practracker output are consistent, even in out-of-tree builds
+cd "${PRACTRACKER_DIR}"/../../..
+PRACTRACKER_DIR="scripts/maint/practracker"
+
TMPDIR="$(mktemp -d -t pracktracker.test.XXXXXX)"
if test -z "${TMPDIR}" || test ! -d "${TMPDIR}" ; then
echo >&2 "mktemp failed."
@@ -33,11 +41,11 @@ run_practracker() {
--max-h-include-count=0 \
--max-include-count=0 \
--terse \
- "${DATA}/" "$@";
+ "${DATA}/" "$@" || echo "practracker exit status: $?"
}
compare() {
# we can't use cmp because we need to use -b for windows
- diff -b -u "$@" > "${TMPDIR}/test-diff"
+ diff -b -u "$@" > "${TMPDIR}/test-diff" || true
if test -z "$(cat "${TMPDIR}"/test-diff)"; then
echo "OK"
else
@@ -49,22 +57,40 @@ compare() {
echo "unit tests:"
-"${PYTHON:-python}" "${PRACTRACKER_DIR}/practracker_tests.py" || exit 1
+"${PYTHON:-python}" "${PRACTRACKER_DIR}/practracker_tests.py"
echo "ex0:"
-run_practracker --exceptions "${DATA}/ex0.txt" > "${TMPDIR}/ex0-received.txt"
+run_practracker --exceptions "${DATA}/ex0.txt" \
+ > "${TMPDIR}/ex0-received.txt" 2>&1
-compare "${TMPDIR}/ex0-received.txt" "${DATA}/ex0-expected.txt"
+compare "${TMPDIR}/ex0-received.txt" \
+ "${DATA}/ex0-expected.txt"
echo "ex1:"
-run_practracker --exceptions "${DATA}/ex1.txt" > "${TMPDIR}/ex1-received.txt"
+run_practracker --exceptions "${DATA}/ex1.txt" \
+ > "${TMPDIR}/ex1-received.txt" 2>&1
-compare "${TMPDIR}/ex1-received.txt" "${DATA}/ex1-expected.txt"
+compare "${TMPDIR}/ex1-received.txt" \
+ "${DATA}/ex1-expected.txt"
echo "ex1.overbroad:"
-run_practracker --exceptions "${DATA}/ex1.txt" --list-overbroad > "${TMPDIR}/ex1-overbroad-received.txt"
+run_practracker --exceptions "${DATA}/ex1.txt" --list-overbroad \
+ > "${TMPDIR}/ex1-overbroad-received.txt" 2>&1
+
+compare "${TMPDIR}/ex1-overbroad-received.txt" \
+ "${DATA}/ex1-overbroad-expected.txt"
+
+echo "ex1.regen:"
+
+cp "${DATA}/ex1.txt" "${TMPDIR}/ex1-copy.txt"
+run_practracker --exceptions "${TMPDIR}/ex1-copy.txt" --regen >/dev/null 2>&1
+compare "${TMPDIR}/ex1-copy.txt" "${DATA}/ex1-regen-expected.txt"
+
+echo "ex1.regen_overbroad:"
-compare "${TMPDIR}/ex1-overbroad-received.txt" "${DATA}/ex1-overbroad-expected.txt"
+cp "${DATA}/ex1.txt" "${TMPDIR}/ex1-copy.txt"
+run_practracker --exceptions "${TMPDIR}/ex1-copy.txt" --regen-overbroad >/dev/null 2>&1
+compare "${TMPDIR}/ex1-copy.txt" "${DATA}/ex1-regen-overbroad-expected.txt"
diff --git a/scripts/maint/practracker/testdata/.may_include b/scripts/maint/practracker/testdata/.may_include
index 40bf8155d9..8542a35807 100644
--- a/scripts/maint/practracker/testdata/.may_include
+++ b/scripts/maint/practracker/testdata/.may_include
@@ -1,3 +1,4 @@
!advisory
permitted.h
+ext/good.c
diff --git a/scripts/maint/practracker/testdata/a.c b/scripts/maint/practracker/testdata/a.c
index 1939773f57..3c338ab40d 100644
--- a/scripts/maint/practracker/testdata/a.c
+++ b/scripts/maint/practracker/testdata/a.c
@@ -5,6 +5,9 @@
# include "permitted.h"
+#include "ext/good.c"
+#include "bad.c"
+
int
i_am_a_function(void)
{
diff --git a/scripts/maint/practracker/testdata/ex0-expected.txt b/scripts/maint/practracker/testdata/ex0-expected.txt
index 5f3d9e5aec..c9fb83bac3 100644
--- a/scripts/maint/practracker/testdata/ex0-expected.txt
+++ b/scripts/maint/practracker/testdata/ex0-expected.txt
@@ -1,11 +1,13 @@
-problem file-size a.c 38
-problem include-count a.c 4
+Unusual pattern permitted.h in scripts/maint/practracker/testdata
+problem file-size a.c 41
+problem include-count a.c 6
problem function-size a.c:i_am_a_function() 9
problem function-size a.c:another_function() 12
-problem dependency-violation a.c 3
+problem dependency-violation a.c 4
problem file-size b.c 15
problem function-size b.c:foo() 4
problem function-size b.c:bar() 5
problem file-size header.h 8
problem include-count header.h 4
problem dependency-violation header.h 3
+practracker exit status: 11
diff --git a/scripts/maint/practracker/testdata/ex1-expected.txt b/scripts/maint/practracker/testdata/ex1-expected.txt
index 58140a4d9a..2713338ae4 100644
--- a/scripts/maint/practracker/testdata/ex1-expected.txt
+++ b/scripts/maint/practracker/testdata/ex1-expected.txt
@@ -1,3 +1,5 @@
+Unusual pattern permitted.h in scripts/maint/practracker/testdata
problem function-size a.c:i_am_a_function() 9
(warning) problem function-size a.c:another_function() 12
problem function-size b.c:foo() 4
+practracker exit status: 2
diff --git a/scripts/maint/practracker/testdata/ex1-overbroad-expected.txt b/scripts/maint/practracker/testdata/ex1-overbroad-expected.txt
index f69c608f40..5ca480dc04 100644
--- a/scripts/maint/practracker/testdata/ex1-overbroad-expected.txt
+++ b/scripts/maint/practracker/testdata/ex1-overbroad-expected.txt
@@ -1,2 +1,4 @@
-problem file-size a.c 40 -> 38
+Unusual pattern permitted.h in scripts/maint/practracker/testdata
+problem file-size a.c 45 -> 41
problem file-size z.c 100 -> 0
+practracker exit status: 3
diff --git a/scripts/maint/practracker/testdata/ex1-regen-expected.txt b/scripts/maint/practracker/testdata/ex1-regen-expected.txt
new file mode 100644
index 0000000000..bdf3681edf
--- /dev/null
+++ b/scripts/maint/practracker/testdata/ex1-regen-expected.txt
@@ -0,0 +1,46 @@
+# Welcome to the exceptions file for Tor's best-practices tracker!
+#
+# Each line of this file represents a single violation of Tor's best
+# practices -- typically, a violation that we had before practracker.py
+# first existed.
+#
+# There are three kinds of problems that we recognize right now:
+# function-size -- a function of more than 100 lines.
+# file-size -- a .c file of more than 3000 lines, or a .h
+# file with more than 500 lines.
+# include-count -- a .c file with more than 50 #includes,
+# or a .h file with more than 15 #includes.
+# dependency-violation -- a file includes a header that it should
+# not, according to an advisory .may_include file.
+#
+# Each line below represents a single exception that practracker should
+# _ignore_. Each line has four parts:
+# 1. The word "problem".
+# 2. The kind of problem.
+# 3. The location of the problem: either a filename, or a
+# filename:functionname pair.
+# 4. The magnitude of the problem to ignore.
+#
+# So for example, consider this line:
+# problem file-size /src/core/or/connection_or.c 3200
+#
+# It tells practracker to allow the mentioned file to be up to 3200 lines
+# long, even though ordinarily it would warn about any file with more than
+# 3000 lines.
+#
+# You can either edit this file by hand, or regenerate it completely by
+# running `make practracker-regen`.
+#
+# Remember: It is better to fix the problem than to add a new exception!
+
+problem file-size a.c 41
+problem include-count a.c 6
+problem function-size a.c:i_am_a_function() 9
+problem function-size a.c:another_function() 12
+problem dependency-violation a.c 4
+problem file-size b.c 15
+problem function-size b.c:foo() 4
+problem function-size b.c:bar() 5
+problem file-size header.h 8
+problem include-count header.h 4
+problem dependency-violation header.h 3
diff --git a/scripts/maint/practracker/testdata/ex1-regen-overbroad-expected.txt b/scripts/maint/practracker/testdata/ex1-regen-overbroad-expected.txt
new file mode 100644
index 0000000000..4521029b10
--- /dev/null
+++ b/scripts/maint/practracker/testdata/ex1-regen-overbroad-expected.txt
@@ -0,0 +1,45 @@
+# Welcome to the exceptions file for Tor's best-practices tracker!
+#
+# Each line of this file represents a single violation of Tor's best
+# practices -- typically, a violation that we had before practracker.py
+# first existed.
+#
+# There are three kinds of problems that we recognize right now:
+# function-size -- a function of more than 100 lines.
+# file-size -- a .c file of more than 3000 lines, or a .h
+# file with more than 500 lines.
+# include-count -- a .c file with more than 50 #includes,
+# or a .h file with more than 15 #includes.
+# dependency-violation -- a file includes a header that it should
+# not, according to an advisory .may_include file.
+#
+# Each line below represents a single exception that practracker should
+# _ignore_. Each line has four parts:
+# 1. The word "problem".
+# 2. The kind of problem.
+# 3. The location of the problem: either a filename, or a
+# filename:functionname pair.
+# 4. The magnitude of the problem to ignore.
+#
+# So for example, consider this line:
+# problem file-size /src/core/or/connection_or.c 3200
+#
+# It tells practracker to allow the mentioned file to be up to 3200 lines
+# long, even though ordinarily it would warn about any file with more than
+# 3000 lines.
+#
+# You can either edit this file by hand, or regenerate it completely by
+# running `make practracker-regen`.
+#
+# Remember: It is better to fix the problem than to add a new exception!
+
+problem file-size a.c 41
+problem include-count a.c 6
+problem function-size a.c:i_am_a_function() 8
+problem function-size a.c:another_function() 11
+problem file-size b.c 15
+problem function-size b.c:bar() 5
+problem dependency-violation a.c 4
+problem dependency-violation header.h 3
+problem file-size header.h 8
+problem include-count header.h 4
diff --git a/scripts/maint/practracker/testdata/ex1.txt b/scripts/maint/practracker/testdata/ex1.txt
index c698005d07..af8de03291 100644
--- a/scripts/maint/practracker/testdata/ex1.txt
+++ b/scripts/maint/practracker/testdata/ex1.txt
@@ -1,6 +1,6 @@
-problem file-size a.c 40
-problem include-count a.c 4
+problem file-size a.c 45
+problem include-count a.c 6
# this problem will produce an error
problem function-size a.c:i_am_a_function() 8
# this problem will produce a warning
@@ -12,7 +12,7 @@ problem file-size b.c 15
problem file-size z.c 100
problem function-size b.c:bar() 5
-problem dependency-violation a.c 3
+problem dependency-violation a.c 4
problem dependency-violation header.h 3
problem file-size header.h 8
problem include-count header.h 4
diff --git a/scripts/maint/practracker/util.py b/scripts/maint/practracker/util.py
index df629110c2..c52ca2fbbf 100644
--- a/scripts/maint/practracker/util.py
+++ b/scripts/maint/practracker/util.py
@@ -1,3 +1,8 @@
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import os
# We don't want to run metrics for unittests, automatically-generated C files,
@@ -35,6 +40,12 @@ def get_tor_c_files(tor_topdir, include_dirs=None):
continue
if filename in EXCLUDE_FILES:
continue
+ # Avoid editor temporary files
+ bname = os.path.basename(filename)
+ if bname.startswith("."):
+ continue
+ if bname.startswith("#"):
+ continue
full_path = os.path.join(root,filename)
diff --git a/scripts/maint/rectify_include_paths.py b/scripts/maint/rectify_include_paths.py
index 1140e8cd22..111cf816ce 100755
--- a/scripts/maint/rectify_include_paths.py
+++ b/scripts/maint/rectify_include_paths.py
@@ -1,5 +1,10 @@
#!/usr/bin/python
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import os
import os.path
import re
diff --git a/scripts/maint/redox.py b/scripts/maint/redox.py
index 203cce0107..3ad3e3f1b8 100755
--- a/scripts/maint/redox.py
+++ b/scripts/maint/redox.py
@@ -29,6 +29,19 @@
# "mv fname.c.newdoc fname.c". Otherwise, you'll need to merge
# the parts you like by hand.
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
+import re
+import sys
+
+try:
+ xrange # Python 2
+except NameError:
+ xrange = range # Python 3
+
# Which files should we ignore warning from? Mostly, these are external
# files that we've snarfed in from somebody else, whose C we do no intend
# to document for them.
@@ -52,9 +65,6 @@ ADD_DOCDOCS_TO_TYPES += [ 'variable', ]
# ====================
# The rest of this should not need hacking.
-import re
-import sys
-
KINDS = [ "type", "field", "typedef", "define", "function", "variable",
"enumeration" ]
@@ -73,7 +83,7 @@ def parsething(thing):
else:
m = THING_RE.match(thing)
if not m:
- print thing, "???? Format didn't match."
+ print(thing, "???? Format didn't match.")
return None, None
else:
name, tp, parent = m.groups()
@@ -150,7 +160,7 @@ def checkf(fn, errs):
"""
for skip in SKIP_FILES:
if fn.endswith(skip):
- print "Skipping",fn
+ print("Skipping",fn)
return
comments = []
@@ -169,8 +179,8 @@ def checkf(fn, errs):
ln = findline(lines, line, name)
if ln == None:
- print "Couldn't find the definition of %s allegedly on %s of %s"%(
- name, line, fn)
+ print("Couldn't find the definition of %s allegedly on %s of %s"%(
+ name, line, fn))
else:
if hasdocdoc(lines, line, kind):
# print "Has a DOCDOC"
@@ -215,12 +225,12 @@ def applyComments(fn, entries):
outf.write(line)
outf.close()
- print "Added %s DOCDOCs to %s" %(N, fn)
+ print("Added %s DOCDOCs to %s" %(N, fn))
e = read()
for fn, errs in e.iteritems():
- print `(fn, errs)`
+ print(repr((fn, errs)))
comments = checkf(fn, errs)
if comments:
applyComments(fn, comments)
diff --git a/scripts/maint/rename_c_identifier.py b/scripts/maint/rename_c_identifier.py
new file mode 100755
index 0000000000..6e0c1d8cf1
--- /dev/null
+++ b/scripts/maint/rename_c_identifier.py
@@ -0,0 +1,266 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2001 Matej Pfajfar.
+# Copyright (c) 2001-2004, Roger Dingledine.
+# Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+# Copyright (c) 2007-2019, The Tor Project, Inc.
+# See LICENSE for licensing information
+
+"""
+Helpful script to replace one or more C identifiers, and optionally
+generate a commit message explaining what happened.
+"""
+
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
+import argparse
+import fileinput
+import os
+import re
+import shlex
+import subprocess
+import sys
+import tempfile
+
+TOPDIR = "src"
+
+
+def is_c_file(fn):
+ """
+ Return true iff fn is the name of a C file.
+
+ >>> is_c_file("a/b/module.c")
+ True
+ >>> is_c_file("a/b/module.h")
+ True
+ >>> is_c_file("a/b/module.c~")
+ False
+ >>> is_c_file("a/b/.module.c")
+ False
+ >>> is_c_file("a/b/module.cpp")
+ False
+ """
+ fn = os.path.split(fn)[1]
+ if fn.startswith("."):
+ return False
+ ext = os.path.splitext(fn)[1]
+ return ext in {".c", ".h", ".i", ".inc"}
+
+
+def list_c_files(topdir=TOPDIR):
+ """
+ Use git to list all the C files under version control.
+
+ >>> lst = list(list_c_files())
+ >>> "src/core/mainloop/mainloop.c" in lst
+ True
+ >>> "src/core/mainloop/twiddledeedoo.c" in lst
+ False
+ >>> "micro-revision.i" in lst
+ False
+ """
+ proc = subprocess.Popen(
+ ["git", "ls-tree", "--name-only", "-r", "HEAD", topdir],
+ stdout=subprocess.PIPE,
+ encoding="utf-8")
+ for line in proc.stdout.readlines():
+ line = line.strip()
+ if is_c_file(line):
+ yield line
+
+
+class Rewriter:
+ """
+ A rewriter applies a series of word-by-word replacements, in
+ sequence. Replacements only happen at "word boundaries",
+ as determined by the \\b regular expression marker.
+
+ ("A word is defined as a sequence of alphanumeric or underscore
+ characters", according to the documentation.)
+
+ >>> R = Rewriter([("magic", "secret"), ("words", "codes")])
+ >>> R.apply("The magic words are rambunctious bluejay")
+ 'The secret codes are rambunctious bluejay'
+ >>> R.apply("The magical words are rambunctious bluejay")
+ 'The magical codes are rambunctious bluejay'
+ >>> R.get_count()
+ 3
+
+ """
+
+ def __init__(self, replacements):
+ """Make a new Rewriter. Takes a sequence of pairs of
+ (from_id, to_id), where from_id is an identifier to replace,
+ and to_id is its replacement.
+ """
+ self._patterns = []
+ for id1, id2 in replacements:
+ pat = re.compile(r"\b{}\b".format(re.escape(id1)))
+ self._patterns.append((pat, id2))
+
+ self._count = 0
+
+ def apply(self, line):
+ """Return `line` as transformed by this rewriter."""
+ for pat, ident in self._patterns:
+ line, count = pat.subn(ident, line)
+ self._count += count
+ return line
+
+ def get_count(self):
+ """Return the number of identifiers that this rewriter has
+ rewritten."""
+ return self._count
+
+
+def rewrite_files(files, rewriter):
+ """
+ Apply `rewriter` to every file in `files`, replacing those files
+ with their rewritten contents.
+ """
+ for line in fileinput.input(files, inplace=True):
+ sys.stdout.write(rewriter.apply(line))
+
+
+def make_commit_msg(pairs, no_verify):
+ """Return a commit message to explain what was replaced by the provided
+ arguments.
+ """
+ script = ["./scripts/maint/rename_c_identifier.py"]
+ for id1, id2 in pairs:
+ qid1 = shlex.quote(id1)
+ qid2 = shlex.quote(id2)
+ script.append(" {} {}".format(qid1, qid2))
+ script = " \\\n".join(script)
+
+ if len(pairs) == 1:
+ line1 = "Rename {} to {}".format(*pairs[0])
+ else:
+ line1 = "Replace several C identifiers."
+
+ msg = """\
+{}
+
+This is an automated commit, generated by this command:
+
+{}
+""".format(line1, script)
+
+ if no_verify:
+ msg += """
+It was generated with --no-verify, so it probably breaks some commit hooks.
+The commiter should be sure to fix them up in a subsequent commit.
+"""
+
+ return msg
+
+
+def commit(pairs, no_verify=False):
+ """Try to commit the current git state, generating the commit message as
+ appropriate. If `no_verify` is True, pass the --no-verify argument to
+ git commit.
+ """
+ args = []
+ if no_verify:
+ args.append("--no-verify")
+
+ # We have to use a try block to delete the temporary file here, since we
+ # are using tempfile with delete=False. We have to use delete=False,
+ # since otherwise we are not guaranteed to be able to give the file to
+ # git for it to open.
+ fname = None
+ try:
+ with tempfile.NamedTemporaryFile(mode="w", delete=False) as f:
+ fname = f.name
+ f.write(make_commit_msg(pairs, no_verify))
+ s = subprocess.run(["git", "commit", "-a", "-F", fname, "--edit"]+args)
+ if s.returncode != 0 and not no_verify:
+ print('"git commit" failed. Maybe retry with --no-verify?',
+ file=sys.stderr)
+ revert_changes()
+ return False
+ finally:
+ os.unlink(fname)
+
+ return True
+
+
+def any_uncommitted_changes():
+ """Return True if git says there are any uncommitted changes in the current
+ working tree; false otherwise.
+ """
+ s = subprocess.run(["git", "diff-index", "--quiet", "HEAD"])
+ return s.returncode != 0
+
+
+DESC = "Replace one identifier with another throughout our source."
+EXAMPLES = """\
+Examples:
+
+ rename_c_identifier.py set_ctrl_id set_controller_id
+ (Replaces every occurrence of "set_ctrl_id" with "set_controller_id".)
+
+ rename_c_identifier.py --commit set_ctrl_id set_controller_id
+ (As above, but also generate a git commit with an appropriate message.)
+
+ rename_c_identifier.py a b c d
+ (Replace "a" with "b", and "c" with "d".)"""
+
+
+def revert_changes():
+ """Tell git to revert all the changes in the current working tree.
+ """
+ print('Reverting changes.', file=sys.stderr)
+ subprocess.run(["git", "checkout", "--quiet", TOPDIR])
+
+
+def main(argv):
+ import argparse
+ parser = argparse.ArgumentParser(description=DESC, epilog=EXAMPLES,
+ # prevent re-wrapping the examples
+ formatter_class=argparse.RawDescriptionHelpFormatter)
+
+ parser.add_argument("--commit", action='store_true',
+ help="Generate a Git commit.")
+ parser.add_argument("--no-verify", action='store_true',
+ help="Tell Git not to run its pre-commit hooks.")
+ parser.add_argument("from_id", type=str, help="Original identifier")
+ parser.add_argument("to_id", type=str, help="New identifier")
+ parser.add_argument("more", type=str, nargs=argparse.REMAINDER,
+ help="Additional identifier pairs")
+
+ args = parser.parse_args(argv[1:])
+
+ if len(args.more) % 2 != 0:
+ print("I require an even number of identifiers.", file=sys.stderr)
+ return 1
+
+ if any_uncommitted_changes():
+ print("Uncommitted changes found. Not running.", file=sys.stderr)
+ return 1
+
+ pairs = []
+ print("renaming {} to {}".format(args.from_id, args.to_id), file=sys.stderr)
+ pairs.append((args.from_id, args.to_id))
+ for idx in range(0, len(args.more), 2):
+ id1 = args.more[idx]
+ id2 = args.more[idx+1]
+ print("renaming {} to {}".format(id1, id2))
+ pairs.append((id1, id2))
+
+ rewriter = Rewriter(pairs)
+
+ rewrite_files(list_c_files(), rewriter)
+
+ print("Replaced {} identifiers".format(rewriter.get_count()),
+ file=sys.stderr)
+
+ if args.commit:
+ commit(pairs, args.no_verify)
+
+
+if __name__ == '__main__':
+ main(sys.argv)
diff --git a/scripts/maint/sortChanges.py b/scripts/maint/sortChanges.py
index 986b94b025..2e049b1e53 100755
--- a/scripts/maint/sortChanges.py
+++ b/scripts/maint/sortChanges.py
@@ -7,6 +7,11 @@
changelog.
"""
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import re
import sys
@@ -43,7 +48,7 @@ REPLACEMENTS = {
def score(s,fname=None):
m = re.match(r'^ +o ([^\n]*)\n(.*)', s, re.M|re.S)
if not m:
- print >>sys.stderr, "Can't score %r from %s"%(s,fname)
+ print("Can't score %r from %s"%(s,fname), file=sys.stderr)
heading = m.group(1)
heading = REPLACEMENTS.get(heading, heading)
lw = m.group(1).lower()
@@ -100,9 +105,9 @@ changes.sort()
last_lw = "this is not a header"
for _, lw, header, rest in changes:
if lw == last_lw:
- print rest,
+ print(rest, end="")
else:
- print
- print " o",header
- print rest,
+ print()
+ print(" o",header)
+ print(rest, end="")
last_lw = lw
diff --git a/scripts/maint/update_versions.py b/scripts/maint/update_versions.py
index 8067f2c6c8..07de1c343a 100755
--- a/scripts/maint/update_versions.py
+++ b/scripts/maint/update_versions.py
@@ -1,6 +1,9 @@
#!/usr/bin/env python
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
from __future__ import print_function
+from __future__ import unicode_literals
import io
import os
@@ -95,7 +98,7 @@ def update_file(fname,
replace_on_change(fname, have_changed)
# Find out our version
-with open("configure.ac") as f:
+with open(P("configure.ac")) as f:
version = find_version(f)
# If we have no version, we can't proceed.
diff --git a/scripts/test/appveyor-irc-notify.py b/scripts/test/appveyor-irc-notify.py
index cfe0afe7ae..598a68f47d 100644
--- a/scripts/test/appveyor-irc-notify.py
+++ b/scripts/test/appveyor-irc-notify.py
@@ -75,8 +75,10 @@ in Appveyor's YAML:
- "python scripts/test/appveyor-irc-notify.py irc.oftc.net:6697 tor-ci failure
"""
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
from __future__ import print_function
-from __future__ import absolute_import
+from __future__ import unicode_literals
import os
import random
diff --git a/src/app/app.md b/src/app/app.md
new file mode 100644
index 0000000000..138e75b127
--- /dev/null
+++ b/src/app/app.md
@@ -0,0 +1,6 @@
+@dir /app
+@brief app: top-level entry point for Tor
+
+The "app" directory has Tor's main entry point and configuration logic,
+and is responsible for initializing and managing the other modules in
+Tor.
diff --git a/src/app/config/.may_include b/src/app/config/.may_include
new file mode 100644
index 0000000000..11c5ffbb14
--- /dev/null
+++ b/src/app/config/.may_include
@@ -0,0 +1,2 @@
+*.h
+*.inc
diff --git a/src/app/config/app_config.md b/src/app/config/app_config.md
new file mode 100644
index 0000000000..b359ce77f6
--- /dev/null
+++ b/src/app/config/app_config.md
@@ -0,0 +1,6 @@
+@dir /app/config
+@brief app/config: Top-level configuration code
+
+Refactoring this module is a work in progress, see
+[ticket 29211](https://trac.torproject.org/projects/tor/ticket/29211).
+
diff --git a/src/app/config/config.c b/src/app/config/config.c
index f27fcd3108..7ed60c4745 100644
--- a/src/app/config/config.c
+++ b/src/app/config/config.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -22,7 +22,8 @@
*
* To add new items to the torrc, there are a minimum of three places to edit:
* <ul>
- * <li>The or_options_t structure in or.h, where the options are stored.
+ * <li>The or_options_t structure in or_options_st.h, where the options are
+ * stored.
* <li>The option_vars_ array below in this module, which configures
* the names of the torrc options, their types, their multiplicities,
* and their mappings to fields in or_options_t.
@@ -32,16 +33,18 @@
*
* Additionally, you might need to edit these places too:
* <ul>
- * <li>options_validate() below, in case you want to reject some possible
+ * <li>options_validate_cb() below, in case you want to reject some possible
* values of the new configuration option.
* <li>options_transition_allowed() below, in case you need to
* forbid some or all changes in the option while Tor is
* running.
* <li>options_transition_affects_workers(), in case changes in the option
* might require Tor to relaunch or reconfigure its worker threads.
+ * (This function is now in the relay module.)
* <li>options_transition_affects_descriptor(), in case changes in the
* option might require a Tor relay to build and publish a new server
* descriptor.
+ * (This function is now in the relay module.)
* <li>options_act() and/or options_act_reversible(), in case there's some
* action that needs to be taken immediately based on the option's
* value.
@@ -61,22 +64,19 @@
#define CONFIG_PRIVATE
#include "core/or/or.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "app/config/statefile.h"
#include "app/main/main.h"
#include "app/main/subsysmgr.h"
#include "core/mainloop/connection.h"
-#include "core/mainloop/cpuworker.h"
#include "core/mainloop/mainloop.h"
#include "core/mainloop/netstatus.h"
#include "core/or/channel.h"
-#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/circuitmux.h"
#include "core/or/circuitmux_ewma.h"
#include "core/or/circuitstats.h"
#include "core/or/connection_edge.h"
-#include "core/or/connection_or.h"
#include "core/or/dos.h"
#include "core/or/policies.h"
#include "core/or/relay.h"
@@ -88,11 +88,7 @@
#include "feature/control/control.h"
#include "feature/control/control_auth.h"
#include "feature/control/control_events.h"
-#include "feature/dirauth/bwauth.h"
-#include "feature/dirauth/guardfraction.h"
-#include "feature/dircache/consdiffmgr.h"
-#include "feature/dircache/dirserv.h"
-#include "feature/dircommon/voting_schedule.h"
+#include "feature/dirclient/dirclient_modes.h"
#include "feature/hibernate/hibernate.h"
#include "feature/hs/hs_config.h"
#include "feature/nodelist/dirlist.h"
@@ -104,12 +100,12 @@
#include "feature/relay/dns.h"
#include "feature/relay/ext_orport.h"
#include "feature/relay/routermode.h"
+#include "feature/relay/relay_config.h"
+#include "feature/relay/transport_config.h"
#include "feature/rend/rendclient.h"
#include "feature/rend/rendservice.h"
#include "lib/geoip/geoip.h"
#include "feature/stats/geoip_stats.h"
-#include "feature/stats/predict_ports.h"
-#include "feature/stats/rephist.h"
#include "lib/compress/compress.h"
#include "lib/confmgt/structvar.h"
#include "lib/crypt_ops/crypto_init.h"
@@ -156,10 +152,8 @@
#include "lib/fs/conffile.h"
#include "lib/evloop/procmon.h"
-#include "feature/dirauth/dirvote.h"
-#include "feature/dirauth/dirauth_periodic.h"
-#include "feature/dirauth/recommend_pkg.h"
#include "feature/dirauth/authmode.h"
+#include "feature/dirauth/dirauth_config.h"
#include "core/or/connection_st.h"
#include "core/or/port_cfg_st.h"
@@ -186,8 +180,12 @@ static const char unix_q_socket_prefix[] = "unix:\"";
/** macro to help with the bulk rename of *DownloadSchedule to
* *DowloadInitialDelay . */
+#ifndef COCCI
#define DOWNLOAD_SCHEDULE(name) \
{ #name "DownloadSchedule", #name "DownloadInitialDelay", 0, 1 }
+#else
+#define DOWNLOAD_SCHEDULE(name) { NULL, NULL, 0, 1 }
+#endif /* !defined(COCCI) */
/** A list of abbreviations and aliases to map command-line options, obsolete
* option names, or alternative option names, to their current values. */
@@ -268,6 +266,9 @@ DUMMY_TYPECHECK_INSTANCE(or_options_t);
#define VAR_NODUMP(varname,conftype,member,initvalue) \
CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, \
CFLG_NODUMP, initvalue)
+#define VAR_NODUMP_IMMUTABLE(varname,conftype,member,initvalue) \
+ CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, \
+ CFLG_NODUMP | CFLG_IMMUTABLE, initvalue)
#define VAR_INVIS(varname,conftype,member,initvalue) \
CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, \
CFLG_NODUMP | CFLG_NOSET | CFLG_NOLIST, initvalue)
@@ -275,6 +276,13 @@ DUMMY_TYPECHECK_INSTANCE(or_options_t);
#define V(member,conftype,initvalue) \
VAR(#member, conftype, member, initvalue)
+#define VAR_IMMUTABLE(varname, conftype, member, initvalue) \
+ CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, \
+ CFLG_IMMUTABLE, initvalue)
+
+#define V_IMMUTABLE(member,conftype,initvalue) \
+ VAR_IMMUTABLE(#member, conftype, member, initvalue)
+
/** As V, but uses a type definition instead of a type enum */
#define V_D(member,type,initvalue) \
VAR_D(#member, type, member, initvalue)
@@ -321,17 +329,11 @@ static const config_var_t option_vars_[] = {
V(AuthDirBadExitCCs, CSV, ""),
V(AuthDirInvalid, LINELIST, NULL),
V(AuthDirInvalidCCs, CSV, ""),
- V(AuthDirFastGuarantee, MEMUNIT, "100 KB"),
- V(AuthDirGuardBWGuarantee, MEMUNIT, "2 MB"),
- V(AuthDirPinKeys, BOOL, "1"),
V(AuthDirReject, LINELIST, NULL),
V(AuthDirRejectCCs, CSV, ""),
OBSOLETE("AuthDirRejectUnlisted"),
OBSOLETE("AuthDirListBadDirs"),
- V(AuthDirListBadExits, BOOL, "0"),
- V(AuthDirMaxServersPerAddr, POSINT, "2"),
OBSOLETE("AuthDirMaxServersPerAuthAddr"),
- V(AuthDirHasIPv6Connectivity, BOOL, "0"),
VAR("AuthoritativeDirectory", BOOL, AuthoritativeDir, "0"),
V(AutomapHostsOnResolve, BOOL, "0"),
V(AutomapHostsSuffixes, CSV, ".onion,.exit"),
@@ -344,7 +346,7 @@ static const config_var_t option_vars_[] = {
V(BridgeRecordUsageByCountry, BOOL, "1"),
V(BridgeRelay, BOOL, "0"),
V(BridgeDistribution, STRING, NULL),
- VAR("CacheDirectory", FILENAME, CacheDirectory_option, NULL),
+ VAR_IMMUTABLE("CacheDirectory",FILENAME, CacheDirectory_option, NULL),
V(CacheDirectoryGroupReadable, AUTOBOOL, "auto"),
V(CellStatistics, BOOL, "0"),
V(PaddingStatistics, BOOL, "1"),
@@ -355,7 +357,13 @@ static const config_var_t option_vars_[] = {
V(CircuitStreamTimeout, INTERVAL, "0"),
V(CircuitPriorityHalflife, DOUBLE, "-1.0"), /*negative:'Use default'*/
V(ClientDNSRejectInternalAddresses, BOOL,"1"),
+#if defined(HAVE_MODULE_RELAY) || defined(TOR_UNIT_TESTS)
+ /* The unit tests expect the ClientOnly default to be 0. */
V(ClientOnly, BOOL, "0"),
+#else
+ /* We must be a Client if the relay module is disabled. */
+ V(ClientOnly, BOOL, "1"),
+#endif /* defined(HAVE_MODULE_RELAY) || defined(TOR_UNIT_TESTS) */
V(ClientPreferIPv6ORPort, AUTOBOOL, "auto"),
V(ClientPreferIPv6DirPort, AUTOBOOL, "auto"),
V(ClientAutoIPv6ORPort, BOOL, "0"),
@@ -363,7 +371,6 @@ static const config_var_t option_vars_[] = {
V(ClientTransportPlugin, LINELIST, NULL),
V(ClientUseIPv6, BOOL, "0"),
V(ClientUseIPv4, BOOL, "1"),
- V(ConsensusParams, STRING, NULL),
V(ConnLimit, POSINT, "1000"),
V(ConnDirectionStatistics, BOOL, "0"),
V(ConstrainedSockets, BOOL, "0"),
@@ -378,21 +385,26 @@ static const config_var_t option_vars_[] = {
V(UnixSocksGroupWritable, BOOL, "0"),
V(CookieAuthentication, BOOL, "0"),
V(CookieAuthFileGroupReadable, BOOL, "0"),
- V(CookieAuthFile, STRING, NULL),
+ V(CookieAuthFile, FILENAME, NULL),
V(CountPrivateBandwidth, BOOL, "0"),
- VAR("DataDirectory", FILENAME, DataDirectory_option, NULL),
+ VAR_IMMUTABLE("DataDirectory", FILENAME, DataDirectory_option, NULL),
V(DataDirectoryGroupReadable, BOOL, "0"),
V(DisableOOSCheck, BOOL, "1"),
V(DisableNetwork, BOOL, "0"),
V(DirAllowPrivateAddresses, BOOL, "0"),
- V(TestingAuthDirTimeToLearnReachability, INTERVAL, "30 minutes"),
OBSOLETE("DirListenAddress"),
V(DirPolicy, LINELIST, NULL),
VPORT(DirPort),
V(DirPortFrontPage, FILENAME, NULL),
VAR("DirReqStatistics", BOOL, DirReqStatistics_option, "1"),
VAR("DirAuthority", LINELIST, DirAuthorities, NULL),
+#if defined(HAVE_MODULE_RELAY) || defined(TOR_UNIT_TESTS)
+ /* The unit tests expect the DirCache default to be 1. */
V(DirCache, BOOL, "1"),
+#else
+ /* We can't be a DirCache if the relay module is disabled. */
+ V(DirCache, BOOL, "0"),
+#endif /* defined(HAVE_MODULE_RELAY) || defined(TOR_UNIT_TESTS) */
/* A DirAuthorityFallbackRate of 0.1 means that 0.5% of clients try an
* authority when all fallbacks are up, and 2% try an authority when 25% of
* fallbacks are down. (We rebuild the list when 25% of fallbacks are down).
@@ -401,8 +413,8 @@ static const config_var_t option_vars_[] = {
* an order of magnitude, so there isn't too much load shifting to
* authorities when fallbacks go down. */
V(DirAuthorityFallbackRate, DOUBLE, "0.1"),
- V(DisableAllSwap, BOOL, "0"),
- V(DisableDebuggerAttachment, BOOL, "1"),
+ V_IMMUTABLE(DisableAllSwap, BOOL, "0"),
+ V_IMMUTABLE(DisableDebuggerAttachment, BOOL, "1"),
OBSOLETE("DisableIOCP"),
OBSOLETE("DisableV2DirectoryInfo_"),
OBSOLETE("DynamicDHGroups"),
@@ -432,7 +444,7 @@ static const config_var_t option_vars_[] = {
V(EnforceDistinctSubnets, BOOL, "1"),
V_D(EntryNodes, ROUTERSET, NULL),
V(EntryStatistics, BOOL, "0"),
- V(TestingEstimatedDescriptorPropagationTime, INTERVAL, "10 minutes"),
+ OBSOLETE("TestingEstimatedDescriptorPropagationTime"),
V_D(ExcludeNodes, ROUTERSET, NULL),
V_D(ExcludeExitNodes, ROUTERSET, NULL),
OBSOLETE("ExcludeSingleHopRelays"),
@@ -448,7 +460,7 @@ static const config_var_t option_vars_[] = {
V(ExtendAllowPrivateAddresses, BOOL, "0"),
V(ExitRelay, AUTOBOOL, "auto"),
VPORT(ExtORPort),
- V(ExtORPortCookieAuthFile, STRING, NULL),
+ V(ExtORPortCookieAuthFile, FILENAME, NULL),
V(ExtORPortCookieAuthFileGroupReadable, BOOL, "0"),
V(ExtraInfoStatistics, BOOL, "1"),
V(ExtendByEd25519ID, AUTOBOOL, "auto"),
@@ -478,11 +490,8 @@ static const config_var_t option_vars_[] = {
#endif /* defined(_WIN32) */
OBSOLETE("Group"),
V(GuardLifetime, INTERVAL, "0 minutes"),
- V(HardwareAccel, BOOL, "0"),
V(HeartbeatPeriod, INTERVAL, "6 hours"),
V(MainloopStats, BOOL, "0"),
- V(AccelName, STRING, NULL),
- V(AccelDir, FILENAME, NULL),
V(HashedControlPassword, LINELIST, NULL),
OBSOLETE("HidServDirectoryV2"),
VAR("HiddenServiceDir", LINELIST_S, RendConfigLines, NULL),
@@ -506,8 +515,8 @@ static const config_var_t option_vars_[] = {
V(ClientOnionAuthDir, FILENAME, NULL),
OBSOLETE("CloseHSClientCircuitsImmediatelyOnTimeout"),
OBSOLETE("CloseHSServiceRendCircuitsImmediatelyOnTimeout"),
- V(HiddenServiceSingleHopMode, BOOL, "0"),
- V(HiddenServiceNonAnonymousMode,BOOL, "0"),
+ V_IMMUTABLE(HiddenServiceSingleHopMode, BOOL, "0"),
+ V_IMMUTABLE(HiddenServiceNonAnonymousMode,BOOL, "0"),
V(HTTPProxy, STRING, NULL),
V(HTTPProxyAuthenticator, STRING, NULL),
V(HTTPSProxy, STRING, NULL),
@@ -522,18 +531,19 @@ static const config_var_t option_vars_[] = {
V(Socks5Proxy, STRING, NULL),
V(Socks5ProxyUsername, STRING, NULL),
V(Socks5ProxyPassword, STRING, NULL),
- VAR("KeyDirectory", FILENAME, KeyDirectory_option, NULL),
- V(KeyDirectoryGroupReadable, BOOL, "0"),
+ V(TCPProxy, STRING, NULL),
+ VAR_IMMUTABLE("KeyDirectory", FILENAME, KeyDirectory_option, NULL),
+ V(KeyDirectoryGroupReadable, AUTOBOOL, "auto"),
VAR_D("HSLayer2Nodes", ROUTERSET, HSLayer2Nodes, NULL),
VAR_D("HSLayer3Nodes", ROUTERSET, HSLayer3Nodes, NULL),
V(KeepalivePeriod, INTERVAL, "5 minutes"),
- V(KeepBindCapabilities, AUTOBOOL, "auto"),
+ V_IMMUTABLE(KeepBindCapabilities, AUTOBOOL, "auto"),
VAR("Log", LINELIST, Logs, NULL),
V(LogMessageDomains, BOOL, "0"),
V(LogTimeGranularity, MSEC_INTERVAL, "1 second"),
V(TruncateLogFile, BOOL, "0"),
- V(SyslogIdentityTag, STRING, NULL),
- V(AndroidIdentityTag, STRING, NULL),
+ V_IMMUTABLE(SyslogIdentityTag, STRING, NULL),
+ V_IMMUTABLE(AndroidIdentityTag,STRING, NULL),
V(LongLivedPorts, CSV,
"21,22,706,1863,5050,5190,5222,5223,6523,6667,6697,8300"),
VAR("MapAddress", LINELIST, AddressMap, NULL),
@@ -545,7 +555,6 @@ static const config_var_t option_vars_[] = {
OBSOLETE("MaxOnionsPending"),
V(MaxOnionQueueDelay, MSEC_INTERVAL, "1750 msec"),
V(MaxUnparseableDescSizeToLog, MEMUNIT, "10 MB"),
- V(MinMeasuredBWsForAuthToIgnoreAdvertised, INT, "500"),
VAR("MyFamily", LINELIST, MyFamily_lines, NULL),
V(NewCircuitPeriod, INTERVAL, "30 seconds"),
OBSOLETE("NamingAuthoritativeDirectory"),
@@ -555,7 +564,7 @@ static const config_var_t option_vars_[] = {
OBSOLETE("PredictedPortsRelevanceTime"),
OBSOLETE("WarnUnsafeSocks"),
VAR("NodeFamily", LINELIST, NodeFamilies, NULL),
- V(NoExec, BOOL, "0"),
+ V_IMMUTABLE(NoExec, BOOL, "0"),
V(NumCPUs, POSINT, "0"),
V(NumDirectoryGuards, POSINT, "0"),
V(NumEntryGuards, POSINT, "0"),
@@ -586,10 +595,8 @@ static const config_var_t option_vars_[] = {
V(PathsNeededToBuildCircuits, DOUBLE, "-1"),
V(PerConnBWBurst, MEMUNIT, "0"),
V(PerConnBWRate, MEMUNIT, "0"),
- V(PidFile, STRING, NULL),
- V(TestingTorNetwork, BOOL, "0"),
- V(TestingMinExitFlagThreshold, MEMUNIT, "0"),
- V(TestingMinFastFlagThreshold, MEMUNIT, "0"),
+ V_IMMUTABLE(PidFile, FILENAME, NULL),
+ V_IMMUTABLE(TestingTorNetwork, BOOL, "0"),
V(TestingLinkCertLifetime, INTERVAL, "2 days"),
V(TestingAuthKeyLifetime, INTERVAL, "2 days"),
@@ -607,9 +614,6 @@ static const config_var_t option_vars_[] = {
V(ReachableAddresses, LINELIST, NULL),
V(ReachableDirAddresses, LINELIST, NULL),
V(ReachableORAddresses, LINELIST, NULL),
- V(RecommendedVersions, LINELIST, NULL),
- V(RecommendedClientVersions, LINELIST, NULL),
- V(RecommendedServerVersions, LINELIST, NULL),
OBSOLETE("RecommendedPackages"),
V(ReducedConnectionPadding, BOOL, "0"),
V(ConnectionPadding, AUTOBOOL, "auto"),
@@ -621,17 +625,17 @@ static const config_var_t option_vars_[] = {
V(RelayBandwidthRate, MEMUNIT, "0"),
V(RendPostPeriod, INTERVAL, "1 hour"),
V(RephistTrackTime, INTERVAL, "24 hours"),
- V(RunAsDaemon, BOOL, "0"),
+ V_IMMUTABLE(RunAsDaemon, BOOL, "0"),
V(ReducedExitPolicy, BOOL, "0"),
OBSOLETE("RunTesting"), // currently unused
- V(Sandbox, BOOL, "0"),
+ V_IMMUTABLE(Sandbox, BOOL, "0"),
V(SafeLogging, STRING, "1"),
V(SafeSocks, BOOL, "0"),
V(ServerDNSAllowBrokenConfig, BOOL, "1"),
V(ServerDNSAllowNonRFC953Hostnames, BOOL,"0"),
V(ServerDNSDetectHijacking, BOOL, "1"),
V(ServerDNSRandomizeCase, BOOL, "1"),
- V(ServerDNSResolvConfFile, STRING, NULL),
+ V(ServerDNSResolvConfFile, FILENAME, NULL),
V(ServerDNSSearchDomains, BOOL, "0"),
V(ServerDNSTestAddresses, CSV,
"www.google.com,www.mit.edu,www.yahoo.com,www.slashdot.org"),
@@ -652,7 +656,7 @@ static const config_var_t option_vars_[] = {
V(StrictNodes, BOOL, "0"),
OBSOLETE("Support022HiddenServices"),
V(TestSocks, BOOL, "0"),
- V(TokenBucketRefillInterval, MSEC_INTERVAL, "100 msec"),
+ V_IMMUTABLE(TokenBucketRefillInterval, MSEC_INTERVAL, "100 msec"),
OBSOLETE("Tor2webMode"),
OBSOLETE("Tor2webRendezvousPoints"),
OBSOLETE("TLSECGroup"),
@@ -669,11 +673,8 @@ static const config_var_t option_vars_[] = {
V(UseGuardFraction, AUTOBOOL, "auto"),
V(UseMicrodescriptors, AUTOBOOL, "auto"),
OBSOLETE("UseNTorHandshake"),
- V(User, STRING, NULL),
+ V_IMMUTABLE(User, STRING, NULL),
OBSOLETE("UserspaceIOCPBuffers"),
- V(AuthDirRejectRequestsUnderLoad, BOOL, "1"),
- V(AuthDirSharedRandomness, BOOL, "1"),
- V(AuthDirTestEd25519LinkKeys, BOOL, "1"),
OBSOLETE("V1AuthoritativeDirectory"),
OBSOLETE("V2AuthoritativeDirectory"),
VAR("V3AuthoritativeDirectory",BOOL, V3AuthoritativeDir, "0"),
@@ -688,7 +689,6 @@ static const config_var_t option_vars_[] = {
V(V3AuthUseLegacyKey, BOOL, "0"),
V(V3BandwidthsFile, FILENAME, NULL),
V(GuardfractionFile, FILENAME, NULL),
- VAR("VersioningAuthoritativeDirectory",BOOL,VersioningAuthoritativeDir, "0"),
OBSOLETE("VoteOnHidServDirectoriesV2"),
V(VirtualAddrNetworkIPv4, STRING, "127.192.0.0/10"),
V(VirtualAddrNetworkIPv6, STRING, "[FE80::]/10"),
@@ -698,15 +698,16 @@ static const config_var_t option_vars_[] = {
VAR_NODUMP("__ReloadTorrcOnSIGHUP", BOOL, ReloadTorrcOnSIGHUP, "1"),
VAR_NODUMP("__AllDirActionsPrivate", BOOL, AllDirActionsPrivate, "0"),
VAR_NODUMP("__DisablePredictedCircuits",BOOL,DisablePredictedCircuits, "0"),
- VAR_NODUMP("__DisableSignalHandlers", BOOL, DisableSignalHandlers, "0"),
+ VAR_NODUMP_IMMUTABLE("__DisableSignalHandlers", BOOL,
+ DisableSignalHandlers, "0"),
VAR_NODUMP("__LeaveStreamsUnattached",BOOL, LeaveStreamsUnattached, "0"),
VAR_NODUMP("__HashedControlSessionPassword", LINELIST,
HashedControlSessionPassword,
NULL),
- VAR_NODUMP("__OwningControllerProcess",STRING,OwningControllerProcess, NULL),
- VAR_NODUMP("__OwningControllerFD", UINT64, OwningControllerFD,
+ VAR_NODUMP("__OwningControllerProcess",STRING,
+ OwningControllerProcess, NULL),
+ VAR_NODUMP_IMMUTABLE("__OwningControllerFD", UINT64, OwningControllerFD,
UINT64_MAX_STRING),
- V(MinUptimeHidServDirectoryV2, INTERVAL, "96 hours"),
V(TestingServerDownloadInitialDelay, CSV_INTERVAL, "0"),
V(TestingClientDownloadInitialDelay, CSV_INTERVAL, "0"),
V(TestingServerConsensusDownloadInitialDelay, CSV_INTERVAL, "0"),
@@ -752,12 +753,6 @@ static const config_var_t option_vars_[] = {
OBSOLETE("TestingDescriptorMaxDownloadTries"),
OBSOLETE("TestingMicrodescMaxDownloadTries"),
OBSOLETE("TestingCertMaxDownloadTries"),
- V_D(TestingDirAuthVoteExit, ROUTERSET, NULL),
- V(TestingDirAuthVoteExitIsStrict, BOOL, "0"),
- V_D(TestingDirAuthVoteGuard, ROUTERSET, NULL),
- V(TestingDirAuthVoteGuardIsStrict, BOOL, "0"),
- V_D(TestingDirAuthVoteHSDir, ROUTERSET, NULL),
- V(TestingDirAuthVoteHSDirIsStrict, BOOL, "0"),
VAR_INVIS("___UsingTestNetworkDefaults", BOOL, UsingTestNetworkDefaults_,
"0"),
@@ -766,7 +761,9 @@ static const config_var_t option_vars_[] = {
/** List of default directory authorities */
static const char *default_authorities[] = {
+#ifndef COCCI
#include "auth_dirs.inc"
+#endif
NULL
};
@@ -774,7 +771,9 @@ static const char *default_authorities[] = {
* relays that meet certain stability criteria.
*/
static const char *default_fallbacks[] = {
+#ifndef COCCI
#include "fallback_dirs.inc"
+#endif
NULL
};
@@ -784,7 +783,9 @@ static const struct {
const char *k;
const char *v;
} testing_tor_network_defaults[] = {
+#ifndef COCCI
#include "testnet.inc"
+#endif
{ NULL, NULL }
};
@@ -807,38 +808,24 @@ static const config_deprecation_t option_deprecation_notes_[] = {
"effect on clients since 0.2.8." },
/* End of options deprecated since 0.3.2.2-alpha. */
+ /* Options deprecated since 0.4.3.1-alpha. */
+ { "ClientAutoIPv6ORPort", "This option is unreliable if a connection isn't "
+ "reliably dual-stack."},
+ /* End of options deprecated since 0.4.3.1-alpha. */
+
{ NULL, NULL }
};
#ifdef _WIN32
static char *get_windows_conf_root(void);
#endif
-static int options_act_reversible(const or_options_t *old_options, char **msg);
-static int options_transition_allowed(const or_options_t *old,
- const or_options_t *new,
- char **msg);
-static int options_transition_affects_workers(
- const or_options_t *old_options, const or_options_t *new_options);
-static int options_transition_affects_descriptor(
- const or_options_t *old_options, const or_options_t *new_options);
-static int options_transition_affects_dirauth_timing(
- const or_options_t *old_options, const or_options_t *new_options);
-static int normalize_nickname_list(config_line_t **normalized_out,
- const config_line_t *lst, const char *name,
- char **msg);
-static char *get_bindaddr_from_transport_listen_line(const char *line,
- const char *transport);
-static int parse_ports(or_options_t *options, int validate_only,
- char **msg_out, int *n_ports_out,
- int *world_writable_control_socket);
-static int check_server_ports(const smartlist_t *ports,
- const or_options_t *options,
- int *num_low_ports_out);
+
+static int options_check_transition_cb(const void *old,
+ const void *new,
+ char **msg);
static int validate_data_directories(or_options_t *options);
static int write_configuration_file(const char *fname,
const or_options_t *options);
-static int options_init_logs(const or_options_t *old_options,
- or_options_t *options, int validate_only);
static void init_libevent(const or_options_t *options);
static int opt_streq(const char *s1, const char *s2);
@@ -846,31 +833,37 @@ static int parse_outbound_addresses(or_options_t *options, int validate_only,
char **msg);
static void config_maybe_load_geoip_files_(const or_options_t *options,
const or_options_t *old_options);
-static int options_validate_cb(void *old_options, void *options,
- void *default_options,
- int from_setconf, char **msg);
+static int options_validate_cb(const void *old_options, void *options,
+ char **msg);
static void cleanup_protocol_warning_severity_level(void);
static void set_protocol_warning_severity_level(int warning_severity);
static void options_clear_cb(const config_mgr_t *mgr, void *opts);
+static setopt_err_t options_validate_and_set(const or_options_t *old_options,
+ or_options_t *new_options,
+ char **msg_out);
+struct listener_transaction_t;
+static void options_rollback_listener_transaction(
+ struct listener_transaction_t *xn);
/** Magic value for or_options_t. */
#define OR_OPTIONS_MAGIC 9090909
/** Configuration format for or_options_t. */
static const config_format_t options_format = {
- sizeof(or_options_t),
- {
+ .size = sizeof(or_options_t),
+ .magic = {
"or_options_t",
OR_OPTIONS_MAGIC,
offsetof(or_options_t, magic_),
},
- option_abbrevs_,
- option_deprecation_notes_,
- option_vars_,
- options_validate_cb,
- options_clear_cb,
- NULL,
- offsetof(or_options_t, subconfigs_),
+ .abbrevs = option_abbrevs_,
+ .deprecations = option_deprecation_notes_,
+ .vars = option_vars_,
+ .legacy_validate_fn = options_validate_cb,
+ .check_transition_fn = options_check_transition_cb,
+ .clear_fn = options_clear_cb,
+ .has_config_suite = true,
+ .config_suite_offset = offsetof(or_options_t, subconfigs_),
};
/*
@@ -886,21 +879,15 @@ static or_options_t *global_default_options = NULL;
static char *torrc_fname = NULL;
/** Name of the most recently read torrc-defaults file.*/
static char *torrc_defaults_fname = NULL;
-/** Configuration options set by command line. */
-static config_line_t *global_cmdline_options = NULL;
-/** Non-configuration options set by the command line */
-static config_line_t *global_cmdline_only_options = NULL;
-/** Boolean: Have we parsed the command line? */
-static int have_parsed_cmdline = 0;
-/** Contents of most recently read DirPortFrontPage file. */
-static char *global_dirfrontpagecontents = NULL;
+/** Result of parsing the command line. */
+static parsed_cmdline_t *global_cmdline = NULL;
/** List of port_cfg_t for all configured ports. */
static smartlist_t *configured_ports = NULL;
/** True iff we're currently validating options, and any calls to
* get_options() are likely to be bugs. */
static int in_option_validation = 0;
-/* True iff we've initialized libevent */
-static int libevent_initialized = 0;
+/** True iff we have run options_act_once_on_startup() */
+static bool have_set_startup_options = false;
/* A global configuration manager to handle all configuration objects. */
static config_mgr_t *options_mgr = NULL;
@@ -911,17 +898,16 @@ get_options_mgr(void)
{
if (PREDICT_UNLIKELY(options_mgr == NULL)) {
options_mgr = config_mgr_new(&options_format);
+ int rv = subsystems_register_options_formats(options_mgr);
+ tor_assert(rv == 0);
config_mgr_freeze(options_mgr);
}
return options_mgr;
}
-/** Return the contents of our frontpage string, or NULL if not configured. */
-MOCK_IMPL(const char*,
-get_dirportfrontpage, (void))
-{
- return global_dirfrontpagecontents;
-}
+#define CHECK_OPTIONS_MAGIC(opt) STMT_BEGIN \
+ config_check_toplevel_magic(get_options_mgr(), (opt)); \
+ STMT_END
/** Returns the currently configured options. */
MOCK_IMPL(or_options_t *,
@@ -981,7 +967,8 @@ set_options(or_options_t *new_val, char **msg)
global_options = old_options;
return -1;
}
- if (options_act(old_options) < 0) { /* acting on the options failed. die. */
+ if (subsystems_set_options(get_options_mgr(), new_val) < 0 ||
+ options_act(old_options) < 0) { /* acting on the options failed. die. */
if (! tor_event_loop_shutdown_is_pending()) {
log_err(LD_BUG,
"Acting on config options left us in a broken state. Dying.");
@@ -993,15 +980,9 @@ set_options(or_options_t *new_val, char **msg)
/* Issues a CONF_CHANGED event to notify controller of the change. If Tor is
* just starting up then the old_options will be undefined. */
if (old_options && old_options != global_options) {
- smartlist_t *elements = smartlist_new();
config_line_t *changes =
config_get_changes(get_options_mgr(), old_options, new_val);
- for (config_line_t *line = changes; line; line = line->next) {
- smartlist_add(elements, line->key);
- smartlist_add(elements, line->value);
- }
- control_event_conf_changed(elements);
- smartlist_free(elements);
+ control_event_conf_changed(changes);
config_free_lines(changes);
}
@@ -1022,6 +1003,7 @@ static void
options_clear_cb(const config_mgr_t *mgr, void *opts)
{
(void)mgr;
+ CHECK_OPTIONS_MAGIC(opts);
or_options_t *options = opts;
routerset_free(options->ExcludeExitNodesUnion_);
@@ -1065,11 +1047,7 @@ config_free_all(void)
or_options_free(global_default_options);
global_default_options = NULL;
- config_free_lines(global_cmdline_options);
- global_cmdline_options = NULL;
-
- config_free_lines(global_cmdline_only_options);
- global_cmdline_only_options = NULL;
+ parsed_cmdline_free(global_cmdline);
if (configured_ports) {
SMARTLIST_FOREACH(configured_ports,
@@ -1080,12 +1058,10 @@ config_free_all(void)
tor_free(torrc_fname);
tor_free(torrc_defaults_fname);
- tor_free(global_dirfrontpagecontents);
cleanup_protocol_warning_severity_level();
- have_parsed_cmdline = 0;
- libevent_initialized = 0;
+ have_set_startup_options = false;
config_mgr_free(options_mgr);
}
@@ -1240,7 +1216,8 @@ add_default_fallback_dir_servers,(void))
* user if we changed any dangerous ones.
*/
static int
-validate_dir_servers(or_options_t *options, or_options_t *old_options)
+validate_dir_servers(const or_options_t *options,
+ const or_options_t *old_options)
{
config_line_t *cl;
@@ -1421,27 +1398,24 @@ create_keys_directory(const or_options_t *options)
/* Helps determine flags to pass to switch_id. */
static int have_low_ports = -1;
-/** Fetch the active option list, and take actions based on it. All of the
- * things we do should survive being done repeatedly. If present,
- * <b>old_options</b> contains the previous value of the options.
- *
- * Return 0 if all goes well, return -1 if things went badly.
- */
+/** Take case of initial startup tasks that must occur before any of the
+ * transactional option-related changes are allowed. */
static int
-options_act_reversible(const or_options_t *old_options, char **msg)
+options_act_once_on_startup(char **msg_out)
{
- smartlist_t *new_listeners = smartlist_new();
- or_options_t *options = get_options_mutable();
- int running_tor = options->command == CMD_RUN_TOR;
- int set_conn_limit = 0;
- int r = -1;
- int logs_marked = 0, logs_initialized = 0;
- int old_min_log_level = get_min_log_level();
+ if (have_set_startup_options)
+ return 0;
+
+ const or_options_t *options = get_options();
+ const bool running_tor = options->command == CMD_RUN_TOR;
+
+ if (!running_tor)
+ return 0;
/* Daemonize _first_, since we only want to open most of this stuff in
* the subprocess. Libevent bases can't be reliably inherited across
* processes. */
- if (running_tor && options->RunAsDaemon) {
+ if (options->RunAsDaemon) {
if (! start_daemon_has_been_called())
subsystems_prefork();
/* No need to roll back, since you can't change the value. */
@@ -1454,105 +1428,43 @@ options_act_reversible(const or_options_t *old_options, char **msg)
sd_notifyf(0, "MAINPID=%ld\n", (long int)getpid());
#endif
-#ifndef HAVE_SYS_UN_H
- if (options->ControlSocket || options->ControlSocketsGroupWritable) {
- *msg = tor_strdup("Unix domain sockets (ControlSocket) not supported "
- "on this OS/with this build.");
- goto rollback;
- }
-#else /* defined(HAVE_SYS_UN_H) */
- if (options->ControlSocketsGroupWritable && !options->ControlSocket) {
- *msg = tor_strdup("Setting ControlSocketGroupWritable without setting"
- "a ControlSocket makes no sense.");
- goto rollback;
- }
-#endif /* !defined(HAVE_SYS_UN_H) */
-
- if (running_tor) {
- int n_ports=0;
- /* We need to set the connection limit before we can open the listeners. */
- if (! sandbox_is_active()) {
- if (set_max_file_descriptors((unsigned)options->ConnLimit,
- &options->ConnLimit_) < 0) {
- *msg = tor_strdup("Problem with ConnLimit value. "
- "See logs for details.");
- goto rollback;
- }
- set_conn_limit = 1;
- } else {
- tor_assert(old_options);
- options->ConnLimit_ = old_options->ConnLimit_;
- }
-
- /* Set up libevent. (We need to do this before we can register the
- * listeners as listeners.) */
- if (running_tor && !libevent_initialized) {
- init_libevent(options);
- libevent_initialized = 1;
-
- /* This has to come up after libevent is initialized. */
- control_initialize_event_queue();
-
- /*
- * Initialize the scheduler - this has to come after
- * options_init_from_torrc() sets up libevent - why yes, that seems
- * completely sensible to hide the libevent setup in the option parsing
- * code! It also needs to happen before init_keys(), so it needs to
- * happen here too. How yucky. */
- scheduler_init();
- }
-
- /* Adjust the port configuration so we can launch listeners. */
- if (parse_ports(options, 0, msg, &n_ports, NULL)) {
- if (!*msg)
- *msg = tor_strdup("Unexpected problem parsing port config");
- goto rollback;
- }
-
- /* Set the hibernation state appropriately.*/
- consider_hibernation(time(NULL));
-
- /* Launch the listeners. (We do this before we setuid, so we can bind to
- * ports under 1024.) We don't want to rebind if we're hibernating or
- * shutting down. If networking is disabled, this will close all but the
- * control listeners, but disable those. */
- if (!we_are_hibernating()) {
- if (retry_all_listeners(new_listeners, options->DisableNetwork) < 0) {
- *msg = tor_strdup("Failed to bind one of the listener ports.");
- goto rollback;
- }
- }
- if (options->DisableNetwork) {
- /* Aggressively close non-controller stuff, NOW */
- log_notice(LD_NET, "DisableNetwork is set. Tor will not make or accept "
- "non-control network connections. Shutting down all existing "
- "connections.");
- connection_mark_all_noncontrol_connections();
- /* We can't complete circuits until the network is re-enabled. */
- note_that_we_maybe_cant_complete_circuits();
- }
- }
+ /* Set up libevent. (We need to do this before we can register the
+ * listeners as listeners.) */
+ init_libevent(options);
-#if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
- /* Open /dev/pf before dropping privileges. */
- if (options->TransPort_set &&
- options->TransProxyType_parsed == TPT_DEFAULT) {
- if (get_pf_socket() < 0) {
- *msg = tor_strdup("Unable to open /dev/pf for transparent proxy.");
- goto rollback;
- }
- }
-#endif /* defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H) */
+ /* This has to come up after libevent is initialized. */
+ control_initialize_event_queue();
- /* Attempt to lock all current and future memory with mlockall() only once */
+ /*
+ * Initialize the scheduler - this has to come after
+ * options_init_from_torrc() sets up libevent - why yes, that seems
+ * completely sensible to hide the libevent setup in the option parsing
+ * code! It also needs to happen before init_keys(), so it needs to
+ * happen here too. How yucky. */
+ scheduler_init();
+
+ /* Attempt to lock all current and future memory with mlockall() only once.
+ * This must happen before setuid. */
if (options->DisableAllSwap) {
if (tor_mlockall() == -1) {
- *msg = tor_strdup("DisableAllSwap failure. Do you have proper "
+ *msg_out = tor_strdup("DisableAllSwap failure. Do you have proper "
"permissions?");
- goto done;
+ return -1;
}
}
+ have_set_startup_options = true;
+ return 0;
+}
+
+/**
+ * Change our user ID if we're configured to do so.
+ **/
+static int
+options_switch_id(char **msg_out)
+{
+ const or_options_t *options = get_options();
+
/* Setuid/setgid as appropriate */
if (options->User) {
tor_assert(have_low_ports != -1);
@@ -1566,11 +1478,52 @@ options_act_reversible(const or_options_t *old_options, char **msg)
}
if (switch_id(options->User, switch_id_flags) != 0) {
/* No need to roll back, since you can't change the value. */
- *msg = tor_strdup("Problem with User value. See logs for details.");
- goto done;
+ *msg_out = tor_strdup("Problem with User value. See logs for details.");
+ return -1;
}
}
+ return 0;
+}
+
+/**
+ * Helper. Given a data directory (<b>datadir</b>) and another directory
+ * (<b>subdir</b>) with respective group-writable permissions
+ * <b>datadir_gr</b> and <b>subdir_gr</b>, compute whether the subdir should
+ * be group-writeable.
+ **/
+static int
+compute_group_readable_flag(const char *datadir,
+ const char *subdir,
+ int datadir_gr,
+ int subdir_gr)
+{
+ if (subdir_gr != -1) {
+ /* The user specified a default for "subdir", so we always obey it. */
+ return subdir_gr;
+ }
+
+ /* The user left the subdir_gr option on "auto." */
+ if (0 == strcmp(subdir, datadir)) {
+ /* The directories are the same, so we use the group-readable flag from
+ * the datadirectory */
+ return datadir_gr;
+ } else {
+ /* The directores are different, so we default to "not group-readable" */
+ return 0;
+ }
+}
+
+/**
+ * Create our DataDirectory, CacheDirectory, and KeyDirectory, and
+ * set their permissions correctly.
+ */
+STATIC int
+options_create_directories(char **msg_out)
+{
+ const or_options_t *options = get_options();
+ const bool running_tor = options->command == CMD_RUN_TOR;
+
/* Ensure data directory is private; create if possible. */
/* It's okay to do this in "options_act_reversible()" even though it isn't
* actually reversible, since you can't change the DataDirectory while
@@ -1579,58 +1532,288 @@ options_act_reversible(const or_options_t *old_options, char **msg)
options->DataDirectory,
options->DataDirectoryGroupReadable,
options->User,
- msg) < 0) {
- goto done;
+ msg_out) < 0) {
+ return -1;
}
+
+ /* We need to handle the group-readable flag for the cache directory and key
+ * directory specially, since they may be the same as the data directory */
+ const int key_dir_group_readable = compute_group_readable_flag(
+ options->DataDirectory,
+ options->KeyDirectory,
+ options->DataDirectoryGroupReadable,
+ options->KeyDirectoryGroupReadable);
+
if (check_and_create_data_directory(running_tor /* create */,
options->KeyDirectory,
- options->KeyDirectoryGroupReadable,
+ key_dir_group_readable,
options->User,
- msg) < 0) {
- goto done;
+ msg_out) < 0) {
+ return -1;
}
- /* We need to handle the group-readable flag for the cache directory
- * specially, since the directory defaults to being the same as the
- * DataDirectory. */
- int cache_dir_group_readable;
- if (options->CacheDirectoryGroupReadable != -1) {
- /* If the user specified a value, use their setting */
- cache_dir_group_readable = options->CacheDirectoryGroupReadable;
- } else if (!strcmp(options->CacheDirectory, options->DataDirectory)) {
- /* If the user left the value as "auto", and the cache is the same as the
- * datadirectory, use the datadirectory setting.
- */
- cache_dir_group_readable = options->DataDirectoryGroupReadable;
- } else {
- /* Otherwise, "auto" means "not group readable". */
- cache_dir_group_readable = 0;
- }
+ const int cache_dir_group_readable = compute_group_readable_flag(
+ options->DataDirectory,
+ options->CacheDirectory,
+ options->DataDirectoryGroupReadable,
+ options->CacheDirectoryGroupReadable);
+
if (check_and_create_data_directory(running_tor /* create */,
options->CacheDirectory,
cache_dir_group_readable,
options->User,
- msg) < 0) {
- goto done;
+ msg_out) < 0) {
+ return -1;
}
- /* Bail out at this point if we're not going to be a client or server:
- * we don't run Tor itself. */
- if (!running_tor)
- goto commit;
+ return 0;
+}
+
+/** Structure to represent an incomplete configuration of a set of
+ * listeners.
+ *
+ * This structure is generated by options_start_listener_transaction(), and is
+ * either committed by options_commit_listener_transaction() or rolled back by
+ * options_rollback_listener_transaction(). */
+typedef struct listener_transaction_t {
+ bool set_conn_limit; /**< True if we've set the connection limit */
+ unsigned old_conn_limit; /**< If nonzero, previous connlimit value. */
+ smartlist_t *new_listeners; /**< List of new listeners that we opened. */
+} listener_transaction_t;
+
+/**
+ * Start configuring our listeners based on the current value of
+ * get_options().
+ *
+ * The value <b>old_options</b> holds either the previous options object,
+ * or NULL if we're starting for the first time.
+ *
+ * On success, return a listener_transaction_t that we can either roll back or
+ * commit.
+ *
+ * On failure return NULL and write a message into a newly allocated string in
+ * *<b>msg_out</b>.
+ **/
+static listener_transaction_t *
+options_start_listener_transaction(const or_options_t *old_options,
+ char **msg_out)
+{
+ listener_transaction_t *xn = tor_malloc_zero(sizeof(listener_transaction_t));
+ xn->new_listeners = smartlist_new();
+ or_options_t *options = get_options_mutable();
+ const bool running_tor = options->command == CMD_RUN_TOR;
+
+ if (! running_tor) {
+ return xn;
+ }
+
+ int n_ports=0;
+ /* We need to set the connection limit before we can open the listeners. */
+ if (! sandbox_is_active()) {
+ if (set_max_file_descriptors((unsigned)options->ConnLimit,
+ &options->ConnLimit_) < 0) {
+ *msg_out = tor_strdup("Problem with ConnLimit value. "
+ "See logs for details.");
+ goto rollback;
+ }
+ xn->set_conn_limit = true;
+ if (old_options)
+ xn->old_conn_limit = (unsigned)old_options->ConnLimit;
+ } else {
+ tor_assert(old_options);
+ options->ConnLimit_ = old_options->ConnLimit_;
+ }
+
+ /* Adjust the port configuration so we can launch listeners. */
+ /* 31851: some ports are relay-only */
+ if (parse_ports(options, 0, msg_out, &n_ports, NULL)) {
+ if (!*msg_out)
+ *msg_out = tor_strdup("Unexpected problem parsing port config");
+ goto rollback;
+ }
+
+ /* Set the hibernation state appropriately.*/
+ consider_hibernation(time(NULL));
+
+ /* Launch the listeners. (We do this before we setuid, so we can bind to
+ * ports under 1024.) We don't want to rebind if we're hibernating or
+ * shutting down. If networking is disabled, this will close all but the
+ * control listeners, but disable those. */
+ /* 31851: some listeners are relay-only */
+ if (!we_are_hibernating()) {
+ if (retry_all_listeners(xn->new_listeners,
+ options->DisableNetwork) < 0) {
+ *msg_out = tor_strdup("Failed to bind one of the listener ports.");
+ goto rollback;
+ }
+ }
+ if (options->DisableNetwork) {
+ /* Aggressively close non-controller stuff, NOW */
+ log_notice(LD_NET, "DisableNetwork is set. Tor will not make or accept "
+ "non-control network connections. Shutting down all existing "
+ "connections.");
+ connection_mark_all_noncontrol_connections();
+ /* We can't complete circuits until the network is re-enabled. */
+ note_that_we_maybe_cant_complete_circuits();
+ }
+
+#if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
+ /* Open /dev/pf before (possibly) dropping privileges. */
+ if (options->TransPort_set &&
+ options->TransProxyType_parsed == TPT_DEFAULT) {
+ if (get_pf_socket() < 0) {
+ *msg_out = tor_strdup("Unable to open /dev/pf for transparent proxy.");
+ goto rollback;
+ }
+ }
+#endif /* defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H) */
+
+ return xn;
+
+ rollback:
+ options_rollback_listener_transaction(xn);
+ return NULL;
+}
+
+/**
+ * Finish configuring the listeners that started to get configured with
+ * <b>xn</b>. Frees <b>xn</b>.
+ **/
+static void
+options_commit_listener_transaction(listener_transaction_t *xn)
+{
+ tor_assert(xn);
+ if (xn->set_conn_limit) {
+ or_options_t *options = get_options_mutable();
+ /*
+ * If we adjusted the conn limit, recompute the OOS threshold too
+ *
+ * How many possible sockets to keep in reserve? If we have lots of
+ * possible sockets, keep this below a limit and set ConnLimit_high_thresh
+ * very close to ConnLimit_, but if ConnLimit_ is low, shrink it in
+ * proportion.
+ *
+ * Somewhat arbitrarily, set socks_in_reserve to 5% of ConnLimit_, but
+ * cap it at 64.
+ */
+ int socks_in_reserve = options->ConnLimit_ / 20;
+ if (socks_in_reserve > 64) socks_in_reserve = 64;
+
+ options->ConnLimit_high_thresh = options->ConnLimit_ - socks_in_reserve;
+ options->ConnLimit_low_thresh = (options->ConnLimit_ / 4) * 3;
+ log_info(LD_GENERAL,
+ "Recomputed OOS thresholds: ConnLimit %d, ConnLimit_ %d, "
+ "ConnLimit_high_thresh %d, ConnLimit_low_thresh %d",
+ options->ConnLimit, options->ConnLimit_,
+ options->ConnLimit_high_thresh,
+ options->ConnLimit_low_thresh);
+
+ /* Give the OOS handler a chance with the new thresholds */
+ connection_check_oos(get_n_open_sockets(), 0);
+ }
+
+ smartlist_free(xn->new_listeners);
+ tor_free(xn);
+}
+
+/**
+ * Revert the listener configuration changes that that started to get
+ * configured with <b>xn</b>. Frees <b>xn</b>.
+ **/
+static void
+options_rollback_listener_transaction(listener_transaction_t *xn)
+{
+ if (! xn)
+ return;
+
+ or_options_t *options = get_options_mutable();
+
+ if (xn->set_conn_limit && xn->old_conn_limit)
+ set_max_file_descriptors(xn->old_conn_limit, &options->ConnLimit_);
+
+ SMARTLIST_FOREACH(xn->new_listeners, connection_t *, conn,
+ {
+ log_notice(LD_NET, "Closing partially-constructed %s on %s:%d",
+ conn_type_to_string(conn->type), conn->address, conn->port);
+ connection_close_immediate(conn);
+ connection_mark_for_close(conn);
+ });
+
+ smartlist_free(xn->new_listeners);
+ tor_free(xn);
+}
+
+/** Structure to represent an incomplete configuration of a set of logs.
+ *
+ * This structure is generated by options_start_log_transaction(), and is
+ * either committed by options_commit_log_transaction() or rolled back by
+ * options_rollback_log_transaction(). */
+typedef struct log_transaction_t {
+ /** Previous lowest severity of any configured log. */
+ int old_min_log_level;
+ /** True if we have marked the previous logs to be closed */
+ bool logs_marked;
+ /** True if we initialized the new set of logs */
+ bool logs_initialized;
+ /** True if our safelogging configuration is different from what it was
+ * previously (or if we are starting for the first time). */
+ bool safelogging_changed;
+} log_transaction_t;
+
+/**
+ * Start configuring our logs based on the current value of get_options().
+ *
+ * The value <b>old_options</b> holds either the previous options object,
+ * or NULL if we're starting for the first time.
+ *
+ * On success, return a log_transaction_t that we can either roll back or
+ * commit.
+ *
+ * On failure return NULL and write a message into a newly allocated string in
+ * *<b>msg_out</b>.
+ **/
+STATIC log_transaction_t *
+options_start_log_transaction(const or_options_t *old_options,
+ char **msg_out)
+{
+ const or_options_t *options = get_options();
+ const bool running_tor = options->command == CMD_RUN_TOR;
+
+ log_transaction_t *xn = tor_malloc_zero(sizeof(log_transaction_t));
+ xn->old_min_log_level = get_min_log_level();
+ xn->safelogging_changed = !old_options ||
+ old_options->SafeLogging_ != options->SafeLogging_;
+
+ if (! running_tor)
+ goto done;
mark_logs_temp(); /* Close current logs once new logs are open. */
- logs_marked = 1;
+ xn->logs_marked = true;
/* Configure the tor_log(s) */
if (options_init_logs(old_options, options, 0)<0) {
- *msg = tor_strdup("Failed to init Log options. See logs for details.");
- goto rollback;
+ *msg_out = tor_strdup("Failed to init Log options. See logs for details.");
+ options_rollback_log_transaction(xn);
+ xn = NULL;
+ goto done;
}
- logs_initialized = 1;
- commit:
- r = 0;
- if (logs_marked) {
+ xn->logs_initialized = true;
+
+ done:
+ return xn;
+}
+
+/**
+ * Finish configuring the logs that started to get configured with <b>xn</b>.
+ * Frees <b>xn</b>.
+ **/
+STATIC void
+options_commit_log_transaction(log_transaction_t *xn)
+{
+ const or_options_t *options = get_options();
+ tor_assert(xn);
+
+ if (xn->logs_marked) {
log_severity_list_t *severity =
tor_malloc_zero(sizeof(log_severity_list_t));
close_temp_logs();
@@ -1640,7 +1823,8 @@ options_act_reversible(const or_options_t *old_options, char **msg)
tor_free(severity);
tor_log_update_sigsafe_err_fds();
}
- if (logs_initialized) {
+
+ if (xn->logs_initialized) {
flush_log_messages_from_startup();
}
@@ -1649,12 +1833,12 @@ options_act_reversible(const or_options_t *old_options, char **msg)
int bad_safelog = 0, bad_severity = 0, new_badness = 0;
if (options->SafeLogging_ != SAFELOG_SCRUB_ALL) {
bad_safelog = 1;
- if (!old_options || old_options->SafeLogging_ != options->SafeLogging_)
+ if (xn->safelogging_changed)
new_badness = 1;
}
if (get_min_log_level() >= LOG_INFO) {
bad_severity = 1;
- if (get_min_log_level() != old_min_log_level)
+ if (get_min_log_level() != xn->old_min_log_level)
new_badness = 1;
}
if (bad_safelog && bad_severity)
@@ -1670,59 +1854,105 @@ options_act_reversible(const or_options_t *old_options, char **msg)
"Overwrite the log afterwards.", badness);
}
- if (set_conn_limit) {
- /*
- * If we adjusted the conn limit, recompute the OOS threshold too
- *
- * How many possible sockets to keep in reserve? If we have lots of
- * possible sockets, keep this below a limit and set ConnLimit_high_thresh
- * very close to ConnLimit_, but if ConnLimit_ is low, shrink it in
- * proportion.
- *
- * Somewhat arbitrarily, set socks_in_reserve to 5% of ConnLimit_, but
- * cap it at 64.
- */
- int socks_in_reserve = options->ConnLimit_ / 20;
- if (socks_in_reserve > 64) socks_in_reserve = 64;
+ tor_free(xn);
+}
- options->ConnLimit_high_thresh = options->ConnLimit_ - socks_in_reserve;
- options->ConnLimit_low_thresh = (options->ConnLimit_ / 4) * 3;
- log_info(LD_GENERAL,
- "Recomputed OOS thresholds: ConnLimit %d, ConnLimit_ %d, "
- "ConnLimit_high_thresh %d, ConnLimit_low_thresh %d",
- options->ConnLimit, options->ConnLimit_,
- options->ConnLimit_high_thresh,
- options->ConnLimit_low_thresh);
+/**
+ * Revert the log configuration changes that that started to get configured
+ * with <b>xn</b>. Frees <b>xn</b>.
+ **/
+STATIC void
+options_rollback_log_transaction(log_transaction_t *xn)
+{
+ if (!xn)
+ return;
- /* Give the OOS handler a chance with the new thresholds */
- connection_check_oos(get_n_open_sockets(), 0);
+ if (xn->logs_marked) {
+ rollback_log_changes();
+ control_adjust_event_log_severity();
+ }
+
+ tor_free(xn);
+}
+
+/**
+ * Fetch the active option list, and take actions based on it. All of
+ * the things we do in this function should survive being done
+ * repeatedly, OR be done only once when starting Tor. If present,
+ * <b>old_options</b> contains the previous value of the options.
+ *
+ * This function is only truly "reversible" _after_ the first time it
+ * is run. The first time that it runs, it performs some irreversible
+ * tasks in the correct sequence between the reversible option changes.
+ *
+ * Option changes should only be marked as "reversible" if they cannot
+ * be validated before switching them, but they can be switched back if
+ * some other validation fails.
+ *
+ * Return 0 if all goes well, return -1 if things went badly.
+ */
+MOCK_IMPL(STATIC int,
+options_act_reversible,(const or_options_t *old_options, char **msg))
+{
+ const bool first_time = ! have_set_startup_options;
+ log_transaction_t *log_transaction = NULL;
+ listener_transaction_t *listener_transaction = NULL;
+ int r = -1;
+
+ /* The ordering of actions in this function is not free, sadly.
+ *
+ * First of all, we _must_ daemonize before we take all kinds of
+ * initialization actions, since they need to happen in the
+ * subprocess.
+ */
+ if (options_act_once_on_startup(msg) < 0)
+ goto rollback;
+
+ /* Once we've handled most of once-off initialization, we need to
+ * open our listeners before we switch IDs. (If we open listeners first,
+ * we might not be able to bind to low ports.)
+ */
+ listener_transaction = options_start_listener_transaction(old_options, msg);
+ if (listener_transaction == NULL)
+ goto rollback;
+
+ if (first_time) {
+ if (options_switch_id(msg) < 0)
+ goto rollback;
}
+ /* On the other hand, we need to touch the file system _after_ we
+ * switch IDs: otherwise, we'll be making directories and opening files
+ * with the wrong permissions.
+ */
+ if (first_time) {
+ if (options_create_directories(msg) < 0)
+ goto rollback;
+ }
+
+ /* Bail out at this point if we're not going to be a client or server:
+ * we don't run Tor itself. */
+ log_transaction = options_start_log_transaction(old_options, msg);
+ if (log_transaction == NULL)
+ goto rollback;
+
+ // Commit!
+ r = 0;
+
+ options_commit_log_transaction(log_transaction);
+
+ options_commit_listener_transaction(listener_transaction);
+
goto done;
rollback:
r = -1;
tor_assert(*msg);
- if (logs_marked) {
- rollback_log_changes();
- control_adjust_event_log_severity();
- }
-
- if (set_conn_limit && old_options)
- set_max_file_descriptors((unsigned)old_options->ConnLimit,
- &options->ConnLimit_);
-
- SMARTLIST_FOREACH(new_listeners, connection_t *, conn,
- {
- log_notice(LD_NET, "Closing partially-constructed %s on %s:%d",
- conn_type_to_string(conn->type), conn->address, conn->port);
- connection_close_immediate(conn);
- connection_mark_for_close(conn);
- });
+ options_rollback_log_transaction(log_transaction);
+ options_rollback_listener_transaction(listener_transaction);
done:
- smartlist_free(new_listeners);
return r;
}
@@ -1753,32 +1983,6 @@ options_need_geoip_info(const or_options_t *options, const char **reason_out)
return bridge_usage || routerset_usage;
}
-/** Return the bandwidthrate that we are going to report to the authorities
- * based on the config options. */
-uint32_t
-get_effective_bwrate(const or_options_t *options)
-{
- uint64_t bw = options->BandwidthRate;
- if (bw > options->MaxAdvertisedBandwidth)
- bw = options->MaxAdvertisedBandwidth;
- if (options->RelayBandwidthRate > 0 && bw > options->RelayBandwidthRate)
- bw = options->RelayBandwidthRate;
- /* ensure_bandwidth_cap() makes sure that this cast can't overflow. */
- return (uint32_t)bw;
-}
-
-/** Return the bandwidthburst that we are going to report to the authorities
- * based on the config options. */
-uint32_t
-get_effective_bwburst(const or_options_t *options)
-{
- uint64_t bw = options->BandwidthBurst;
- if (options->RelayBandwidthBurst > 0 && bw > options->RelayBandwidthBurst)
- bw = options->RelayBandwidthBurst;
- /* ensure_bandwidth_cap() makes sure that this cast can't overflow. */
- return (uint32_t)bw;
-}
-
/* Used in the various options_transition_affects* functions. */
#define YES_IF_CHANGED_BOOL(opt) \
if (!CFG_EQ_BOOL(old_options, new_options, opt)) return 1;
@@ -1821,32 +2025,6 @@ options_transition_affects_guards(const or_options_t *old_options,
return 0;
}
-/**
- * Return true if changing the configuration from <b>old</b> to <b>new</b>
- * affects the timing of the voting subsystem
- */
-static int
-options_transition_affects_dirauth_timing(const or_options_t *old_options,
- const or_options_t *new_options)
-{
- tor_assert(old_options);
- tor_assert(new_options);
-
- if (authdir_mode_v3(old_options) != authdir_mode_v3(new_options))
- return 1;
- if (! authdir_mode_v3(new_options))
- return 0;
- YES_IF_CHANGED_INT(V3AuthVotingInterval);
- YES_IF_CHANGED_INT(V3AuthVoteDelay);
- YES_IF_CHANGED_INT(V3AuthDistDelay);
- YES_IF_CHANGED_INT(TestingV3AuthInitialVotingInterval);
- YES_IF_CHANGED_INT(TestingV3AuthInitialVoteDelay);
- YES_IF_CHANGED_INT(TestingV3AuthInitialDistDelay);
- YES_IF_CHANGED_INT(TestingV3AuthVotingStartOffset);
-
- return 0;
-}
-
/** Fetch the active option list, and take actions based on it. All of the
* things we do should survive being done repeatedly. If present,
* <b>old_options</b> contains the previous value of the options.
@@ -1854,17 +2032,16 @@ options_transition_affects_dirauth_timing(const or_options_t *old_options,
* Return 0 if all goes well, return -1 if it's time to die.
*
* Note: We haven't moved all the "act on new configuration" logic
- * here yet. Some is still in do_hup() and other places.
+ * the options_act* functions yet. Some is still in do_hup() and other
+ * places.
*/
-STATIC int
-options_act(const or_options_t *old_options)
+MOCK_IMPL(STATIC int,
+options_act,(const or_options_t *old_options))
{
config_line_t *cl;
or_options_t *options = get_options_mutable();
int running_tor = options->command == CMD_RUN_TOR;
char *msg=NULL;
- const int transition_affects_workers =
- old_options && options_transition_affects_workers(old_options, options);
const int transition_affects_guards =
old_options && options_transition_affects_guards(old_options, options);
@@ -1922,19 +2099,6 @@ options_act(const or_options_t *old_options)
"in a non-anonymous mode. It will provide NO ANONYMITY.");
}
- /* If we are a bridge with a pluggable transport proxy but no
- Extended ORPort, inform the user that they are missing out. */
- if (server_mode(options) && options->ServerTransportPlugin &&
- !options->ExtORPort_lines) {
- log_notice(LD_CONFIG, "We use pluggable transports but the Extended "
- "ORPort is disabled. Tor and your pluggable transports proxy "
- "communicate with each other via the Extended ORPort so it "
- "is suggested you enable it: it will also allow your Bridge "
- "to collect statistics about its clients that use pluggable "
- "transports. Please enable it using the ExtORPort torrc option "
- "(e.g. set 'ExtORPort auto').");
- }
-
if (options->Bridges) {
mark_bridge_list();
for (cl = options->Bridges; cl; cl = cl->next) {
@@ -1984,22 +2148,17 @@ options_act(const or_options_t *old_options)
if (! or_state_loaded() && running_tor) {
if (or_state_load())
return -1;
- rep_hist_load_mtbf_data(time(NULL));
- }
-
- /* If we have an ExtORPort, initialize its auth cookie. */
- if (running_tor &&
- init_ext_or_cookie_authentication(!!options->ExtORPort_lines) < 0) {
- log_warn(LD_CONFIG,"Error creating Extended ORPort cookie file.");
- return -1;
+ if (options_act_dirauth_mtbf(options) < 0)
+ return -1;
}
+ /* 31851: some of the code in these functions is relay-only */
mark_transport_list();
pt_prepare_proxy_list_for_config_read();
if (!options->DisableNetwork) {
if (options->ClientTransportPlugin) {
for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
- if (parse_transport_line(options, cl->value, 0, 0) < 0) {
+ if (pt_parse_transport_line(options, cl->value, 0, 0) < 0) {
// LCOV_EXCL_START
log_warn(LD_BUG,
"Previously validated ClientTransportPlugin line "
@@ -2009,20 +2168,11 @@ options_act(const or_options_t *old_options)
}
}
}
-
- if (options->ServerTransportPlugin && server_mode(options)) {
- for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
- if (parse_transport_line(options, cl->value, 0, 1) < 0) {
- // LCOV_EXCL_START
- log_warn(LD_BUG,
- "Previously validated ServerTransportPlugin line "
- "could not be added!");
- return -1;
- // LCOV_EXCL_STOP
- }
- }
- }
}
+
+ if (options_act_server_transport(old_options) < 0)
+ return -1;
+
sweep_transport_list();
sweep_proxy_list();
@@ -2043,16 +2193,8 @@ options_act(const or_options_t *old_options)
finish_daemon(options->DataDirectory);
}
- /* We want to reinit keys as needed before we do much of anything else:
- keys are important, and other things can depend on them. */
- if (transition_affects_workers ||
- (options->V3AuthoritativeDir && (!old_options ||
- !old_options->V3AuthoritativeDir))) {
- if (init_keys() < 0) {
- log_warn(LD_BUG,"Error initializing keys; exiting");
- return -1;
- }
- }
+ if (options_act_relay(old_options) < 0)
+ return -1;
/* Write our PID to the PID file. If we do not have write permissions we
* will log a warning and exit. */
@@ -2076,15 +2218,6 @@ options_act(const or_options_t *old_options)
return -1;
}
- if (server_mode(options)) {
- static int cdm_initialized = 0;
- if (cdm_initialized == 0) {
- cdm_initialized = 1;
- consdiffmgr_configure(NULL);
- consdiffmgr_validate();
- }
- }
-
if (init_control_cookie_authentication(options->CookieAuthentication) < 0) {
log_warn(LD_CONFIG,"Error creating control cookie authentication file.");
return -1;
@@ -2102,15 +2235,8 @@ options_act(const or_options_t *old_options)
* might be a change of scheduler or parameter. */
scheduler_conf_changed();
- /* Set up accounting */
- if (accounting_parse_options(options, 0)<0) {
- // LCOV_EXCL_START
- log_warn(LD_BUG,"Error in previously validated accounting options");
+ if (options_act_relay_accounting(old_options) < 0)
return -1;
- // LCOV_EXCL_STOP
- }
- if (accounting_is_enabled(options))
- configure_accounting(time(NULL));
/* Change the cell EWMA settings */
cmux_ewma_set_options(options, networkstatus_get_latest_consensus());
@@ -2134,6 +2260,7 @@ options_act(const or_options_t *old_options)
tor_free(http_authenticator);
}
+ /* 31851: OutboundBindAddressExit is relay-only */
if (parse_outbound_addresses(options, 0, &msg) < 0) {
// LCOV_EXCL_START
log_warn(LD_BUG, "Failed parsing previously validated outbound "
@@ -2220,65 +2347,17 @@ options_act(const or_options_t *old_options)
if (revise_automap_entries)
addressmap_clear_invalid_automaps(options);
-/* How long should we delay counting bridge stats after becoming a bridge?
- * We use this so we don't count clients who used our bridge thinking it is
- * a relay. If you change this, don't forget to change the log message
- * below. It's 4 hours (the time it takes to stop being used by clients)
- * plus some extra time for clock skew. */
-#define RELAY_BRIDGE_STATS_DELAY (6 * 60 * 60)
-
- if (! bool_eq(options->BridgeRelay, old_options->BridgeRelay)) {
- int was_relay = 0;
- if (options->BridgeRelay) {
- time_t int_start = time(NULL);
- if (config_lines_eq(old_options->ORPort_lines,options->ORPort_lines)) {
- int_start += RELAY_BRIDGE_STATS_DELAY;
- was_relay = 1;
- }
- geoip_bridge_stats_init(int_start);
- log_info(LD_CONFIG, "We are acting as a bridge now. Starting new "
- "GeoIP stats interval%s.", was_relay ? " in 6 "
- "hours from now" : "");
- } else {
- geoip_bridge_stats_term();
- log_info(LD_GENERAL, "We are no longer acting as a bridge. "
- "Forgetting GeoIP stats.");
- }
- }
-
- if (transition_affects_workers) {
- log_info(LD_GENERAL,
- "Worker-related options changed. Rotating workers.");
- const int server_mode_turned_on =
- server_mode(options) && !server_mode(old_options);
- const int dir_server_mode_turned_on =
- dir_server_mode(options) && !dir_server_mode(old_options);
-
- if (server_mode_turned_on || dir_server_mode_turned_on) {
- cpu_init();
- }
+ if (options_act_bridge_stats(old_options) < 0)
+ return -1;
- if (server_mode_turned_on) {
- ip_address_changed(0);
- if (have_completed_a_circuit() || !any_predicted_circuits(time(NULL)))
- inform_testing_reachability();
- }
- cpuworkers_rotate_keyinfo();
- if (dns_reset())
- return -1;
- } else {
- if (dns_reset())
- return -1;
- }
+ if (dns_reset())
+ return -1;
- if (options->PerConnBWRate != old_options->PerConnBWRate ||
- options->PerConnBWBurst != old_options->PerConnBWBurst)
- connection_or_update_token_buckets(get_connection_array(), options);
+ if (options_act_relay_bandwidth(old_options) < 0)
+ return -1;
if (options->BandwidthRate != old_options->BandwidthRate ||
- options->BandwidthBurst != old_options->BandwidthBurst ||
- options->RelayBandwidthRate != old_options->RelayBandwidthRate ||
- options->RelayBandwidthBurst != old_options->RelayBandwidthBurst)
+ options->BandwidthBurst != old_options->BandwidthBurst)
connection_bucket_adjust(options);
if (options->MainloopStats != old_options->MainloopStats) {
@@ -2286,132 +2365,43 @@ options_act(const or_options_t *old_options)
}
}
+ /* 31851: These options are relay-only, but we need to disable them if we
+ * are in client mode. In 29211, we will disable all relay options in
+ * client mode. */
/* Only collect directory-request statistics on relays and bridges. */
options->DirReqStatistics = options->DirReqStatistics_option &&
server_mode(options);
options->HiddenServiceStatistics =
options->HiddenServiceStatistics_option && server_mode(options);
- if (options->CellStatistics || options->DirReqStatistics ||
- options->EntryStatistics || options->ExitPortStatistics ||
- options->ConnDirectionStatistics ||
- options->HiddenServiceStatistics ||
- options->BridgeAuthoritativeDir) {
- time_t now = time(NULL);
- int print_notice = 0;
-
- /* Only collect other relay-only statistics on relays. */
- if (!public_server_mode(options)) {
- options->CellStatistics = 0;
- options->EntryStatistics = 0;
- options->ConnDirectionStatistics = 0;
- options->ExitPortStatistics = 0;
- }
-
- if ((!old_options || !old_options->CellStatistics) &&
- options->CellStatistics) {
- rep_hist_buffer_stats_init(now);
- print_notice = 1;
- }
- if ((!old_options || !old_options->DirReqStatistics) &&
- options->DirReqStatistics) {
- if (geoip_is_loaded(AF_INET)) {
- geoip_dirreq_stats_init(now);
- print_notice = 1;
- } else {
- /* disable statistics collection since we have no geoip file */
- options->DirReqStatistics = 0;
- if (options->ORPort_set)
- log_notice(LD_CONFIG, "Configured to measure directory request "
- "statistics, but no GeoIP database found. "
- "Please specify a GeoIP database using the "
- "GeoIPFile option.");
- }
- }
- if ((!old_options || !old_options->EntryStatistics) &&
- options->EntryStatistics && !should_record_bridge_info(options)) {
- /* If we get here, we've started recording bridge info when we didn't
- * do so before. Note that "should_record_bridge_info()" will
- * always be false at this point, because of the earlier block
- * that cleared EntryStatistics when public_server_mode() was false.
- * We're leaving it in as defensive programming. */
- if (geoip_is_loaded(AF_INET) || geoip_is_loaded(AF_INET6)) {
- geoip_entry_stats_init(now);
- print_notice = 1;
- } else {
- options->EntryStatistics = 0;
- log_notice(LD_CONFIG, "Configured to measure entry node "
- "statistics, but no GeoIP database found. "
- "Please specify a GeoIP database using the "
- "GeoIPFile option.");
- }
- }
- if ((!old_options || !old_options->ExitPortStatistics) &&
- options->ExitPortStatistics) {
- rep_hist_exit_stats_init(now);
- print_notice = 1;
- }
- if ((!old_options || !old_options->ConnDirectionStatistics) &&
- options->ConnDirectionStatistics) {
- rep_hist_conn_stats_init(now);
- }
- if ((!old_options || !old_options->HiddenServiceStatistics) &&
- options->HiddenServiceStatistics) {
- log_info(LD_CONFIG, "Configured to measure hidden service statistics.");
- rep_hist_hs_stats_init(now);
- }
- if ((!old_options || !old_options->BridgeAuthoritativeDir) &&
- options->BridgeAuthoritativeDir) {
- rep_hist_desc_stats_init(now);
- print_notice = 1;
- }
- if (print_notice)
- log_notice(LD_CONFIG, "Configured to measure statistics. Look for "
- "the *-stats files that will first be written to the "
- "data directory in 24 hours from now.");
- }
-
- /* If we used to have statistics enabled but we just disabled them,
- stop gathering them. */
- if (old_options && old_options->CellStatistics &&
- !options->CellStatistics)
- rep_hist_buffer_stats_term();
- if (old_options && old_options->DirReqStatistics &&
- !options->DirReqStatistics)
- geoip_dirreq_stats_term();
- if (old_options && old_options->EntryStatistics &&
- !options->EntryStatistics)
- geoip_entry_stats_term();
- if (old_options && old_options->HiddenServiceStatistics &&
- !options->HiddenServiceStatistics)
- rep_hist_hs_stats_term();
- if (old_options && old_options->ExitPortStatistics &&
- !options->ExitPortStatistics)
- rep_hist_exit_stats_term();
- if (old_options && old_options->ConnDirectionStatistics &&
- !options->ConnDirectionStatistics)
- rep_hist_conn_stats_term();
- if (old_options && old_options->BridgeAuthoritativeDir &&
- !options->BridgeAuthoritativeDir)
- rep_hist_desc_stats_term();
-
- /* Since our options changed, we might need to regenerate and upload our
- * server descriptor.
- */
- if (!old_options ||
- options_transition_affects_descriptor(old_options, options))
- mark_my_descriptor_dirty("config change");
+ /* Only collect other relay-only statistics on relays. */
+ if (!public_server_mode(options)) {
+ options->CellStatistics = 0;
+ options->EntryStatistics = 0;
+ options->ConnDirectionStatistics = 0;
+ options->ExitPortStatistics = 0;
+ }
+
+ bool print_notice = 0;
+ if (options_act_relay_stats(old_options, &print_notice) < 0)
+ return -1;
+ if (options_act_dirauth_stats(old_options, &print_notice) < 0)
+ return -1;
+ if (print_notice)
+ options_act_relay_stats_msg();
+
+ if (options_act_relay_desc(old_options) < 0)
+ return -1;
+
+ if (options_act_dirauth(old_options) < 0)
+ return -1;
/* We may need to reschedule some directory stuff if our status changed. */
if (old_options) {
- if (options_transition_affects_dirauth_timing(old_options, options)) {
- voting_schedule_recalculate_timing(options, time(NULL));
- reschedule_dirvote(options);
- }
- if (!bool_eq(directory_fetches_dir_info_early(options),
- directory_fetches_dir_info_early(old_options)) ||
- !bool_eq(directory_fetches_dir_info_later(options),
- directory_fetches_dir_info_later(old_options)) ||
+ if (!bool_eq(dirclient_fetches_dir_info_early(options),
+ dirclient_fetches_dir_info_early(old_options)) ||
+ !bool_eq(dirclient_fetches_dir_info_later(options),
+ dirclient_fetches_dir_info_later(old_options)) ||
!config_lines_eq(old_options->Bridges, options->Bridges)) {
/* Make sure update_router_have_minimum_dir_info() gets called. */
router_dir_info_changed();
@@ -2421,87 +2411,110 @@ options_act(const or_options_t *old_options)
}
}
- /* DoS mitigation subsystem only applies to public relay. */
- if (public_server_mode(options)) {
- /* If we are configured as a relay, initialize the subsystem. Even on HUP,
- * this is safe to call as it will load data from the current options
- * or/and the consensus. */
- dos_init();
- } else if (old_options && public_server_mode(old_options)) {
- /* Going from relay to non relay, clean it up. */
- dos_free_all();
- }
-
- /* Load the webpage we're going to serve every time someone asks for '/' on
- our DirPort. */
- tor_free(global_dirfrontpagecontents);
- if (options->DirPortFrontPage) {
- global_dirfrontpagecontents =
- read_file_to_str(options->DirPortFrontPage, 0, NULL);
- if (!global_dirfrontpagecontents) {
- log_warn(LD_CONFIG,
- "DirPortFrontPage file '%s' not found. Continuing anyway.",
- options->DirPortFrontPage);
- }
- }
+ if (options_act_relay_dos(old_options) < 0)
+ return -1;
+ if (options_act_relay_dir(old_options) < 0)
+ return -1;
return 0;
}
+/**
+ * Enumeration to describe the syntax for a command-line option.
+ **/
typedef enum {
- TAKES_NO_ARGUMENT = 0,
+ /** Describe an option that does not take an argument. */
+ ARGUMENT_NONE = 0,
+ /** Describes an option that takes a single argument. */
ARGUMENT_NECESSARY = 1,
+ /** Describes an option that takes a single optional argument. */
ARGUMENT_OPTIONAL = 2
} takes_argument_t;
+/** Table describing arguments that Tor accepts on the command line,
+ * other than those that are the same as in torrc. */
static const struct {
+ /** The string that the user has to provide. */
const char *name;
+ /** Does this option accept an argument? */
takes_argument_t takes_argument;
+ /** If not CMD_RUN_TOR, what should Tor do when it starts? */
+ tor_cmdline_mode_t command;
+ /** If nonzero, set the quiet level to this. 1 is "hush", 2 is "quiet" */
+ int quiet;
} CMDLINE_ONLY_OPTIONS[] = {
- { "-f", ARGUMENT_NECESSARY },
- { "--allow-missing-torrc", TAKES_NO_ARGUMENT },
- { "--defaults-torrc", ARGUMENT_NECESSARY },
- { "--hash-password", ARGUMENT_NECESSARY },
- { "--dump-config", ARGUMENT_OPTIONAL },
- { "--list-fingerprint", TAKES_NO_ARGUMENT },
- { "--keygen", TAKES_NO_ARGUMENT },
- { "--key-expiration", ARGUMENT_OPTIONAL },
- { "--newpass", TAKES_NO_ARGUMENT },
- { "--no-passphrase", TAKES_NO_ARGUMENT },
- { "--passphrase-fd", ARGUMENT_NECESSARY },
- { "--verify-config", TAKES_NO_ARGUMENT },
- { "--ignore-missing-torrc", TAKES_NO_ARGUMENT },
- { "--quiet", TAKES_NO_ARGUMENT },
- { "--hush", TAKES_NO_ARGUMENT },
- { "--version", TAKES_NO_ARGUMENT },
- { "--list-modules", TAKES_NO_ARGUMENT },
- { "--library-versions", TAKES_NO_ARGUMENT },
- { "-h", TAKES_NO_ARGUMENT },
- { "--help", TAKES_NO_ARGUMENT },
- { "--list-torrc-options", TAKES_NO_ARGUMENT },
- { "--list-deprecated-options",TAKES_NO_ARGUMENT },
- { "--nt-service", TAKES_NO_ARGUMENT },
- { "-nt-service", TAKES_NO_ARGUMENT },
- { NULL, 0 },
+ { .name="-f",
+ .takes_argument=ARGUMENT_NECESSARY },
+ { .name="--allow-missing-torrc" },
+ { .name="--defaults-torrc",
+ .takes_argument=ARGUMENT_NECESSARY },
+ { .name="--hash-password",
+ .takes_argument=ARGUMENT_NECESSARY,
+ .command=CMD_HASH_PASSWORD,
+ .quiet=QUIET_HUSH },
+ { .name="--dump-config",
+ .takes_argument=ARGUMENT_OPTIONAL,
+ .command=CMD_DUMP_CONFIG,
+ .quiet=QUIET_SILENT },
+ { .name="--list-fingerprint",
+ .command=CMD_LIST_FINGERPRINT },
+ { .name="--keygen",
+ .command=CMD_KEYGEN },
+ { .name="--key-expiration",
+ .takes_argument=ARGUMENT_OPTIONAL,
+ .command=CMD_KEY_EXPIRATION },
+ { .name="--newpass" },
+ { .name="--no-passphrase" },
+ { .name="--passphrase-fd",
+ .takes_argument=ARGUMENT_NECESSARY },
+ { .name="--verify-config",
+ .command=CMD_VERIFY_CONFIG },
+ { .name="--ignore-missing-torrc" },
+ { .name="--quiet",
+ .quiet=QUIET_SILENT },
+ { .name="--hush",
+ .quiet=QUIET_HUSH },
+ { .name="--version",
+ .command=CMD_IMMEDIATE,
+ .quiet=QUIET_HUSH },
+ { .name="--list-modules",
+ .command=CMD_IMMEDIATE,
+ .quiet=QUIET_HUSH },
+ { .name="--library-versions",
+ .command=CMD_IMMEDIATE,
+ .quiet=QUIET_HUSH },
+ { .name="-h",
+ .command=CMD_IMMEDIATE,
+ .quiet=QUIET_HUSH },
+ { .name="--help",
+ .command=CMD_IMMEDIATE,
+ .quiet=QUIET_HUSH },
+ { .name="--list-torrc-options",
+ .command=CMD_IMMEDIATE,
+ .quiet=QUIET_HUSH },
+ { .name="--list-deprecated-options",
+ .command=CMD_IMMEDIATE },
+ { .name="--nt-service" },
+ { .name="-nt-service" },
+ { .name=NULL },
};
/** Helper: Read a list of configuration options from the command line. If
- * successful, or if ignore_errors is set, put them in *<b>result</b>, put the
- * commandline-only options in *<b>cmdline_result</b>, and return 0;
- * otherwise, return -1 and leave *<b>result</b> and <b>cmdline_result</b>
- * alone. */
-int
-config_parse_commandline(int argc, char **argv, int ignore_errors,
- config_line_t **result,
- config_line_t **cmdline_result)
+ * successful, return a newly allocated parsed_cmdline_t; otherwise return
+ * NULL.
+ *
+ * If <b>ignore_errors</b> is set, try to recover from all recoverable
+ * errors and return the best command line we can.
+ */
+parsed_cmdline_t *
+config_parse_commandline(int argc, char **argv, int ignore_errors)
{
+ parsed_cmdline_t *result = tor_malloc_zero(sizeof(parsed_cmdline_t));
+ result->command = CMD_RUN_TOR;
config_line_t *param = NULL;
- config_line_t *front = NULL;
- config_line_t **new = &front;
-
- config_line_t *front_cmdline = NULL;
- config_line_t **new_cmdline = &front_cmdline;
+ config_line_t **new_cmdline = &result->cmdline_opts;
+ config_line_t **new = &result->other_opts;
char *s, *arg;
int i = 1;
@@ -2511,11 +2524,19 @@ config_parse_commandline(int argc, char **argv, int ignore_errors,
takes_argument_t want_arg = ARGUMENT_NECESSARY;
int is_cmdline = 0;
int j;
+ bool is_a_command = false;
for (j = 0; CMDLINE_ONLY_OPTIONS[j].name != NULL; ++j) {
if (!strcmp(argv[i], CMDLINE_ONLY_OPTIONS[j].name)) {
is_cmdline = 1;
want_arg = CMDLINE_ONLY_OPTIONS[j].takes_argument;
+ if (CMDLINE_ONLY_OPTIONS[j].command != CMD_RUN_TOR) {
+ is_a_command = true;
+ result->command = CMDLINE_ONLY_OPTIONS[j].command;
+ }
+ quiet_level_t quiet = CMDLINE_ONLY_OPTIONS[j].quiet;
+ if (quiet > result->quiet_level)
+ result->quiet_level = quiet;
break;
}
}
@@ -2546,14 +2567,13 @@ config_parse_commandline(int argc, char **argv, int ignore_errors,
} else {
log_warn(LD_CONFIG,"Command-line option '%s' with no value. Failing.",
argv[i]);
- config_free_lines(front);
- config_free_lines(front_cmdline);
- return -1;
+ parsed_cmdline_free(result);
+ return NULL;
}
} else if (want_arg == ARGUMENT_OPTIONAL && is_last) {
arg = tor_strdup("");
} else {
- arg = (want_arg != TAKES_NO_ARGUMENT) ? tor_strdup(argv[i+1]) :
+ arg = (want_arg != ARGUMENT_NONE) ? tor_strdup(argv[i+1]) :
tor_strdup("");
}
@@ -2566,6 +2586,10 @@ config_parse_commandline(int argc, char **argv, int ignore_errors,
log_debug(LD_CONFIG, "command line: parsed keyword '%s', value '%s'",
param->key, param->value);
+ if (is_a_command) {
+ result->command_arg = param->value;
+ }
+
if (is_cmdline) {
*new_cmdline = param;
new_cmdline = &((*new_cmdline)->next);
@@ -2576,9 +2600,19 @@ config_parse_commandline(int argc, char **argv, int ignore_errors,
i += want_arg ? 2 : 1;
}
- *cmdline_result = front_cmdline;
- *result = front;
- return 0;
+
+ return result;
+}
+
+/** Release all storage held by <b>cmdline</b>. */
+void
+parsed_cmdline_free_(parsed_cmdline_t *cmdline)
+{
+ if (!cmdline)
+ return;
+ config_free_lines(cmdline->cmdline_opts);
+ config_free_lines(cmdline->other_opts);
+ tor_free(cmdline);
}
/** Return true iff key is a valid configuration option. */
@@ -2624,37 +2658,9 @@ options_trial_assign(config_line_t *list, unsigned flags, char **msg)
or_options_free(trial_options);
return r;
}
+ const or_options_t *cur_options = get_options();
- setopt_err_t rv;
- or_options_t *cur_options = get_options_mutable();
-
- in_option_validation = 1;
-
- if (options_validate(cur_options, trial_options,
- global_default_options, 1, msg) < 0) {
- or_options_free(trial_options);
- rv = SETOPT_ERR_PARSE; /*XXX make this a separate return value. */
- goto done;
- }
-
- if (options_transition_allowed(cur_options, trial_options, msg) < 0) {
- or_options_free(trial_options);
- rv = SETOPT_ERR_TRANSITION;
- goto done;
- }
- in_option_validation = 0;
-
- if (set_options(trial_options, msg)<0) {
- or_options_free(trial_options);
- rv = SETOPT_ERR_SETTING;
- goto done;
- }
-
- /* we liked it. put it in place. */
- rv = SETOPT_OK;
- done:
- in_option_validation = 0;
- return rv;
+ return options_validate_and_set(cur_options, trial_options, msg);
}
/** Print a usage message for tor. */
@@ -2664,7 +2670,7 @@ print_usage(void)
printf(
"Copyright (c) 2001-2004, Roger Dingledine\n"
"Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson\n"
-"Copyright (c) 2007-2019, The Tor Project, Inc.\n\n"
+"Copyright (c) 2007-2020, The Tor Project, Inc.\n\n"
"tor -f <torrc> [args]\n"
"See man page for options, or https://www.torproject.org/ for "
"documentation.\n");
@@ -2704,7 +2710,11 @@ list_deprecated_options(void)
static void
list_enabled_modules(void)
{
+ printf("%s: %s\n", "relay", have_module_relay() ? "yes" : "no");
printf("%s: %s\n", "dirauth", have_module_dirauth() ? "yes" : "no");
+ // We don't list dircache, because it cannot be enabled or disabled
+ // independently from relay. Listing it here would proliferate
+ // test variants in test_parseconf.sh to no useful purpose.
}
/** Last value actually set by resolve_my_address. */
@@ -3007,7 +3017,9 @@ is_local_addr, (const tor_addr_t *addr))
or_options_t *
options_new(void)
{
- return config_new(get_options_mgr());
+ or_options_t *options = config_new(get_options_mgr());
+ options->command = CMD_RUN_TOR;
+ return options;
}
/** Set <b>options</b> to hold reasonable defaults for most options.
@@ -3085,8 +3097,8 @@ validate_ports_csv(smartlist_t *sl, const char *name, char **msg)
* a complaint into *<b>msg</b> using string <b>desc</b>, and return -1.
* Else return 0.
*/
-static int
-ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg)
+int
+config_ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg)
{
if (*value > ROUTER_MAX_DECLARED_BANDWIDTH) {
/* This handles an understandable special case where somebody says "2gb"
@@ -3102,48 +3114,6 @@ ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg)
return 0;
}
-/** Parse an authority type from <b>options</b>-\>PublishServerDescriptor
- * and write it to <b>options</b>-\>PublishServerDescriptor_. Treat "1"
- * as "v3" unless BridgeRelay is 1, in which case treat it as "bridge".
- * Treat "0" as "".
- * Return 0 on success or -1 if not a recognized authority type (in which
- * case the value of PublishServerDescriptor_ is undefined). */
-static int
-compute_publishserverdescriptor(or_options_t *options)
-{
- smartlist_t *list = options->PublishServerDescriptor;
- dirinfo_type_t *auth = &options->PublishServerDescriptor_;
- *auth = NO_DIRINFO;
- if (!list) /* empty list, answer is none */
- return 0;
- SMARTLIST_FOREACH_BEGIN(list, const char *, string) {
- if (!strcasecmp(string, "v1"))
- log_warn(LD_CONFIG, "PublishServerDescriptor v1 has no effect, because "
- "there are no v1 directory authorities anymore.");
- else if (!strcmp(string, "1"))
- if (options->BridgeRelay)
- *auth |= BRIDGE_DIRINFO;
- else
- *auth |= V3_DIRINFO;
- else if (!strcasecmp(string, "v2"))
- log_warn(LD_CONFIG, "PublishServerDescriptor v2 has no effect, because "
- "there are no v2 directory authorities anymore.");
- else if (!strcasecmp(string, "v3"))
- *auth |= V3_DIRINFO;
- else if (!strcasecmp(string, "bridge"))
- *auth |= BRIDGE_DIRINFO;
- else if (!strcasecmp(string, "hidserv"))
- log_warn(LD_CONFIG,
- "PublishServerDescriptor hidserv is invalid. See "
- "PublishHidServDescriptors.");
- else if (!strcasecmp(string, "") || !strcmp(string, "0"))
- /* no authority */;
- else
- return -1;
- } SMARTLIST_FOREACH_END(string);
- return 0;
-}
-
/** Lowest allowable value for RendPostPeriod; if this is too low, hidden
* services can overload the directory system. */
#define MIN_REND_POST_PERIOD (10*60)
@@ -3176,17 +3146,68 @@ compute_publishserverdescriptor(or_options_t *options)
* */
#define RECOMMENDED_MIN_CIRCUIT_BUILD_TIMEOUT (10)
-static int
-options_validate_cb(void *old_options, void *options, void *default_options,
- int from_setconf, char **msg)
+/**
+ * Validate <b>new_options</b>. If it is valid, and it is a reasonable
+ * replacement for <b>old_options</b>, replace the previous value of the
+ * global options, and return return SETOPT_OK.
+ *
+ * If it is not valid, then free <b>new_options</b>, set *<b>msg_out</b> to a
+ * newly allocated error message, and return an error code.
+ */
+static setopt_err_t
+options_validate_and_set(const or_options_t *old_options,
+ or_options_t *new_options,
+ char **msg_out)
{
+ setopt_err_t rv;
+ validation_status_t vs;
+
in_option_validation = 1;
- int rv = options_validate(old_options, options, default_options,
- from_setconf, msg);
+ vs = config_validate(get_options_mgr(), old_options, new_options, msg_out);
+
+ if (vs == VSTAT_TRANSITION_ERR) {
+ rv = SETOPT_ERR_TRANSITION;
+ goto err;
+ } else if (vs < 0) {
+ rv = SETOPT_ERR_PARSE;
+ goto err;
+ }
+ in_option_validation = 0;
+
+ if (set_options(new_options, msg_out)) {
+ rv = SETOPT_ERR_SETTING;
+ goto err;
+ }
+
+ rv = SETOPT_OK;
+ new_options = NULL; /* prevent free */
+ err:
in_option_validation = 0;
+ tor_assert(new_options == NULL || rv != SETOPT_OK);
+ or_options_free(new_options);
return rv;
}
+#ifdef TOR_UNIT_TESTS
+/**
+ * Return 0 if every setting in <b>options</b> is reasonable, is a
+ * permissible transition from <b>old_options</b>, and none of the
+ * testing-only settings differ from <b>default_options</b> unless in
+ * testing mode. Else return -1. Should have no side effects, except for
+ * normalizing the contents of <b>options</b>.
+ *
+ * On error, tor_strdup an error explanation into *<b>msg</b>.
+ */
+int
+options_validate(const or_options_t *old_options, or_options_t *options,
+ char **msg)
+{
+ validation_status_t vs;
+ vs = config_validate(get_options_mgr(), old_options, options, msg);
+ return vs < 0 ? -1 : 0;
+}
+#endif /* defined(TOR_UNIT_TESTS) */
+
#define REJECT(arg) \
STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
#if defined(__GNUC__) && __GNUC__ <= 3
@@ -3207,7 +3228,7 @@ options_validate_cb(void *old_options, void *options, void *default_options,
*/
static int
warn_if_option_path_is_relative(const char *option,
- char *filepath)
+ const char *filepath)
{
if (filepath && path_is_relative(filepath)) {
char *abs_path = make_path_absolute(filepath);
@@ -3220,34 +3241,29 @@ warn_if_option_path_is_relative(const char *option,
}
/** Scan <b>options</b> for occurrences of relative file/directory
- * path and log a warning whenever it is found.
+ * paths and log a warning whenever one is found.
*
* Return 1 if there were relative paths; 0 otherwise.
*/
static int
-warn_about_relative_paths(or_options_t *options)
+warn_about_relative_paths(const or_options_t *options)
{
tor_assert(options);
int n = 0;
+ const config_mgr_t *mgr = get_options_mgr();
- n += warn_if_option_path_is_relative("CookieAuthFile",
- options->CookieAuthFile);
- n += warn_if_option_path_is_relative("ExtORPortCookieAuthFile",
- options->ExtORPortCookieAuthFile);
- n += warn_if_option_path_is_relative("DirPortFrontPage",
- options->DirPortFrontPage);
- n += warn_if_option_path_is_relative("V3BandwidthsFile",
- options->V3BandwidthsFile);
- n += warn_if_option_path_is_relative("ControlPortWriteToFile",
- options->ControlPortWriteToFile);
- n += warn_if_option_path_is_relative("GeoIPFile",options->GeoIPFile);
- n += warn_if_option_path_is_relative("GeoIPv6File",options->GeoIPv6File);
- n += warn_if_option_path_is_relative("Log",options->DebugLogFile);
- n += warn_if_option_path_is_relative("AccelDir",options->AccelDir);
- n += warn_if_option_path_is_relative("DataDirectory",options->DataDirectory);
- n += warn_if_option_path_is_relative("PidFile",options->PidFile);
- n += warn_if_option_path_is_relative("ClientOnionAuthDir",
- options->ClientOnionAuthDir);
+ smartlist_t *vars = config_mgr_list_vars(mgr);
+ SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, cv) {
+ config_line_t *line;
+ if (cv->member.type != CONFIG_TYPE_FILENAME)
+ continue;
+ const char *name = cv->member.name;
+ line = config_get_assigned_option(mgr, options, name, 0);
+ if (line)
+ n += warn_if_option_path_is_relative(name, line->value);
+ config_free_lines(line);
+ } SMARTLIST_FOREACH_END(cv);
+ smartlist_free(vars);
for (config_line_t *hs_line = options->RendConfigLines; hs_line;
hs_line = hs_line->next) {
@@ -3274,6 +3290,10 @@ options_validate_scheduler(or_options_t *options, char **msg)
"can be used or set at least one value.");
}
/* Ok, we do have scheduler types, validate them. */
+ if (options->SchedulerTypes_) {
+ SMARTLIST_FOREACH(options->SchedulerTypes_, int *, iptr, tor_free(iptr));
+ smartlist_free(options->SchedulerTypes_);
+ }
options->SchedulerTypes_ = smartlist_new();
SMARTLIST_FOREACH_BEGIN(options->Schedulers, const char *, type) {
int *sched_type;
@@ -3366,25 +3386,20 @@ options_validate_single_onion(or_options_t *options, char **msg)
return 0;
}
-/** Return 0 if every setting in <b>options</b> is reasonable, is a
- * permissible transition from <b>old_options</b>, and none of the
- * testing-only settings differ from <b>default_options</b> unless in
- * testing mode. Else return -1. Should have no side effects, except for
- * normalizing the contents of <b>options</b>.
- *
- * On error, tor_strdup an error explanation into *<b>msg</b>.
- *
- * XXX
- * If <b>from_setconf</b>, we were called by the controller, and our
- * Log line should stay empty. If it's 0, then give us a default log
- * if there are no logs defined.
+/**
+ * Legacy validation/normalization callback for or_options_t. See
+ * legacy_validate_fn_t for more information.
*/
-STATIC int
-options_validate(or_options_t *old_options, or_options_t *options,
- or_options_t *default_options, int from_setconf, char **msg)
+static int
+options_validate_cb(const void *old_options_, void *options_, char **msg)
{
+ if (old_options_)
+ CHECK_OPTIONS_MAGIC(old_options_);
+ CHECK_OPTIONS_MAGIC(options_);
+ const or_options_t *old_options = old_options_;
+ or_options_t *options = options_;
+
config_line_t *cl;
- const char *uname = get_uname();
int n_ports=0;
int world_writable_control_socket=0;
@@ -3395,22 +3410,30 @@ options_validate(or_options_t *old_options, or_options_t *options,
&world_writable_control_socket) < 0)
return -1;
+#ifndef HAVE_SYS_UN_H
+ if (options->ControlSocket || options->ControlSocketsGroupWritable) {
+ *msg = tor_strdup("Unix domain sockets (ControlSocket) not supported "
+ "on this OS/with this build.");
+ return -1;
+ }
+#else /* defined(HAVE_SYS_UN_H) */
+ if (options->ControlSocketsGroupWritable && !options->ControlSocket) {
+ *msg = tor_strdup("Setting ControlSocketGroupWritable without setting "
+ "a ControlSocket makes no sense.");
+ return -1;
+ }
+#endif /* !defined(HAVE_SYS_UN_H) */
+
/* Set UseEntryGuards from the configured value, before we check it below.
* We change UseEntryGuards when it's incompatible with other options,
* but leave UseEntryGuards_option with the original value.
* Always use the value of UseEntryGuards, not UseEntryGuards_option. */
options->UseEntryGuards = options->UseEntryGuards_option;
- if (server_mode(options) &&
- (!strcmpstart(uname, "Windows 95") ||
- !strcmpstart(uname, "Windows 98") ||
- !strcmpstart(uname, "Windows Me"))) {
- log_warn(LD_CONFIG, "Tor is running as a server, but you are "
- "running %s; this probably won't work. See "
- "https://www.torproject.org/docs/faq.html#BestOSForRelay "
- "for details.", uname);
- }
+ if (options_validate_relay_os(old_options, options, msg) < 0)
+ return -1;
+ /* 31851: OutboundBindAddressExit is unused in client mode */
if (parse_outbound_addresses(options, 1, msg) < 0)
return -1;
@@ -3425,61 +3448,16 @@ options_validate(or_options_t *old_options, or_options_t *options,
"with relative paths.");
}
- if (options->Nickname == NULL) {
- if (server_mode(options)) {
- options->Nickname = tor_strdup(UNNAMED_ROUTER_NICKNAME);
- }
- } else {
- if (!is_legal_nickname(options->Nickname)) {
- tor_asprintf(msg,
- "Nickname '%s', nicknames must be between 1 and 19 characters "
- "inclusive, and must contain only the characters [a-zA-Z0-9].",
- options->Nickname);
- return -1;
- }
- }
-
- if (server_mode(options) && !options->ContactInfo) {
- log_warn(LD_CONFIG,
- "Your ContactInfo config option is not set. Please strongly "
- "consider setting it, so we can contact you if your relay is "
- "misconfigured, end-of-life, or something else goes wrong. "
- "It is also possible that your relay might get rejected from "
- "the network due to a missing valid contact address.");
- }
-
- const char *ContactInfo = options->ContactInfo;
- if (ContactInfo && !string_is_utf8(ContactInfo, strlen(ContactInfo)))
- REJECT("ContactInfo config option must be UTF-8.");
+ if (options_validate_relay_info(old_options, options, msg) < 0)
+ return -1;
+ /* 31851: this function is currently a no-op in client mode */
check_network_configuration(server_mode(options));
- /* Special case on first boot if no Log options are given. */
- if (!options->Logs && !options->RunAsDaemon && !from_setconf) {
- if (quiet_level == 0)
- config_line_append(&options->Logs, "Log", "notice stdout");
- else if (quiet_level == 1)
- config_line_append(&options->Logs, "Log", "warn stdout");
- }
-
/* Validate the tor_log(s) */
if (options_init_logs(old_options, options, 1)<0)
REJECT("Failed to validate Log options. See logs for details.");
- if (authdir_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, NULL) < 0)
- REJECT("Failed to resolve/guess local address. See logs for details.");
- }
-
- if (server_mode(options) && options->RendConfigLines)
- log_warn(LD_CONFIG,
- "Tor is currently configured as a relay and a hidden service. "
- "That's not very secure: you should probably run your hidden service "
- "in a separate Tor process, at least -- see "
- "https://trac.torproject.org/8742");
-
/* XXXX require that the only port not be DirPort? */
/* XXXX require that at least one port be listened-upon. */
if (n_ports == 0 && !options->RendConfigLines)
@@ -3494,13 +3472,13 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (!strcasecmp(options->TransProxyType, "default")) {
options->TransProxyType_parsed = TPT_DEFAULT;
} else if (!strcasecmp(options->TransProxyType, "pf-divert")) {
-#if !defined(OpenBSD) && !defined( DARWIN )
+#if !defined(OpenBSD) && !defined(DARWIN)
/* Later versions of OS X have pf */
REJECT("pf-divert is a OpenBSD-specific "
"and OS X/Darwin-specific feature.");
#else
options->TransProxyType_parsed = TPT_PF_DIVERT;
-#endif /* !defined(OpenBSD) && !defined( DARWIN ) */
+#endif /* !defined(OpenBSD) && !defined(DARWIN) */
} else if (!strcasecmp(options->TransProxyType, "tproxy")) {
#if !defined(__linux__)
REJECT("TPROXY is a Linux-specific feature.");
@@ -3558,65 +3536,8 @@ options_validate(or_options_t *old_options, or_options_t *options,
"features to be broken in unpredictable ways.");
}
- if (options->AuthoritativeDir) {
- if (!options->ContactInfo && !options->TestingTorNetwork)
- REJECT("Authoritative directory servers must set ContactInfo");
- if (!options->RecommendedClientVersions)
- options->RecommendedClientVersions =
- config_lines_dup(options->RecommendedVersions);
- if (!options->RecommendedServerVersions)
- options->RecommendedServerVersions =
- config_lines_dup(options->RecommendedVersions);
- if (options->VersioningAuthoritativeDir &&
- (!options->RecommendedClientVersions ||
- !options->RecommendedServerVersions))
- REJECT("Versioning authoritative dir servers must set "
- "Recommended*Versions.");
-
-#ifdef HAVE_MODULE_DIRAUTH
- char *t;
- /* Call these functions to produce warnings only. */
- t = format_recommended_version_list(options->RecommendedClientVersions, 1);
- tor_free(t);
- t = format_recommended_version_list(options->RecommendedServerVersions, 1);
- tor_free(t);
-#endif /* defined(HAVE_MODULE_DIRAUTH) */
-
- if (options->UseEntryGuards) {
- log_info(LD_CONFIG, "Authoritative directory servers can't set "
- "UseEntryGuards. Disabling.");
- options->UseEntryGuards = 0;
- }
- if (!options->DownloadExtraInfo && authdir_mode_v3(options)) {
- log_info(LD_CONFIG, "Authoritative directories always try to download "
- "extra-info documents. Setting DownloadExtraInfo.");
- options->DownloadExtraInfo = 1;
- }
- if (!(options->BridgeAuthoritativeDir ||
- options->V3AuthoritativeDir))
- REJECT("AuthoritativeDir is set, but none of "
- "(Bridge/V3)AuthoritativeDir is set.");
-#ifdef HAVE_MODULE_DIRAUTH
- /* If we have a v3bandwidthsfile and it's broken, complain on startup */
- if (options->V3BandwidthsFile && !old_options) {
- dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL, NULL,
- NULL);
- }
- /* same for guardfraction file */
- if (options->GuardfractionFile && !old_options) {
- dirserv_read_guardfraction_file(options->GuardfractionFile, NULL);
- }
-#endif /* defined(HAVE_MODULE_DIRAUTH) */
- }
-
- if (options->AuthoritativeDir && !options->DirPort_set)
- REJECT("Running as authoritative directory, but no DirPort set.");
-
- if (options->AuthoritativeDir && !options->ORPort_set)
- REJECT("Running as authoritative directory, but no ORPort set.");
-
- if (options->AuthoritativeDir && options->ClientOnly)
- REJECT("Running as authoritative directory, but ClientOnly also set.");
+ if (options_validate_dirauth_mode(old_options, options, msg) < 0)
+ return -1;
if (options->FetchDirInfoExtraEarly && !options->FetchDirInfoEarly)
REJECT("FetchDirInfoExtraEarly requires that you also set "
@@ -3755,57 +3676,11 @@ options_validate(or_options_t *old_options, or_options_t *options,
return -1;
}
- if (compute_publishserverdescriptor(options) < 0) {
- tor_asprintf(msg, "Unrecognized value in PublishServerDescriptor");
+ if (options_validate_publish_server(old_options, options, msg) < 0)
return -1;
- }
-
- if ((options->BridgeRelay
- || options->PublishServerDescriptor_ & BRIDGE_DIRINFO)
- && (options->PublishServerDescriptor_ & V3_DIRINFO)) {
- REJECT("Bridges are not supposed to publish router descriptors to the "
- "directory authorities. Please correct your "
- "PublishServerDescriptor line.");
- }
- if (options->BridgeRelay && options->DirPort_set) {
- log_warn(LD_CONFIG, "Can't set a DirPort on a bridge relay; disabling "
- "DirPort");
- config_free_lines(options->DirPort_lines);
- options->DirPort_lines = NULL;
- options->DirPort_set = 0;
- }
-
- if (server_mode(options) && options->ConnectionPadding != -1) {
- REJECT("Relays must use 'auto' for the ConnectionPadding setting.");
- }
-
- if (server_mode(options) && options->ReducedConnectionPadding != 0) {
- REJECT("Relays cannot set ReducedConnectionPadding. ");
- }
-
- if (server_mode(options) && options->CircuitPadding == 0) {
- REJECT("Relays cannot set CircuitPadding to 0. ");
- }
-
- if (server_mode(options) && options->ReducedCircuitPadding == 1) {
- REJECT("Relays cannot set ReducedCircuitPadding. ");
- }
-
- if (options->BridgeDistribution) {
- if (!options->BridgeRelay) {
- REJECT("You set BridgeDistribution, but you didn't set BridgeRelay!");
- }
- if (check_bridge_distribution_setting(options->BridgeDistribution) < 0) {
- REJECT("Invalid BridgeDistribution value.");
- }
- }
-
- if (options->MinUptimeHidServDirectoryV2 < 0) {
- log_warn(LD_CONFIG, "MinUptimeHidServDirectoryV2 option must be at "
- "least 0 seconds. Changing to 0.");
- options->MinUptimeHidServDirectoryV2 = 0;
- }
+ if (options_validate_relay_padding(old_options, options, msg) < 0)
+ return -1;
const int min_rendpostperiod =
options->TestingTorNetwork ?
@@ -3979,134 +3854,24 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (options->KeepalivePeriod < 1)
REJECT("KeepalivePeriod option must be positive.");
- if (ensure_bandwidth_cap(&options->BandwidthRate,
+ if (config_ensure_bandwidth_cap(&options->BandwidthRate,
"BandwidthRate", msg) < 0)
return -1;
- if (ensure_bandwidth_cap(&options->BandwidthBurst,
+ if (config_ensure_bandwidth_cap(&options->BandwidthBurst,
"BandwidthBurst", msg) < 0)
return -1;
- if (ensure_bandwidth_cap(&options->MaxAdvertisedBandwidth,
- "MaxAdvertisedBandwidth", msg) < 0)
- return -1;
- if (ensure_bandwidth_cap(&options->RelayBandwidthRate,
- "RelayBandwidthRate", msg) < 0)
- return -1;
- if (ensure_bandwidth_cap(&options->RelayBandwidthBurst,
- "RelayBandwidthBurst", msg) < 0)
- return -1;
- if (ensure_bandwidth_cap(&options->PerConnBWRate,
- "PerConnBWRate", msg) < 0)
- return -1;
- if (ensure_bandwidth_cap(&options->PerConnBWBurst,
- "PerConnBWBurst", msg) < 0)
- return -1;
- if (ensure_bandwidth_cap(&options->AuthDirFastGuarantee,
- "AuthDirFastGuarantee", msg) < 0)
- return -1;
- if (ensure_bandwidth_cap(&options->AuthDirGuardBWGuarantee,
- "AuthDirGuardBWGuarantee", msg) < 0)
- return -1;
- if (options->RelayBandwidthRate && !options->RelayBandwidthBurst)
- options->RelayBandwidthBurst = options->RelayBandwidthRate;
- if (options->RelayBandwidthBurst && !options->RelayBandwidthRate)
- options->RelayBandwidthRate = options->RelayBandwidthBurst;
-
- if (server_mode(options)) {
- const unsigned required_min_bw =
- public_server_mode(options) ?
- RELAY_REQUIRED_MIN_BANDWIDTH : BRIDGE_REQUIRED_MIN_BANDWIDTH;
- const char * const optbridge =
- public_server_mode(options) ? "" : "bridge ";
- if (options->BandwidthRate < required_min_bw) {
- tor_asprintf(msg,
- "BandwidthRate is set to %d bytes/second. "
- "For %sservers, it must be at least %u.",
- (int)options->BandwidthRate, optbridge,
- required_min_bw);
- return -1;
- } else if (options->MaxAdvertisedBandwidth <
- required_min_bw/2) {
- tor_asprintf(msg,
- "MaxAdvertisedBandwidth is set to %d bytes/second. "
- "For %sservers, it must be at least %u.",
- (int)options->MaxAdvertisedBandwidth, optbridge,
- required_min_bw/2);
- return -1;
- }
- if (options->RelayBandwidthRate &&
- options->RelayBandwidthRate < required_min_bw) {
- tor_asprintf(msg,
- "RelayBandwidthRate is set to %d bytes/second. "
- "For %sservers, it must be at least %u.",
- (int)options->RelayBandwidthRate, optbridge,
- required_min_bw);
- return -1;
- }
- }
-
- if (options->RelayBandwidthRate > options->RelayBandwidthBurst)
- REJECT("RelayBandwidthBurst must be at least equal "
- "to RelayBandwidthRate.");
+ if (options_validate_relay_bandwidth(old_options, options, msg) < 0)
+ return -1;
if (options->BandwidthRate > options->BandwidthBurst)
REJECT("BandwidthBurst must be at least equal to BandwidthRate.");
- /* if they set relaybandwidth* really high but left bandwidth*
- * at the default, raise the defaults. */
- if (options->RelayBandwidthRate > options->BandwidthRate)
- options->BandwidthRate = options->RelayBandwidthRate;
- if (options->RelayBandwidthBurst > options->BandwidthBurst)
- options->BandwidthBurst = options->RelayBandwidthBurst;
-
- if (accounting_parse_options(options, 1)<0)
- REJECT("Failed to parse accounting options. See logs for details.");
-
- if (options->AccountingMax) {
- if (options->RendConfigLines && server_mode(options)) {
- log_warn(LD_CONFIG, "Using accounting with a hidden service and an "
- "ORPort is risky: your hidden service(s) and your public "
- "address will all turn off at the same time, which may alert "
- "observers that they are being run by the same party.");
- } else if (config_count_key(options->RendConfigLines,
- "HiddenServiceDir") > 1) {
- log_warn(LD_CONFIG, "Using accounting with multiple hidden services is "
- "risky: they will all turn off at the same time, which may "
- "alert observers that they are being run by the same party.");
- }
- }
-
- options->AccountingRule = ACCT_MAX;
- if (options->AccountingRule_option) {
- if (!strcmp(options->AccountingRule_option, "sum"))
- options->AccountingRule = ACCT_SUM;
- else if (!strcmp(options->AccountingRule_option, "max"))
- options->AccountingRule = ACCT_MAX;
- else if (!strcmp(options->AccountingRule_option, "in"))
- options->AccountingRule = ACCT_IN;
- else if (!strcmp(options->AccountingRule_option, "out"))
- options->AccountingRule = ACCT_OUT;
- else
- REJECT("AccountingRule must be 'sum', 'max', 'in', or 'out'");
- }
-
- if (options->DirPort_set && !options->DirCache) {
- REJECT("DirPort configured but DirCache disabled. DirPort requires "
- "DirCache.");
- }
-
- if (options->BridgeRelay && !options->DirCache) {
- REJECT("We're a bridge but DirCache is disabled. BridgeRelay requires "
- "DirCache.");
- }
+ if (options_validate_relay_accounting(old_options, options, msg) < 0)
+ return -1;
- if (server_mode(options)) {
- char *dircache_msg = NULL;
- if (have_enough_mem_for_dircache(options, 0, &dircache_msg)) {
- log_warn(LD_CONFIG, "%s", dircache_msg);
- tor_free(dircache_msg);
- }
- }
+ if (options_validate_relay_mode(old_options, options, msg) < 0)
+ return -1;
if (options->HTTPProxy) { /* parse it now */
if (tor_addr_port_lookup(options->HTTPProxy,
@@ -4156,19 +3921,28 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
}
+ if (options->TCPProxy) {
+ int res = parse_tcp_proxy_line(options->TCPProxy, options, msg);
+ if (res < 0) {
+ return res;
+ }
+ }
+
/* Check if more than one exclusive proxy type has been enabled. */
if (!!options->Socks4Proxy + !!options->Socks5Proxy +
- !!options->HTTPSProxy > 1)
+ !!options->HTTPSProxy + !!options->TCPProxy > 1)
REJECT("You have configured more than one proxy type. "
- "(Socks4Proxy|Socks5Proxy|HTTPSProxy)");
+ "(Socks4Proxy|Socks5Proxy|HTTPSProxy|TCPProxy)");
/* Check if the proxies will give surprising behavior. */
if (options->HTTPProxy && !(options->Socks4Proxy ||
options->Socks5Proxy ||
- options->HTTPSProxy)) {
- log_warn(LD_CONFIG, "HTTPProxy configured, but no SOCKS proxy or "
- "HTTPS proxy configured. Watch out: this configuration will "
- "proxy unencrypted directory connections only.");
+ options->HTTPSProxy ||
+ options->TCPProxy)) {
+ log_warn(LD_CONFIG, "HTTPProxy configured, but no SOCKS proxy, "
+ "HTTPS proxy, or any other TCP proxy configured. Watch out: "
+ "this configuration will proxy unencrypted directory "
+ "connections only.");
}
if (options->Socks5ProxyUsername) {
@@ -4236,19 +4010,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
"have it group-readable.");
}
- if (options->MyFamily_lines && options->BridgeRelay) {
- log_warn(LD_CONFIG, "Listing a family for a bridge relay is not "
- "supported: it can reveal bridge fingerprints to censors. "
- "You should also make sure you aren't listing this bridge's "
- "fingerprint in any other MyFamily.");
- }
- if (options->MyFamily_lines && !options->ContactInfo) {
- log_warn(LD_CONFIG, "MyFamily is set but ContactInfo is not configured. "
- "ContactInfo should always be set when MyFamily option is too.");
- }
- if (normalize_nickname_list(&options->MyFamily,
- options->MyFamily_lines, "MyFamily", msg))
- return -1;
for (cl = options->NodeFamilies; cl; cl = cl->next) {
routerset_t *rs = routerset_new();
if (routerset_parse(rs, cl->value, cl->key)) {
@@ -4283,50 +4044,12 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
- if (parse_transport_line(options, cl->value, 1, 0) < 0)
+ if (pt_parse_transport_line(options, cl->value, 1, 0) < 0)
REJECT("Invalid client transport line. See logs for details.");
}
- for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
- if (parse_transport_line(options, cl->value, 1, 1) < 0)
- REJECT("Invalid server transport line. See logs for details.");
- }
-
- if (options->ServerTransportPlugin && !server_mode(options)) {
- log_notice(LD_GENERAL, "Tor is not configured as a relay but you specified"
- " a ServerTransportPlugin line (%s). The ServerTransportPlugin "
- "line will be ignored.",
- escaped(options->ServerTransportPlugin->value));
- }
-
- for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) {
- /** If get_bindaddr_from_transport_listen_line() fails with
- 'transport' being NULL, it means that something went wrong
- while parsing the ServerTransportListenAddr line. */
- char *bindaddr = get_bindaddr_from_transport_listen_line(cl->value, NULL);
- if (!bindaddr)
- REJECT("ServerTransportListenAddr did not parse. See logs for details.");
- tor_free(bindaddr);
- }
-
- if (options->ServerTransportListenAddr && !options->ServerTransportPlugin) {
- log_notice(LD_GENERAL, "You need at least a single managed-proxy to "
- "specify a transport listen address. The "
- "ServerTransportListenAddr line will be ignored.");
- }
-
- for (cl = options->ServerTransportOptions; cl; cl = cl->next) {
- /** If get_options_from_transport_options_line() fails with
- 'transport' being NULL, it means that something went wrong
- while parsing the ServerTransportOptions line. */
- smartlist_t *options_sl =
- get_options_from_transport_options_line(cl->value, NULL);
- if (!options_sl)
- REJECT("ServerTransportOptions did not parse. See logs for details.");
-
- SMARTLIST_FOREACH(options_sl, char *, cp, tor_free(cp));
- smartlist_free(options_sl);
- }
+ if (options_validate_server_transport(old_options, options, msg) < 0)
+ return -1;
if (options->ConstrainedSockets) {
/* If the user wants to constrain socket buffer use, make sure the desired
@@ -4340,85 +4063,10 @@ options_validate(or_options_t *old_options, or_options_t *options,
MIN_CONSTRAINED_TCP_BUFFER, MAX_CONSTRAINED_TCP_BUFFER);
return -1;
}
- if (options->DirPort_set) {
- /* Providing cached directory entries while system TCP buffers are scarce
- * will exacerbate the socket errors. Suggest that this be disabled. */
- COMPLAIN("You have requested constrained socket buffers while also "
- "serving directory entries via DirPort. It is strongly "
- "suggested that you disable serving directory requests when "
- "system TCP buffer resources are scarce.");
- }
- }
-
- if (options->V3AuthVoteDelay + options->V3AuthDistDelay >=
- options->V3AuthVotingInterval/2) {
- /*
- This doesn't work, but it seems like it should:
- what code is preventing the interval being less than twice the lead-up?
- if (options->TestingTorNetwork) {
- if (options->V3AuthVoteDelay + options->V3AuthDistDelay >=
- options->V3AuthVotingInterval) {
- REJECT("V3AuthVoteDelay plus V3AuthDistDelay must be less than "
- "V3AuthVotingInterval");
- } else {
- COMPLAIN("V3AuthVoteDelay plus V3AuthDistDelay is more than half "
- "V3AuthVotingInterval. This may lead to "
- "consensus instability, particularly if clocks drift.");
- }
- } else {
- */
- REJECT("V3AuthVoteDelay plus V3AuthDistDelay must be less than half "
- "V3AuthVotingInterval");
- /*
- }
- */
- }
-
- if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS) {
- if (options->TestingTorNetwork) {
- if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS_TESTING) {
- REJECT("V3AuthVoteDelay is way too low.");
- } else {
- COMPLAIN("V3AuthVoteDelay is very low. "
- "This may lead to failure to vote for a consensus.");
- }
- } else {
- REJECT("V3AuthVoteDelay is way too low.");
- }
}
- if (options->V3AuthDistDelay < MIN_DIST_SECONDS) {
- if (options->TestingTorNetwork) {
- if (options->V3AuthDistDelay < MIN_DIST_SECONDS_TESTING) {
- REJECT("V3AuthDistDelay is way too low.");
- } else {
- COMPLAIN("V3AuthDistDelay is very low. "
- "This may lead to missing votes in a consensus.");
- }
- } else {
- REJECT("V3AuthDistDelay is way too low.");
- }
- }
-
- if (options->V3AuthNIntervalsValid < 2)
- REJECT("V3AuthNIntervalsValid must be at least 2.");
-
- if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL) {
- if (options->TestingTorNetwork) {
- if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL_TESTING) {
- REJECT("V3AuthVotingInterval is insanely low.");
- } else {
- COMPLAIN("V3AuthVotingInterval is very low. "
- "This may lead to failure to synchronise for a consensus.");
- }
- } else {
- REJECT("V3AuthVotingInterval is insanely low.");
- }
- } else if (options->V3AuthVotingInterval > 24*60*60) {
- REJECT("V3AuthVotingInterval is insanely high.");
- } else if (((24*60*60) % options->V3AuthVotingInterval) != 0) {
- COMPLAIN("V3AuthVotingInterval does not divide evenly into 24 hours.");
- }
+ if (options_validate_dirauth_schedule(old_options, options, msg) < 0)
+ return -1;
if (hs_config_service_all(options, 1) < 0)
REJECT("Failed to configure rendezvous options. See logs for details.");
@@ -4446,88 +4094,51 @@ options_validate(or_options_t *old_options, or_options_t *options,
#define CHECK_DEFAULT(arg) \
STMT_BEGIN \
- if (!options->TestingTorNetwork && \
- !options->UsingTestNetworkDefaults_ && \
- !config_is_same(get_options_mgr(),options, \
- default_options,#arg)) { \
+ if (!config_is_same(get_options_mgr(),options, \
+ dflt_options,#arg)) { \
+ or_options_free(dflt_options); \
REJECT(#arg " may only be changed in testing Tor " \
"networks!"); \
- } STMT_END
- CHECK_DEFAULT(TestingV3AuthInitialVotingInterval);
- CHECK_DEFAULT(TestingV3AuthInitialVoteDelay);
- CHECK_DEFAULT(TestingV3AuthInitialDistDelay);
- CHECK_DEFAULT(TestingV3AuthVotingStartOffset);
- CHECK_DEFAULT(TestingAuthDirTimeToLearnReachability);
- CHECK_DEFAULT(TestingEstimatedDescriptorPropagationTime);
- CHECK_DEFAULT(TestingServerDownloadInitialDelay);
- CHECK_DEFAULT(TestingClientDownloadInitialDelay);
- CHECK_DEFAULT(TestingServerConsensusDownloadInitialDelay);
- CHECK_DEFAULT(TestingClientConsensusDownloadInitialDelay);
- CHECK_DEFAULT(TestingBridgeDownloadInitialDelay);
- CHECK_DEFAULT(TestingBridgeBootstrapDownloadInitialDelay);
- CHECK_DEFAULT(TestingClientMaxIntervalWithoutRequest);
- CHECK_DEFAULT(TestingDirConnectionMaxStall);
- CHECK_DEFAULT(TestingAuthKeyLifetime);
- CHECK_DEFAULT(TestingLinkCertLifetime);
- CHECK_DEFAULT(TestingSigningKeySlop);
- CHECK_DEFAULT(TestingAuthKeySlop);
- CHECK_DEFAULT(TestingLinkKeySlop);
+ } \
+ STMT_END
+
+ /* Check for options that can only be changed from the defaults in testing
+ networks. */
+ if (! options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) {
+ or_options_t *dflt_options = options_new();
+ options_init(dflt_options);
+ /* 31851: some of these options are dirauth or relay only */
+ CHECK_DEFAULT(TestingV3AuthInitialVotingInterval);
+ CHECK_DEFAULT(TestingV3AuthInitialVoteDelay);
+ CHECK_DEFAULT(TestingV3AuthInitialDistDelay);
+ CHECK_DEFAULT(TestingV3AuthVotingStartOffset);
+ CHECK_DEFAULT(TestingAuthDirTimeToLearnReachability);
+ CHECK_DEFAULT(TestingServerDownloadInitialDelay);
+ CHECK_DEFAULT(TestingClientDownloadInitialDelay);
+ CHECK_DEFAULT(TestingServerConsensusDownloadInitialDelay);
+ CHECK_DEFAULT(TestingClientConsensusDownloadInitialDelay);
+ CHECK_DEFAULT(TestingBridgeDownloadInitialDelay);
+ CHECK_DEFAULT(TestingBridgeBootstrapDownloadInitialDelay);
+ CHECK_DEFAULT(TestingClientMaxIntervalWithoutRequest);
+ CHECK_DEFAULT(TestingDirConnectionMaxStall);
+ CHECK_DEFAULT(TestingAuthKeyLifetime);
+ CHECK_DEFAULT(TestingLinkCertLifetime);
+ CHECK_DEFAULT(TestingSigningKeySlop);
+ CHECK_DEFAULT(TestingAuthKeySlop);
+ CHECK_DEFAULT(TestingLinkKeySlop);
+ or_options_free(dflt_options);
+ }
#undef CHECK_DEFAULT
if (!options->ClientDNSRejectInternalAddresses &&
!(options->DirAuthorities ||
(options->AlternateDirAuthority && options->AlternateBridgeAuthority)))
REJECT("ClientDNSRejectInternalAddresses used for default network.");
- if (options->SigningKeyLifetime < options->TestingSigningKeySlop*2)
- REJECT("SigningKeyLifetime is too short.");
- if (options->TestingLinkCertLifetime < options->TestingAuthKeySlop*2)
- REJECT("LinkCertLifetime is too short.");
- if (options->TestingAuthKeyLifetime < options->TestingLinkKeySlop*2)
- REJECT("TestingAuthKeyLifetime is too short.");
-
- if (options->TestingV3AuthInitialVotingInterval
- < MIN_VOTE_INTERVAL_TESTING_INITIAL) {
- REJECT("TestingV3AuthInitialVotingInterval is insanely low.");
- } else if (((30*60) % options->TestingV3AuthInitialVotingInterval) != 0) {
- REJECT("TestingV3AuthInitialVotingInterval does not divide evenly into "
- "30 minutes.");
- }
-
- if (options->TestingV3AuthInitialVoteDelay < MIN_VOTE_SECONDS_TESTING) {
- REJECT("TestingV3AuthInitialVoteDelay is way too low.");
- }
-
- if (options->TestingV3AuthInitialDistDelay < MIN_DIST_SECONDS_TESTING) {
- REJECT("TestingV3AuthInitialDistDelay is way too low.");
- }
-
- if (options->TestingV3AuthInitialVoteDelay +
- options->TestingV3AuthInitialDistDelay >=
- options->TestingV3AuthInitialVotingInterval) {
- REJECT("TestingV3AuthInitialVoteDelay plus TestingV3AuthInitialDistDelay "
- "must be less than TestingV3AuthInitialVotingInterval");
- }
-
- if (options->TestingV3AuthVotingStartOffset >
- MIN(options->TestingV3AuthInitialVotingInterval,
- options->V3AuthVotingInterval)) {
- REJECT("TestingV3AuthVotingStartOffset is higher than the voting "
- "interval.");
- } else if (options->TestingV3AuthVotingStartOffset < 0) {
- REJECT("TestingV3AuthVotingStartOffset must be non-negative.");
- }
-
- if (options->TestingAuthDirTimeToLearnReachability < 0) {
- REJECT("TestingAuthDirTimeToLearnReachability must be non-negative.");
- } else if (options->TestingAuthDirTimeToLearnReachability > 2*60*60) {
- COMPLAIN("TestingAuthDirTimeToLearnReachability is insanely high.");
- }
- if (options->TestingEstimatedDescriptorPropagationTime < 0) {
- REJECT("TestingEstimatedDescriptorPropagationTime must be non-negative.");
- } else if (options->TestingEstimatedDescriptorPropagationTime > 60*60) {
- COMPLAIN("TestingEstimatedDescriptorPropagationTime is insanely high.");
- }
+ if (options_validate_relay_testing(old_options, options, msg) < 0)
+ return -1;
+ if (options_validate_dirauth_testing(old_options, options, msg) < 0)
+ return -1;
if (options->TestingClientMaxIntervalWithoutRequest < 1) {
REJECT("TestingClientMaxIntervalWithoutRequest is way too low.");
@@ -4569,27 +4180,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
"testing Tor network!");
}
- if (options->AccelName && !options->HardwareAccel)
- options->HardwareAccel = 1;
- if (options->AccelDir && !options->AccelName)
- REJECT("Can't use hardware crypto accelerator dir without engine name.");
-
- if (options->PublishServerDescriptor)
- SMARTLIST_FOREACH(options->PublishServerDescriptor, const char *, pubdes, {
- if (!strcmp(pubdes, "1") || !strcmp(pubdes, "0"))
- if (smartlist_len(options->PublishServerDescriptor) > 1) {
- COMPLAIN("You have passed a list of multiple arguments to the "
- "PublishServerDescriptor option that includes 0 or 1. "
- "0 or 1 should only be used as the sole argument. "
- "This configuration will be rejected in a future release.");
- break;
- }
- });
-
- if (options->BridgeRelay == 1 && ! options->ORPort_set)
- REJECT("BridgeRelay is 1, ORPort is not set. This is an invalid "
- "combination.");
-
if (options_validate_scheduler(options, msg) < 0) {
return -1;
}
@@ -4681,50 +4271,6 @@ compute_real_max_mem_in_queues(const uint64_t val, int log_guess)
}
}
-/* If we have less than 300 MB suggest disabling dircache */
-#define DIRCACHE_MIN_MEM_MB 300
-#define DIRCACHE_MIN_MEM_BYTES (DIRCACHE_MIN_MEM_MB*ONE_MEGABYTE)
-#define STRINGIFY(val) #val
-
-/** Create a warning message for emitting if we are a dircache but may not have
- * enough system memory, or if we are not a dircache but probably should be.
- * Return -1 when a message is returned in *msg*, else return 0. */
-STATIC int
-have_enough_mem_for_dircache(const or_options_t *options, size_t total_mem,
- char **msg)
-{
- *msg = NULL;
- /* XXX We should possibly be looking at MaxMemInQueues here
- * unconditionally. Or we should believe total_mem unconditionally. */
- if (total_mem == 0) {
- if (get_total_system_memory(&total_mem) < 0) {
- total_mem = options->MaxMemInQueues >= SIZE_MAX ?
- SIZE_MAX : (size_t)options->MaxMemInQueues;
- }
- }
- if (options->DirCache) {
- if (total_mem < DIRCACHE_MIN_MEM_BYTES) {
- if (options->BridgeRelay) {
- tor_asprintf(msg, "Running a Bridge with less than %d MB of memory "
- "is not recommended.", DIRCACHE_MIN_MEM_MB);
- } else {
- tor_asprintf(msg, "Being a directory cache (default) with less than "
- "%d MB of memory is not recommended and may consume "
- "most of the available resources. Consider disabling "
- "this functionality by setting the DirCache option "
- "to 0.", DIRCACHE_MIN_MEM_MB);
- }
- }
- } else {
- if (total_mem >= DIRCACHE_MIN_MEM_BYTES) {
- *msg = tor_strdup("DirCache is disabled and we are configured as a "
- "relay. We will not become a Guard.");
- }
- }
- return *msg == NULL ? 0 : -1;
-}
-#undef STRINGIFY
-
/** Helper: return true iff s1 and s2 are both NULL, or both non-NULL
* equal strings. */
static int
@@ -4733,13 +4279,19 @@ opt_streq(const char *s1, const char *s2)
return 0 == strcmp_opt(s1, s2);
}
-/** Check if any of the previous options have changed but aren't allowed to. */
+/** Check if any config options have changed but aren't allowed to. */
static int
-options_transition_allowed(const or_options_t *old,
- const or_options_t *new_val,
- char **msg)
+options_check_transition_cb(const void *old_,
+ const void *new_val_,
+ char **msg)
{
- if (!old)
+ CHECK_OPTIONS_MAGIC(old_);
+ CHECK_OPTIONS_MAGIC(new_val_);
+
+ const or_options_t *old = old_;
+ const or_options_t *new_val = new_val_;
+
+ if (BUG(!old))
return 0;
#define BAD_CHANGE_TO(opt, how) do { \
@@ -4748,36 +4300,6 @@ options_transition_allowed(const or_options_t *old,
return -1; \
} while (0)
-#define NO_CHANGE_BOOL(opt) \
- if (! CFG_EQ_BOOL(old, new_val, opt)) BAD_CHANGE_TO(opt,"")
-#define NO_CHANGE_INT(opt) \
- if (! CFG_EQ_INT(old, new_val, opt)) BAD_CHANGE_TO(opt,"")
-#define NO_CHANGE_STRING(opt) \
- if (! CFG_EQ_STRING(old, new_val, opt)) BAD_CHANGE_TO(opt,"")
-
- NO_CHANGE_STRING(PidFile);
- NO_CHANGE_BOOL(RunAsDaemon);
- NO_CHANGE_BOOL(Sandbox);
- NO_CHANGE_STRING(DataDirectory);
- NO_CHANGE_STRING(KeyDirectory);
- NO_CHANGE_STRING(CacheDirectory);
- NO_CHANGE_STRING(User);
- NO_CHANGE_BOOL(KeepBindCapabilities);
- NO_CHANGE_STRING(SyslogIdentityTag);
- NO_CHANGE_STRING(AndroidIdentityTag);
- NO_CHANGE_BOOL(HardwareAccel);
- NO_CHANGE_STRING(AccelName);
- NO_CHANGE_STRING(AccelDir);
- NO_CHANGE_BOOL(TestingTorNetwork);
- NO_CHANGE_BOOL(DisableAllSwap);
- NO_CHANGE_INT(TokenBucketRefillInterval);
- NO_CHANGE_BOOL(HiddenServiceSingleHopMode);
- NO_CHANGE_BOOL(HiddenServiceNonAnonymousMode);
- NO_CHANGE_BOOL(DisableDebuggerAttachment);
- NO_CHANGE_BOOL(NoExec);
- NO_CHANGE_INT(OwningControllerFD);
- NO_CHANGE_BOOL(DisableSignalHandlers);
-
if (sandbox_is_active()) {
#define SB_NOCHANGE_STR(opt) \
if (! CFG_EQ_STRING(old, new_val, opt)) \
@@ -4814,71 +4336,6 @@ options_transition_allowed(const or_options_t *old,
return 0;
}
-/** Return 1 if any change from <b>old_options</b> to <b>new_options</b>
- * will require us to rotate the CPU and DNS workers; else return 0. */
-static int
-options_transition_affects_workers(const or_options_t *old_options,
- const or_options_t *new_options)
-{
- YES_IF_CHANGED_STRING(DataDirectory);
- YES_IF_CHANGED_INT(NumCPUs);
- YES_IF_CHANGED_LINELIST(ORPort_lines);
- YES_IF_CHANGED_BOOL(ServerDNSSearchDomains);
- YES_IF_CHANGED_BOOL(SafeLogging_);
- YES_IF_CHANGED_BOOL(ClientOnly);
- YES_IF_CHANGED_BOOL(LogMessageDomains);
- YES_IF_CHANGED_LINELIST(Logs);
-
- if (server_mode(old_options) != server_mode(new_options) ||
- public_server_mode(old_options) != public_server_mode(new_options) ||
- dir_server_mode(old_options) != dir_server_mode(new_options))
- return 1;
-
- /* Nothing that changed matters. */
- return 0;
-}
-
-/** Return 1 if any change from <b>old_options</b> to <b>new_options</b>
- * will require us to generate a new descriptor; else return 0. */
-static int
-options_transition_affects_descriptor(const or_options_t *old_options,
- const or_options_t *new_options)
-{
- /* XXX We can be smarter here. If your DirPort isn't being
- * published and you just turned it off, no need to republish. Etc. */
-
- YES_IF_CHANGED_STRING(DataDirectory);
- YES_IF_CHANGED_STRING(Nickname);
- YES_IF_CHANGED_STRING(Address);
- YES_IF_CHANGED_LINELIST(ExitPolicy);
- YES_IF_CHANGED_BOOL(ExitRelay);
- YES_IF_CHANGED_BOOL(ExitPolicyRejectPrivate);
- YES_IF_CHANGED_BOOL(ExitPolicyRejectLocalInterfaces);
- YES_IF_CHANGED_BOOL(IPv6Exit);
- YES_IF_CHANGED_LINELIST(ORPort_lines);
- YES_IF_CHANGED_LINELIST(DirPort_lines);
- YES_IF_CHANGED_LINELIST(DirPort_lines);
- YES_IF_CHANGED_BOOL(ClientOnly);
- YES_IF_CHANGED_BOOL(DisableNetwork);
- YES_IF_CHANGED_BOOL(PublishServerDescriptor_);
- YES_IF_CHANGED_STRING(ContactInfo);
- YES_IF_CHANGED_STRING(BridgeDistribution);
- YES_IF_CHANGED_LINELIST(MyFamily);
- YES_IF_CHANGED_STRING(AccountingStart);
- YES_IF_CHANGED_INT(AccountingMax);
- YES_IF_CHANGED_INT(AccountingRule);
- YES_IF_CHANGED_BOOL(DirCache);
- YES_IF_CHANGED_BOOL(AssumeReachable);
-
- if (get_effective_bwrate(old_options) != get_effective_bwrate(new_options) ||
- get_effective_bwburst(old_options) !=
- get_effective_bwburst(new_options) ||
- public_server_mode(old_options) != public_server_mode(new_options))
- return 1;
-
- return 0;
-}
-
#ifdef _WIN32
/** Return the directory on windows where we expect to find our application
* data. */
@@ -4963,85 +4420,6 @@ get_default_conf_file(int defaults_file)
#endif /* defined(DISABLE_SYSTEM_TORRC) || ... */
}
-/** Verify whether lst is a list of strings containing valid-looking
- * comma-separated nicknames, or NULL. Will normalise <b>lst</b> to prefix '$'
- * to any nickname or fingerprint that needs it. Also splits comma-separated
- * list elements into multiple elements. Return 0 on success.
- * Warn and return -1 on failure.
- */
-static int
-normalize_nickname_list(config_line_t **normalized_out,
- const config_line_t *lst, const char *name,
- char **msg)
-{
- if (!lst)
- return 0;
-
- config_line_t *new_nicknames = NULL;
- config_line_t **new_nicknames_next = &new_nicknames;
-
- const config_line_t *cl;
- for (cl = lst; cl; cl = cl->next) {
- const char *line = cl->value;
- if (!line)
- continue;
-
- int valid_line = 1;
- smartlist_t *sl = smartlist_new();
- smartlist_split_string(sl, line, ",",
- SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK|SPLIT_STRIP_SPACE, 0);
- SMARTLIST_FOREACH_BEGIN(sl, char *, s)
- {
- char *normalized = NULL;
- if (!is_legal_nickname_or_hexdigest(s)) {
- // check if first char is dollar
- if (s[0] != '$') {
- // Try again but with a dollar symbol prepended
- char *prepended;
- tor_asprintf(&prepended, "$%s", s);
-
- if (is_legal_nickname_or_hexdigest(prepended)) {
- // The nickname is valid when it's prepended, set it as the
- // normalized version
- normalized = prepended;
- } else {
- // Still not valid, free and fallback to error message
- tor_free(prepended);
- }
- }
-
- if (!normalized) {
- tor_asprintf(msg, "Invalid nickname '%s' in %s line", s, name);
- valid_line = 0;
- break;
- }
- } else {
- normalized = tor_strdup(s);
- }
-
- config_line_t *next = tor_malloc_zero(sizeof(*next));
- next->key = tor_strdup(cl->key);
- next->value = normalized;
- next->next = NULL;
-
- *new_nicknames_next = next;
- new_nicknames_next = &next->next;
- } SMARTLIST_FOREACH_END(s);
-
- SMARTLIST_FOREACH(sl, char *, s, tor_free(s));
- smartlist_free(sl);
-
- if (!valid_line) {
- config_free_lines(new_nicknames);
- return -1;
- }
- }
-
- *normalized_out = new_nicknames;
-
- return 0;
-}
-
/** Learn config file name from command line arguments, or use the default.
*
* If <b>defaults_file</b> is true, we're looking for torrc-defaults;
@@ -5054,12 +4432,12 @@ normalize_nickname_list(config_line_t **normalized_out,
* filename if it doesn't exist.
*/
static char *
-find_torrc_filename(config_line_t *cmd_arg,
+find_torrc_filename(const config_line_t *cmd_arg,
int defaults_file,
int *using_default_fname, int *ignore_missing_torrc)
{
char *fname=NULL;
- config_line_t *p_index;
+ const config_line_t *p_index;
const char *fname_opt = defaults_file ? "--defaults-torrc" : "-f";
const char *ignore_opt = defaults_file ? NULL : "--ignore-missing-torrc";
@@ -5138,7 +4516,7 @@ load_torrc_from_stdin(void)
* Return the contents of the file on success, and NULL on failure.
*/
static char *
-load_torrc_from_disk(config_line_t *cmd_arg, int defaults_file)
+load_torrc_from_disk(const config_line_t *cmd_arg, int defaults_file)
{
char *fname=NULL;
char *cf = NULL;
@@ -5193,24 +4571,20 @@ int
options_init_from_torrc(int argc, char **argv)
{
char *cf=NULL, *cf_defaults=NULL;
- int command;
int retval = -1;
- char *command_arg = NULL;
char *errmsg=NULL;
- config_line_t *p_index = NULL;
- config_line_t *cmdline_only_options = NULL;
+ const config_line_t *cmdline_only_options;
/* Go through command-line variables */
- if (! have_parsed_cmdline) {
+ if (global_cmdline == NULL) {
/* Or we could redo the list every time we pass this place.
* It does not really matter */
- if (config_parse_commandline(argc, argv, 0, &global_cmdline_options,
- &global_cmdline_only_options) < 0) {
+ global_cmdline = config_parse_commandline(argc, argv, 0);
+ if (global_cmdline == NULL) {
goto err;
}
- have_parsed_cmdline = 1;
}
- cmdline_only_options = global_cmdline_only_options;
+ cmdline_only_options = global_cmdline->cmdline_opts;
if (config_line_find(cmdline_only_options, "-h") ||
config_line_find(cmdline_only_options, "--help")) {
@@ -5273,25 +4647,10 @@ options_init_from_torrc(int argc, char **argv)
return 1;
}
- command = CMD_RUN_TOR;
- for (p_index = cmdline_only_options; p_index; p_index = p_index->next) {
- if (!strcmp(p_index->key,"--keygen")) {
- command = CMD_KEYGEN;
- } else if (!strcmp(p_index->key, "--key-expiration")) {
- command = CMD_KEY_EXPIRATION;
- command_arg = p_index->value;
- } else if (!strcmp(p_index->key,"--list-fingerprint")) {
- command = CMD_LIST_FINGERPRINT;
- } else if (!strcmp(p_index->key, "--hash-password")) {
- command = CMD_HASH_PASSWORD;
- command_arg = p_index->value;
- } else if (!strcmp(p_index->key, "--dump-config")) {
- command = CMD_DUMP_CONFIG;
- command_arg = p_index->value;
- } else if (!strcmp(p_index->key, "--verify-config")) {
- command = CMD_VERIFY_CONFIG;
- }
- }
+ int command = global_cmdline->command;
+ const char *command_arg = global_cmdline->command_arg;
+ /* "immediate" has already been handled by this point. */
+ tor_assert(command != CMD_IMMEDIATE);
if (command == CMD_HASH_PASSWORD) {
cf_defaults = tor_strdup("");
@@ -5459,8 +4818,15 @@ options_init_from_string(const char *cf_defaults, const char *cf,
}
/* Go through command-line variables too */
- retval = config_assign(get_options_mgr(), newoptions,
- global_cmdline_options, CAL_WARN_DEPRECATIONS, msg);
+ {
+ config_line_t *other_opts = NULL;
+ if (global_cmdline) {
+ other_opts = global_cmdline->other_opts;
+ }
+ retval = config_assign(get_options_mgr(), newoptions,
+ other_opts,
+ CAL_WARN_DEPRECATIONS, msg);
+ }
if (retval < 0) {
err = SETOPT_ERR_PARSE;
goto err;
@@ -5468,6 +4834,7 @@ options_init_from_string(const char *cf_defaults, const char *cf,
newoptions->IncludeUsed = cf_has_include;
newoptions->FilesOpenedByIncludes = opened_files;
+ opened_files = NULL; // prevent double-free.
/* If this is a testing network configuration, change defaults
* for a list of dependent config options, and try this function again. */
@@ -5478,27 +4845,11 @@ options_init_from_string(const char *cf_defaults, const char *cf,
goto err;
}
- newoptions->IncludeUsed = cf_has_include;
- in_option_validation = 1;
- newoptions->FilesOpenedByIncludes = opened_files;
-
- /* Validate newoptions */
- if (options_validate(oldoptions, newoptions, newdefaultoptions,
- 0, msg) < 0) {
- err = SETOPT_ERR_PARSE; /*XXX make this a separate return value.*/
- goto err;
- }
-
- if (options_transition_allowed(oldoptions, newoptions, msg) < 0) {
- err = SETOPT_ERR_TRANSITION;
+ err = options_validate_and_set(oldoptions, newoptions, msg);
+ if (err < 0) {
+ newoptions = NULL; // This was already freed in options_validate_and_set.
goto err;
}
- in_option_validation = 0;
-
- if (set_options(newoptions, msg)) {
- err = SETOPT_ERR_SETTING;
- goto err; /* frees and replaces old options */
- }
or_options_free(global_default_options);
global_default_options = newdefaultoptions;
@@ -5511,10 +4862,8 @@ options_init_from_string(const char *cf_defaults, const char *cf,
SMARTLIST_FOREACH(opened_files, char *, f, tor_free(f));
smartlist_free(opened_files);
}
- // may have been set to opened_files, avoid double free
- newoptions->FilesOpenedByIncludes = NULL;
- or_options_free(newoptions);
or_options_free(newdefaultoptions);
+ or_options_free(newoptions);
if (*msg) {
char *old_msg = *msg;
tor_asprintf(msg, "Failed to parse/validate config: %s", old_msg);
@@ -5647,22 +4996,14 @@ open_and_add_file_log(const log_severity_list_t *severity,
}
/**
- * Initialize the logs based on the configuration file.
- */
+ * Try to set our global log granularity from `options->LogGranularity`,
+ * adjusting it as needed so that we are an even divisor of a second, or an
+ * even multiple of seconds. Return 0 on success, -1 on failure.
+ **/
static int
-options_init_logs(const or_options_t *old_options, or_options_t *options,
- int validate_only)
+options_init_log_granularity(const or_options_t *options,
+ int validate_only)
{
- config_line_t *opt;
- int ok;
- smartlist_t *elts;
- int run_as_daemon =
-#ifdef _WIN32
- 0;
-#else
- options->RunAsDaemon;
-#endif
-
if (options->LogTimeGranularity <= 0) {
log_warn(LD_CONFIG, "Log time granularity '%d' has to be positive.",
options->LogTimeGranularity);
@@ -5692,9 +5033,38 @@ options_init_logs(const or_options_t *old_options, or_options_t *options,
set_log_time_granularity(options->LogTimeGranularity);
}
+ return 0;
+}
+
+/**
+ * Initialize the logs based on the configuration file.
+ */
+STATIC int
+options_init_logs(const or_options_t *old_options, const or_options_t *options,
+ int validate_only)
+{
+ config_line_t *opt;
+ int ok;
+ smartlist_t *elts;
+ int run_as_daemon =
+#ifdef _WIN32
+ 0;
+#else
+ options->RunAsDaemon;
+#endif
+
+ if (options_init_log_granularity(options, validate_only) < 0)
+ return -1;
+
ok = 1;
elts = smartlist_new();
+ if (options->Logs == NULL && !run_as_daemon && !validate_only) {
+ /* When no logs are given, the default behavior is to log nothing (if
+ RunAsDaemon is set) or to log based on the quiet level otherwise. */
+ add_default_log_for_quiet_level(quiet_level);
+ }
+
for (opt = options->Logs; opt; opt = opt->next) {
log_severity_list_t *severity;
const char *cfg = opt->value;
@@ -5968,6 +5338,68 @@ parse_bridge_line(const char *line)
return bridge_line;
}
+/** Parse the contents of a TCPProxy line from <b>line</b> and put it
+ * in <b>options</b>. Return 0 if the line is well-formed, and -1 if it
+ * isn't.
+ *
+ * This will mutate only options->TCPProxyProtocol, options->TCPProxyAddr,
+ * and options->TCPProxyPort.
+ *
+ * On error, tor_strdup an error explanation into *<b>msg</b>.
+ */
+STATIC int
+parse_tcp_proxy_line(const char *line, or_options_t *options, char **msg)
+{
+ int ret = 0;
+ tor_assert(line);
+ tor_assert(options);
+ tor_assert(msg);
+
+ smartlist_t *sl = smartlist_new();
+ /* Split between the protocol and the address/port. */
+ smartlist_split_string(sl, line, " ",
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2);
+
+ /* The address/port is not specified. */
+ if (smartlist_len(sl) < 2) {
+ *msg = tor_strdup("TCPProxy has no address/port. Please fix.");
+ goto err;
+ }
+
+ char *protocol_string = smartlist_get(sl, 0);
+ char *addrport_string = smartlist_get(sl, 1);
+
+ /* The only currently supported protocol is 'haproxy'. */
+ if (strcasecmp(protocol_string, "haproxy")) {
+ *msg = tor_strdup("TCPProxy protocol is not supported. Currently "
+ "the only supported protocol is 'haproxy'. "
+ "Please fix.");
+ goto err;
+ } else {
+ /* Otherwise, set the correct protocol. */
+ options->TCPProxyProtocol = TCP_PROXY_PROTOCOL_HAPROXY;
+ }
+
+ /* Parse the address/port. */
+ if (tor_addr_port_lookup(addrport_string, &options->TCPProxyAddr,
+ &options->TCPProxyPort) < 0) {
+ *msg = tor_strdup("TCPProxy address/port failed to parse or resolve. "
+ "Please fix.");
+ goto err;
+ }
+
+ /* Success. */
+ ret = 0;
+ goto end;
+
+ err:
+ ret = -1;
+ end:
+ SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
+ smartlist_free(sl);
+ return ret;
+}
+
/** Read the contents of a ClientTransportPlugin or ServerTransportPlugin
* line from <b>line</b>, depending on the value of <b>server</b>. Return 0
* if the line is well-formed, and -1 if it isn't.
@@ -5978,9 +5410,8 @@ parse_bridge_line(const char *line)
* our internal transport list.
* - If it's a managed proxy line, launch the managed proxy.
*/
-
-STATIC int
-parse_transport_line(const or_options_t *options,
+int
+pt_parse_transport_line(const or_options_t *options,
const char *line, int validate_only,
int server)
{
@@ -6116,9 +5547,10 @@ parse_transport_line(const or_options_t *options,
/* ClientTransportPlugins connecting through a proxy is managed only. */
if (!server && (options->Socks4Proxy || options->Socks5Proxy ||
- options->HTTPSProxy)) {
+ options->HTTPSProxy || options->TCPProxy)) {
log_warn(LD_CONFIG, "You have configured an external proxy with another "
- "proxy type. (Socks4Proxy|Socks5Proxy|HTTPSProxy)");
+ "proxy type. (Socks4Proxy|Socks5Proxy|HTTPSProxy|"
+ "TCPProxy)");
goto err;
}
@@ -6173,157 +5605,6 @@ parse_transport_line(const or_options_t *options,
return r;
}
-/** Given a ServerTransportListenAddr <b>line</b>, return its
- * <address:port> string. Return NULL if the line was not
- * well-formed.
- *
- * If <b>transport</b> is set, return NULL if the line is not
- * referring to <b>transport</b>.
- *
- * The returned string is allocated on the heap and it's the
- * responsibility of the caller to free it. */
-static char *
-get_bindaddr_from_transport_listen_line(const char *line,const char *transport)
-{
- smartlist_t *items = NULL;
- const char *parsed_transport = NULL;
- char *addrport = NULL;
- tor_addr_t addr;
- uint16_t port = 0;
-
- items = smartlist_new();
- smartlist_split_string(items, line, NULL,
- SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
-
- if (smartlist_len(items) < 2) {
- log_warn(LD_CONFIG,"Too few arguments on ServerTransportListenAddr line.");
- goto err;
- }
-
- parsed_transport = smartlist_get(items, 0);
- addrport = tor_strdup(smartlist_get(items, 1));
-
- /* If 'transport' is given, check if it matches the one on the line */
- if (transport && strcmp(transport, parsed_transport))
- goto err;
-
- /* Validate addrport */
- if (tor_addr_port_parse(LOG_WARN, addrport, &addr, &port, -1)<0) {
- log_warn(LD_CONFIG, "Error parsing ServerTransportListenAddr "
- "address '%s'", addrport);
- goto err;
- }
-
- goto done;
-
- err:
- tor_free(addrport);
- addrport = NULL;
-
- done:
- SMARTLIST_FOREACH(items, char*, s, tor_free(s));
- smartlist_free(items);
-
- return addrport;
-}
-
-/** Given a ServerTransportOptions <b>line</b>, return a smartlist
- * with the options. Return NULL if the line was not well-formed.
- *
- * If <b>transport</b> is set, return NULL if the line is not
- * referring to <b>transport</b>.
- *
- * The returned smartlist and its strings are allocated on the heap
- * and it's the responsibility of the caller to free it. */
-smartlist_t *
-get_options_from_transport_options_line(const char *line,const char *transport)
-{
- smartlist_t *items = smartlist_new();
- smartlist_t *options = smartlist_new();
- const char *parsed_transport = NULL;
-
- smartlist_split_string(items, line, NULL,
- SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
-
- if (smartlist_len(items) < 2) {
- log_warn(LD_CONFIG,"Too few arguments on ServerTransportOptions line.");
- goto err;
- }
-
- parsed_transport = smartlist_get(items, 0);
- /* If 'transport' is given, check if it matches the one on the line */
- if (transport && strcmp(transport, parsed_transport))
- goto err;
-
- SMARTLIST_FOREACH_BEGIN(items, const char *, option) {
- if (option_sl_idx == 0) /* skip the transport field (first field)*/
- continue;
-
- /* validate that it's a k=v value */
- if (!string_is_key_value(LOG_WARN, option)) {
- log_warn(LD_CONFIG, "%s is not a k=v value.", escaped(option));
- goto err;
- }
-
- /* add it to the options smartlist */
- smartlist_add_strdup(options, option);
- log_debug(LD_CONFIG, "Added %s to the list of options", escaped(option));
- } SMARTLIST_FOREACH_END(option);
-
- goto done;
-
- err:
- SMARTLIST_FOREACH(options, char*, s, tor_free(s));
- smartlist_free(options);
- options = NULL;
-
- done:
- SMARTLIST_FOREACH(items, char*, s, tor_free(s));
- smartlist_free(items);
-
- return options;
-}
-
-/** Given the name of a pluggable transport in <b>transport</b>, check
- * the configuration file to see if the user has explicitly asked for
- * it to listen on a specific port. Return a <address:port> string if
- * so, otherwise NULL. */
-char *
-get_transport_bindaddr_from_config(const char *transport)
-{
- config_line_t *cl;
- const or_options_t *options = get_options();
-
- for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) {
- char *bindaddr =
- get_bindaddr_from_transport_listen_line(cl->value, transport);
- if (bindaddr)
- return bindaddr;
- }
-
- return NULL;
-}
-
-/** Given the name of a pluggable transport in <b>transport</b>, check
- * the configuration file to see if the user has asked us to pass any
- * parameters to the pluggable transport. Return a smartlist
- * containing the parameters, otherwise NULL. */
-smartlist_t *
-get_options_for_server_transport(const char *transport)
-{
- config_line_t *cl;
- const or_options_t *options = get_options();
-
- for (cl = options->ServerTransportOptions; cl; cl = cl->next) {
- smartlist_t *options_sl =
- get_options_from_transport_options_line(cl->value, transport);
- if (options_sl)
- return options_sl;
- }
-
- return NULL;
-}
-
/** Read the contents of a DirAuthority line from <b>line</b>. If
* <b>validate_only</b> is 0, and the line is well-formed, and it
* shares any bits with <b>required_type</b> or <b>required_type</b>
@@ -6595,13 +5876,14 @@ parse_dir_fallback_line(const char *line,
}
/** Allocate and return a new port_cfg_t with reasonable defaults. */
-STATIC port_cfg_t *
+port_cfg_t *
port_cfg_new(size_t namelen)
{
tor_assert(namelen <= SIZE_T_CEILING - sizeof(port_cfg_t) - 1);
port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t) + namelen + 1);
cfg->entry_cfg.ipv4_traffic = 1;
cfg->entry_cfg.ipv6_traffic = 1;
+ cfg->entry_cfg.prefer_ipv6 = 0;
cfg->entry_cfg.dns_request = 1;
cfg->entry_cfg.onion_traffic = 1;
cfg->entry_cfg.prefer_ipv6_virtaddr = 1;
@@ -6609,7 +5891,7 @@ port_cfg_new(size_t namelen)
}
/** Free all storage held in <b>port</b> */
-STATIC void
+void
port_cfg_free_(port_cfg_t *port)
{
tor_free(port);
@@ -6643,27 +5925,6 @@ warn_nonlocal_client_ports(const smartlist_t *ports,
} SMARTLIST_FOREACH_END(port);
}
-/** Warn for every Extended ORPort port in <b>ports</b> that is on a
- * publicly routable address. */
-static void
-warn_nonlocal_ext_orports(const smartlist_t *ports, const char *portname)
-{
- SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) {
- if (port->type != CONN_TYPE_EXT_OR_LISTENER)
- continue;
- if (port->is_unix_addr)
- continue;
- /* XXX maybe warn even if address is RFC1918? */
- if (!tor_addr_is_internal(&port->addr, 1)) {
- log_warn(LD_CONFIG, "You specified a public address '%s' for %sPort. "
- "This is not advised; this address is supposed to only be "
- "exposed on localhost so that your pluggable transport "
- "proxies can connect to it.",
- fmt_addrport(&port->addr, port->port), portname);
- }
- } SMARTLIST_FOREACH_END(port);
-}
-
/** Given a list of port_cfg_t in <b>ports</b>, warn if any controller port
* there is listening on any non-loopback address. If <b>forbid_nonlocal</b>
* is true, then emit a stronger warning and remove the port from the list.
@@ -6777,55 +6038,6 @@ warn_client_dns_cache(const char *option, int disabling)
}
/**
- * Validate the configured bridge distribution method from a BridgeDistribution
- * config line.
- *
- * The input <b>bd</b>, is a string taken from the BridgeDistribution config
- * line (if present). If the option wasn't set, return 0 immediately. The
- * BridgeDistribution option is then validated. Currently valid, recognised
- * options are:
- *
- * - "none"
- * - "any"
- * - "https"
- * - "email"
- * - "moat"
- * - "hyphae"
- *
- * If the option string is unrecognised, a warning will be logged and 0 is
- * returned. If the option string contains an invalid character, -1 is
- * returned.
- **/
-STATIC int
-check_bridge_distribution_setting(const char *bd)
-{
- if (bd == NULL)
- return 0;
-
- const char *RECOGNIZED[] = {
- "none", "any", "https", "email", "moat", "hyphae"
- };
- unsigned i;
- for (i = 0; i < ARRAY_LENGTH(RECOGNIZED); ++i) {
- if (!strcasecmp(bd, RECOGNIZED[i]))
- return 0;
- }
-
- const char *cp = bd;
- // Method = (KeywordChar | "_") +
- while (TOR_ISALNUM(*cp) || *cp == '-' || *cp == '_')
- ++cp;
-
- if (*cp == 0) {
- log_warn(LD_CONFIG, "Unrecognized BridgeDistribution value %s. I'll "
- "assume you know what you are doing...", escaped(bd));
- return 0; // we reached the end of the string; all is well
- } else {
- return -1; // we found a bad character in the string.
- }
-}
-
-/**
* Parse port configuration for a single port type.
*
* Read entries of the "FooPort" type from the list <b>ports</b>. Syntax is
@@ -6855,8 +6067,8 @@ check_bridge_distribution_setting(const char *bd)
* <b>out</b> for every port that the client should listen on. Return 0
* on success, -1 on failure.
*/
-STATIC int
-parse_port_config(smartlist_t *out,
+int
+port_parse_config(smartlist_t *out,
const config_line_t *ports,
const char *portname,
int listener_type,
@@ -6925,7 +6137,7 @@ parse_port_config(smartlist_t *out,
cache_ipv6 = 0, use_cached_ipv6 = 0,
prefer_ipv6_automap = 1, world_writable = 0, group_writable = 0,
relax_dirmode_check = 0,
- has_used_unix_socket_only_option = 0;
+ has_used_unix_socket_only_option = 0, extended_errors = 0;
int is_unix_tagged_addr = 0;
const char *rest_of_line = NULL;
@@ -7164,6 +6376,9 @@ parse_port_config(smartlist_t *out,
} else if (!strcasecmp(elt, "KeepAliveIsolateSOCKSAuth")) {
socks_iso_keep_alive = ! no;
continue;
+ } else if (!strcasecmp(elt, "ExtendedErrors")) {
+ extended_errors = ! no;
+ continue;
}
if (!strcasecmpend(elt, "s"))
@@ -7276,6 +6491,7 @@ parse_port_config(smartlist_t *out,
if (! (isolation & ISO_SOCKSAUTH))
cfg->entry_cfg.socks_prefer_no_auth = 1;
cfg->entry_cfg.socks_iso_keep_alive = socks_iso_keep_alive;
+ cfg->entry_cfg.extended_socks5_codes = extended_errors;
smartlist_add(out, cfg);
}
@@ -7289,7 +6505,7 @@ parse_port_config(smartlist_t *out,
if (is_control)
warn_nonlocal_controller_ports(out, forbid_nonlocal);
else if (is_ext_orport)
- warn_nonlocal_ext_orports(out, portname);
+ port_warn_nonlocal_ext_orports(out, portname);
else
warn_nonlocal_client_ports(out, portname, listener_type);
}
@@ -7313,8 +6529,8 @@ parse_port_config(smartlist_t *out,
/** Return the number of ports which are actually going to listen with type
* <b>listenertype</b>. Do not count no_listen ports. Only count unix
* sockets if count_sockets is true. */
-static int
-count_real_listeners(const smartlist_t *ports, int listenertype,
+int
+port_count_real_listeners(const smartlist_t *ports, int listenertype,
int count_sockets)
{
int n = 0;
@@ -7338,7 +6554,7 @@ count_real_listeners(const smartlist_t *ports, int listenertype,
* If <b>validate_only</b> is false, set configured_client_ports to the
* new list of ports parsed from <b>options</b>.
**/
-static int
+STATIC int
parse_ports(or_options_t *options, int validate_only,
char **msg, int *n_ports_out,
int *world_writable_control_socket)
@@ -7352,7 +6568,7 @@ parse_ports(or_options_t *options, int validate_only,
const unsigned gw_flag = options->UnixSocksGroupWritable ?
CL_PORT_DFLT_GROUP_WRITABLE : 0;
- if (parse_port_config(ports,
+ if (port_parse_config(ports,
options->SocksPort_lines,
"Socks", CONN_TYPE_AP_LISTENER,
"127.0.0.1", 9050,
@@ -7361,7 +6577,7 @@ parse_ports(or_options_t *options, int validate_only,
*msg = tor_strdup("Invalid SocksPort configuration");
goto err;
}
- if (parse_port_config(ports,
+ if (port_parse_config(ports,
options->DNSPort_lines,
"DNS", CONN_TYPE_AP_DNS_LISTENER,
"127.0.0.1", 0,
@@ -7369,7 +6585,7 @@ parse_ports(or_options_t *options, int validate_only,
*msg = tor_strdup("Invalid DNSPort configuration");
goto err;
}
- if (parse_port_config(ports,
+ if (port_parse_config(ports,
options->TransPort_lines,
"Trans", CONN_TYPE_AP_TRANS_LISTENER,
"127.0.0.1", 0,
@@ -7377,7 +6593,7 @@ parse_ports(or_options_t *options, int validate_only,
*msg = tor_strdup("Invalid TransPort configuration");
goto err;
}
- if (parse_port_config(ports,
+ if (port_parse_config(ports,
options->NATDPort_lines,
"NATD", CONN_TYPE_AP_NATD_LISTENER,
"127.0.0.1", 0,
@@ -7385,7 +6601,7 @@ parse_ports(or_options_t *options, int validate_only,
*msg = tor_strdup("Invalid NatdPort configuration");
goto err;
}
- if (parse_port_config(ports,
+ if (port_parse_config(ports,
options->HTTPTunnelPort_lines,
"HTTP Tunnel", CONN_TYPE_AP_HTTP_CONNECT_LISTENER,
"127.0.0.1", 0,
@@ -7405,7 +6621,7 @@ parse_ports(or_options_t *options, int validate_only,
if (options->ControlSocketsGroupWritable)
control_port_flags |= CL_PORT_DFLT_GROUP_WRITABLE;
- if (parse_port_config(ports,
+ if (port_parse_config(ports,
options->ControlPort_lines,
"Control", CONN_TYPE_CONTROL_LISTENER,
"127.0.0.1", 0,
@@ -7414,7 +6630,7 @@ parse_ports(or_options_t *options, int validate_only,
goto err;
}
- if (parse_port_config(ports, options->ControlSocket,
+ if (port_parse_config(ports, options->ControlSocket,
"ControlSocket",
CONN_TYPE_CONTROL_LISTENER, NULL, 0,
control_port_flags | CL_PORT_IS_UNIXSOCKET) < 0) {
@@ -7422,40 +6638,9 @@ parse_ports(or_options_t *options, int validate_only,
goto err;
}
}
- if (! options->ClientOnly) {
- if (parse_port_config(ports,
- options->ORPort_lines,
- "OR", CONN_TYPE_OR_LISTENER,
- "0.0.0.0", 0,
- CL_PORT_SERVER_OPTIONS) < 0) {
- *msg = tor_strdup("Invalid ORPort configuration");
- goto err;
- }
- if (parse_port_config(ports,
- options->ExtORPort_lines,
- "ExtOR", CONN_TYPE_EXT_OR_LISTENER,
- "127.0.0.1", 0,
- CL_PORT_SERVER_OPTIONS|CL_PORT_WARN_NONLOCAL) < 0) {
- *msg = tor_strdup("Invalid ExtORPort configuration");
- goto err;
- }
- if (parse_port_config(ports,
- options->DirPort_lines,
- "Dir", CONN_TYPE_DIR_LISTENER,
- "0.0.0.0", 0,
- CL_PORT_SERVER_OPTIONS) < 0) {
- *msg = tor_strdup("Invalid DirPort configuration");
- goto err;
- }
- }
- int n_low_ports = 0;
- if (check_server_ports(ports, options, &n_low_ports) < 0) {
- *msg = tor_strdup("Misconfigured server ports");
+ if (port_parse_ports_relay(options, msg, ports, &have_low_ports) < 0)
goto err;
- }
- if (have_low_ports < 0)
- have_low_ports = (n_low_ports > 0);
*n_ports_out = smartlist_len(ports);
@@ -7463,25 +6648,20 @@ parse_ports(or_options_t *options, int validate_only,
/* Update the *Port_set options. The !! here is to force a boolean out of
an integer. */
- options->ORPort_set =
- !! count_real_listeners(ports, CONN_TYPE_OR_LISTENER, 0);
+ port_update_port_set_relay(options, ports);
options->SocksPort_set =
- !! count_real_listeners(ports, CONN_TYPE_AP_LISTENER, 1);
+ !! port_count_real_listeners(ports, CONN_TYPE_AP_LISTENER, 1);
options->TransPort_set =
- !! count_real_listeners(ports, CONN_TYPE_AP_TRANS_LISTENER, 1);
+ !! port_count_real_listeners(ports, CONN_TYPE_AP_TRANS_LISTENER, 1);
options->NATDPort_set =
- !! count_real_listeners(ports, CONN_TYPE_AP_NATD_LISTENER, 1);
+ !! port_count_real_listeners(ports, CONN_TYPE_AP_NATD_LISTENER, 1);
options->HTTPTunnelPort_set =
- !! count_real_listeners(ports, CONN_TYPE_AP_HTTP_CONNECT_LISTENER, 1);
+ !! port_count_real_listeners(ports, CONN_TYPE_AP_HTTP_CONNECT_LISTENER, 1);
/* Use options->ControlSocket to test if a control socket is set */
options->ControlPort_set =
- !! count_real_listeners(ports, CONN_TYPE_CONTROL_LISTENER, 0);
- options->DirPort_set =
- !! count_real_listeners(ports, CONN_TYPE_DIR_LISTENER, 0);
+ !! port_count_real_listeners(ports, CONN_TYPE_CONTROL_LISTENER, 0);
options->DNSPort_set =
- !! count_real_listeners(ports, CONN_TYPE_AP_DNS_LISTENER, 1);
- options->ExtORPort_set =
- !! count_real_listeners(ports, CONN_TYPE_EXT_OR_LISTENER, 0);
+ !! port_count_real_listeners(ports, CONN_TYPE_AP_DNS_LISTENER, 1);
if (world_writable_control_socket) {
SMARTLIST_FOREACH(ports, port_cfg_t *, p,
@@ -7512,7 +6692,7 @@ parse_ports(or_options_t *options, int validate_only,
}
/* Does port bind to IPv4? */
-static int
+int
port_binds_ipv4(const port_cfg_t *port)
{
return tor_addr_family(&port->addr) == AF_INET ||
@@ -7521,7 +6701,7 @@ port_binds_ipv4(const port_cfg_t *port)
}
/* Does port bind to IPv6? */
-static int
+int
port_binds_ipv6(const port_cfg_t *port)
{
return tor_addr_family(&port->addr) == AF_INET6 ||
@@ -7529,94 +6709,6 @@ port_binds_ipv6(const port_cfg_t *port)
&& !port->server_cfg.bind_ipv4_only);
}
-/** Given a list of <b>port_cfg_t</b> in <b>ports</b>, check them for internal
- * consistency and warn as appropriate. Set *<b>n_low_ports_out</b> to the
- * number of sub-1024 ports we will be binding. */
-static int
-check_server_ports(const smartlist_t *ports,
- const or_options_t *options,
- int *n_low_ports_out)
-{
- int n_orport_advertised = 0;
- int n_orport_advertised_ipv4 = 0;
- int n_orport_listeners = 0;
- int n_dirport_advertised = 0;
- int n_dirport_listeners = 0;
- int n_low_port = 0;
- int r = 0;
-
- SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) {
- if (port->type == CONN_TYPE_DIR_LISTENER) {
- if (! port->server_cfg.no_advertise)
- ++n_dirport_advertised;
- if (! port->server_cfg.no_listen)
- ++n_dirport_listeners;
- } else if (port->type == CONN_TYPE_OR_LISTENER) {
- if (! port->server_cfg.no_advertise) {
- ++n_orport_advertised;
- if (port_binds_ipv4(port))
- ++n_orport_advertised_ipv4;
- }
- if (! port->server_cfg.no_listen)
- ++n_orport_listeners;
- } else {
- continue;
- }
-#ifndef _WIN32
- if (!port->server_cfg.no_listen && port->port < 1024)
- ++n_low_port;
-#endif
- } SMARTLIST_FOREACH_END(port);
-
- if (n_orport_advertised && !n_orport_listeners) {
- log_warn(LD_CONFIG, "We are advertising an ORPort, but not actually "
- "listening on one.");
- r = -1;
- }
- if (n_orport_listeners && !n_orport_advertised) {
- log_warn(LD_CONFIG, "We are listening on an ORPort, but not advertising "
- "any ORPorts. This will keep us from building a %s "
- "descriptor, and make us impossible to use.",
- options->BridgeRelay ? "bridge" : "router");
- r = -1;
- }
- if (n_dirport_advertised && !n_dirport_listeners) {
- log_warn(LD_CONFIG, "We are advertising a DirPort, but not actually "
- "listening on one.");
- r = -1;
- }
- if (n_dirport_advertised > 1) {
- log_warn(LD_CONFIG, "Can't advertise more than one DirPort.");
- r = -1;
- }
- if (n_orport_advertised && !n_orport_advertised_ipv4 &&
- !options->BridgeRelay) {
- log_warn(LD_CONFIG, "Configured public relay to listen only on an IPv6 "
- "address. Tor needs to listen on an IPv4 address too.");
- r = -1;
- }
-
- if (n_low_port && options->AccountingMax &&
- (!have_capability_support() || options->KeepBindCapabilities == 0)) {
- const char *extra = "";
- if (options->KeepBindCapabilities == 0 && have_capability_support())
- extra = ", and you have disabled KeepBindCapabilities.";
- log_warn(LD_CONFIG,
- "You have set AccountingMax to use hibernation. You have also "
- "chosen a low DirPort or OrPort%s."
- "This combination can make Tor stop "
- "working when it tries to re-attach the port after a period of "
- "hibernation. Please choose a different port or turn off "
- "hibernation unless you know this combination will work on your "
- "platform.", extra);
- }
-
- if (n_low_ports_out)
- *n_low_ports_out = n_low_port;
-
- return r;
-}
-
/** Return a list of port_cfg_t for client ports parsed from the
* options. */
MOCK_IMPL(const smartlist_t *,
@@ -7986,7 +7078,7 @@ get_num_cpus(const or_options_t *options)
static void
init_libevent(const or_options_t *options)
{
- tor_libevent_cfg cfg;
+ tor_libevent_cfg_t cfg;
tor_assert(options);
@@ -8095,43 +7187,6 @@ write_to_data_subdir(const char* subdir, const char* fname,
return return_val;
}
-/** Return a smartlist of ports that must be forwarded by
- * tor-fw-helper. The smartlist contains the ports in a string format
- * that is understandable by tor-fw-helper. */
-smartlist_t *
-get_list_of_ports_to_forward(void)
-{
- smartlist_t *ports_to_forward = smartlist_new();
- int port = 0;
-
- /** XXX TODO tor-fw-helper does not support forwarding ports to
- other hosts than the local one. If the user is binding to a
- different IP address, tor-fw-helper won't work. */
- port = router_get_advertised_or_port(get_options()); /* Get ORPort */
- if (port)
- smartlist_add_asprintf(ports_to_forward, "%d:%d", port, port);
-
- port = router_get_advertised_dir_port(get_options(), 0); /* Get DirPort */
- if (port)
- smartlist_add_asprintf(ports_to_forward, "%d:%d", port, port);
-
- /* Get ports of transport proxies */
- {
- smartlist_t *transport_ports = get_transport_proxy_ports();
- if (transport_ports) {
- smartlist_add_all(ports_to_forward, transport_ports);
- smartlist_free(transport_ports);
- }
- }
-
- if (!smartlist_len(ports_to_forward)) {
- smartlist_free(ports_to_forward);
- ports_to_forward = NULL;
- }
-
- return ports_to_forward;
-}
-
/** Helper to implement GETINFO functions about configuration variables (not
* their values). Given a "config/names" question, set *<b>answer</b> to a
* new string describing the supported configuration variables and their
diff --git a/src/app/config/config.h b/src/app/config/config.h
index 44f09e5ee9..311e27917a 100644
--- a/src/app/config/config.h
+++ b/src/app/config/config.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,6 +14,7 @@
#include "app/config/or_options_st.h"
#include "lib/testsupport/testsupport.h"
+#include "app/config/quiet_level.h"
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(DARWIN)
#define KERNEL_MAY_SUPPORT_IPFW
@@ -30,7 +31,6 @@
#define MAX_DEFAULT_MEMORY_QUEUE_SIZE (UINT64_C(2) << 30)
#endif
-MOCK_DECL(const char*, get_dirportfrontpage, (void));
MOCK_DECL(const or_options_t *, get_options, (void));
MOCK_DECL(or_options_t *, get_options_mutable, (void));
int set_options(or_options_t *new_val, char **msg);
@@ -162,6 +162,8 @@ int write_to_data_subdir(const char* subdir, const char* fname,
int get_num_cpus(const or_options_t *options);
MOCK_DECL(const smartlist_t *,get_configured_ports,(void));
+int port_binds_ipv4(const port_cfg_t *port);
+int port_binds_ipv6(const port_cfg_t *port);
int get_first_advertised_port_by_type_af(int listener_type,
int address_family);
#define get_primary_or_port() \
@@ -180,26 +182,36 @@ char *get_first_listener_addrport_string(int listener_type);
int options_need_geoip_info(const or_options_t *options,
const char **reason_out);
-smartlist_t *get_list_of_ports_to_forward(void);
-
int getinfo_helper_config(control_connection_t *conn,
const char *question, char **answer,
const char **errmsg);
-uint32_t get_effective_bwrate(const or_options_t *options);
-uint32_t get_effective_bwburst(const or_options_t *options);
-
-char *get_transport_bindaddr_from_config(const char *transport);
-
int init_cookie_authentication(const char *fname, const char *header,
int cookie_len, int group_readable,
uint8_t **cookie_out, int *cookie_is_set_out);
or_options_t *options_new(void);
-int config_parse_commandline(int argc, char **argv, int ignore_errors,
- struct config_line_t **result,
- struct config_line_t **cmdline_result);
+/** Options settings parsed from the command-line. */
+typedef struct {
+ /** List of options that can only be set from the command-line */
+ struct config_line_t *cmdline_opts;
+ /** List of other options, to be handled by the general Tor configuration
+ system. */
+ struct config_line_t *other_opts;
+ /** Subcommand that Tor has been told to run */
+ tor_cmdline_mode_t command;
+ /** Argument for the command mode, if any. */
+ const char *command_arg;
+ /** How quiet have we been told to be? */
+ quiet_level_t quiet_level;
+} parsed_cmdline_t;
+
+parsed_cmdline_t *config_parse_commandline(int argc, char **argv,
+ int ignore_errors);
+void parsed_cmdline_free_(parsed_cmdline_t *cmdline);
+#define parsed_cmdline_free(c) \
+ FREE_AND_NULL(parsed_cmdline_t, parsed_cmdline_free_, (c))
void config_register_addressmaps(const or_options_t *options);
/* XXXX move to connection_edge.h */
@@ -228,14 +240,16 @@ void bridge_line_free_(bridge_line_t *bridge_line);
#define bridge_line_free(line) \
FREE_AND_NULL(bridge_line_t, bridge_line_free_, (line))
bridge_line_t *parse_bridge_line(const char *line);
-smartlist_t *get_options_from_transport_options_line(const char *line,
- const char *transport);
-smartlist_t *get_options_for_server_transport(const char *transport);
/* Port helper functions. */
int options_any_client_port_set(const or_options_t *options);
-
-#ifdef CONFIG_PRIVATE
+int port_parse_config(smartlist_t *out,
+ const struct config_line_t *ports,
+ const char *portname,
+ int listener_type,
+ const char *defaultaddr,
+ int defaultport,
+ const unsigned flags);
#define CL_PORT_NO_STREAM_OPTIONS (1u<<0)
#define CL_PORT_WARN_NONLOCAL (1u<<1)
@@ -246,26 +260,34 @@ int options_any_client_port_set(const or_options_t *options);
#define CL_PORT_IS_UNIXSOCKET (1u<<6)
#define CL_PORT_DFLT_GROUP_WRITABLE (1u<<7)
-STATIC int options_act(const or_options_t *old_options);
+port_cfg_t *port_cfg_new(size_t namelen);
+#define port_cfg_free(port) \
+ FREE_AND_NULL(port_cfg_t, port_cfg_free_, (port))
+void port_cfg_free_(port_cfg_t *port);
+
+int port_count_real_listeners(const smartlist_t *ports,
+ int listenertype,
+ int count_sockets);
+int pt_parse_transport_line(const or_options_t *options,
+ const char *line, int validate_only,
+ int server);
+int config_ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg);
+
+#ifdef CONFIG_PRIVATE
+
+MOCK_DECL(STATIC int, options_act,(const or_options_t *old_options));
+MOCK_DECL(STATIC int, options_act_reversible,(const or_options_t *old_options,
+ char **msg));
struct config_mgr_t;
STATIC const struct config_mgr_t *get_options_mgr(void);
-STATIC port_cfg_t *port_cfg_new(size_t namelen);
-#define port_cfg_free(port) \
- FREE_AND_NULL(port_cfg_t, port_cfg_free_, (port))
-STATIC void port_cfg_free_(port_cfg_t *port);
#define or_options_free(opt) \
FREE_AND_NULL(or_options_t, or_options_free_, (opt))
STATIC void or_options_free_(or_options_t *options);
STATIC int options_validate_single_onion(or_options_t *options,
char **msg);
-STATIC int options_validate(or_options_t *old_options,
- or_options_t *options,
- or_options_t *default_options,
- int from_setconf, char **msg);
-STATIC int parse_transport_line(const or_options_t *options,
- const char *line, int validate_only,
- int server);
+STATIC int parse_tcp_proxy_line(const char *line, or_options_t *options,
+ char **msg);
STATIC int consider_adding_dir_servers(const or_options_t *options,
const or_options_t *old_options);
STATIC void add_default_trusted_dir_authorities(dirinfo_type_t type);
@@ -274,23 +296,32 @@ STATIC int parse_dir_authority_line(const char *line,
dirinfo_type_t required_type,
int validate_only);
STATIC int parse_dir_fallback_line(const char *line, int validate_only);
-STATIC int have_enough_mem_for_dircache(const or_options_t *options,
- size_t total_mem, char **msg);
-STATIC int parse_port_config(smartlist_t *out,
- const struct config_line_t *ports,
- const char *portname,
- int listener_type,
- const char *defaultaddr,
- int defaultport,
- const unsigned flags);
-
-STATIC int check_bridge_distribution_setting(const char *bd);
STATIC uint64_t compute_real_max_mem_in_queues(const uint64_t val,
int log_guess);
STATIC int open_and_add_file_log(const log_severity_list_t *severity,
const char *fname,
int truncate_log);
+STATIC int options_init_logs(const or_options_t *old_options,
+ const or_options_t *options, int validate_only);
+
+STATIC int options_create_directories(char **msg_out);
+struct log_transaction_t;
+STATIC struct log_transaction_t *options_start_log_transaction(
+ const or_options_t *old_options,
+ char **msg_out);
+STATIC void options_commit_log_transaction(struct log_transaction_t *xn);
+STATIC void options_rollback_log_transaction(struct log_transaction_t *xn);
+
+#ifdef TOR_UNIT_TESTS
+int options_validate(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg);
+#endif
+
+STATIC int parse_ports(or_options_t *options, int validate_only,
+ char **msg, int *n_ports_out,
+ int *world_writable_control_socket);
#endif /* defined(CONFIG_PRIVATE) */
diff --git a/src/app/config/include.am b/src/app/config/include.am
new file mode 100644
index 0000000000..5d625efecf
--- /dev/null
+++ b/src/app/config/include.am
@@ -0,0 +1,21 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/app/config/config.c \
+ src/app/config/quiet_level.c \
+ src/app/config/statefile.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/app/config/config.h \
+ src/app/config/or_options_st.h \
+ src/app/config/or_state_st.h \
+ src/app/config/quiet_level.h \
+ src/app/config/statefile.h \
+ src/app/config/tor_cmdline_mode.h
+
+
+noinst_HEADERS += \
+ src/app/config/auth_dirs.inc \
+ src/app/config/fallback_dirs.inc \
+ src/app/config/testnet.inc
diff --git a/src/app/config/or_options_st.h b/src/app/config/or_options_st.h
index e6be797017..35ba15a9e2 100644
--- a/src/app/config/or_options_st.h
+++ b/src/app/config/or_options_st.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,12 +13,15 @@
#ifndef TOR_OR_OPTIONS_ST_H
#define TOR_OR_OPTIONS_ST_H
+#include "core/or/or.h"
#include "lib/cc/torint.h"
#include "lib/net/address.h"
+#include "app/config/tor_cmdline_mode.h"
struct smartlist_t;
struct config_line_t;
struct config_suite_t;
+struct routerset_t;
/** Enumeration of outbound address configuration types:
* Exit-only, OR-only, or both */
@@ -26,17 +29,18 @@ typedef enum {OUTBOUND_ADDR_EXIT, OUTBOUND_ADDR_OR,
OUTBOUND_ADDR_EXIT_AND_OR,
OUTBOUND_ADDR_MAX} outbound_addr_t;
+/** Which protocol to use for TCPProxy. */
+typedef enum {
+ /** Use the HAProxy proxy protocol. */
+ TCP_PROXY_PROTOCOL_HAPROXY
+} tcp_proxy_protocol_t;
+
/** Configuration options for a Tor process. */
struct or_options_t {
uint32_t magic_;
/** What should the tor process actually do? */
- enum {
- CMD_RUN_TOR=0, CMD_LIST_FINGERPRINT, CMD_HASH_PASSWORD,
- CMD_VERIFY_CONFIG, CMD_RUN_UNITTESTS, CMD_DUMP_CONFIG,
- CMD_KEYGEN,
- CMD_KEY_EXPIRATION,
- } command;
+ tor_cmdline_mode_t command;
char *command_arg; /**< Argument for command-line option. */
struct config_line_t *Logs; /**< New-style list of configuration lines
@@ -70,28 +74,29 @@ struct or_options_t {
char *Address; /**< OR only: configured address for this onion router. */
char *PidFile; /**< Where to store PID of Tor process. */
- routerset_t *ExitNodes; /**< Structure containing nicknames, digests,
+ struct routerset_t *ExitNodes; /**< Structure containing nicknames, digests,
* country codes and IP address patterns of ORs to
* consider as exits. */
- routerset_t *MiddleNodes; /**< Structure containing nicknames, digests,
- * country codes and IP address patterns of ORs to
- * consider as middles. */
- routerset_t *EntryNodes;/**< Structure containing nicknames, digests,
+ struct routerset_t *MiddleNodes; /**< Structure containing nicknames,
+ * digests, country codes and IP address patterns
+ * of ORs to consider as middles. */
+ struct routerset_t *EntryNodes;/**< Structure containing nicknames, digests,
* country codes and IP address patterns of ORs to
* consider as entry points. */
int StrictNodes; /**< Boolean: When none of our EntryNodes or ExitNodes
* are up, or we need to access a node in ExcludeNodes,
* do we just fail instead? */
- routerset_t *ExcludeNodes;/**< Structure containing nicknames, digests,
- * country codes and IP address patterns of ORs
- * not to use in circuits. But see StrictNodes
- * above. */
- routerset_t *ExcludeExitNodes;/**< Structure containing nicknames, digests,
- * country codes and IP address patterns of
- * ORs not to consider as exits. */
+ struct routerset_t *ExcludeNodes;/**< Structure containing nicknames,
+ * digests, country codes and IP address patterns
+ * of ORs not to use in circuits. But see
+ * StrictNodes above. */
+ struct routerset_t *ExcludeExitNodes;/**< Structure containing nicknames,
+ * digests, country codes and IP address
+ * patterns of ORs not to consider as
+ * exits. */
/** Union of ExcludeNodes and ExcludeExitNodes */
- routerset_t *ExcludeExitNodesUnion_;
+ struct routerset_t *ExcludeExitNodesUnion_;
int DisableAllSwap; /**< Boolean: Attempt to call mlockall() on our
* process for all current and future memory. */
@@ -117,11 +122,6 @@ struct or_options_t {
* [][0] is IPv4, [][1] is IPv6
*/
tor_addr_t OutboundBindAddresses[OUTBOUND_ADDR_MAX][2];
- /** Directory server only: which versions of
- * Tor should we tell users to run? */
- struct config_line_t *RecommendedVersions;
- struct config_line_t *RecommendedClientVersions;
- struct config_line_t *RecommendedServerVersions;
/** Whether dirservers allow router descriptors with private IPs. */
int DirAllowPrivateAddresses;
/** Whether routers accept EXTEND cells to routers with private IPs. */
@@ -196,9 +196,6 @@ struct or_options_t {
int AuthoritativeDir; /**< Boolean: is this an authoritative directory? */
int V3AuthoritativeDir; /**< Boolean: is this an authoritative directory
* for version 3 directories? */
- int VersioningAuthoritativeDir; /**< Boolean: is this an authoritative
- * directory that's willing to recommend
- * versions? */
int BridgeAuthoritativeDir; /**< Boolean: is this an authoritative directory
* that aggregates bridge descriptors? */
@@ -269,20 +266,17 @@ struct or_options_t {
int FetchServerDescriptors; /**< Do we fetch server descriptors as normal? */
int FetchHidServDescriptors; /**< and hidden service descriptors? */
- int MinUptimeHidServDirectoryV2; /**< As directory authority, accept hidden
- * service directories after what time? */
-
int FetchUselessDescriptors; /**< Do we fetch non-running descriptors too? */
int AllDirActionsPrivate; /**< Should every directory action be sent
* through a Tor circuit? */
/** A routerset that should be used when picking middle nodes for HS
* circuits. */
- routerset_t *HSLayer2Nodes;
+ struct routerset_t *HSLayer2Nodes;
/** A routerset that should be used when picking third-hop nodes for HS
* circuits. */
- routerset_t *HSLayer3Nodes;
+ struct routerset_t *HSLayer3Nodes;
/** Onion Services in HiddenServiceSingleHopMode make one-hop (direct)
* circuits between the onion service server, and the introduction and
@@ -423,6 +417,11 @@ struct or_options_t {
char *Socks5ProxyUsername; /**< Username for SOCKS5 authentication, if any */
char *Socks5ProxyPassword; /**< Password for SOCKS5 authentication, if any */
+ char *TCPProxy; /**< protocol and hostname:port to use as a proxy, if any. */
+ tcp_proxy_protocol_t TCPProxyProtocol; /**< Derived from TCPProxy. */
+ tor_addr_t TCPProxyAddr; /**< Derived from TCPProxy. */
+ uint16_t TCPProxyPort; /**< Derived from TCPProxy. */
+
/** List of configuration lines for replacement directory authorities.
* If you just want to replace one class of authority at a time,
* use the "Alternate*Authority" options below instead. */
@@ -469,21 +468,6 @@ struct or_options_t {
struct smartlist_t *AuthDirRejectCCs;
/**@}*/
- int AuthDirListBadExits; /**< True iff we should list bad exits,
- * and vote for all other exits as good. */
- int AuthDirMaxServersPerAddr; /**< Do not permit more than this
- * number of servers per IP address. */
- int AuthDirHasIPv6Connectivity; /**< Boolean: are we on IPv6? */
- int AuthDirPinKeys; /**< Boolean: Do we enforce key-pinning? */
-
- /** If non-zero, always vote the Fast flag for any relay advertising
- * this amount of capacity or more. */
- uint64_t AuthDirFastGuarantee;
-
- /** If non-zero, this advertised capacity or more is always sufficient
- * to satisfy the bandwidth requirement for the Guard flag. */
- uint64_t AuthDirGuardBWGuarantee;
-
char *AccountingStart; /**< How long is the accounting interval, and when
* does it start? */
uint64_t AccountingMax; /**< How many bytes do we allow per accounting
@@ -540,12 +524,8 @@ struct or_options_t {
* protocol, is it a warn or an info in our logs? */
int TestSocks; /**< Boolean: when we get a socks connection, do we loudly
* log whether it was DNS-leaking or not? */
- int HardwareAccel; /**< Boolean: Should we enable OpenSSL hardware
- * acceleration where available? */
/** Token Bucket Refill resolution in milliseconds. */
int TokenBucketRefillInterval;
- char *AccelName; /**< Optional hardware acceleration engine name. */
- char *AccelDir; /**< Optional hardware acceleration engine search dir. */
/** Boolean: Do we try to enter from a smallish number
* of fixed nodes? */
@@ -577,7 +557,9 @@ struct or_options_t {
int DirCache; /**< Cache all directory documents and accept requests via
* tunnelled dir conns from clients. If 1, enabled (default);
- * If 0, disabled. */
+ * If 0, disabled. Use dir_server_mode() rather than
+ * referencing this option directly. (Except for routermode
+ * and relay_config, which do direct checks.) */
char *VirtualAddrNetworkIPv4; /**< Address and mask to hand out for virtual
* MAPADDRESS requests for IPv4 addresses */
@@ -702,14 +684,6 @@ struct or_options_t {
/** Location of guardfraction file */
char *GuardfractionFile;
- /** Authority only: key=value pairs that we add to our networkstatus
- * consensus vote on the 'params' line. */
- char *ConsensusParams;
-
- /** Authority only: minimum number of measured bandwidths we must see
- * before we only believe measured bandwidths to assign flags. */
- int MinMeasuredBWsForAuthToIgnoreAdvertised;
-
/** The length of time that we think an initial consensus should be fresh.
* Only altered on testing networks. */
int TestingV3AuthInitialVotingInterval;
@@ -726,16 +700,6 @@ struct or_options_t {
voting. Only altered on testing networks. */
int TestingV3AuthVotingStartOffset;
- /** If an authority has been around for less than this amount of time, it
- * does not believe its reachability information is accurate. Only
- * altered on testing networks. */
- int TestingAuthDirTimeToLearnReachability;
-
- /** Clients don't download any descriptor this recent, since it will
- * probably not have propagated to enough caches. Only altered on testing
- * networks. */
- int TestingEstimatedDescriptorPropagationTime;
-
/** Schedule for when servers should download things in general. Only
* altered on testing networks. */
int TestingServerDownloadInitialDelay;
@@ -809,27 +773,6 @@ struct or_options_t {
* of certain configuration options. */
int TestingTorNetwork;
- /** Minimum value for the Exit flag threshold on testing networks. */
- uint64_t TestingMinExitFlagThreshold;
-
- /** Minimum value for the Fast flag threshold on testing networks. */
- uint64_t TestingMinFastFlagThreshold;
-
- /** Relays in a testing network which should be voted Exit
- * regardless of exit policy. */
- routerset_t *TestingDirAuthVoteExit;
- int TestingDirAuthVoteExitIsStrict;
-
- /** Relays in a testing network which should be voted Guard
- * regardless of uptime and bandwidth. */
- routerset_t *TestingDirAuthVoteGuard;
- int TestingDirAuthVoteGuardIsStrict;
-
- /** Relays in a testing network which should be voted HSDir
- * regardless of uptime and DirPort. */
- routerset_t *TestingDirAuthVoteHSDir;
- int TestingDirAuthVoteHSDirIsStrict;
-
/** Enable CONN_BW events. Only altered on testing networks. */
int TestingEnableConnBwEvent;
@@ -854,7 +797,7 @@ struct or_options_t {
* to make this false. */
int ReloadTorrcOnSIGHUP;
- /* The main parameter for picking circuits within a connection.
+ /** The main parameter for picking circuits within a connection.
*
* If this value is positive, when picking a cell to relay on a connection,
* we always relay from the circuit whose weighted cell count is lowest.
@@ -1008,19 +951,6 @@ struct or_options_t {
*/
uint64_t MaxUnparseableDescSizeToLog;
- /** Bool (default: 1): Under bandwidth pressure, if set to 1, the authority
- * will always answer directory requests from relays but will start sending
- * 503 error code for the other connections. If set to 0, all connections
- * are considered the same and the authority will try to answer them all
- * regardless of bandwidth pressure or not. */
- int AuthDirRejectRequestsUnderLoad;
-
- /** Bool (default: 1): Switch for the shared random protocol. Only
- * relevant to a directory authority. If off, the authority won't
- * participate in the protocol. If on (default), a flag is added to the
- * vote indicating participation. */
- int AuthDirSharedRandomness;
-
/** If 1, we skip all OOS checks. */
int DisableOOSCheck;
@@ -1028,11 +958,6 @@ struct or_options_t {
* If -1, we should do whatever the consensus parameter says. */
int ExtendByEd25519ID;
- /** Bool (default: 1): When testing routerinfos as a directory authority,
- * do we enforce Ed25519 identity match? */
- /* NOTE: remove this option someday. */
- int AuthDirTestEd25519LinkKeys;
-
/** Bool (default: 0): Tells if a %include was used on torrc */
int IncludeUsed;
@@ -1057,7 +982,7 @@ struct or_options_t {
/** The list of scheduler type string ordered by priority that is first one
* has to be tried first. Default: KIST,KISTLite,Vanilla */
struct smartlist_t *Schedulers;
- /* An ordered list of scheduler_types mapped from Schedulers. */
+ /** An ordered list of scheduler_types mapped from Schedulers. */
struct smartlist_t *SchedulerTypes_;
/** List of files that were opened by %include in torrc and torrc-defaults */
diff --git a/src/app/config/or_state_st.h b/src/app/config/or_state_st.h
index 225003bb7e..8c4e9d5e61 100644
--- a/src/app/config/or_state_st.h
+++ b/src/app/config/or_state_st.h
@@ -1,11 +1,11 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file or_state_t
+ * \file or_state_st.h
*
* \brief The or_state_t structure, which represents Tor's state file.
*/
@@ -89,13 +89,6 @@ struct or_state_t {
/** When did we last rotate our onion key? "0" for 'no idea'. */
time_t LastRotatedOnionKey;
- /** Number of minutes since the last user-initiated request (as defined by
- * the dormant net-status system.) Set to zero if we are dormant. */
- int MinutesSinceUserActivity;
- /** True if we were dormant when we last wrote the file; false if we
- * weren't. "auto" on initial startup. */
- int Dormant;
-
/**
* State objects for individual modules.
*
diff --git a/src/app/config/quiet_level.c b/src/app/config/quiet_level.c
new file mode 100644
index 0000000000..e04faaef3a
--- /dev/null
+++ b/src/app/config/quiet_level.c
@@ -0,0 +1,38 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file quiet_level.c
+ * @brief Code to handle default logging level (quiet/hush/normal).
+ **/
+
+#include "orconfig.h"
+#include "lib/log/log.h"
+#include "app/config/quiet_level.h"
+
+/** Decides our behavior when no logs are configured/before any logs have been
+ * configured. For QUIET_NONE, we log notice to stdout as normal. For
+ * QUIET_HUSH, we log warnings only. For QUIET_SILENT, we log nothing.
+ */
+quiet_level_t quiet_level = 0;
+
+/** Add a default log (or not), depending on the value of <b>quiet</b>. */
+void
+add_default_log_for_quiet_level(quiet_level_t quiet)
+{
+ switch (quiet) {
+ case QUIET_SILENT:
+ /* --quiet: no initial logging */
+ return;
+ case QUIET_HUSH:
+ /* --hush: log at warning or higher. */
+ add_default_log(LOG_WARN);
+ break;
+ case QUIET_NONE: FALLTHROUGH;
+ default:
+ add_default_log(LOG_NOTICE);
+ }
+}
diff --git a/src/app/config/quiet_level.h b/src/app/config/quiet_level.h
new file mode 100644
index 0000000000..3a630b90e7
--- /dev/null
+++ b/src/app/config/quiet_level.h
@@ -0,0 +1,30 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file quiet_level.h
+ * \brief Declare the quiet_level enumeration and global.
+ **/
+
+#ifndef QUIET_LEVEL_H
+#define QUIET_LEVEL_H
+
+/** Enumeration to define how quietly Tor should log at startup. */
+typedef enum {
+ /** Default quiet level: we log everything of level NOTICE or higher. */
+ QUIET_NONE = 0,
+ /** "--hush" quiet level: we log everything of level WARNING or higher. */
+ QUIET_HUSH = 1 ,
+ /** "--quiet" quiet level: we log nothing at all. */
+ QUIET_SILENT = 2
+} quiet_level_t;
+
+/** How quietly should Tor log at startup? */
+extern quiet_level_t quiet_level;
+
+void add_default_log_for_quiet_level(quiet_level_t quiet);
+
+#endif /* !defined(QUIET_LEVEL_H) */
diff --git a/src/app/config/statefile.c b/src/app/config/statefile.c
index 552bd2c443..d9667733cc 100644
--- a/src/app/config/statefile.c
+++ b/src/app/config/statefile.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,7 +12,7 @@
*
* This 'state' file is a typed key-value store that allows multiple
* entries for the same key. It follows the same metaformat as described
- * in confparse.c, and uses the same code to read and write itself.
+ * in confmgt.c, and uses the same code to read and write itself.
*
* The state file is most suitable for small values that don't change too
* frequently. For values that become very large, we typically use a separate
@@ -32,7 +32,8 @@
#include "core/or/or.h"
#include "core/or/circuitstats.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "feature/relay/transport_config.h"
+#include "lib/confmgt/confmgt.h"
#include "core/mainloop/mainloop.h"
#include "core/mainloop/netstatus.h"
#include "core/mainloop/connection.h"
@@ -44,6 +45,7 @@
#include "feature/relay/routermode.h"
#include "lib/sandbox/sandbox.h"
#include "app/config/statefile.h"
+#include "app/main/subsysmgr.h"
#include "lib/encoding/confline.h"
#include "lib/net/resolve.h"
#include "lib/version/torversion.h"
@@ -130,9 +132,6 @@ static const config_var_t state_vars_[] = {
VAR("CircuitBuildTimeBin", LINELIST_S, BuildtimeHistogram, NULL),
VAR("BuildtimeHistogram", LINELIST_V, BuildtimeHistogram, NULL),
- V(MinutesSinceUserActivity, POSINT, NULL),
- V(Dormant, AUTOBOOL, "auto"),
-
END_OF_CONFIG_VARS
};
@@ -141,9 +140,8 @@ static const config_var_t state_vars_[] = {
static int or_state_validate(or_state_t *state, char **msg);
-static int or_state_validate_cb(void *old_options, void *options,
- void *default_options,
- int from_setconf, char **msg);
+static int or_state_validate_cb(const void *old_options,
+ void *options, char **msg);
/** Magic value for or_state_t. */
#define OR_STATE_MAGIC 0x57A73f57
@@ -158,35 +156,40 @@ static struct_member_t state_extra_var = {
/** Configuration format for or_state_t. */
static const config_format_t state_format = {
- sizeof(or_state_t),
- {
+ .size = sizeof(or_state_t),
+ .magic = {
"or_state_t",
OR_STATE_MAGIC,
offsetof(or_state_t, magic_),
},
- state_abbrevs_,
- NULL,
- state_vars_,
- or_state_validate_cb,
- NULL,
- &state_extra_var,
- offsetof(or_state_t, substates_),
+ .abbrevs = state_abbrevs_,
+ .vars = state_vars_,
+ .legacy_validate_fn = or_state_validate_cb,
+ .extra = &state_extra_var,
+ .has_config_suite = true,
+ .config_suite_offset = offsetof(or_state_t, substates_),
};
/* A global configuration manager for state-file objects */
static config_mgr_t *state_mgr = NULL;
/** Return the configuration manager for state-file objects. */
-static const config_mgr_t *
+STATIC const config_mgr_t *
get_state_mgr(void)
{
if (PREDICT_UNLIKELY(state_mgr == NULL)) {
state_mgr = config_mgr_new(&state_format);
+ int rv = subsystems_register_state_formats(state_mgr);
+ tor_assert(rv == 0);
config_mgr_freeze(state_mgr);
}
return state_mgr;
}
+#define CHECK_STATE_MAGIC(s) STMT_BEGIN \
+ config_check_toplevel_magic(get_state_mgr(), (s)); \
+ STMT_END
+
/** Persistent serialized state. */
static or_state_t *global_state = NULL;
@@ -268,19 +271,6 @@ validate_transports_in_state(or_state_t *state)
return 0;
}
-static int
-or_state_validate_cb(void *old_state, void *state, void *default_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) default_state;
- (void) old_state;
-
- return or_state_validate(state, msg);
-}
-
/** Return 0 if every setting in <b>state</b> is reasonable, and a
* permissible transition from <b>old_state</b>. Else warn and return -1.
* Should have no side effects, except for normalizing the contents of
@@ -289,6 +279,23 @@ or_state_validate_cb(void *old_state, void *state, void *default_state,
static int
or_state_validate(or_state_t *state, char **msg)
{
+ return config_validate(get_state_mgr(), NULL, state, msg);
+}
+
+/**
+ * Legacy validation/normalization callback for or_state_t. See
+ * legacy_validate_fn_t for more information.
+ */
+static int
+or_state_validate_cb(const void *old_state, void *state_, char **msg)
+{
+ /* There is not a meaningful concept of a state-to-state transition,
+ * since we do not reload the state after we start. */
+ (void) old_state;
+ CHECK_STATE_MAGIC(state_);
+
+ or_state_t *state = state_;
+
if (entry_guards_parse_state(state, 0, msg)<0)
return -1;
@@ -307,6 +314,9 @@ or_state_set(or_state_t *new_state)
tor_assert(new_state);
config_free(get_state_mgr(), global_state);
global_state = new_state;
+ if (subsystems_set_state(get_state_mgr(), global_state) < 0) {
+ ret = -1;
+ }
if (entry_guards_parse_state(global_state, 1, &err)<0) {
log_warn(LD_GENERAL,"%s",err);
tor_free(err);
@@ -321,7 +331,6 @@ or_state_set(or_state_t *new_state)
get_circuit_build_times_mutable(),global_state) < 0) {
ret = -1;
}
- netstatus_load_from_state(global_state, time(NULL));
return ret;
}
@@ -510,10 +519,10 @@ or_state_save(time_t now)
/* Call everything else that might dirty the state even more, in order
* to avoid redundant writes. */
+ (void) subsystems_flush_state(get_state_mgr(), global_state);
entry_guards_update_state(global_state);
rep_hist_update_state(global_state);
circuit_build_times_update_state(get_circuit_build_times(), global_state);
- netstatus_flush_to_state(global_state, now);
if (accounting_is_enabled(get_options()))
accounting_run_housekeeping(now);
@@ -633,7 +642,7 @@ get_stored_bindaddr_for_server_transport(const char *transport)
{
/* See if the user explicitly asked for a specific listening
address for this transport. */
- char *conf_bindaddr = get_transport_bindaddr_from_config(transport);
+ char *conf_bindaddr = pt_get_bindaddr_from_config(transport);
if (conf_bindaddr)
return conf_bindaddr;
}
diff --git a/src/app/config/statefile.h b/src/app/config/statefile.h
index 515c90a52f..98d9d2dda1 100644
--- a/src/app/config/statefile.h
+++ b/src/app/config/statefile.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -31,6 +31,8 @@ STATIC struct config_line_t *get_transport_in_state_by_name(
STATIC void or_state_free_(or_state_t *state);
#define or_state_free(st) FREE_AND_NULL(or_state_t, or_state_free_, (st))
STATIC or_state_t *or_state_new(void);
+struct config_mgr_t;
+STATIC const struct config_mgr_t *get_state_mgr(void);
#endif /* defined(STATEFILE_PRIVATE) */
#endif /* !defined(TOR_STATEFILE_H) */
diff --git a/src/app/config/testnet.inc b/src/app/config/testnet.inc
index 0ed3c38627..f146a03cd1 100644
--- a/src/app/config/testnet.inc
+++ b/src/app/config/testnet.inc
@@ -17,7 +17,6 @@
{ "TestingV3AuthInitialVoteDelay", "20 seconds" },
{ "TestingV3AuthInitialDistDelay", "20 seconds" },
{ "TestingAuthDirTimeToLearnReachability", "0 minutes" },
-{ "TestingEstimatedDescriptorPropagationTime", "0 minutes" },
{ "MinUptimeHidServDirectoryV2", "0 minutes" },
{ "TestingServerDownloadInitialDelay", "0" },
{ "TestingClientDownloadInitialDelay", "0" },
diff --git a/src/app/config/tor_cmdline_mode.h b/src/app/config/tor_cmdline_mode.h
new file mode 100644
index 0000000000..30a339a438
--- /dev/null
+++ b/src/app/config/tor_cmdline_mode.h
@@ -0,0 +1,34 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file tor_cmdline_mode.h
+ * \brief Declare the tor_cmdline_mode_t enumeration
+ **/
+
+#ifndef TOR_CMDLINE_MODE_H
+#define TOR_CMDLINE_MODE_H
+
+/**
+ * Enumeration to describe which command Tor is running. These commands
+ * are controlled by command-line options.
+ **/
+typedef enum {
+ CMD_RUN_TOR=0, /**< The default: run Tor as a daemon. */
+ CMD_LIST_FINGERPRINT, /**< Running --list-fingerprint. */
+ CMD_HASH_PASSWORD, /**< Running --hash-password. */
+ CMD_VERIFY_CONFIG, /**< Running --verify-config. */
+ CMD_DUMP_CONFIG, /**< Running --dump-config. */
+ CMD_KEYGEN, /**< Running --keygen */
+ CMD_KEY_EXPIRATION, /**< Running --key-expiration */
+ CMD_IMMEDIATE, /**< Special value: indicates a command that is handled
+ * immediately during configuration processing. */
+ CMD_RUN_UNITTESTS, /**< Special value: indicates that we have entered
+ * the Tor code from the unit tests, not from the
+ * regular Tor binary at all. */
+} tor_cmdline_mode_t;
+
+#endif /* !defined(TOR_CMDLINE_MODE_H) */
diff --git a/src/app/main/.may_include b/src/app/main/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/app/main/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/app/main/app_main.md b/src/app/main/app_main.md
new file mode 100644
index 0000000000..b8c789716c
--- /dev/null
+++ b/src/app/main/app_main.md
@@ -0,0 +1,2 @@
+@dir /app/main
+@brief app/main: Entry point for tor.
diff --git a/src/app/main/include.am b/src/app/main/include.am
new file mode 100644
index 0000000000..ea392a8581
--- /dev/null
+++ b/src/app/main/include.am
@@ -0,0 +1,18 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/app/main/main.c \
+ src/app/main/shutdown.c \
+ src/app/main/subsystem_list.c \
+ src/app/main/subsysmgr.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/app/main/main.h \
+ src/app/main/ntmain.h \
+ src/app/main/shutdown.h \
+ src/app/main/subsysmgr.h
+
+if BUILD_NT_SERVICES
+LIBTOR_APP_A_SOURCES += src/app/main/ntmain.c
+endif
diff --git a/src/app/main/main.c b/src/app/main/main.c
index 1901479eba..689bc526ab 100644
--- a/src/app/main/main.c
+++ b/src/app/main/main.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,6 +13,7 @@
#include "app/config/config.h"
#include "app/config/statefile.h"
+#include "app/config/quiet_level.h"
#include "app/main/main.h"
#include "app/main/ntmain.h"
#include "app/main/shutdown.h"
@@ -66,7 +67,6 @@
#include "lib/osinfo/uname.h"
#include "lib/sandbox/sandbox.h"
#include "lib/fs/lockfile.h"
-#include "lib/net/resolve.h"
#include "lib/tls/tortls.h"
#include "lib/evloop/compat_libevent.h"
#include "lib/encoding/confline.h"
@@ -108,16 +108,6 @@ static void dumpmemusage(int severity);
static void dumpstats(int severity); /* log stats */
static void process_signal(int sig);
-/********* START VARIABLES **********/
-
-/** Decides our behavior when no logs are configured/before any
- * logs have been configured. For 0, we log notice to stdout as normal.
- * For 1, we log warnings only. For 2, we log nothing.
- */
-int quiet_level = 0;
-
-/********* END VARIABLES ************/
-
/** Called when we get a SIGHUP: reload configuration files and keys,
* retry all connections, and so on. */
static int
@@ -528,7 +518,7 @@ int
tor_init(int argc, char *argv[])
{
char progname[256];
- int quiet = 0;
+ quiet_level_t quiet = QUIET_NONE;
time_of_process_start = time(NULL);
tor_init_connection_lists();
@@ -547,43 +537,17 @@ tor_init(int argc, char *argv[])
hs_init();
{
- /* We search for the "quiet" option first, since it decides whether we
- * will log anything at all to the command line. */
- config_line_t *opts = NULL, *cmdline_opts = NULL;
- const config_line_t *cl;
- (void) config_parse_commandline(argc, argv, 1, &opts, &cmdline_opts);
- for (cl = cmdline_opts; cl; cl = cl->next) {
- if (!strcmp(cl->key, "--hush"))
- quiet = 1;
- if (!strcmp(cl->key, "--quiet") ||
- !strcmp(cl->key, "--dump-config"))
- quiet = 2;
- /* The following options imply --hush */
- if (!strcmp(cl->key, "--version") || !strcmp(cl->key, "--digests") ||
- !strcmp(cl->key, "--list-torrc-options") ||
- !strcmp(cl->key, "--library-versions") ||
- !strcmp(cl->key, "--list-modules") ||
- !strcmp(cl->key, "--hash-password") ||
- !strcmp(cl->key, "-h") || !strcmp(cl->key, "--help")) {
- if (quiet < 1)
- quiet = 1;
- }
- }
- config_free_lines(opts);
- config_free_lines(cmdline_opts);
+ /* We check for the "quiet"/"hush" settings first, since they decide
+ whether we log anything at all to stdout. */
+ parsed_cmdline_t *cmdline;
+ cmdline = config_parse_commandline(argc, argv, 1);
+ if (cmdline)
+ quiet = cmdline->quiet_level;
+ parsed_cmdline_free(cmdline);
}
/* give it somewhere to log to initially */
- switch (quiet) {
- case 2:
- /* no initial logging */
- break;
- case 1:
- add_temp_log(LOG_WARN);
- break;
- default:
- add_temp_log(LOG_NOTICE);
- }
+ add_default_log_for_quiet_level(quiet);
quiet_level = quiet;
{
@@ -627,9 +591,6 @@ tor_init(int argc, char *argv[])
return 1;
}
- /* The options are now initialised */
- const or_options_t *options = get_options();
-
/* Initialize channelpadding and circpad parameters to defaults
* until we get a consensus */
channelpadding_new_consensus_params(NULL);
@@ -651,13 +612,6 @@ tor_init(int argc, char *argv[])
"and you probably shouldn't.");
#endif
- if (crypto_global_init(options->HardwareAccel,
- options->AccelName,
- options->AccelDir)) {
- log_err(LD_BUG, "Unable to initialize OpenSSL. Exiting.");
- return -1;
- }
-
/* Scan/clean unparseable descriptors; after reading config */
routerparse_init();
@@ -1284,15 +1238,10 @@ tor_run_main(const tor_main_configuration_t *tor_cfg)
memcpy(argv + tor_cfg->argc, tor_cfg->argv_owned,
tor_cfg->argc_owned*sizeof(char*));
-#ifdef NT_SERVICE
- {
- int done = 0;
- result = nt_service_parse_options(argc, argv, &done);
- if (done) {
- goto done;
- }
- }
-#endif /* defined(NT_SERVICE) */
+ int done = 0;
+ result = nt_service_parse_options(argc, argv, &done);
+ if (POSSIBLE(done))
+ goto done;
pubsub_install();
@@ -1327,9 +1276,7 @@ tor_run_main(const tor_main_configuration_t *tor_cfg)
switch (get_options()->command) {
case CMD_RUN_TOR:
-#ifdef NT_SERVICE
nt_service_set_state(SERVICE_RUNNING);
-#endif
result = run_tor_main_loop();
break;
case CMD_KEYGEN:
@@ -1347,7 +1294,7 @@ tor_run_main(const tor_main_configuration_t *tor_cfg)
result = 0;
break;
case CMD_VERIFY_CONFIG:
- if (quiet_level == 0)
+ if (quiet_level == QUIET_NONE)
printf("Configuration was valid\n");
result = 0;
break;
@@ -1355,6 +1302,7 @@ tor_run_main(const tor_main_configuration_t *tor_cfg)
result = do_dump_config();
break;
case CMD_RUN_UNITTESTS: /* only set by test.c */
+ case CMD_IMMEDIATE: /* Handled in config.c */
default:
log_warn(LD_BUG,"Illegal command number %d: internal error.",
get_options()->command);
diff --git a/src/app/main/main.h b/src/app/main/main.h
index 76574a9071..e6ed978c61 100644
--- a/src/app/main/main.h
+++ b/src/app/main/main.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/app/main/ntmain.c b/src/app/main/ntmain.c
index de82eeb1de..4941199759 100644
--- a/src/app/main/ntmain.c
+++ b/src/app/main/ntmain.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -66,7 +66,7 @@ static int nt_service_cmd_stop(void);
/** Struct to hold dynamically loaded NT-service related function pointers.
*/
-struct service_fns {
+struct {
int loaded;
/** @{ */
@@ -347,6 +347,7 @@ nt_service_main(void)
"or --key-expiration) in NT service.");
break;
case CMD_RUN_UNITTESTS:
+ case CMD_IMMEDIATE:
default:
log_err(LD_CONFIG, "Illegal command number %d: internal error.",
get_options()->command);
diff --git a/src/app/main/ntmain.h b/src/app/main/ntmain.h
index c39386c054..c2d6e23da7 100644
--- a/src/app/main/ntmain.h
+++ b/src/app/main/ntmain.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -22,7 +22,8 @@ int nt_service_is_stopping(void);
void nt_service_set_state(DWORD state);
#else
#define nt_service_is_stopping() 0
+#define nt_service_parse_options(a, b, c) (0)
+#define nt_service_set_state(s) STMT_NIL
#endif /* defined(NT_SERVICE) */
#endif /* !defined(TOR_NTMAIN_H) */
-
diff --git a/src/app/main/shutdown.c b/src/app/main/shutdown.c
index 93d6351d1b..27d92609eb 100644
--- a/src/app/main/shutdown.c
+++ b/src/app/main/shutdown.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -43,8 +43,8 @@
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodelist.h"
#include "feature/nodelist/routerlist.h"
-#include "feature/nodelist/routerlist.h"
#include "feature/relay/ext_orport.h"
+#include "feature/relay/relay_config.h"
#include "feature/rend/rendcache.h"
#include "feature/rend/rendclient.h"
#include "feature/stats/geoip_stats.h"
@@ -143,6 +143,7 @@ tor_free_all(int postfork)
if (!postfork) {
config_free_all();
+ relay_config_free_all();
or_state_free_all();
}
if (!postfork) {
diff --git a/src/app/main/shutdown.h b/src/app/main/shutdown.h
index 1bca96a0aa..623ae9525b 100644
--- a/src/app/main/shutdown.h
+++ b/src/app/main/shutdown.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/app/main/subsysmgr.c b/src/app/main/subsysmgr.c
index 5aa4fd76c9..5807cbbaa4 100644
--- a/src/app/main/subsysmgr.c
+++ b/src/app/main/subsysmgr.c
@@ -1,15 +1,25 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file subsysmgr.c
+ * @brief Manager for Tor's subsystems.
+ *
+ * This code is responsible for initializing, configuring, and shutting
+ * down all of Tor's individual subsystems.
+ **/
+
#include "orconfig.h"
#include "app/main/subsysmgr.h"
+#include "lib/confmgt/confmgt.h"
#include "lib/dispatch/dispatch_naming.h"
#include "lib/dispatch/msgtypes.h"
#include "lib/err/torerr.h"
#include "lib/log/log.h"
+#include "lib/log/util_bug.h"
#include "lib/malloc/malloc.h"
#include "lib/pubsub/pubsub_build.h"
#include "lib/pubsub/pubsub_connect.h"
@@ -23,12 +33,42 @@
**/
static bool subsystem_array_validated = false;
+/** Index value indicating that a subsystem has no options/state object, and
+ * so that object does not have an index. */
+#define IDX_NONE (-1)
+
+/**
+ * Runtime status of a single subsystem.
+ **/
+typedef struct subsys_status_t {
+ /** True if the given subsystem is initialized. */
+ bool initialized;
+ /** Index for this subsystem's options object, or IDX_NONE for none. */
+ int options_idx;
+ /** Index for this subsystem's state object, or IDX_NONE for none. */
+ int state_idx;
+} subsys_status_t;
+
+/** An overestimate of the number of subsystems. */
+#define N_SYS_STATUS 128
/**
* True if a given subsystem is initialized. Expand this array if there
* are more than this number of subsystems. (We'd rather not
* dynamically allocate in this module.)
**/
-static bool sys_initialized[128];
+static subsys_status_t sys_status[N_SYS_STATUS];
+
+/** Set <b>status</b> to a default (not set-up) state. */
+static void
+subsys_status_clear(subsys_status_t *status)
+{
+ if (!status)
+ return;
+ memset(status, 0, sizeof(*status));
+ status->initialized = false;
+ status->state_idx = IDX_NONE;
+ status->options_idx = IDX_NONE;
+}
/**
* Exit with a raw assertion if the subsystems list is inconsistent;
@@ -40,8 +80,8 @@ check_and_setup(void)
if (subsystem_array_validated)
return;
- raw_assert(ARRAY_LENGTH(sys_initialized) >= n_tor_subsystems);
- memset(sys_initialized, 0, sizeof(sys_initialized));
+ raw_assert(ARRAY_LENGTH(sys_status) >= n_tor_subsystems);
+ memset(sys_status, 0, sizeof(sys_status));
int last_level = MIN_SUBSYS_LEVEL;
@@ -59,6 +99,8 @@ check_and_setup(void)
sys->name, i, sys->level, last_level);
raw_assert_unreached_msg("There is a bug in subsystem_list.c");
}
+ subsys_status_clear(&sys_status[i]);
+
last_level = sys->level;
}
@@ -89,7 +131,7 @@ subsystems_init_upto(int target_level)
continue;
if (sys->level > target_level)
break;
- if (sys_initialized[i])
+ if (sys_status[i].initialized)
continue;
int r = 0;
if (sys->initialize) {
@@ -104,7 +146,7 @@ subsystems_init_upto(int target_level)
sys->name, i);
raw_assert_unreached_msg("A subsystem couldn't be initialized.");
}
- sys_initialized[i] = true;
+ sys_status[i].initialized = true;
}
return 0;
@@ -124,7 +166,7 @@ subsystems_add_pubsub_upto(pubsub_builder_t *builder,
continue;
if (sys->level > target_level)
break;
- if (! sys_initialized[i])
+ if (! sys_status[i].initialized)
continue;
int r = 0;
if (sys->add_pubsub) {
@@ -178,13 +220,13 @@ subsystems_shutdown_downto(int target_level)
continue;
if (sys->level <= target_level)
break;
- if (! sys_initialized[i])
+ if (! sys_status[i].initialized)
continue;
if (sys->shutdown) {
log_debug(LD_GENERAL, "Shutting down %s", sys->name);
sys->shutdown();
}
- sys_initialized[i] = false;
+ subsys_status_clear(&sys_status[i]);
}
}
@@ -200,7 +242,7 @@ subsystems_prefork(void)
const subsys_fns_t *sys = tor_subsystems[i];
if (!sys->supported)
continue;
- if (! sys_initialized[i])
+ if (! sys_status[i].initialized)
continue;
if (sys->prefork) {
log_debug(LD_GENERAL, "Pre-fork: %s", sys->name);
@@ -221,7 +263,7 @@ subsystems_postfork(void)
const subsys_fns_t *sys = tor_subsystems[i];
if (!sys->supported)
continue;
- if (! sys_initialized[i])
+ if (! sys_status[i].initialized)
continue;
if (sys->postfork) {
log_debug(LD_GENERAL, "Post-fork: %s", sys->name);
@@ -242,7 +284,7 @@ subsystems_thread_cleanup(void)
const subsys_fns_t *sys = tor_subsystems[i];
if (!sys->supported)
continue;
- if (! sys_initialized[i])
+ if (! sys_status[i].initialized)
continue;
if (sys->thread_cleanup) {
log_debug(LD_GENERAL, "Thread cleanup: %s", sys->name);
@@ -250,3 +292,173 @@ subsystems_thread_cleanup(void)
}
}
}
+
+/**
+ * Register all subsystem-declared options formats in <b>mgr</b>.
+ *
+ * Return 0 on success, -1 on failure.
+ **/
+int
+subsystems_register_options_formats(config_mgr_t *mgr)
+{
+ tor_assert(mgr);
+ check_and_setup();
+
+ for (unsigned i = 0; i < n_tor_subsystems; ++i) {
+ const subsys_fns_t *sys = tor_subsystems[i];
+ if (sys->options_format) {
+ int options_idx = config_mgr_add_format(mgr, sys->options_format);
+ sys_status[i].options_idx = options_idx;
+ log_debug(LD_CONFIG, "Added options format for %s with index %d",
+ sys->name, options_idx);
+ }
+ }
+ return 0;
+}
+
+/**
+ * Register all subsystem-declared state formats in <b>mgr</b>.
+ *
+ * Return 0 on success, -1 on failure.
+ **/
+int
+subsystems_register_state_formats(config_mgr_t *mgr)
+{
+ tor_assert(mgr);
+ check_and_setup();
+
+ for (unsigned i = 0; i < n_tor_subsystems; ++i) {
+ const subsys_fns_t *sys = tor_subsystems[i];
+ if (sys->state_format) {
+ int state_idx = config_mgr_add_format(mgr, sys->state_format);
+ sys_status[i].state_idx = state_idx;
+ log_debug(LD_CONFIG, "Added state format for %s with index %d",
+ sys->name, state_idx);
+ }
+ }
+ return 0;
+}
+
+#ifdef TOR_UNIT_TESTS
+/**
+ * Helper: look up the index for <b>sys</b>. Return -1 if the subsystem
+ * is not recognized.
+ **/
+static int
+subsys_get_idx(const subsys_fns_t *sys)
+{
+ for (unsigned i = 0; i < n_tor_subsystems; ++i) {
+ if (sys == tor_subsystems[i])
+ return (int)i;
+ }
+ return -1;
+}
+
+/**
+ * Return the current state-manager's index for any state held by the
+ * subsystem <b>sys</b>. If <b>sys</b> has no options, return -1.
+ *
+ * Using raw indices can be error-prone: only do this from the unit
+ * tests. If you need a way to access another subsystem's configuration,
+ * that subsystem should provide access functions.
+ **/
+int
+subsystems_get_options_idx(const subsys_fns_t *sys)
+{
+ int i = subsys_get_idx(sys);
+ tor_assert(i >= 0);
+ return sys_status[i].options_idx;
+}
+
+/**
+ * Return the current state-manager's index for any state held by the
+ * subsystem <b>sys</b>. If <b>sys</b> has no state, return -1.
+ *
+ * Using raw indices can be error-prone: only do this from the unit
+ * tests. If you need a way to access another subsystem's state
+ * that subsystem should provide access functions.
+ **/
+int
+subsystems_get_state_idx(const subsys_fns_t *sys)
+{
+ int i = subsys_get_idx(sys);
+ tor_assert(i >= 0);
+ return sys_status[i].state_idx;
+}
+#endif /* defined(TOR_UNIT_TESTS) */
+
+/**
+ * Call all appropriate set_options() methods to tell the various subsystems
+ * about a new set of torrc options. Return 0 on success, -1 on
+ * nonrecoverable failure.
+ **/
+int
+subsystems_set_options(const config_mgr_t *mgr, struct or_options_t *options)
+{
+ /* XXXX This does not yet handle reversible option assignment; I'll
+ * do that later in this branch. */
+
+ for (unsigned i = 0; i < n_tor_subsystems; ++i) {
+ const subsys_fns_t *sys = tor_subsystems[i];
+ if (sys_status[i].options_idx >= 0 && sys->set_options) {
+ void *obj = config_mgr_get_obj_mutable(mgr, options,
+ sys_status[i].options_idx);
+ int rv = sys->set_options(obj);
+ if (rv < 0) {
+ log_err(LD_CONFIG, "Error when handling option for %s; "
+ "cannot proceed.", sys->name);
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * Call all appropriate set_state() methods to tell the various subsystems
+ * about an initial DataDir/state file. Return 0 on success, -1 on
+ * nonrecoverable failure.
+ **/
+int
+subsystems_set_state(const config_mgr_t *mgr, struct or_state_t *state)
+{
+ for (unsigned i = 0; i < n_tor_subsystems; ++i) {
+ const subsys_fns_t *sys = tor_subsystems[i];
+ if (sys_status[i].state_idx >= 0 && sys->set_state) {
+ void *obj = config_mgr_get_obj_mutable(mgr, state,
+ sys_status[i].state_idx);
+ int rv = sys->set_state(obj);
+ if (rv < 0) {
+ log_err(LD_CONFIG, "Error when handling state for %s; "
+ "cannot proceed.", sys->name);
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * Call all appropriate flush_state() methods to tell the various subsystems
+ * to update the state objects in <b>state</b>. Return 0 on success,
+ * -1 on failure.
+ **/
+int
+subsystems_flush_state(const config_mgr_t *mgr, struct or_state_t *state)
+{
+ int result = 0;
+ for (unsigned i = 0; i < n_tor_subsystems; ++i) {
+ const subsys_fns_t *sys = tor_subsystems[i];
+ if (sys_status[i].state_idx >= 0 && sys->flush_state) {
+ void *obj = config_mgr_get_obj_mutable(mgr, state,
+ sys_status[i].state_idx);
+ int rv = sys->flush_state(obj);
+ if (rv < 0) {
+ log_warn(LD_CONFIG, "Error when flushing state to state object for %s",
+ sys->name);
+ result = -1;
+ }
+ }
+ }
+ return result;
+}
diff --git a/src/app/main/subsysmgr.h b/src/app/main/subsysmgr.h
index d4426614e3..35635a756e 100644
--- a/src/app/main/subsysmgr.h
+++ b/src/app/main/subsysmgr.h
@@ -1,8 +1,13 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file subsysmgr.h
+ * @brief Header for subsysmgr.c
+ **/
+
#ifndef TOR_SUBSYSMGR_T
#define TOR_SUBSYSMGR_T
@@ -26,4 +31,21 @@ void subsystems_prefork(void);
void subsystems_postfork(void);
void subsystems_thread_cleanup(void);
+struct config_mgr_t;
+int subsystems_register_options_formats(struct config_mgr_t *mgr);
+int subsystems_register_state_formats(struct config_mgr_t *mgr);
+struct or_options_t;
+struct or_state_t;
+int subsystems_set_options(const struct config_mgr_t *mgr,
+ struct or_options_t *options);
+int subsystems_set_state(const struct config_mgr_t *mgr,
+ struct or_state_t *state);
+int subsystems_flush_state(const struct config_mgr_t *mgr,
+ struct or_state_t *state);
+
+#ifdef TOR_UNIT_TESTS
+int subsystems_get_options_idx(const subsys_fns_t *sys);
+int subsystems_get_state_idx(const subsys_fns_t *sys);
+#endif
+
#endif /* !defined(TOR_SUBSYSMGR_T) */
diff --git a/src/app/main/subsystem_list.c b/src/app/main/subsystem_list.c
index 1af9340c1a..b4439cdc7b 100644
--- a/src/app/main/subsystem_list.c
+++ b/src/app/main/subsystem_list.c
@@ -1,8 +1,13 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file subsystem_list.c
+ * @brief List of Tor's subsystems.
+ **/
+
#include "orconfig.h"
#include "app/main/subsysmgr.h"
#include "lib/cc/compat_compiler.h"
@@ -13,7 +18,6 @@
#include "core/or/or_sys.h"
#include "core/or/orconn_event_sys.h"
#include "feature/control/btrack_sys.h"
-#include "feature/relay/relay_sys.h"
#include "lib/compress/compress_sys.h"
#include "lib/crypt_ops/crypto_sys.h"
#include "lib/err/torerr_sys.h"
@@ -28,6 +32,7 @@
#include "lib/evloop/evloop_sys.h"
#include "feature/dirauth/dirauth_sys.h"
+#include "feature/relay/relay_sys.h"
#include <stddef.h>
@@ -63,9 +68,7 @@ const subsys_fns_t *tor_subsystems[] = {
&sys_relay,
-#ifdef HAVE_MODULE_DIRAUTH
&sys_dirauth,
-#endif
};
const unsigned n_tor_subsystems = ARRAY_LENGTH(tor_subsystems);
diff --git a/src/app/main/tor_main.c b/src/app/main/tor_main.c
index 8a887ed269..0ee03fd5e9 100644
--- a/src/app/main/tor_main.c
+++ b/src/app/main/tor_main.c
@@ -1,6 +1,6 @@
/* Copyright 2001-2004 Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/arch_goals.md b/src/arch_goals.md
new file mode 100644
index 0000000000..92c86d9df8
--- /dev/null
+++ b/src/arch_goals.md
@@ -0,0 +1,31 @@
+@page arch_goals High level code design practices
+
+This page describes the high level design practices for Tor's code.
+This design is a long-term goal of what we want our code to look like,
+rather than a description of how it currently is.
+
+Overall, we want various parts of tor's code to interact with each
+other through a small number of interfaces.
+
+We want to avoid having "god objects" or "god modules". These are
+objects or modules that know far too much about other parts of the
+code. God objects/modules are generally recognized to be an
+antipattern of software design.
+
+Historically, there have been modules in tor that have tended toward
+becoming god modules. These include modules that help more
+specialized code communicate with the outside world: the configuration
+and control modules, for example. Others are modules that deal with
+global state, initialization, or shutdown.
+
+If a centralized module needs to invoke code in almost every other
+module in the system, it is better if it exports a small, general
+interface that other modules call. The centralized module should not
+explicitly call out to all the modules that interact with it.
+
+Instead, modules that interact with the centralized module should call
+registration interfaces. These interfaces allow modules to register
+handlers for things like configuration parsing and control command
+execution. (The config and control modules are examples of this.)
+Alternatively, registration can happen through statically initialized
+data structures. (The subsystem mechanism is an example of this.)
diff --git a/src/config/mmdb-convert.py b/src/config/mmdb-convert.py
index b861e9433e..a58f5d43e1 100644
--- a/src/config/mmdb-convert.py
+++ b/src/config/mmdb-convert.py
@@ -28,6 +28,11 @@
pieces.
"""
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import struct
import bisect
import socket
diff --git a/src/core/core.md b/src/core/core.md
new file mode 100644
index 0000000000..8ecc43eaae
--- /dev/null
+++ b/src/core/core.md
@@ -0,0 +1,18 @@
+@dir /core
+@brief core: main loop and onion routing functionality
+
+The "core" directory has the central protocols for Tor, which every
+client and relay must implement in order to perform onion routing.
+
+It is divided into three lower-level pieces:
+
+ - \refdir{core/crypto} -- Tor-specific cryptography.
+
+ - \refdir{core/proto} -- Protocol encoding/decoding.
+
+ - \refdir{core/mainloop} -- A connection-oriented asynchronous mainloop.
+
+and one high-level piece:
+
+ - \refdir{core/or} -- Implements onion routing itself.
+
diff --git a/src/core/crypto/core_crypto.md b/src/core/crypto/core_crypto.md
new file mode 100644
index 0000000000..26ade1f8f8
--- /dev/null
+++ b/src/core/crypto/core_crypto.md
@@ -0,0 +1,6 @@
+@dir /core/crypto
+@brief core/crypto: Tor-specific cryptography
+
+This module implements Tor's circuit-construction crypto and Tor's
+relay crypto.
+
diff --git a/src/core/crypto/hs_ntor.c b/src/core/crypto/hs_ntor.c
index add8a2b8f2..2bd4c32446 100644
--- a/src/core/crypto/hs_ntor.c
+++ b/src/core/crypto/hs_ntor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/** \file hs_ntor.c
diff --git a/src/core/crypto/hs_ntor.h b/src/core/crypto/hs_ntor.h
index e5a5171915..2bce5686cd 100644
--- a/src/core/crypto/hs_ntor.h
+++ b/src/core/crypto/hs_ntor.h
@@ -1,6 +1,11 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file hs_ntor.h
+ * @brief Header for hs_ntor.c
+ **/
+
#ifndef TOR_HS_NTOR_H
#define TOR_HS_NTOR_H
@@ -14,7 +19,7 @@ struct curve25519_keypair_t;
(DIGEST256_LEN*2 + CIPHER256_KEY_LEN*2)
/* Key material needed to encode/decode INTRODUCE1 cells */
-typedef struct {
+typedef struct hs_ntor_intro_cell_keys_t {
/* Key used for encryption of encrypted INTRODUCE1 blob */
uint8_t enc_key[CIPHER256_KEY_LEN];
/* MAC key used to protect encrypted INTRODUCE1 blob */
@@ -22,7 +27,7 @@ typedef struct {
} hs_ntor_intro_cell_keys_t;
/* Key material needed to encode/decode RENDEZVOUS1 cells */
-typedef struct {
+typedef struct hs_ntor_rend_cell_keys_t {
/* This is the MAC of the HANDSHAKE_INFO field */
uint8_t rend_cell_auth_mac[DIGEST256_LEN];
/* This is the key seed used to derive further rendezvous crypto keys as
diff --git a/src/core/crypto/include.am b/src/core/crypto/include.am
new file mode 100644
index 0000000000..28b7e22905
--- /dev/null
+++ b/src/core/crypto/include.am
@@ -0,0 +1,18 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/core/crypto/hs_ntor.c \
+ src/core/crypto/onion_crypto.c \
+ src/core/crypto/onion_fast.c \
+ src/core/crypto/onion_ntor.c \
+ src/core/crypto/onion_tap.c \
+ src/core/crypto/relay_crypto.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/core/crypto/hs_ntor.h \
+ src/core/crypto/onion_crypto.h \
+ src/core/crypto/onion_fast.h \
+ src/core/crypto/onion_ntor.h \
+ src/core/crypto/onion_tap.h \
+ src/core/crypto/relay_crypto.h
diff --git a/src/core/crypto/onion_crypto.c b/src/core/crypto/onion_crypto.c
index 56b02e2996..69b4dc40aa 100644
--- a/src/core/crypto/onion_crypto.c
+++ b/src/core/crypto/onion_crypto.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/crypto/onion_crypto.h b/src/core/crypto/onion_crypto.h
index 7abdd6538e..2665d326a3 100644
--- a/src/core/crypto/onion_crypto.h
+++ b/src/core/crypto/onion_crypto.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/crypto/onion_fast.c b/src/core/crypto/onion_fast.c
index 31bd20235f..d760549325 100644
--- a/src/core/crypto/onion_fast.c
+++ b/src/core/crypto/onion_fast.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/crypto/onion_fast.h b/src/core/crypto/onion_fast.h
index 0ba8cbbc35..da983a56d9 100644
--- a/src/core/crypto/onion_fast.h
+++ b/src/core/crypto/onion_fast.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/crypto/onion_ntor.c b/src/core/crypto/onion_ntor.c
index 7087fe1bd7..5a77230d02 100644
--- a/src/core/crypto/onion_ntor.c
+++ b/src/core/crypto/onion_ntor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/crypto/onion_ntor.h b/src/core/crypto/onion_ntor.h
index 51e72b4083..9473409e40 100644
--- a/src/core/crypto/onion_ntor.h
+++ b/src/core/crypto/onion_ntor.h
@@ -1,6 +1,11 @@
-/* Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file onion_ntor.h
+ * @brief Header for onion_ntor.c
+ **/
+
#ifndef TOR_ONION_NTOR_H
#define TOR_ONION_NTOR_H
diff --git a/src/core/crypto/onion_tap.c b/src/core/crypto/onion_tap.c
index 854889d88d..119f55f206 100644
--- a/src/core/crypto/onion_tap.c
+++ b/src/core/crypto/onion_tap.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/crypto/onion_tap.h b/src/core/crypto/onion_tap.h
index 0e43b9c8ba..78174b1fab 100644
--- a/src/core/crypto/onion_tap.h
+++ b/src/core/crypto/onion_tap.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/crypto/relay_crypto.c b/src/core/crypto/relay_crypto.c
index 8a285131a8..3e6167e0e1 100644
--- a/src/core/crypto/relay_crypto.c
+++ b/src/core/crypto/relay_crypto.c
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file relay_crypto.h
+ * @brief Header for relay_crypto.c
+ **/
+
#include "core/or/or.h"
#include "core/or/circuitlist.h"
#include "core/or/crypt_path.h"
diff --git a/src/core/crypto/relay_crypto.h b/src/core/crypto/relay_crypto.h
index 9478f8d359..5e36c7678c 100644
--- a/src/core/crypto/relay_crypto.h
+++ b/src/core/crypto/relay_crypto.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/include.am b/src/core/include.am
index 9b4b251c81..7752a7974b 100644
--- a/src/core/include.am
+++ b/src/core/include.am
@@ -1,201 +1,21 @@
-noinst_LIBRARIES += \
- src/core/libtor-app.a
-if UNITTESTS_ENABLED
-noinst_LIBRARIES += \
- src/core/libtor-app-testing.a
-endif
-
-# ADD_C_FILE: INSERT SOURCES HERE.
-LIBTOR_APP_A_SOURCES = \
- src/app/config/config.c \
- src/app/config/statefile.c \
- src/app/main/main.c \
- src/app/main/shutdown.c \
- src/app/main/subsystem_list.c \
- src/app/main/subsysmgr.c \
- src/core/crypto/hs_ntor.c \
- src/core/crypto/onion_crypto.c \
- src/core/crypto/onion_fast.c \
- src/core/crypto/onion_ntor.c \
- src/core/crypto/onion_tap.c \
- src/core/crypto/relay_crypto.c \
- src/core/mainloop/connection.c \
- src/core/mainloop/cpuworker.c \
- src/core/mainloop/mainloop.c \
- src/core/mainloop/mainloop_pubsub.c \
- src/core/mainloop/mainloop_sys.c \
- src/core/mainloop/netstatus.c \
- src/core/mainloop/periodic.c \
- src/core/or/address_set.c \
- src/core/or/channel.c \
- src/core/or/channelpadding.c \
- src/core/or/channeltls.c \
- src/core/or/circuitbuild.c \
- src/core/or/circuitlist.c \
- src/core/or/circuitmux.c \
- src/core/or/circuitmux_ewma.c \
- src/core/or/circuitpadding.c \
- src/core/or/circuitpadding_machines.c \
- src/core/or/circuitstats.c \
- src/core/or/circuituse.c \
- src/core/or/crypt_path.c \
- src/core/or/command.c \
- src/core/or/connection_edge.c \
- src/core/or/connection_or.c \
- src/core/or/dos.c \
- src/core/or/onion.c \
- src/core/or/ocirc_event.c \
- src/core/or/or_periodic.c \
- src/core/or/or_sys.c \
- src/core/or/orconn_event.c \
- src/core/or/policies.c \
- src/core/or/protover.c \
- src/core/or/protover_rust.c \
- src/core/or/reasons.c \
- src/core/or/relay.c \
- src/core/or/scheduler.c \
- src/core/or/scheduler_kist.c \
- src/core/or/scheduler_vanilla.c \
- src/core/or/sendme.c \
- src/core/or/status.c \
- src/core/or/versions.c \
- src/core/proto/proto_cell.c \
- src/core/proto/proto_control0.c \
- src/core/proto/proto_ext_or.c \
- src/core/proto/proto_http.c \
- src/core/proto/proto_socks.c \
- src/feature/api/tor_api.c \
- src/feature/client/addressmap.c \
- src/feature/client/bridges.c \
- src/feature/client/circpathbias.c \
- src/feature/client/dnsserv.c \
- src/feature/client/entrynodes.c \
- src/feature/client/transports.c \
- src/feature/control/btrack.c \
- src/feature/control/btrack_circuit.c \
- src/feature/control/btrack_orconn.c \
- src/feature/control/btrack_orconn_cevent.c \
- src/feature/control/btrack_orconn_maps.c \
- src/feature/control/control.c \
- src/feature/control/control_auth.c \
- src/feature/control/control_bootstrap.c \
- src/feature/control/control_cmd.c \
- src/feature/control/control_events.c \
- src/feature/control/control_fmt.c \
- src/feature/control/control_getinfo.c \
- src/feature/control/control_proto.c \
- src/feature/control/fmt_serverstatus.c \
- src/feature/control/getinfo_geoip.c \
- src/feature/dircache/conscache.c \
- src/feature/dircache/consdiffmgr.c \
- src/feature/dircache/dircache.c \
- src/feature/dircache/dirserv.c \
- src/feature/dirclient/dirclient.c \
- src/feature/dirclient/dlstatus.c \
- src/feature/dircommon/consdiff.c \
- src/feature/dircommon/directory.c \
- src/feature/dircommon/fp_pair.c \
- src/feature/dircommon/voting_schedule.c \
- src/feature/dirparse/authcert_parse.c \
- src/feature/dirparse/microdesc_parse.c \
- src/feature/dirparse/ns_parse.c \
- src/feature/dirparse/parsecommon.c \
- src/feature/dirparse/policy_parse.c \
- src/feature/dirparse/routerparse.c \
- src/feature/dirparse/sigcommon.c \
- src/feature/dirparse/signing.c \
- src/feature/dirparse/unparseable.c \
- src/feature/hibernate/hibernate.c \
- src/feature/hs/hs_cache.c \
- src/feature/hs/hs_cell.c \
- src/feature/hs/hs_circuit.c \
- src/feature/hs/hs_circuitmap.c \
- src/feature/hs/hs_client.c \
- src/feature/hs/hs_common.c \
- src/feature/hs/hs_config.c \
- src/feature/hs/hs_control.c \
- src/feature/hs/hs_descriptor.c \
- src/feature/hs/hs_dos.c \
- src/feature/hs/hs_ident.c \
- src/feature/hs/hs_intropoint.c \
- src/feature/hs/hs_service.c \
- src/feature/hs/hs_stats.c \
- src/feature/hs_common/replaycache.c \
- src/feature/hs_common/shared_random_client.c \
- src/feature/keymgt/loadkey.c \
- src/feature/nodelist/authcert.c \
- src/feature/nodelist/describe.c \
- src/feature/nodelist/dirlist.c \
- src/feature/nodelist/microdesc.c \
- src/feature/nodelist/networkstatus.c \
- src/feature/nodelist/nickname.c \
- src/feature/nodelist/nodefamily.c \
- src/feature/nodelist/nodelist.c \
- src/feature/nodelist/node_select.c \
- src/feature/nodelist/routerinfo.c \
- src/feature/nodelist/routerlist.c \
- src/feature/nodelist/routerset.c \
- src/feature/nodelist/fmt_routerstatus.c \
- src/feature/nodelist/torcert.c \
- src/feature/relay/dns.c \
- src/feature/relay/ext_orport.c \
- src/feature/relay/onion_queue.c \
- src/feature/relay/relay_periodic.c \
- src/feature/relay/relay_sys.c \
- src/feature/relay/router.c \
- src/feature/relay/routerkeys.c \
- src/feature/relay/routermode.c \
- src/feature/relay/selftest.c \
- src/feature/rend/rendcache.c \
- src/feature/rend/rendclient.c \
- src/feature/rend/rendcommon.c \
- src/feature/rend/rendmid.c \
- src/feature/rend/rendparse.c \
- src/feature/rend/rendservice.c \
- src/feature/stats/geoip_stats.c \
- src/feature/stats/rephist.c \
- src/feature/stats/predict_ports.c
-
-if BUILD_NT_SERVICES
-LIBTOR_APP_A_SOURCES += src/app/main/ntmain.c
-endif
-
#
-# Modules are conditionnally compiled in tor starting here. We add the C files
+# Modules are conditionally compiled in tor starting here. We add the C files
# only if the modules has been enabled at configure time. We always add the
# source files of every module to libtor-testing.a so we can build the unit
# tests for everything. See the UNITTESTS_ENABLED branch below.
#
LIBTOR_APP_TESTING_A_SOURCES = $(LIBTOR_APP_A_SOURCES)
-# The Directory Authority module.
-MODULE_DIRAUTH_SOURCES = \
- src/feature/dirauth/authmode.c \
- src/feature/dirauth/bridgeauth.c \
- src/feature/dirauth/bwauth.c \
- src/feature/dirauth/dirauth_periodic.c \
- src/feature/dirauth/dirauth_sys.c \
- src/feature/dirauth/dircollate.c \
- src/feature/dirauth/dirvote.c \
- src/feature/dirauth/dsigs_parse.c \
- src/feature/dirauth/guardfraction.c \
- src/feature/dirauth/keypin.c \
- src/feature/dirauth/process_descs.c \
- src/feature/dirauth/reachability.c \
- src/feature/dirauth/recommend_pkg.c \
- src/feature/dirauth/shared_random.c \
- src/feature/dirauth/shared_random_state.c \
- src/feature/dirauth/voteflags.c
+src_core_libtor_app_a_SOURCES = \
+ $(LIBTOR_APP_A_SOURCES) \
+ $(LIBTOR_APP_A_STUB_SOURCES)
-if BUILD_MODULE_DIRAUTH
-LIBTOR_APP_A_SOURCES += $(MODULE_DIRAUTH_SOURCES)
-endif
-
-src_core_libtor_app_a_SOURCES = $(LIBTOR_APP_A_SOURCES)
if UNITTESTS_ENABLED
# Add the sources of the modules that are needed for tests to work here.
+LIBTOR_APP_TESTING_A_SOURCES += $(MODULE_RELAY_SOURCES)
+LIBTOR_APP_TESTING_A_SOURCES += $(MODULE_DIRCACHE_SOURCES)
LIBTOR_APP_TESTING_A_SOURCES += $(MODULE_DIRAUTH_SOURCES)
src_core_libtor_app_testing_a_SOURCES = $(LIBTOR_APP_TESTING_A_SOURCES)
@@ -210,239 +30,6 @@ AM_CPPFLAGS += -DSHARE_DATADIR="\"$(datadir)\"" \
src_core_libtor_app_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
src_core_libtor_app_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
-# ADD_C_FILE: INSERT HEADERS HERE.
-noinst_HEADERS += \
- src/app/config/config.h \
- src/app/config/or_options_st.h \
- src/app/config/or_state_st.h \
- src/app/config/statefile.h \
- src/app/main/main.h \
- src/app/main/ntmain.h \
- src/app/main/shutdown.h \
- src/app/main/subsysmgr.h \
- src/core/crypto/hs_ntor.h \
- src/core/crypto/onion_crypto.h \
- src/core/crypto/onion_fast.h \
- src/core/crypto/onion_ntor.h \
- src/core/crypto/onion_tap.h \
- src/core/crypto/relay_crypto.h \
- src/core/mainloop/connection.h \
- src/core/mainloop/cpuworker.h \
- src/core/mainloop/mainloop.h \
- src/core/mainloop/mainloop_pubsub.h \
- src/core/mainloop/mainloop_sys.h \
- src/core/mainloop/netstatus.h \
- src/core/mainloop/periodic.h \
- src/core/or/addr_policy_st.h \
- src/core/or/address_set.h \
- src/core/or/cell_queue_st.h \
- src/core/or/cell_st.h \
- src/core/or/channel.h \
- src/core/or/channelpadding.h \
- src/core/or/channeltls.h \
- src/core/or/circuit_st.h \
- src/core/or/circuitbuild.h \
- src/core/or/circuitlist.h \
- src/core/or/circuitmux.h \
- src/core/or/circuitmux_ewma.h \
- src/core/or/circuitstats.h \
- src/core/or/circuitpadding.h \
- src/core/or/circuitpadding_machines.h \
- src/core/or/circuituse.h \
- src/core/or/command.h \
- src/core/or/connection_edge.h \
- src/core/or/connection_or.h \
- src/core/or/connection_st.h \
- src/core/or/crypt_path.h \
- src/core/or/cpath_build_state_st.h \
- src/core/or/crypt_path_reference_st.h \
- src/core/or/crypt_path_st.h \
- src/core/or/destroy_cell_queue_st.h \
- src/core/or/dos.h \
- src/core/or/edge_connection_st.h \
- src/core/or/half_edge_st.h \
- src/core/or/entry_connection_st.h \
- src/core/or/entry_port_cfg_st.h \
- src/core/or/extend_info_st.h \
- src/core/or/listener_connection_st.h \
- src/core/or/onion.h \
- src/core/or/or.h \
- src/core/or/or_periodic.h \
- src/core/or/or_sys.h \
- src/core/or/orconn_event.h \
- src/core/or/orconn_event_sys.h \
- src/core/or/or_circuit_st.h \
- src/core/or/or_connection_st.h \
- src/core/or/or_handshake_certs_st.h \
- src/core/or/or_handshake_state_st.h \
- src/core/or/ocirc_event.h \
- src/core/or/ocirc_event_sys.h \
- src/core/or/origin_circuit_st.h \
- src/core/or/policies.h \
- src/core/or/port_cfg_st.h \
- src/core/or/protover.h \
- src/core/or/reasons.h \
- src/core/or/relay.h \
- src/core/or/relay_crypto_st.h \
- src/core/or/scheduler.h \
- src/core/or/sendme.h \
- src/core/or/server_port_cfg_st.h \
- src/core/or/socks_request_st.h \
- src/core/or/status.h \
- src/core/or/tor_version_st.h \
- src/core/or/var_cell_st.h \
- src/core/or/versions.h \
- src/core/proto/proto_cell.h \
- src/core/proto/proto_control0.h \
- src/core/proto/proto_ext_or.h \
- src/core/proto/proto_http.h \
- src/core/proto/proto_socks.h \
- src/feature/api/tor_api_internal.h \
- src/feature/client/addressmap.h \
- src/feature/client/bridges.h \
- src/feature/client/circpathbias.h \
- src/feature/client/dnsserv.h \
- src/feature/client/entrynodes.h \
- src/feature/client/transports.h \
- src/feature/control/btrack_circuit.h \
- src/feature/control/btrack_orconn.h \
- src/feature/control/btrack_orconn_cevent.h \
- src/feature/control/btrack_orconn_maps.h \
- src/feature/control/btrack_sys.h \
- src/feature/control/control.h \
- src/feature/control/control_auth.h \
- src/feature/control/control_cmd.h \
- src/feature/control/control_cmd_args_st.h \
- src/feature/control/control_connection_st.h \
- src/feature/control/control_events.h \
- src/feature/control/control_fmt.h \
- src/feature/control/control_getinfo.h \
- src/feature/control/control_proto.h \
- src/feature/control/fmt_serverstatus.h \
- src/feature/control/getinfo_geoip.h \
- src/feature/dirauth/authmode.h \
- src/feature/dirauth/bridgeauth.h \
- src/feature/dirauth/bwauth.h \
- src/feature/dirauth/dirauth_periodic.h \
- src/feature/dirauth/dirauth_sys.h \
- src/feature/dirauth/dircollate.h \
- src/feature/dirauth/dirvote.h \
- src/feature/dirauth/dsigs_parse.h \
- src/feature/dirauth/guardfraction.h \
- src/feature/dirauth/keypin.h \
- src/feature/dirauth/ns_detached_signatures_st.h \
- src/feature/dirauth/reachability.h \
- src/feature/dirauth/recommend_pkg.h \
- src/feature/dirauth/process_descs.h \
- src/feature/dirauth/shared_random.h \
- src/feature/dirauth/shared_random_state.h \
- src/feature/dirauth/vote_microdesc_hash_st.h \
- src/feature/dirauth/voteflags.h \
- src/feature/dircache/cached_dir_st.h \
- src/feature/dircache/conscache.h \
- src/feature/dircache/consdiffmgr.h \
- src/feature/dircache/dircache.h \
- src/feature/dircache/dirserv.h \
- src/feature/dirclient/dir_server_st.h \
- src/feature/dirclient/dirclient.h \
- src/feature/dirclient/dlstatus.h \
- src/feature/dirclient/download_status_st.h \
- src/feature/dircommon/consdiff.h \
- src/feature/dircommon/dir_connection_st.h \
- src/feature/dircommon/directory.h \
- src/feature/dircommon/fp_pair.h \
- src/feature/dircommon/vote_timing_st.h \
- src/feature/dircommon/voting_schedule.h \
- src/feature/dirparse/authcert_members.i \
- src/feature/dirparse/authcert_parse.h \
- src/feature/dirparse/microdesc_parse.h \
- src/feature/dirparse/ns_parse.h \
- src/feature/dirparse/parsecommon.h \
- src/feature/dirparse/policy_parse.h \
- src/feature/dirparse/routerparse.h \
- src/feature/dirparse/sigcommon.h \
- src/feature/dirparse/signing.h \
- src/feature/dirparse/unparseable.h \
- src/feature/hibernate/hibernate.h \
- src/feature/hs/hs_cache.h \
- src/feature/hs/hs_cell.h \
- src/feature/hs/hs_circuit.h \
- src/feature/hs/hs_circuitmap.h \
- src/feature/hs/hs_client.h \
- src/feature/hs/hs_common.h \
- src/feature/hs/hs_config.h \
- src/feature/hs/hs_control.h \
- src/feature/hs/hs_descriptor.h \
- src/feature/hs/hs_dos.h \
- src/feature/hs/hs_ident.h \
- src/feature/hs/hs_intropoint.h \
- src/feature/hs/hs_service.h \
- src/feature/hs/hs_stats.h \
- src/feature/hs/hsdir_index_st.h \
- src/feature/hs_common/replaycache.h \
- src/feature/hs_common/shared_random_client.h \
- src/feature/keymgt/loadkey.h \
- src/feature/nodelist/authcert.h \
- src/feature/nodelist/authority_cert_st.h \
- src/feature/nodelist/describe.h \
- src/feature/nodelist/desc_store_st.h \
- src/feature/nodelist/dirlist.h \
- src/feature/nodelist/document_signature_st.h \
- src/feature/nodelist/extrainfo_st.h \
- src/feature/nodelist/microdesc.h \
- src/feature/nodelist/microdesc_st.h \
- src/feature/nodelist/networkstatus.h \
- src/feature/nodelist/networkstatus_sr_info_st.h \
- src/feature/nodelist/networkstatus_st.h \
- src/feature/nodelist/networkstatus_voter_info_st.h \
- src/feature/nodelist/nickname.h \
- src/feature/nodelist/node_st.h \
- src/feature/nodelist/nodefamily.h \
- src/feature/nodelist/nodefamily_st.h \
- src/feature/nodelist/nodelist.h \
- src/feature/nodelist/node_select.h \
- src/feature/nodelist/routerinfo.h \
- src/feature/nodelist/routerinfo_st.h \
- src/feature/nodelist/routerlist.h \
- src/feature/nodelist/routerlist_st.h \
- src/feature/nodelist/routerset.h \
- src/feature/nodelist/fmt_routerstatus.h \
- src/feature/nodelist/routerstatus_st.h \
- src/feature/nodelist/signed_descriptor_st.h \
- src/feature/nodelist/torcert.h \
- src/feature/nodelist/vote_routerstatus_st.h \
- src/feature/relay/dns.h \
- src/feature/relay/dns_structs.h \
- src/feature/relay/ext_orport.h \
- src/feature/relay/onion_queue.h \
- src/feature/relay/relay_periodic.h \
- src/feature/relay/relay_sys.h \
- src/feature/relay/router.h \
- src/feature/relay/routerkeys.h \
- src/feature/relay/routermode.h \
- src/feature/relay/selftest.h \
- src/feature/rend/rend_authorized_client_st.h \
- src/feature/rend/rend_encoded_v2_service_descriptor_st.h \
- src/feature/rend/rend_intro_point_st.h \
- src/feature/rend/rend_service_descriptor_st.h \
- src/feature/rend/rendcache.h \
- src/feature/rend/rendclient.h \
- src/feature/rend/rendcommon.h \
- src/feature/rend/rendmid.h \
- src/feature/rend/rendparse.h \
- src/feature/rend/rendservice.h \
- src/feature/stats/geoip_stats.h \
- src/feature/stats/rephist.h \
- src/feature/stats/predict_ports.h
-
-noinst_HEADERS += \
- src/app/config/auth_dirs.inc \
- src/app/config/fallback_dirs.inc \
- src/app/config/testnet.inc
-
-# This may someday want to be an installed file?
-noinst_HEADERS += src/feature/api/tor_api.h
-
micro-revision.i: FORCE
$(AM_V_at)rm -f micro-revision.tmp; \
if test -r "$(top_srcdir)/.git" && \
diff --git a/src/core/mainloop/.may_include b/src/core/mainloop/.may_include
index 79d6a130a4..8e01cf910e 100644
--- a/src/core/mainloop/.may_include
+++ b/src/core/mainloop/.may_include
@@ -2,6 +2,7 @@
orconfig.h
+lib/conf/*.h
lib/container/*.h
lib/dispatch/*.h
lib/evloop/*.h
@@ -15,6 +16,9 @@ lib/net/*.h
lib/evloop/*.h
lib/geoip/*.h
lib/sandbox/*.h
+lib/smartlist_core/*.h
lib/compress/*.h
+lib/log/*.h
-core/mainloop/*.h \ No newline at end of file
+core/mainloop/*.h
+core/mainloop/*.inc \ No newline at end of file
diff --git a/src/core/mainloop/connection.c b/src/core/mainloop/connection.c
index 50cd3810a4..57b48d49f3 100644
--- a/src/core/mainloop/connection.c
+++ b/src/core/mainloop/connection.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -65,8 +65,7 @@
* Define this so we get channel internal functions, since we're implementing
* part of a subclass (channel_tls_t).
*/
-#define TOR_CHANNEL_INTERNAL_
-#define CONNECTION_PRIVATE
+#define CHANNEL_OBJECT_PRIVATE
#include "app/config/config.h"
#include "core/mainloop/connection.h"
#include "core/mainloop/mainloop.h"
@@ -83,6 +82,7 @@
#include "core/or/reasons.h"
#include "core/or/relay.h"
#include "core/or/crypt_path.h"
+#include "core/proto/proto_haproxy.h"
#include "core/proto/proto_http.h"
#include "core/proto/proto_socks.h"
#include "feature/client/dnsserv.h"
@@ -91,6 +91,7 @@
#include "feature/control/control.h"
#include "feature/control/control_events.h"
#include "feature/dirauth/authmode.h"
+#include "feature/dirauth/dirauth_config.h"
#include "feature/dircache/dirserv.h"
#include "feature/dircommon/directory.h"
#include "feature/hibernate/hibernate.h"
@@ -107,6 +108,7 @@
#include "lib/crypt_ops/crypto_util.h"
#include "lib/geoip/geoip.h"
+#include "lib/cc/ctassert.h"
#include "lib/sandbox/sandbox.h"
#include "lib/net/buffers_net.h"
#include "lib/tls/tortls.h"
@@ -718,11 +720,7 @@ connection_free_minimal(connection_t *conn)
tor_free(dir_conn->requested_resource);
tor_compress_free(dir_conn->compress_state);
- if (dir_conn->spool) {
- SMARTLIST_FOREACH(dir_conn->spool, spooled_resource_t *, spooled,
- spooled_resource_free(spooled));
- smartlist_free(dir_conn->spool);
- }
+ dir_conn_clear_spool(dir_conn);
rend_data_free(dir_conn->rend_data);
hs_ident_dir_conn_free(dir_conn->hs_ident);
@@ -1516,10 +1514,11 @@ connection_listener_new(const struct sockaddr *listensockaddr,
}
}
+ /* Force IPv4 and IPv6 traffic on for non-SOCKSPorts.
+ * Forcing options on isn't a good idea, see #32994 and #33607. */
if (type != CONN_TYPE_AP_LISTENER) {
lis_conn->entry_cfg.ipv4_traffic = 1;
lis_conn->entry_cfg.ipv6_traffic = 1;
- lis_conn->entry_cfg.prefer_ipv6 = 0;
}
if (connection_add(conn) < 0) { /* no space, forget it */
@@ -1905,6 +1904,8 @@ connection_init_accepted_conn(connection_t *conn,
conn->state = AP_CONN_STATE_SOCKS_WAIT;
TO_ENTRY_CONN(conn)->socks_request->socks_prefer_no_auth =
listener->entry_cfg.socks_prefer_no_auth;
+ TO_ENTRY_CONN(conn)->socks_request->socks_use_extended_errors =
+ listener->entry_cfg.extended_socks5_codes;
break;
case CONN_TYPE_AP_TRANS_LISTENER:
TO_ENTRY_CONN(conn)->is_transparent_ap = 1;
@@ -2282,9 +2283,12 @@ connection_proxy_state_to_string(int state)
"PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929",
"PROXY_SOCKS5_WANT_AUTH_RFC1929_OK",
"PROXY_SOCKS5_WANT_CONNECT_OK",
+ "PROXY_HAPROXY_WAIT_FOR_FLUSH",
"PROXY_CONNECTED",
};
+ CTASSERT(ARRAY_LENGTH(states) == PROXY_CONNECTED+1);
+
if (state < PROXY_NONE || state > PROXY_CONNECTED)
return unknown;
@@ -2317,7 +2321,11 @@ conn_get_proxy_type(const connection_t *conn)
return PROXY_SOCKS4;
else if (options->Socks5Proxy)
return PROXY_SOCKS5;
- else
+ else if (options->TCPProxy) {
+ /* The only supported protocol in TCPProxy is haproxy. */
+ tor_assert(options->TCPProxyProtocol == TCP_PROXY_PROTOCOL_HAPROXY);
+ return PROXY_HAPROXY;
+ } else
return PROXY_NONE;
}
@@ -2326,165 +2334,245 @@ conn_get_proxy_type(const connection_t *conn)
username NUL: */
#define SOCKS4_STANDARD_BUFFER_SIZE (1 + 1 + 2 + 4 + 1)
-/** Write a proxy request of <b>type</b> (socks4, socks5, https) to conn
- * for conn->addr:conn->port, authenticating with the auth details given
- * in the configuration (if available). SOCKS 5 and HTTP CONNECT proxies
- * support authentication.
+/** Write a proxy request of https to conn for conn->addr:conn->port,
+ * authenticating with the auth details given in the configuration
+ * (if available).
*
* Returns -1 if conn->addr is incompatible with the proxy protocol, and
* 0 otherwise.
- *
- * Use connection_read_proxy_handshake() to complete the handshake.
*/
-int
-connection_proxy_connect(connection_t *conn, int type)
+static int
+connection_https_proxy_connect(connection_t *conn)
{
- const or_options_t *options;
+ tor_assert(conn);
+
+ const or_options_t *options = get_options();
+ char buf[1024];
+ char *base64_authenticator = NULL;
+ const char *authenticator = options->HTTPSProxyAuthenticator;
+
+ /* Send HTTP CONNECT and authentication (if available) in
+ * one request */
+
+ if (authenticator) {
+ base64_authenticator = alloc_http_authenticator(authenticator);
+ if (!base64_authenticator)
+ log_warn(LD_OR, "Encoding https authenticator failed");
+ }
+
+ if (base64_authenticator) {
+ const char *addrport = fmt_addrport(&conn->addr, conn->port);
+ tor_snprintf(buf, sizeof(buf), "CONNECT %s HTTP/1.1\r\n"
+ "Host: %s\r\n"
+ "Proxy-Authorization: Basic %s\r\n\r\n",
+ addrport,
+ addrport,
+ base64_authenticator);
+ tor_free(base64_authenticator);
+ } else {
+ tor_snprintf(buf, sizeof(buf), "CONNECT %s HTTP/1.0\r\n\r\n",
+ fmt_addrport(&conn->addr, conn->port));
+ }
+ connection_buf_add(buf, strlen(buf), conn);
+ conn->proxy_state = PROXY_HTTPS_WANT_CONNECT_OK;
+
+ return 0;
+}
+
+/** Write a proxy request of socks4 to conn for conn->addr:conn->port.
+ *
+ * Returns -1 if conn->addr is incompatible with the proxy protocol, and
+ * 0 otherwise.
+ */
+static int
+connection_socks4_proxy_connect(connection_t *conn)
+{
tor_assert(conn);
- options = get_options();
+ unsigned char *buf;
+ uint16_t portn;
+ uint32_t ip4addr;
+ size_t buf_size = 0;
+ char *socks_args_string = NULL;
- switch (type) {
- case PROXY_CONNECT: {
- char buf[1024];
- char *base64_authenticator=NULL;
- const char *authenticator = options->HTTPSProxyAuthenticator;
-
- /* Send HTTP CONNECT and authentication (if available) in
- * one request */
-
- if (authenticator) {
- base64_authenticator = alloc_http_authenticator(authenticator);
- if (!base64_authenticator)
- log_warn(LD_OR, "Encoding https authenticator failed");
- }
+ /* Send a SOCKS4 connect request */
- if (base64_authenticator) {
- const char *addrport = fmt_addrport(&conn->addr, conn->port);
- tor_snprintf(buf, sizeof(buf), "CONNECT %s HTTP/1.1\r\n"
- "Host: %s\r\n"
- "Proxy-Authorization: Basic %s\r\n\r\n",
- addrport,
- addrport,
- base64_authenticator);
- tor_free(base64_authenticator);
- } else {
- tor_snprintf(buf, sizeof(buf), "CONNECT %s HTTP/1.0\r\n\r\n",
- fmt_addrport(&conn->addr, conn->port));
- }
+ if (tor_addr_family(&conn->addr) != AF_INET) {
+ log_warn(LD_NET, "SOCKS4 client is incompatible with IPv6");
+ return -1;
+ }
- connection_buf_add(buf, strlen(buf), conn);
- conn->proxy_state = PROXY_HTTPS_WANT_CONNECT_OK;
- break;
+ { /* If we are here because we are trying to connect to a
+ pluggable transport proxy, check if we have any SOCKS
+ arguments to transmit. If we do, compress all arguments to
+ a single string in 'socks_args_string': */
+
+ if (conn_get_proxy_type(conn) == PROXY_PLUGGABLE) {
+ socks_args_string =
+ pt_get_socks_args_for_proxy_addrport(&conn->addr, conn->port);
+ if (socks_args_string)
+ log_debug(LD_NET, "Sending out '%s' as our SOCKS argument string.",
+ socks_args_string);
}
+ }
- case PROXY_SOCKS4: {
- unsigned char *buf;
- uint16_t portn;
- uint32_t ip4addr;
- size_t buf_size = 0;
- char *socks_args_string = NULL;
+ { /* Figure out the buffer size we need for the SOCKS message: */
- /* Send a SOCKS4 connect request */
+ buf_size = SOCKS4_STANDARD_BUFFER_SIZE;
- if (tor_addr_family(&conn->addr) != AF_INET) {
- log_warn(LD_NET, "SOCKS4 client is incompatible with IPv6");
- return -1;
- }
+ /* If we have a SOCKS argument string, consider its size when
+ calculating the buffer size: */
+ if (socks_args_string)
+ buf_size += strlen(socks_args_string);
+ }
- { /* If we are here because we are trying to connect to a
- pluggable transport proxy, check if we have any SOCKS
- arguments to transmit. If we do, compress all arguments to
- a single string in 'socks_args_string': */
+ buf = tor_malloc_zero(buf_size);
- if (conn_get_proxy_type(conn) == PROXY_PLUGGABLE) {
- socks_args_string =
- pt_get_socks_args_for_proxy_addrport(&conn->addr, conn->port);
- if (socks_args_string)
- log_debug(LD_NET, "Sending out '%s' as our SOCKS argument string.",
- socks_args_string);
- }
- }
+ ip4addr = tor_addr_to_ipv4n(&conn->addr);
+ portn = htons(conn->port);
- { /* Figure out the buffer size we need for the SOCKS message: */
+ buf[0] = 4; /* version */
+ buf[1] = SOCKS_COMMAND_CONNECT; /* command */
+ memcpy(buf + 2, &portn, 2); /* port */
+ memcpy(buf + 4, &ip4addr, 4); /* addr */
+
+ /* Next packet field is the userid. If we have pluggable
+ transport SOCKS arguments, we have to embed them
+ there. Otherwise, we use an empty userid. */
+ if (socks_args_string) { /* place the SOCKS args string: */
+ tor_assert(strlen(socks_args_string) > 0);
+ tor_assert(buf_size >=
+ SOCKS4_STANDARD_BUFFER_SIZE + strlen(socks_args_string));
+ strlcpy((char *)buf + 8, socks_args_string, buf_size - 8);
+ tor_free(socks_args_string);
+ } else {
+ buf[8] = 0; /* no userid */
+ }
- buf_size = SOCKS4_STANDARD_BUFFER_SIZE;
+ connection_buf_add((char *)buf, buf_size, conn);
+ tor_free(buf);
- /* If we have a SOCKS argument string, consider its size when
- calculating the buffer size: */
- if (socks_args_string)
- buf_size += strlen(socks_args_string);
- }
+ conn->proxy_state = PROXY_SOCKS4_WANT_CONNECT_OK;
+ return 0;
+}
- buf = tor_malloc_zero(buf_size);
-
- ip4addr = tor_addr_to_ipv4n(&conn->addr);
- portn = htons(conn->port);
-
- buf[0] = 4; /* version */
- buf[1] = SOCKS_COMMAND_CONNECT; /* command */
- memcpy(buf + 2, &portn, 2); /* port */
- memcpy(buf + 4, &ip4addr, 4); /* addr */
-
- /* Next packet field is the userid. If we have pluggable
- transport SOCKS arguments, we have to embed them
- there. Otherwise, we use an empty userid. */
- if (socks_args_string) { /* place the SOCKS args string: */
- tor_assert(strlen(socks_args_string) > 0);
- tor_assert(buf_size >=
- SOCKS4_STANDARD_BUFFER_SIZE + strlen(socks_args_string));
- strlcpy((char *)buf + 8, socks_args_string, buf_size - 8);
- tor_free(socks_args_string);
- } else {
- buf[8] = 0; /* no userid */
- }
+/** Write a proxy request of socks5 to conn for conn->addr:conn->port,
+ * authenticating with the auth details given in the configuration
+ * (if available).
+ *
+ * Returns -1 if conn->addr is incompatible with the proxy protocol, and
+ * 0 otherwise.
+ */
+static int
+connection_socks5_proxy_connect(connection_t *conn)
+{
+ tor_assert(conn);
- connection_buf_add((char *)buf, buf_size, conn);
- tor_free(buf);
+ const or_options_t *options = get_options();
+ unsigned char buf[4]; /* fields: vers, num methods, method list */
- conn->proxy_state = PROXY_SOCKS4_WANT_CONNECT_OK;
- break;
- }
+ /* Send a SOCKS5 greeting (connect request must wait) */
- case PROXY_SOCKS5: {
- unsigned char buf[4]; /* fields: vers, num methods, method list */
+ buf[0] = 5; /* version */
- /* Send a SOCKS5 greeting (connect request must wait) */
+ /* We have to use SOCKS5 authentication, if we have a
+ Socks5ProxyUsername or if we want to pass arguments to our
+ pluggable transport proxy: */
+ if ((options->Socks5ProxyUsername) ||
+ (conn_get_proxy_type(conn) == PROXY_PLUGGABLE &&
+ (get_socks_args_by_bridge_addrport(&conn->addr, conn->port)))) {
+ /* number of auth methods */
+ buf[1] = 2;
+ buf[2] = 0x00; /* no authentication */
+ buf[3] = 0x02; /* rfc1929 Username/Passwd auth */
+ conn->proxy_state = PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929;
+ } else {
+ buf[1] = 1;
+ buf[2] = 0x00; /* no authentication */
+ conn->proxy_state = PROXY_SOCKS5_WANT_AUTH_METHOD_NONE;
+ }
- buf[0] = 5; /* version */
+ connection_buf_add((char *)buf, 2 + buf[1], conn);
+ return 0;
+}
- /* We have to use SOCKS5 authentication, if we have a
- Socks5ProxyUsername or if we want to pass arguments to our
- pluggable transport proxy: */
- if ((options->Socks5ProxyUsername) ||
- (conn_get_proxy_type(conn) == PROXY_PLUGGABLE &&
- (get_socks_args_by_bridge_addrport(&conn->addr, conn->port)))) {
- /* number of auth methods */
- buf[1] = 2;
- buf[2] = 0x00; /* no authentication */
- buf[3] = 0x02; /* rfc1929 Username/Passwd auth */
- conn->proxy_state = PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929;
- } else {
- buf[1] = 1;
- buf[2] = 0x00; /* no authentication */
- conn->proxy_state = PROXY_SOCKS5_WANT_AUTH_METHOD_NONE;
- }
+/** Write a proxy request of haproxy to conn for conn->addr:conn->port.
+ *
+ * Returns -1 if conn->addr is incompatible with the proxy protocol, and
+ * 0 otherwise.
+ */
+static int
+connection_haproxy_proxy_connect(connection_t *conn)
+{
+ int ret = 0;
+ tor_addr_port_t *addr_port = tor_addr_port_new(&conn->addr, conn->port);
+ char *buf = haproxy_format_proxy_header_line(addr_port);
+
+ if (buf == NULL) {
+ ret = -1;
+ goto done;
+ }
+
+ connection_buf_add(buf, strlen(buf), conn);
+ /* In haproxy, we don't have to wait for the response, but we wait for ack.
+ * So we can set the state to be PROXY_HAPROXY_WAIT_FOR_FLUSH. */
+ conn->proxy_state = PROXY_HAPROXY_WAIT_FOR_FLUSH;
+
+ ret = 0;
+ done:
+ tor_free(buf);
+ tor_free(addr_port);
+ return ret;
+}
+
+/** Write a proxy request of <b>type</b> (socks4, socks5, https, haproxy)
+ * to conn for conn->addr:conn->port, authenticating with the auth details
+ * given in the configuration (if available). SOCKS 5 and HTTP CONNECT
+ * proxies support authentication.
+ *
+ * Returns -1 if conn->addr is incompatible with the proxy protocol, and
+ * 0 otherwise.
+ *
+ * Use connection_read_proxy_handshake() to complete the handshake.
+ */
+int
+connection_proxy_connect(connection_t *conn, int type)
+{
+ int ret = 0;
+
+ tor_assert(conn);
- connection_buf_add((char *)buf, 2 + buf[1], conn);
+ switch (type) {
+ case PROXY_CONNECT:
+ ret = connection_https_proxy_connect(conn);
+ break;
+
+ case PROXY_SOCKS4:
+ ret = connection_socks4_proxy_connect(conn);
+ break;
+
+ case PROXY_SOCKS5:
+ ret = connection_socks5_proxy_connect(conn);
+ break;
+
+ case PROXY_HAPROXY:
+ ret = connection_haproxy_proxy_connect(conn);
break;
- }
default:
log_err(LD_BUG, "Invalid proxy protocol, %d", type);
tor_fragile_assert();
- return -1;
+ ret = -1;
+ break;
}
- log_debug(LD_NET, "set state %s",
- connection_proxy_state_to_string(conn->proxy_state));
+ if (ret == 0) {
+ log_debug(LD_NET, "set state %s",
+ connection_proxy_state_to_string(conn->proxy_state));
+ }
- return 0;
+ return ret;
}
/** Read conn's inbuf. If the http response from the proxy is all
@@ -3215,7 +3303,7 @@ connection_dir_is_global_write_low(const connection_t *conn, size_t attempt)
/* Special case for authorities (directory only). */
if (authdir_mode_v3(get_options())) {
/* Are we configured to possibly reject requests under load? */
- if (!get_options()->AuthDirRejectRequestsUnderLoad) {
+ if (!dirauth_should_reject_requests_under_load()) {
/* Answer request no matter what. */
return false;
}
@@ -4885,10 +4973,10 @@ connection_finished_flushing(connection_t *conn)
}
}
-/** Called when our attempt to connect() to another server has just
- * succeeded.
+/** Called when our attempt to connect() to a server has just succeeded.
*
- * This function just passes conn to the connection-specific
+ * This function checks if the interface address has changed (clients only),
+ * and then passes conn to the connection-specific
* connection_*_finished_connecting() function.
*/
static int
@@ -5452,6 +5540,13 @@ get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type,
*port = options->Socks5ProxyPort;
*proxy_type = PROXY_SOCKS5;
return 0;
+ } else if (options->TCPProxy) {
+ tor_addr_copy(addr, &options->TCPProxyAddr);
+ *port = options->TCPProxyPort;
+ /* The only supported protocol in TCPProxy is haproxy. */
+ tor_assert(options->TCPProxyProtocol == TCP_PROXY_PROTOCOL_HAPROXY);
+ *proxy_type = PROXY_HAPROXY;
+ return 0;
}
tor_addr_make_unspec(addr);
@@ -5489,6 +5584,7 @@ proxy_type_to_string(int proxy_type)
case PROXY_CONNECT: return "HTTP";
case PROXY_SOCKS4: return "SOCKS4";
case PROXY_SOCKS5: return "SOCKS5";
+ case PROXY_HAPROXY: return "HAPROXY";
case PROXY_PLUGGABLE: return "pluggable transports SOCKS";
case PROXY_NONE: return "NULL";
default: tor_assert(0);
diff --git a/src/core/mainloop/connection.h b/src/core/mainloop/connection.h
index 668c740042..bcd3d590a5 100644
--- a/src/core/mainloop/connection.h
+++ b/src/core/mainloop/connection.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,7 +12,25 @@
#ifndef TOR_CONNECTION_H
#define TOR_CONNECTION_H
-listener_connection_t *TO_LISTENER_CONN(connection_t *);
+#include "lib/smartlist_core/smartlist_core.h"
+#include "lib/log/log.h"
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+struct listener_connection_t;
+struct connection_t;
+struct dir_connection_t;
+struct or_connection_t;
+struct edge_connection_t;
+struct entry_connection_t;
+struct control_connection_t;
+struct port_cfg_t;
+struct tor_addr_t;
+struct or_options_t;
+
+struct listener_connection_t *TO_LISTENER_CONN(struct connection_t *);
struct buf_t;
@@ -56,7 +74,7 @@ struct buf_t;
#define CONN_TYPE_MAX_ 19
/* !!!! If _CONN_TYPE_MAX is ever over 31, we must grow the type field in
- * connection_t. */
+ * struct connection_t. */
/* Proxy client handshake states */
/* We use a proxy but we haven't even connected to it yet. */
@@ -75,8 +93,10 @@ struct buf_t;
#define PROXY_SOCKS5_WANT_AUTH_RFC1929_OK 6
/* We use a SOCKS5 proxy and we just sent our CONNECT command. */
#define PROXY_SOCKS5_WANT_CONNECT_OK 7
+/* We use an HAPROXY proxy and we just sent the proxy header. */
+#define PROXY_HAPROXY_WAIT_FOR_FLUSH 8
/* We use a proxy and we CONNECTed successfully!. */
-#define PROXY_CONNECTED 8
+#define PROXY_CONNECTED 9
/** State for any listener connection. */
#define LISTENER_STATE_READY 0
@@ -88,34 +108,36 @@ struct buf_t;
*/
typedef struct
{
- connection_t *old_conn; /* Old listener connection to be replaced */
- const port_cfg_t *new_port; /* New port configuration */
+ struct connection_t *old_conn; /* Old listener connection to be replaced */
+ const struct port_cfg_t *new_port; /* New port configuration */
} listener_replacement_t;
const char *conn_type_to_string(int type);
const char *conn_state_to_string(int type, int state);
int conn_listener_type_supports_af_unix(int type);
-dir_connection_t *dir_connection_new(int socket_family);
-or_connection_t *or_connection_new(int type, int socket_family);
-edge_connection_t *edge_connection_new(int type, int socket_family);
-entry_connection_t *entry_connection_new(int type, int socket_family);
-control_connection_t *control_connection_new(int socket_family);
-listener_connection_t *listener_connection_new(int type, int socket_family);
-connection_t *connection_new(int type, int socket_family);
-int connection_init_accepted_conn(connection_t *conn,
- const listener_connection_t *listener);
-void connection_link_connections(connection_t *conn_a, connection_t *conn_b);
-MOCK_DECL(void,connection_free_,(connection_t *conn));
+struct dir_connection_t *dir_connection_new(int socket_family);
+struct or_connection_t *or_connection_new(int type, int socket_family);
+struct edge_connection_t *edge_connection_new(int type, int socket_family);
+struct entry_connection_t *entry_connection_new(int type, int socket_family);
+struct control_connection_t *control_connection_new(int socket_family);
+struct listener_connection_t *listener_connection_new(int type,
+ int socket_family);
+struct connection_t *connection_new(int type, int socket_family);
+int connection_init_accepted_conn(struct connection_t *conn,
+ const struct listener_connection_t *listener);
+void connection_link_connections(struct connection_t *conn_a,
+ struct connection_t *conn_b);
+MOCK_DECL(void,connection_free_,(struct connection_t *conn));
#define connection_free(conn) \
- FREE_AND_NULL(connection_t, connection_free_, (conn))
+ FREE_AND_NULL(struct connection_t, connection_free_, (conn))
void connection_free_all(void);
-void connection_about_to_close_connection(connection_t *conn);
-void connection_close_immediate(connection_t *conn);
-void connection_mark_for_close_(connection_t *conn,
+void connection_about_to_close_connection(struct connection_t *conn);
+void connection_close_immediate(struct connection_t *conn);
+void connection_mark_for_close_(struct connection_t *conn,
int line, const char *file);
MOCK_DECL(void, connection_mark_for_close_internal_,
- (connection_t *conn, int line, const char *file));
+ (struct connection_t *conn, int line, const char *file));
#define connection_mark_for_close(c) \
connection_mark_for_close_((c), __LINE__, SHORT_FILE__)
@@ -130,11 +152,11 @@ MOCK_DECL(void, connection_mark_for_close_internal_,
* connection_or_notify_error()), or you actually are the
* connection_or_close_for_error() or connection_or_close_normally function.
* For all other cases, use connection_mark_and_flush() instead, which
- * checks for or_connection_t properly, instead. See below.
+ * checks for struct or_connection_t properly, instead. See below.
*/
#define connection_mark_and_flush_internal_(c,line,file) \
do { \
- connection_t *tmp_conn__ = (c); \
+ struct connection_t *tmp_conn__ = (c); \
connection_mark_for_close_internal_(tmp_conn__, (line), (file)); \
tmp_conn__->hold_open_until_flushed = 1; \
} while (0)
@@ -147,7 +169,7 @@ MOCK_DECL(void, connection_mark_for_close_internal_,
*/
#define connection_mark_and_flush_(c,line,file) \
do { \
- connection_t *tmp_conn_ = (c); \
+ struct connection_t *tmp_conn_ = (c); \
if (tmp_conn_->type == CONN_TYPE_OR) { \
log_warn(LD_CHANNEL | LD_BUG, \
"Something tried to close (and flush) an or_connection_t" \
@@ -164,13 +186,13 @@ MOCK_DECL(void, connection_mark_for_close_internal_,
void connection_expire_held_open(void);
-int connection_connect(connection_t *conn, const char *address,
- const tor_addr_t *addr,
+int connection_connect(struct connection_t *conn, const char *address,
+ const struct tor_addr_t *addr,
uint16_t port, int *socket_error);
#ifdef HAVE_SYS_UN_H
-int connection_connect_unix(connection_t *conn, const char *socket_path,
+int connection_connect_unix(struct connection_t *conn, const char *socket_path,
int *socket_error);
#endif /* defined(HAVE_SYS_UN_H) */
@@ -183,13 +205,14 @@ int connection_connect_unix(connection_t *conn, const char *socket_path,
username and password fields. */
#define MAX_SOCKS5_AUTH_SIZE_TOTAL 2*MAX_SOCKS5_AUTH_FIELD_SIZE
-int connection_proxy_connect(connection_t *conn, int type);
-int connection_read_proxy_handshake(connection_t *conn);
-void log_failed_proxy_connection(connection_t *conn);
-int get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type,
- int *is_pt_out, const connection_t *conn);
+int connection_proxy_connect(struct connection_t *conn, int type);
+int connection_read_proxy_handshake(struct connection_t *conn);
+void log_failed_proxy_connection(struct connection_t *conn);
+int get_proxy_addrport(struct tor_addr_t *addr, uint16_t *port,
+ int *proxy_type,
+ int *is_pt_out, const struct connection_t *conn);
-int retry_all_listeners(smartlist_t *new_conns,
+int retry_all_listeners(struct smartlist_t *new_conns,
int close_all_noncontrol);
void connection_mark_all_noncontrol_listeners(void);
@@ -199,63 +222,69 @@ ssize_t connection_bucket_write_limit(struct connection_t *conn, time_t now);
bool connection_dir_is_global_write_low(const struct connection_t *conn,
size_t attempt);
void connection_bucket_init(void);
-void connection_bucket_adjust(const or_options_t *options);
+void connection_bucket_adjust(const struct or_options_t *options);
void connection_bucket_refill_all(time_t now,
uint32_t now_ts);
-void connection_read_bw_exhausted(connection_t *conn, bool is_global_bw);
-void connection_write_bw_exhausted(connection_t *conn, bool is_global_bw);
-void connection_consider_empty_read_buckets(connection_t *conn);
-void connection_consider_empty_write_buckets(connection_t *conn);
-
-int connection_handle_read(connection_t *conn);
-
-int connection_buf_get_bytes(char *string, size_t len, connection_t *conn);
-int connection_buf_get_line(connection_t *conn, char *data,
- size_t *data_len);
-int connection_fetch_from_buf_http(connection_t *conn,
+void connection_read_bw_exhausted(struct connection_t *conn,
+ bool is_global_bw);
+void connection_write_bw_exhausted(struct connection_t *conn,
+ bool is_global_bw);
+void connection_consider_empty_read_buckets(struct connection_t *conn);
+void connection_consider_empty_write_buckets(struct connection_t *conn);
+
+int connection_handle_read(struct connection_t *conn);
+
+int connection_buf_get_bytes(char *string, size_t len,
+ struct connection_t *conn);
+int connection_buf_get_line(struct connection_t *conn, char *data,
+ size_t *data_len);
+int connection_fetch_from_buf_http(struct connection_t *conn,
char **headers_out, size_t max_headerlen,
char **body_out, size_t *body_used,
size_t max_bodylen, int force_complete);
-int connection_wants_to_flush(connection_t *conn);
-int connection_outbuf_too_full(connection_t *conn);
-int connection_handle_write(connection_t *conn, int force);
-int connection_flush(connection_t *conn);
+int connection_wants_to_flush(struct connection_t *conn);
+int connection_outbuf_too_full(struct connection_t *conn);
+int connection_handle_write(struct connection_t *conn, int force);
+int connection_flush(struct connection_t *conn);
MOCK_DECL(void, connection_write_to_buf_impl_,
- (const char *string, size_t len, connection_t *conn, int zlib));
+ (const char *string, size_t len, struct connection_t *conn,
+ int zlib));
/* DOCDOC connection_write_to_buf */
static void connection_buf_add(const char *string, size_t len,
- connection_t *conn);
+ struct connection_t *conn);
void connection_dir_buf_add(const char *string, size_t len,
- dir_connection_t *dir_conn, int done);
+ struct dir_connection_t *dir_conn, int done);
static inline void
-connection_buf_add(const char *string, size_t len, connection_t *conn)
+connection_buf_add(const char *string, size_t len, struct connection_t *conn)
{
connection_write_to_buf_impl_(string, len, conn, 0);
}
void connection_buf_add_compress(const char *string, size_t len,
- dir_connection_t *conn, int done);
-void connection_buf_add_buf(connection_t *conn, struct buf_t *buf);
-
-size_t connection_get_inbuf_len(connection_t *conn);
-size_t connection_get_outbuf_len(connection_t *conn);
-connection_t *connection_get_by_global_id(uint64_t id);
-
-connection_t *connection_get_by_type(int type);
-MOCK_DECL(connection_t *,connection_get_by_type_nonlinked,(int type));
-MOCK_DECL(connection_t *,connection_get_by_type_addr_port_purpose,(int type,
- const tor_addr_t *addr,
- uint16_t port, int purpose));
-connection_t *connection_get_by_type_state(int type, int state);
-connection_t *connection_get_by_type_state_rendquery(int type, int state,
+ struct dir_connection_t *conn, int done);
+void connection_buf_add_buf(struct connection_t *conn, struct buf_t *buf);
+
+size_t connection_get_inbuf_len(struct connection_t *conn);
+size_t connection_get_outbuf_len(struct connection_t *conn);
+struct connection_t *connection_get_by_global_id(uint64_t id);
+
+struct connection_t *connection_get_by_type(int type);
+MOCK_DECL(struct connection_t *,connection_get_by_type_nonlinked,(int type));
+MOCK_DECL(struct connection_t *,connection_get_by_type_addr_port_purpose,
+ (int type,
+ const struct tor_addr_t *addr,
+ uint16_t port, int purpose));
+struct connection_t *connection_get_by_type_state(int type, int state);
+struct connection_t *connection_get_by_type_state_rendquery(
+ int type, int state,
const char *rendquery);
-smartlist_t *connection_list_by_type_state(int type, int state);
-smartlist_t *connection_list_by_type_purpose(int type, int purpose);
-smartlist_t *connection_dir_list_by_purpose_and_resource(
+struct smartlist_t *connection_list_by_type_state(int type, int state);
+struct smartlist_t *connection_list_by_type_purpose(int type, int purpose);
+struct smartlist_t *connection_dir_list_by_purpose_and_resource(
int purpose,
const char *resource);
-smartlist_t *connection_dir_list_by_purpose_resource_and_state(
+struct smartlist_t *connection_dir_list_by_purpose_resource_and_state(
int purpose,
const char *resource,
int state);
@@ -274,7 +303,7 @@ connection_dir_count_by_purpose_and_resource(
int purpose,
const char *resource)
{
- smartlist_t *conns = connection_dir_list_by_purpose_and_resource(
+ struct smartlist_t *conns = connection_dir_list_by_purpose_and_resource(
purpose,
resource);
CONN_LEN_AND_FREE_TEMPLATE(conns);
@@ -288,7 +317,7 @@ connection_dir_count_by_purpose_resource_and_state(
const char *resource,
int state)
{
- smartlist_t *conns =
+ struct smartlist_t *conns =
connection_dir_list_by_purpose_resource_and_state(
purpose,
resource,
@@ -298,26 +327,26 @@ connection_dir_count_by_purpose_resource_and_state(
#undef CONN_LEN_AND_FREE_TEMPLATE
-int any_other_active_or_conns(const or_connection_t *this_conn);
+int any_other_active_or_conns(const struct or_connection_t *this_conn);
/* || 0 is for -Wparentheses-equality (-Wall?) appeasement under clang */
#define connection_speaks_cells(conn) (((conn)->type == CONN_TYPE_OR) || 0)
-int connection_is_listener(connection_t *conn);
-int connection_state_is_open(connection_t *conn);
-int connection_state_is_connecting(connection_t *conn);
+int connection_is_listener(struct connection_t *conn);
+int connection_state_is_open(struct connection_t *conn);
+int connection_state_is_connecting(struct 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);
+void assert_connection_ok(struct connection_t *conn, time_t now);
+int connection_or_nonopen_was_started_here(struct or_connection_t *conn);
void connection_dump_buffer_mem_stats(int severity);
MOCK_DECL(void, clock_skew_warning,
- (const connection_t *conn, long apparent_skew, int trusted,
+ (const struct connection_t *conn, long apparent_skew, int trusted,
log_domain_mask_t domain, const char *received,
const char *source));
-int connection_is_moribund(connection_t *conn);
+int connection_is_moribund(struct connection_t *conn);
void connection_check_oos(int n_socks, int failed);
/** Execute the statement <b>stmt</b>, which may log events concerning the
@@ -339,18 +368,18 @@ void connection_check_oos(int n_socks, int failed);
STMT_END
#ifdef CONNECTION_PRIVATE
-STATIC void connection_free_minimal(connection_t *conn);
+STATIC void connection_free_minimal(struct connection_t *conn);
/* Used only by connection.c and test*.c */
MOCK_DECL(STATIC int,connection_connect_sockaddr,
- (connection_t *conn,
+ (struct connection_t *conn,
const struct sockaddr *sa,
socklen_t sa_len,
const struct sockaddr *bindaddr,
socklen_t bindaddr_len,
int *socket_error));
-MOCK_DECL(STATIC void, kill_conn_list_for_oos, (smartlist_t *conns));
-MOCK_DECL(STATIC smartlist_t *, pick_oos_victims, (int n));
+MOCK_DECL(STATIC void, kill_conn_list_for_oos, (struct smartlist_t *conns));
+MOCK_DECL(STATIC struct smartlist_t *, pick_oos_victims, (int n));
#endif /* defined(CONNECTION_PRIVATE) */
diff --git a/src/core/mainloop/core_mainloop.md b/src/core/mainloop/core_mainloop.md
new file mode 100644
index 0000000000..fee8a8179c
--- /dev/null
+++ b/src/core/mainloop/core_mainloop.md
@@ -0,0 +1,10 @@
+@dir /core/mainloop
+@brief core/mainloop: Non-onion-routing mainloop functionality
+
+This module uses the event-loop code of \refdir{lib/evloop} to implement an
+asynchronous connection-oriented protocol handler.
+
+The layering here is imperfect: the code here was split from \refdir{core/or}
+without refactoring how the two modules call one another. Probably many
+functions should be moved and refactored.
+
diff --git a/src/core/mainloop/cpuworker.c b/src/core/mainloop/cpuworker.c
index 436fcd28c3..abd48f886c 100644
--- a/src/core/mainloop/cpuworker.c
+++ b/src/core/mainloop/cpuworker.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -37,7 +37,7 @@
static void queue_pending_tasks(void);
-typedef struct worker_state_s {
+typedef struct worker_state_t {
int generation;
server_onion_keys_t *onion_keys;
} worker_state_t;
@@ -160,7 +160,7 @@ typedef struct cpuworker_reply_t {
uint8_t rend_auth_material[DIGEST_LEN];
} cpuworker_reply_t;
-typedef struct cpuworker_job_u {
+typedef struct cpuworker_job_u_t {
or_circuit_t *circ;
union {
cpuworker_request_t request;
diff --git a/src/core/mainloop/cpuworker.h b/src/core/mainloop/cpuworker.h
index 77e2c42508..7e71961750 100644
--- a/src/core/mainloop/cpuworker.h
+++ b/src/core/mainloop/cpuworker.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,10 +14,10 @@
void cpu_init(void);
void cpuworkers_rotate_keyinfo(void);
-struct workqueue_entry_s;
+struct workqueue_entry_t;
enum workqueue_reply_t;
enum workqueue_priority_t;
-MOCK_DECL(struct workqueue_entry_s *, cpuworker_queue_work, (
+MOCK_DECL(struct workqueue_entry_t *, cpuworker_queue_work, (
enum workqueue_priority_t priority,
enum workqueue_reply_t (*fn)(void *, void *),
void (*reply_fn)(void *),
diff --git a/src/core/mainloop/include.am b/src/core/mainloop/include.am
new file mode 100644
index 0000000000..63643127f3
--- /dev/null
+++ b/src/core/mainloop/include.am
@@ -0,0 +1,22 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/core/mainloop/connection.c \
+ src/core/mainloop/cpuworker.c \
+ src/core/mainloop/mainloop.c \
+ src/core/mainloop/mainloop_pubsub.c \
+ src/core/mainloop/mainloop_sys.c \
+ src/core/mainloop/netstatus.c \
+ src/core/mainloop/periodic.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/core/mainloop/connection.h \
+ src/core/mainloop/cpuworker.h \
+ src/core/mainloop/mainloop.h \
+ src/core/mainloop/mainloop_pubsub.h \
+ src/core/mainloop/mainloop_state.inc \
+ src/core/mainloop/mainloop_state_st.h \
+ src/core/mainloop/mainloop_sys.h \
+ src/core/mainloop/netstatus.h \
+ src/core/mainloop/periodic.h
diff --git a/src/core/mainloop/mainloop.c b/src/core/mainloop/mainloop.c
index c47e440774..260de181e5 100644
--- a/src/core/mainloop/mainloop.c
+++ b/src/core/mainloop/mainloop.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -71,12 +71,13 @@
#include "feature/client/bridges.h"
#include "feature/client/dnsserv.h"
#include "feature/client/entrynodes.h"
+#include "feature/client/proxymode.h"
#include "feature/client/transports.h"
#include "feature/control/control.h"
#include "feature/control/control_events.h"
#include "feature/dirauth/authmode.h"
#include "feature/dircache/consdiffmgr.h"
-#include "feature/dircache/dirserv.h"
+#include "feature/dirclient/dirclient_modes.h"
#include "feature/dircommon/directory.h"
#include "feature/hibernate/hibernate.h"
#include "feature/hs/hs_cache.h"
@@ -1132,14 +1133,14 @@ directory_info_has_arrived(time_t now, int from_cache, int suppress_logs)
if (!router_have_minimum_dir_info()) {
int quiet = suppress_logs || from_cache ||
- directory_too_idle_to_fetch_descriptors(options, now);
+ dirclient_too_idle_to_fetch_descriptors(options, now);
tor_log(quiet ? LOG_INFO : LOG_NOTICE, LD_DIR,
"I learned some more directory information, but not enough to "
"build a circuit: %s", get_dir_info_status_string());
update_all_descriptor_downloads(now);
return;
} else {
- if (directory_fetches_from_authorities(options)) {
+ if (dirclient_fetches_from_authorities(options)) {
update_all_descriptor_downloads(now);
}
@@ -1352,9 +1353,11 @@ get_signewnym_epoch(void)
static int periodic_events_initialized = 0;
/* Declare all the timer callback functions... */
+#ifndef COCCI
#undef CALLBACK
#define CALLBACK(name) \
static int name ## _callback(time_t, const or_options_t *)
+
CALLBACK(add_entropy);
CALLBACK(check_expired_networkstatus);
CALLBACK(clean_caches);
@@ -1377,9 +1380,10 @@ CALLBACK(second_elapsed);
#undef CALLBACK
/* Now we declare an array of periodic_event_item_t for each periodic event */
-#define CALLBACK(name, r, f) \
+#define CALLBACK(name, r, f) \
PERIODIC_EVENT(name, PERIODIC_EVENT_ROLE_ ## r, f)
#define FL(name) (PERIODIC_EVENT_FLAG_ ## name)
+#endif /* !defined(COCCI) */
STATIC periodic_event_item_t mainloop_periodic_events[] = {
@@ -1430,8 +1434,10 @@ STATIC periodic_event_item_t mainloop_periodic_events[] = {
END_OF_PERIODIC_EVENTS
};
+#ifndef COCCI
#undef CALLBACK
#undef FL
+#endif
/* These are pointers to members of periodic_events[] that are used to
* implement particular callbacks. We keep them separate here so that we
@@ -1530,8 +1536,10 @@ initialize_periodic_events(void)
/* Set up all periodic events. We'll launch them by roles. */
+#ifndef COCCI
#define NAMED_CALLBACK(name) \
STMT_BEGIN name ## _event = periodic_events_find( #name ); STMT_END
+#endif
NAMED_CALLBACK(prune_old_routers);
NAMED_CALLBACK(fetch_networkstatus);
@@ -2061,7 +2069,7 @@ fetch_networkstatus_callback(time_t now, const or_options_t *options)
* documents? */
const int we_are_bootstrapping = networkstatus_consensus_is_bootstrapping(
now);
- const int prefer_mirrors = !directory_fetches_from_authorities(
+ const int prefer_mirrors = !dirclient_fetches_from_authorities(
get_options());
int networkstatus_dl_check_interval = 60;
/* check more often when testing, or when bootstrapping from mirrors
@@ -2265,18 +2273,23 @@ systemd_watchdog_callback(periodic_timer_t *timer, void *arg)
#define UPTIME_CUTOFF_FOR_NEW_BANDWIDTH_TEST (6*60*60)
-/** Called when our IP address seems to have changed. <b>at_interface</b>
- * should be true if we detected a change in our interface, and false if we
- * detected a change in our published address. */
+/** Called when our IP address seems to have changed. <b>on_client_conn</b>
+ * should be true if:
+ * - we detected a change in our interface address, using an outbound
+ * connection, and therefore
+ * - our client TLS keys need to be rotated.
+ * Otherwise, it should be false, and:
+ * - we detected a change in our published address
+ * (using some other method), and therefore
+ * - the published addresses in our descriptor need to change.
+ */
void
-ip_address_changed(int at_interface)
+ip_address_changed(int on_client_conn)
{
const or_options_t *options = get_options();
int server = server_mode(options);
- int exit_reject_interfaces = (server && options->ExitRelay
- && options->ExitPolicyRejectLocalInterfaces);
- if (at_interface) {
+ if (on_client_conn) {
if (! server) {
/* Okay, change our keys. */
if (init_keys_client() < 0)
@@ -2288,15 +2301,14 @@ ip_address_changed(int at_interface)
reset_bandwidth_test();
reset_uptime();
router_reset_reachability();
+ /* All relays include their IP addresses as their ORPort addresses in
+ * their descriptor.
+ * Exit relays also incorporate interface addresses in their exit
+ * policies, when ExitPolicyRejectLocalInterfaces is set. */
+ mark_my_descriptor_dirty("IP address changed");
}
}
- /* Exit relays incorporate interface addresses in their exit policies when
- * ExitPolicyRejectLocalInterfaces is set */
- if (exit_reject_interfaces || (server && !at_interface)) {
- mark_my_descriptor_dirty("IP address changed");
- }
-
dns_servers_relaunch_checks();
}
diff --git a/src/core/mainloop/mainloop.h b/src/core/mainloop/mainloop.h
index caef736c15..1ddfec2162 100644
--- a/src/core/mainloop/mainloop.h
+++ b/src/core/mainloop/mainloop.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -56,7 +56,7 @@ MOCK_DECL(int, connection_count_moribund, (void));
void directory_all_unreachable(time_t now);
void directory_info_has_arrived(time_t now, int from_cache, int suppress_logs);
-void ip_address_changed(int at_interface);
+void ip_address_changed(int on_client_conn);
void dns_servers_relaunch_checks(void);
void reset_all_main_loop_timers(void);
void reschedule_directory_downloads(void);
@@ -94,7 +94,6 @@ void tor_mainloop_free_all(void);
struct token_bucket_rw_t;
extern time_t time_of_process_start;
-extern int quiet_level;
extern struct token_bucket_rw_t global_bucket;
extern struct token_bucket_rw_t global_relayed_bucket;
diff --git a/src/core/mainloop/mainloop_pubsub.c b/src/core/mainloop/mainloop_pubsub.c
index 53275d8119..0e982d4c40 100644
--- a/src/core/mainloop/mainloop_pubsub.c
+++ b/src/core/mainloop/mainloop_pubsub.c
@@ -1,9 +1,18 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file mainloop_pubsub.c
+ * @brief Connect the publish-subscribe code to the main-loop.
+ *
+ * This module is responsible for instantiating all the channels used by the
+ * publish-subscribe code, and making sure that each one's messages are
+ * processed when appropriate.
+ **/
+
#include "orconfig.h"
#include "core/or/or.h"
diff --git a/src/core/mainloop/mainloop_pubsub.h b/src/core/mainloop/mainloop_pubsub.h
index 365a3dd565..3698fd8d03 100644
--- a/src/core/mainloop/mainloop_pubsub.h
+++ b/src/core/mainloop/mainloop_pubsub.h
@@ -1,17 +1,54 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file mainloop_pubsub.h
+ * @brief Header for mainloop_pubsub.c
+ **/
+
#ifndef TOR_MAINLOOP_PUBSUB_H
#define TOR_MAINLOOP_PUBSUB_H
struct pubsub_builder_t;
+/**
+ * Describe when and how messages are delivered on message channel.
+ *
+ * Every message channel must be associated with one of these strategies.
+ **/
typedef enum {
+ /**
+ * Never deliver messages automatically.
+ *
+ * If a message channel uses this strategy, then no matter now many
+ * messages are published on it, they are not delivered until something
+ * manually calls dispatch_flush() for that channel
+ **/
DELIV_NEVER=0,
+ /**
+ * Deliver messages promptly, via the event loop.
+ *
+ * If a message channel uses this strategy, then publishing a messages
+ * that channel activates an event that causes messages to be handled
+ * later in the mainloop. The messages will be processed at some point
+ * very soon, delaying only for pending IO events and the like.
+ *
+ * Generally this is the best choice for a delivery strategy, since
+ * it avoids stack explosion.
+ **/
DELIV_PROMPT,
+ /**
+ * Deliver messages immediately, skipping the event loop.
+ *
+ * Every event on this channel is flushed immediately after it is queued,
+ * using the stack.
+ *
+ * This delivery type should be used with caution, since it can cause
+ * unexpected call chains, resource starvation, and the like.
+ **/
DELIV_IMMEDIATE,
} deliv_strategy_t;
diff --git a/src/core/mainloop/mainloop_state.inc b/src/core/mainloop/mainloop_state.inc
new file mode 100644
index 0000000000..34a37caaa2
--- /dev/null
+++ b/src/core/mainloop/mainloop_state.inc
@@ -0,0 +1,19 @@
+
+/**
+ * @file mainloop_state.inc
+ * @brief Declare configuration options for the crypto_ops module.
+ **/
+
+/** Holds state for the mainloop, corresponding to part of the state
+ * file in Tor's DataDirectory. */
+BEGIN_CONF_STRUCT(mainloop_state_t)
+
+/** Number of minutes since the last user-initiated request (as defined by
+ * the dormant net-status system.) Set to zero if we are dormant. */
+CONF_VAR(MinutesSinceUserActivity, POSINT, 0, NULL)
+
+/** True if we were dormant when we last wrote the file; false if we
+ * weren't. "auto" on initial startup. */
+CONF_VAR(Dormant, AUTOBOOL, 0, "auto")
+
+END_CONF_STRUCT(mainloop_state_t)
diff --git a/src/core/mainloop/mainloop_state_st.h b/src/core/mainloop/mainloop_state_st.h
new file mode 100644
index 0000000000..5649b536f9
--- /dev/null
+++ b/src/core/mainloop/mainloop_state_st.h
@@ -0,0 +1,23 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file mainloop_state_st.h
+ * @brief Declare a state structure for mainloop-relevant fields
+ **/
+
+#ifndef TOR_CORE_MAINLOOP_MAINLOOP_STATE_ST_H
+#define TOR_CORE_MAINLOOP_MAINLOOP_STATE_ST_H
+
+#include "lib/conf/confdecl.h"
+
+#define CONF_CONTEXT STRUCT
+#include "core/mainloop/mainloop_state.inc"
+#undef CONF_CONTEXT
+
+typedef struct mainloop_state_t mainloop_state_t;
+
+#endif /* !defined(TOR_CORE_MAINLOOP_MAINLOOP_STATE_ST_H) */
diff --git a/src/core/mainloop/mainloop_sys.c b/src/core/mainloop/mainloop_sys.c
index fbd5a40327..4b78c90b96 100644
--- a/src/core/mainloop/mainloop_sys.c
+++ b/src/core/mainloop/mainloop_sys.c
@@ -1,12 +1,21 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file mainloop_sys.c
+ * @brief Declare the "mainloop" subsystem.
+ **/
+
#include "core/or/or.h"
#include "core/mainloop/mainloop_sys.h"
#include "core/mainloop/mainloop.h"
+#include "core/mainloop/mainloop_state_st.h"
+#include "core/mainloop/netstatus.h"
+#include "lib/conf/conftypes.h"
+#include "lib/conf/confdecl.h"
#include "lib/subsys/subsys.h"
@@ -23,10 +32,58 @@ subsys_mainloop_shutdown(void)
tor_mainloop_free_all();
}
+/** Declare a list of state variables for mainloop state. */
+#define CONF_CONTEXT TABLE
+#include "core/mainloop/mainloop_state.inc"
+#undef CONF_CONTEXT
+
+/** Magic number for mainloop state objects */
+#define MAINLOOP_STATE_MAGIC 0x59455449
+
+/**
+ * Format object for mainloop state.
+ **/
+static config_format_t mainloop_state_fmt = {
+ .size = sizeof(mainloop_state_t),
+ .magic = { "mainloop_state",
+ MAINLOOP_STATE_MAGIC,
+ offsetof(mainloop_state_t, magic)
+ },
+ .vars = mainloop_state_t_vars,
+};
+
+/**
+ */
+static int
+mainloop_set_state(void *arg)
+{
+ const mainloop_state_t *state = arg;
+ tor_assert(state->magic == MAINLOOP_STATE_MAGIC);
+
+ netstatus_load_from_state(state, approx_time());
+
+ return 0;
+}
+
+static int
+mainloop_flush_state(void *arg)
+{
+ mainloop_state_t *state = arg;
+ tor_assert(state->magic == MAINLOOP_STATE_MAGIC);
+
+ netstatus_flush_to_state(state, approx_time());
+
+ return 0;
+}
+
const struct subsys_fns_t sys_mainloop = {
.name = "mainloop",
.supported = true,
.level = 5,
.initialize = subsys_mainloop_initialize,
.shutdown = subsys_mainloop_shutdown,
+
+ .state_format = &mainloop_state_fmt,
+ .set_state = mainloop_set_state,
+ .flush_state = mainloop_flush_state,
};
diff --git a/src/core/mainloop/mainloop_sys.h b/src/core/mainloop/mainloop_sys.h
index fa74fe5d4b..b3ade33cd1 100644
--- a/src/core/mainloop/mainloop_sys.h
+++ b/src/core/mainloop/mainloop_sys.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file mainloop_sys.h
+ * @brief Header for mainloop_sys.c
+ **/
+
#ifndef MAINLOOP_SYS_H
#define MAINLOOP_SYS_H
diff --git a/src/core/mainloop/netstatus.c b/src/core/mainloop/netstatus.c
index 4924888598..61a3469eaa 100644
--- a/src/core/mainloop/netstatus.c
+++ b/src/core/mainloop/netstatus.c
@@ -1,12 +1,18 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file netstatus.c
+ * @brief Track whether the network is disabled, dormant, etc.
+ **/
+
#include "core/or/or.h"
#include "core/mainloop/netstatus.h"
#include "core/mainloop/mainloop.h"
+#include "core/mainloop/mainloop_state_st.h"
#include "app/config/config.h"
#include "feature/hibernate/hibernate.h"
@@ -110,7 +116,7 @@ is_participating_on_network(void)
* Update 'state' with the last time at which we were active on the network.
**/
void
-netstatus_flush_to_state(or_state_t *state, time_t now)
+netstatus_flush_to_state(mainloop_state_t *state, time_t now)
{
state->Dormant = ! participating_on_network;
if (participating_on_network) {
@@ -125,7 +131,7 @@ netstatus_flush_to_state(or_state_t *state, time_t now)
* Update our current view of network participation from an or_state_t object.
**/
void
-netstatus_load_from_state(const or_state_t *state, time_t now)
+netstatus_load_from_state(const mainloop_state_t *state, time_t now)
{
time_t last_activity;
if (state->Dormant == -1) { // Initial setup.
diff --git a/src/core/mainloop/netstatus.h b/src/core/mainloop/netstatus.h
index e8469ff558..5f54e54553 100644
--- a/src/core/mainloop/netstatus.h
+++ b/src/core/mainloop/netstatus.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file netstatus.h
+ * @brief Header for netstatus.c
+ **/
+
#ifndef TOR_NETSTATUS_H
#define TOR_NETSTATUS_H
@@ -17,8 +22,11 @@ time_t get_last_user_activity_time(void);
void set_network_participation(bool participation);
bool is_participating_on_network(void);
-void netstatus_flush_to_state(or_state_t *state, time_t now);
-void netstatus_load_from_state(const or_state_t *state, time_t now);
+struct mainloop_state_t;
+
+void netstatus_flush_to_state(struct mainloop_state_t *state, time_t now);
+void netstatus_load_from_state(const struct mainloop_state_t *state,
+ time_t now);
void netstatus_note_clock_jumped(time_t seconds_diff);
#endif /* !defined(TOR_NETSTATUS_H) */
diff --git a/src/core/mainloop/periodic.c b/src/core/mainloop/periodic.c
index 5c2f6f2b36..b5fd8fab61 100644
--- a/src/core/mainloop/periodic.c
+++ b/src/core/mainloop/periodic.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2019, The Tor Project, Inc. */
+/* Copyright (c) 2015-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -29,7 +29,6 @@
#include "app/config/config.h"
#include "core/mainloop/mainloop.h"
#include "core/mainloop/periodic.h"
-#include "lib/evloop/compat_libevent.h"
/** We disable any interval greater than this number of seconds, on the
* grounds that it is probably an absolute time mistakenly passed in as a
@@ -39,7 +38,7 @@ static const int MAX_INTERVAL = 10 * 365 * 86400;
/**
* Global list of periodic events that have been registered with
- * <b>periodic_event_register</a>.
+ * <b>periodic_event_register</b>.
**/
static smartlist_t *the_periodic_events = NULL;
diff --git a/src/core/mainloop/periodic.h b/src/core/mainloop/periodic.h
index a9aa461969..de556a6bdb 100644
--- a/src/core/mainloop/periodic.h
+++ b/src/core/mainloop/periodic.h
@@ -1,6 +1,11 @@
-/* Copyright (c) 2015-2019, The Tor Project, Inc. */
+/* Copyright (c) 2015-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file periodic.h
+ * @brief Header for periodic.c
+ **/
+
#ifndef TOR_PERIODIC_H
#define TOR_PERIODIC_H
@@ -71,8 +76,10 @@ typedef struct periodic_event_item_t {
} periodic_event_item_t;
/** events will get their interval from first execution */
+#ifndef COCCI
#define PERIODIC_EVENT(fn, r, f) { fn##_callback, 0, NULL, #fn, r, f, 0 }
#define END_OF_PERIODIC_EVENTS { NULL, 0, NULL, NULL, 0, 0, 0 }
+#endif
/* Return true iff the given event was setup before thus is enabled to be
* scheduled. */
diff --git a/src/core/or/.may_include b/src/core/or/.may_include
index 5173e8a2b6..beb12f155d 100644
--- a/src/core/or/.may_include
+++ b/src/core/or/.may_include
@@ -35,4 +35,6 @@ trunnel/*.h
core/mainloop/*.h
core/proto/*.h
core/crypto/*.h
-core/or/*.h \ No newline at end of file
+core/or/*.h
+
+ext/*.h
diff --git a/src/core/or/addr_policy_st.h b/src/core/or/addr_policy_st.h
index 11442d29b4..5a2b7f6fb3 100644
--- a/src/core/or/addr_policy_st.h
+++ b/src/core/or/addr_policy_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file addr_policy_st.h
+ * @brief Address policy structures.
+ **/
+
#ifndef TOR_ADDR_POLICY_ST_H
#define TOR_ADDR_POLICY_ST_H
diff --git a/src/core/or/address_set.c b/src/core/or/address_set.c
index 758fba4aac..d618ffc3d6 100644
--- a/src/core/or/address_set.c
+++ b/src/core/or/address_set.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -17,7 +17,7 @@
#include "lib/crypt_ops/crypto_rand.h"
#include "siphash.h"
-/* Wrap our hash function to have the signature that the bloom filter
+/** Wrap our hash function to have the signature that the bloom filter
* needs. */
static uint64_t
bloomfilt_addr_hash(const struct sipkey *key,
diff --git a/src/core/or/address_set.h b/src/core/or/address_set.h
index 95608a9a53..33887a7c9e 100644
--- a/src/core/or/address_set.h
+++ b/src/core/or/address_set.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/cell_queue_st.h b/src/core/or/cell_queue_st.h
index 7ba339b965..0681dba1b8 100644
--- a/src/core/or/cell_queue_st.h
+++ b/src/core/or/cell_queue_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file cell_queue_st.h
+ * @brief Cell queue structures
+ **/
+
#ifndef PACKED_CELL_ST_H
#define PACKED_CELL_ST_H
@@ -22,7 +27,7 @@ struct packed_cell_t {
* or_connection_t's outbuf. */
struct cell_queue_t {
/** Linked list of packed_cell_t*/
- TOR_SIMPLEQ_HEAD(cell_simpleq, packed_cell_t) head;
+ TOR_SIMPLEQ_HEAD(cell_simpleq_t, packed_cell_t) head;
int n; /**< The number of cells in the queue. */
};
diff --git a/src/core/or/cell_st.h b/src/core/or/cell_st.h
index c4eec4f4b5..a640d6a456 100644
--- a/src/core/or/cell_st.h
+++ b/src/core/or/cell_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file cell_st.h
+ * @brief Fixed-size cell structure.
+ **/
+
#ifndef CELL_ST_H
#define CELL_ST_H
@@ -17,4 +22,3 @@ struct cell_t {
};
#endif /* !defined(CELL_ST_H) */
-
diff --git a/src/core/or/channel.c b/src/core/or/channel.c
index 596932b008..18940bd81f 100644
--- a/src/core/or/channel.c
+++ b/src/core/or/channel.c
@@ -1,5 +1,5 @@
-/* * Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -52,10 +52,10 @@
* Define this so channel.h gives us things only channel_t subclasses
* should touch.
*/
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
/* This one's for stuff only channel.c and the test suite should see */
-#define CHANNEL_PRIVATE_
+#define CHANNEL_FILE_PRIVATE
#include "core/or/or.h"
#include "app/config/config.h"
@@ -106,7 +106,7 @@ static smartlist_t *finished_listeners = NULL;
/** Map from channel->global_identifier to channel. Contains the same
* elements as all_channels. */
-static HT_HEAD(channel_gid_map, channel_s) channel_gid_map = HT_INITIALIZER();
+static HT_HEAD(channel_gid_map, channel_t) channel_gid_map = HT_INITIALIZER();
static unsigned
channel_id_hash(const channel_t *chan)
@@ -118,13 +118,13 @@ channel_id_eq(const channel_t *a, const channel_t *b)
{
return a->global_identifier == b->global_identifier;
}
-HT_PROTOTYPE(channel_gid_map, channel_s, gidmap_node,
+HT_PROTOTYPE(channel_gid_map, channel_t, gidmap_node,
channel_id_hash, channel_id_eq)
-HT_GENERATE2(channel_gid_map, channel_s, gidmap_node,
+HT_GENERATE2(channel_gid_map, channel_t, gidmap_node,
channel_id_hash, channel_id_eq,
0.6, tor_reallocarray_, tor_free_)
-HANDLE_IMPL(channel, channel_s,)
+HANDLE_IMPL(channel, channel_t,)
/* Counter for ID numbers */
static uint64_t n_channels_allocated = 0;
@@ -137,13 +137,13 @@ static uint64_t n_channels_allocated = 0;
* If more than one channel exists, follow the next_with_same_id pointer
* as a linked list.
*/
-static HT_HEAD(channel_idmap, channel_idmap_entry_s) channel_identity_map =
+static HT_HEAD(channel_idmap, channel_idmap_entry_t) channel_identity_map =
HT_INITIALIZER();
-typedef struct channel_idmap_entry_s {
- HT_ENTRY(channel_idmap_entry_s) node;
+typedef struct channel_idmap_entry_t {
+ HT_ENTRY(channel_idmap_entry_t) node;
uint8_t digest[DIGEST_LEN];
- TOR_LIST_HEAD(channel_list_s, channel_s) channel_list;
+ TOR_LIST_HEAD(channel_list_t, channel_t) channel_list;
} channel_idmap_entry_t;
static inline unsigned
@@ -159,9 +159,9 @@ channel_idmap_eq(const channel_idmap_entry_t *a,
return tor_memeq(a->digest, b->digest, DIGEST_LEN);
}
-HT_PROTOTYPE(channel_idmap, channel_idmap_entry_s, node, channel_idmap_hash,
+HT_PROTOTYPE(channel_idmap, channel_idmap_entry_t, node, channel_idmap_hash,
channel_idmap_eq)
-HT_GENERATE2(channel_idmap, channel_idmap_entry_s, node, channel_idmap_hash,
+HT_GENERATE2(channel_idmap, channel_idmap_entry_t, node, channel_idmap_hash,
channel_idmap_eq, 0.5, tor_reallocarray_, tor_free_)
/* Functions to maintain the digest map */
@@ -1067,23 +1067,6 @@ channel_get_cell_handler(channel_t *chan)
}
/**
- * Return the variable-length cell handler for a channel.
- *
- * This function gets the handler for incoming variable-length cells
- * installed on a channel.
- */
-channel_var_cell_handler_fn_ptr
-channel_get_var_cell_handler(channel_t *chan)
-{
- tor_assert(chan);
-
- if (CHANNEL_CAN_HANDLE_CELLS(chan))
- return chan->var_cell_handler;
-
- return NULL;
-}
-
-/**
* Set both cell handlers for a channel.
*
* This function sets both the fixed-length and variable length cell handlers
@@ -1091,9 +1074,7 @@ channel_get_var_cell_handler(channel_t *chan)
*/
void
channel_set_cell_handlers(channel_t *chan,
- channel_cell_handler_fn_ptr cell_handler,
- channel_var_cell_handler_fn_ptr
- var_cell_handler)
+ channel_cell_handler_fn_ptr cell_handler)
{
tor_assert(chan);
tor_assert(CHANNEL_CAN_HANDLE_CELLS(chan));
@@ -1101,13 +1082,9 @@ channel_set_cell_handlers(channel_t *chan,
log_debug(LD_CHANNEL,
"Setting cell_handler callback for channel %p to %p",
chan, cell_handler);
- log_debug(LD_CHANNEL,
- "Setting var_cell_handler callback for channel %p to %p",
- chan, var_cell_handler);
/* Change them */
chan->cell_handler = cell_handler;
- chan->var_cell_handler = var_cell_handler;
}
/*
@@ -3406,7 +3383,7 @@ channel_sort_by_ed25519_identity(const void **a_, const void **b_)
* all of which MUST have the same RSA ID. (They MAY have different
* Ed25519 IDs.) */
static void
-channel_rsa_id_group_set_badness(struct channel_list_s *lst, int force)
+channel_rsa_id_group_set_badness(struct channel_list_t *lst, int force)
{
/*XXXX This function should really be about channels. 15056 */
channel_t *chan = TOR_LIST_FIRST(lst);
diff --git a/src/core/or/channel.h b/src/core/or/channel.h
index 97aa000337..2e2936a69a 100644
--- a/src/core/or/channel.h
+++ b/src/core/or/channel.h
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,6 +14,7 @@
#include "lib/container/handles.h"
#include "lib/crypt_ops/crypto_ed25519.h"
+#include "ext/ht.h"
#include "tor_queue.h"
#define tor_timer_t timeout
@@ -22,7 +23,6 @@ struct tor_timer_t;
/* Channel handler function pointer typedefs */
typedef void (*channel_listener_fn_ptr)(channel_listener_t *, channel_t *);
typedef void (*channel_cell_handler_fn_ptr)(channel_t *, cell_t *);
-typedef void (*channel_var_cell_handler_fn_ptr)(channel_t *, var_cell_t *);
/**
* This enum is used by channelpadding to decide when to pad channels.
@@ -48,7 +48,7 @@ typedef enum {
/* channel states for channel_t */
typedef enum {
- /*
+ /**
* Closed state - channel is inactive
*
* Permitted transitions from:
@@ -57,7 +57,7 @@ typedef enum {
* - CHANNEL_STATE_OPENING
*/
CHANNEL_STATE_CLOSED = 0,
- /*
+ /**
* Opening state - channel is trying to connect
*
* Permitted transitions from:
@@ -68,7 +68,7 @@ typedef enum {
* - CHANNEL_STATE_OPEN
*/
CHANNEL_STATE_OPENING,
- /*
+ /**
* Open state - channel is active and ready for use
*
* Permitted transitions from:
@@ -80,7 +80,7 @@ typedef enum {
* - CHANNEL_STATE_MAINT
*/
CHANNEL_STATE_OPEN,
- /*
+ /**
* Maintenance state - channel is temporarily offline for subclass specific
* maintenance activities such as TLS renegotiation.
*
@@ -92,7 +92,7 @@ typedef enum {
* - CHANNEL_STATE_OPEN
*/
CHANNEL_STATE_MAINT,
- /*
+ /**
* Closing state - channel is shutting down
*
* Permitted transitions from:
@@ -103,7 +103,7 @@ typedef enum {
* - CHANNEL_STATE_ERROR
*/
CHANNEL_STATE_CLOSING,
- /*
+ /**
* Error state - channel has experienced a permanent error
*
* Permitted transitions from:
@@ -115,7 +115,7 @@ typedef enum {
* - None
*/
CHANNEL_STATE_ERROR,
- /*
+ /**
* Placeholder for maximum state value
*/
CHANNEL_STATE_LAST
@@ -124,7 +124,7 @@ typedef enum {
/* channel listener states for channel_listener_t */
typedef enum {
- /*
+ /**
* Closed state - channel listener is inactive
*
* Permitted transitions from:
@@ -133,7 +133,7 @@ typedef enum {
* - CHANNEL_LISTENER_STATE_LISTENING
*/
CHANNEL_LISTENER_STATE_CLOSED = 0,
- /*
+ /**
* Listening state - channel listener is listening for incoming
* connections
*
@@ -144,7 +144,7 @@ typedef enum {
* - CHANNEL_LISTENER_STATE_ERROR
*/
CHANNEL_LISTENER_STATE_LISTENING,
- /*
+ /**
* Closing state - channel listener is shutting down
*
* Permitted transitions from:
@@ -154,7 +154,7 @@ typedef enum {
* - CHANNEL_LISTENER_STATE_ERROR
*/
CHANNEL_LISTENER_STATE_CLOSING,
- /*
+ /**
* Error state - channel listener has experienced a permanent error
*
* Permitted transitions from:
@@ -164,7 +164,7 @@ typedef enum {
* - None
*/
CHANNEL_LISTENER_STATE_ERROR,
- /*
+ /**
* Placeholder for maximum state value
*/
CHANNEL_LISTENER_STATE_LAST
@@ -178,15 +178,15 @@ typedef enum {
* to a particular node, and once constructed support the abstract operations
* defined below.
*/
-struct channel_s {
+struct channel_t {
/** Magic number for type-checking cast macros */
uint32_t magic;
/** List entry for hashtable for global-identifier lookup. */
- HT_ENTRY(channel_s) gidmap_node;
+ HT_ENTRY(channel_t) gidmap_node;
/** Handle entry for handle-based lookup */
- HANDLE_ENTRY(channel, channel_s);
+ HANDLE_ENTRY(channel, channel_t);
/** Current channel state */
channel_state_t state;
@@ -267,21 +267,21 @@ struct channel_s {
/** State variable for use by the scheduler */
enum {
- /*
+ /**
* The channel is not open, or it has a full output buffer but no queued
* cells.
*/
SCHED_CHAN_IDLE = 0,
- /*
+ /**
* The channel has space on its output buffer to write, but no queued
* cells.
*/
SCHED_CHAN_WAITING_FOR_CELLS,
- /*
+ /**
* The scheduler has queued cells but no output buffer space to write.
*/
SCHED_CHAN_WAITING_TO_WRITE,
- /*
+ /**
* The scheduler has both queued cells and output buffer space, and is
* eligible for the scheduler loop.
*/
@@ -320,7 +320,6 @@ struct channel_s {
/** Registered handlers for incoming cells */
channel_cell_handler_fn_ptr cell_handler;
- channel_var_cell_handler_fn_ptr var_cell_handler;
/* Methods implemented by the lower layer */
@@ -397,7 +396,7 @@ struct channel_s {
* Linked list of channels with the same RSA identity digest, for use with
* the digest->channel map
*/
- TOR_LIST_ENTRY(channel_s) next_with_same_id;
+ TOR_LIST_ENTRY(channel_t) next_with_same_id;
/** Circuit mux for circuits sending on this channel */
circuitmux_t *cmux;
@@ -444,9 +443,9 @@ struct channel_s {
ratelim_t last_warned_circ_ids_exhausted;
/** Channel timestamps for cell channels */
- time_t timestamp_client; /* Client used this, according to relay.c */
- time_t timestamp_recv; /* Cell received from lower layer */
- time_t timestamp_xmit; /* Cell sent to lower layer */
+ time_t timestamp_client; /*(< Client used this, according to relay.c */
+ time_t timestamp_recv; /**< Cell received from lower layer */
+ time_t timestamp_xmit; /**< Cell sent to lower layer */
/** Timestamp for run_connection_housekeeping(). We update this once a
* second when we run housekeeping and find a circuit on this channel, and
@@ -458,16 +457,17 @@ struct channel_s {
* distinct namespace. */
uint64_t dirreq_id;
- /** Channel counters for cell channels */
+ /** Channel counters for cells and bytes we have received. */
uint64_t n_cells_recved, n_bytes_recved;
+ /** Channel counters for cells and bytes we have sent. */
uint64_t n_cells_xmitted, n_bytes_xmitted;
};
-struct channel_listener_s {
- /* Current channel listener state */
+struct channel_listener_t {
+ /** Current channel listener state */
channel_listener_state_t state;
- /* Globally unique ID number for a channel over the lifetime of a Tor
+ /** Globally unique ID number for a channel over the lifetime of a Tor
* process.
*/
uint64_t global_identifier;
@@ -541,13 +541,8 @@ void channel_listener_set_listener_fn(channel_listener_t *chan,
/* Incoming cell callbacks */
channel_cell_handler_fn_ptr channel_get_cell_handler(channel_t *chan);
-channel_var_cell_handler_fn_ptr
-channel_get_var_cell_handler(channel_t *chan);
-
void channel_set_cell_handlers(channel_t *chan,
- channel_cell_handler_fn_ptr cell_handler,
- channel_var_cell_handler_fn_ptr
- var_cell_handler);
+ channel_cell_handler_fn_ptr cell_handler);
/* Clean up closed channels and channel listeners periodically; these are
* called from run_scheduled_events() in main.c.
@@ -562,13 +557,13 @@ void channel_free_all(void);
void channel_dumpstats(int severity);
void channel_listener_dumpstats(int severity);
-#ifdef TOR_CHANNEL_INTERNAL_
+#ifdef CHANNEL_OBJECT_PRIVATE
-#ifdef CHANNEL_PRIVATE_
+#ifdef CHANNEL_FILE_PRIVATE
STATIC void channel_add_to_digest_map(channel_t *chan);
-#endif /* defined(CHANNEL_PRIVATE_) */
+#endif /* defined(CHANNEL_FILE_PRIVATE) */
/* Channel operations for subclasses and internal use only */
@@ -647,7 +642,7 @@ void channel_notify_flushed(channel_t *chan);
/* Handle stuff we need to do on open like notifying circuits */
void channel_do_open_actions(channel_t *chan);
-#endif /* defined(TOR_CHANNEL_INTERNAL_) */
+#endif /* defined(CHANNEL_OBJECT_PRIVATE) */
/* Helper functions to perform operations on channels */
@@ -772,7 +767,7 @@ int packed_cell_is_destroy(channel_t *chan,
circid_t *circid_out);
/* Declare the handle helpers */
-HANDLE_DECL(channel, channel_s,)
+HANDLE_DECL(channel, channel_t,)
#define channel_handle_free(h) \
FREE_AND_NULL(channel_handle_t, channel_handle_free_, (h))
#undef tor_timer_t
diff --git a/src/core/or/channelpadding.c b/src/core/or/channelpadding.c
index 4a0f0e00da..be2ce78a17 100644
--- a/src/core/or/channelpadding.c
+++ b/src/core/or/channelpadding.c
@@ -1,12 +1,17 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-/* TOR_CHANNEL_INTERNAL_ define needed for an O(1) implementation of
+/**
+ * @file channelpadding.c
+ * @brief Link-level padding code.
+ **/
+
+/* CHANNEL_OBJECT_PRIVATE define needed for an O(1) implementation of
* channelpadding_channel_to_channelinfo() */
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#include "core/or/or.h"
#include "core/or/channel.h"
diff --git a/src/core/or/channelpadding.h b/src/core/or/channelpadding.h
index 48002eedb7..d1c7192ffd 100644
--- a/src/core/or/channelpadding.h
+++ b/src/core/or/channelpadding.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/channeltls.c b/src/core/or/channeltls.c
index d6c9e21631..efa8e2d891 100644
--- a/src/core/or/channeltls.c
+++ b/src/core/or/channeltls.c
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -34,7 +34,7 @@
* Define this so channel.h gives us things only channel_t subclasses
* should touch.
*/
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define CHANNELTLS_PRIVATE
@@ -563,7 +563,8 @@ channel_tls_get_transport_name_method(channel_t *chan, char **transport_out)
static const char *
channel_tls_get_remote_descr_method(channel_t *chan, int flags)
{
-#define MAX_DESCR_LEN 32
+ /* IPv6 address, colon, port */
+#define MAX_DESCR_LEN (TOR_ADDR_BUF_LEN + 1 + 5)
static char buf[MAX_DESCR_LEN + 1];
channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan);
diff --git a/src/core/or/channeltls.h b/src/core/or/channeltls.h
index 634a2a00e9..f04ce0fa9c 100644
--- a/src/core/or/channeltls.h
+++ b/src/core/or/channeltls.h
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -22,16 +22,16 @@ struct curve25519_public_key_t;
#define TLS_CHAN_MAGIC 0x8a192427U
-#ifdef TOR_CHANNEL_INTERNAL_
+#ifdef CHANNEL_OBJECT_PRIVATE
-struct channel_tls_s {
+struct channel_tls_t {
/* Base channel_t struct */
channel_t base_;
/* or_connection_t pointer */
or_connection_t *conn;
};
-#endif /* defined(TOR_CHANNEL_INTERNAL_) */
+#endif /* defined(CHANNEL_OBJECT_PRIVATE) */
channel_t * channel_tls_connect(const tor_addr_t *addr, uint16_t port,
const char *id_digest,
diff --git a/src/core/or/circuit_st.h b/src/core/or/circuit_st.h
index eae3c908d5..4baafb1848 100644
--- a/src/core/or/circuit_st.h
+++ b/src/core/or/circuit_st.h
@@ -1,15 +1,23 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file circuit_st.h
+ * @brief Base circuit structure.
+ **/
+
#ifndef CIRCUIT_ST_H
#define CIRCUIT_ST_H
#include "core/or/or.h"
+#include "lib/container/handles.h"
+
#include "core/or/cell_queue_st.h"
+#include "ext/ht.h"
struct hs_token_t;
struct circpad_machine_spec_t;
@@ -54,6 +62,9 @@ struct circuit_t {
uint32_t magic; /**< For memory and type debugging: must equal
* ORIGIN_CIRCUIT_MAGIC or OR_CIRCUIT_MAGIC. */
+ /** Handle entry for handle-based lookup */
+ HANDLE_ENTRY(circuit, circuit_t);
+
/** The channel that is next in this circuit. */
channel_t *n_chan;
diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c
index 16bb7e7d79..4865d05d98 100644
--- a/src/core/or/circuitbuild.c
+++ b/src/core/or/circuitbuild.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -30,7 +30,7 @@
#include "core/or/or.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "core/crypto/hs_ntor.h"
#include "core/crypto/onion_crypto.h"
#include "core/crypto/onion_fast.h"
diff --git a/src/core/or/circuitbuild.h b/src/core/or/circuitbuild.h
index ad7d032cd4..f5a3439064 100644
--- a/src/core/or/circuitbuild.h
+++ b/src/core/or/circuitbuild.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/circuitlist.c b/src/core/or/circuitlist.c
index 4102cf3d4c..96cc718029 100644
--- a/src/core/or/circuitlist.c
+++ b/src/core/or/circuitlist.c
@@ -1,7 +1,7 @@
/* Copyright 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -99,7 +99,6 @@
#include "lib/compress/compress_zstd.h"
#include "lib/buf/buffers.h"
-#define OCIRC_EVENT_PRIVATE
#include "core/or/ocirc_event.h"
#include "ht.h"
@@ -147,6 +146,9 @@ static int any_opened_circs_cached_val = 0;
/********* END VARIABLES ************/
+/* Implement circuit handle helpers. */
+HANDLE_IMPL(circuit, circuit_t,)
+
or_circuit_t *
TO_OR_CIRCUIT(circuit_t *x)
{
@@ -1134,7 +1136,7 @@ circuit_free_(circuit_t *circ)
* circuit is closed. This is to avoid any code path that free registered
* circuits without closing them before. This needs to be done before the
* hs identifier is freed. */
- hs_circ_cleanup(circ);
+ hs_circ_cleanup_on_free(circ);
if (CIRCUIT_IS_ORIGIN(circ)) {
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
@@ -1247,6 +1249,9 @@ circuit_free_(circuit_t *circ)
/* Free any circuit padding structures */
circpad_circuit_free_all_machineinfos(circ);
+ /* Clear all dangling handle references. */
+ circuit_handles_clear(circ);
+
if (should_free) {
memwipe(mem, 0xAA, memlen); /* poison memory */
tor_free(mem);
@@ -2255,7 +2260,7 @@ circuit_mark_for_close_, (circuit_t *circ, int reason, int line,
}
/* Notify the HS subsystem that this circuit is closing. */
- hs_circ_cleanup(circ);
+ hs_circ_cleanup_on_close(circ);
if (circuits_pending_close == NULL)
circuits_pending_close = smartlist_new();
@@ -2337,43 +2342,6 @@ circuit_about_to_free(circuit_t *circ)
orig_reason);
}
- if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
- origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
- int timed_out = (reason == END_CIRC_REASON_TIMEOUT);
- tor_assert(circ->state == CIRCUIT_STATE_OPEN);
- tor_assert(ocirc->build_state->chosen_exit);
- if (orig_reason != END_CIRC_REASON_IP_NOW_REDUNDANT &&
- ocirc->rend_data) {
- /* treat this like getting a nack from it */
- log_info(LD_REND, "Failed intro circ %s to %s (awaiting ack). %s",
- safe_str_client(rend_data_get_address(ocirc->rend_data)),
- safe_str_client(build_state_get_exit_nickname(ocirc->build_state)),
- timed_out ? "Recording timeout." : "Removing from descriptor.");
- rend_client_report_intro_point_failure(ocirc->build_state->chosen_exit,
- ocirc->rend_data,
- timed_out ?
- INTRO_POINT_FAILURE_TIMEOUT :
- INTRO_POINT_FAILURE_GENERIC);
- }
- } else if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCING &&
- reason != END_CIRC_REASON_TIMEOUT) {
- origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
- if (ocirc->build_state->chosen_exit && ocirc->rend_data) {
- if (orig_reason != END_CIRC_REASON_IP_NOW_REDUNDANT &&
- ocirc->rend_data) {
- log_info(LD_REND, "Failed intro circ %s to %s "
- "(building circuit to intro point). "
- "Marking intro point as possibly unreachable.",
- safe_str_client(rend_data_get_address(ocirc->rend_data)),
- safe_str_client(build_state_get_exit_nickname(
- ocirc->build_state)));
- rend_client_report_intro_point_failure(ocirc->build_state->chosen_exit,
- ocirc->rend_data,
- INTRO_POINT_FAILURE_UNREACHABLE);
- }
- }
- }
-
if (circ->n_chan) {
circuit_clear_cell_queue(circ, circ->n_chan);
/* Only send destroy if the channel isn't closing anyway */
diff --git a/src/core/or/circuitlist.h b/src/core/or/circuitlist.h
index 80c1f7ac4e..fd7e22e4c0 100644
--- a/src/core/or/circuitlist.h
+++ b/src/core/or/circuitlist.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,6 +12,7 @@
#ifndef TOR_CIRCUITLIST_H
#define TOR_CIRCUITLIST_H
+#include "lib/container/handles.h"
#include "lib/testsupport/testsupport.h"
#include "feature/hs/hs_ident.h"
#include "core/or/ocirc_event.h"
@@ -242,6 +243,11 @@ MOCK_DECL(void, channel_note_destroy_not_pending,
smartlist_t *circuit_find_circuits_to_upgrade_from_guard_wait(void);
+/* Declare the handle helpers */
+HANDLE_DECL(circuit, circuit_t, )
+#define circuit_handle_free(h) \
+ FREE_AND_NULL(circuit_handle_t, circuit_handle_free_, (h))
+
#ifdef CIRCUITLIST_PRIVATE
STATIC void circuit_free_(circuit_t *circ);
#define circuit_free(circ) FREE_AND_NULL(circuit_t, circuit_free_, (circ))
diff --git a/src/core/or/circuitmux.c b/src/core/or/circuitmux.c
index 4b19a12e3c..da95e93657 100644
--- a/src/core/or/circuitmux.c
+++ b/src/core/or/circuitmux.c
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -69,14 +69,14 @@
* made to attach all existing circuits to the new policy.
**/
+#define CIRCUITMUX_PRIVATE
+
#include "core/or/or.h"
#include "core/or/channel.h"
#include "core/or/circuitlist.h"
#include "core/or/circuitmux.h"
#include "core/or/relay.h"
-#include "core/or/cell_queue_st.h"
-#include "core/or/destroy_cell_queue_st.h"
#include "core/or/or_circuit_st.h"
#include "lib/crypt_ops/crypto_util.h"
@@ -86,12 +86,6 @@
*/
/*
- * Map of muxinfos for circuitmux_t to use; struct is defined below (name
- * of struct must match HT_HEAD line).
- */
-typedef struct chanid_circid_muxinfo_map chanid_circid_muxinfo_map_t;
-
-/*
* Hash table entry (yeah, calling it chanid_circid_muxinfo_s seems to
* break the hash table code).
*/
@@ -102,57 +96,14 @@ typedef struct chanid_circid_muxinfo_t chanid_circid_muxinfo_t;
* a count of queued cells.
*/
-typedef struct circuit_muxinfo_s circuit_muxinfo_t;
-
-/*
- * Structures for circuitmux.c
- */
-
-struct circuitmux_s {
- /* Keep count of attached, active circuits */
- unsigned int n_circuits, n_active_circuits;
-
- /* Total number of queued cells on all circuits */
- unsigned int n_cells;
-
- /*
- * Map from (channel ID, circuit ID) pairs to circuit_muxinfo_t
- */
- chanid_circid_muxinfo_map_t *chanid_circid_map;
-
- /** List of queued destroy cells */
- destroy_cell_queue_t destroy_cell_queue;
- /** Boolean: True iff the last cell to circuitmux_get_first_active_circuit
- * returned the destroy queue. Used to force alternation between
- * destroy/non-destroy cells.
- *
- * XXXX There is no reason to think that alternating is a particularly good
- * approach -- it's just designed to prevent destroys from starving other
- * cells completely.
- */
- unsigned int last_cell_was_destroy : 1;
- /** Destroy counter: increment this when a destroy gets queued, decrement
- * when we unqueue it, so we can test to make sure they don't starve.
- */
- int64_t destroy_ctr;
-
- /*
- * Circuitmux policy; if this is non-NULL, it can override the built-
- * in round-robin active circuits behavior. This is how EWMA works in
- * the new circuitmux_t world.
- */
- const circuitmux_policy_t *policy;
-
- /* Policy-specific data */
- circuitmux_policy_data_t *policy_data;
-};
+typedef struct circuit_muxinfo_t circuit_muxinfo_t;
/*
* This struct holds whatever we want to store per attached circuit on a
* circuitmux_t; right now, just the count of queued cells and the direction.
*/
-struct circuit_muxinfo_s {
+struct circuit_muxinfo_t {
/* Count of cells on this circuit at last update */
unsigned int cell_count;
/* Direction of flow */
@@ -223,9 +174,6 @@ chanid_circid_entry_hash(chanid_circid_muxinfo_t *a)
((unsigned int)(a->chan_id & 0xffffffff)));
}
-/* Declare the struct chanid_circid_muxinfo_map type */
-HT_HEAD(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t);
-
/* Emit a bunch of hash table stuff */
HT_PROTOTYPE(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t, node,
chanid_circid_entry_hash, chanid_circid_entries_eq)
diff --git a/src/core/or/circuitmux.h b/src/core/or/circuitmux.h
index 67cd9bcdd8..191ca12e30 100644
--- a/src/core/or/circuitmux.h
+++ b/src/core/or/circuitmux.h
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,11 +12,11 @@
#include "core/or/or.h"
#include "lib/testsupport/testsupport.h"
-typedef struct circuitmux_policy_s circuitmux_policy_t;
-typedef struct circuitmux_policy_data_s circuitmux_policy_data_t;
-typedef struct circuitmux_policy_circ_data_s circuitmux_policy_circ_data_t;
+typedef struct circuitmux_policy_t circuitmux_policy_t;
+typedef struct circuitmux_policy_data_t circuitmux_policy_data_t;
+typedef struct circuitmux_policy_circ_data_t circuitmux_policy_circ_data_t;
-struct circuitmux_policy_s {
+struct circuitmux_policy_t {
/* Allocate cmux-wide policy-specific data */
circuitmux_policy_data_t * (*alloc_cmux_data)(circuitmux_t *cmux);
/* Free cmux-wide policy-specific data */
@@ -67,7 +67,7 @@ struct circuitmux_policy_s {
* wide data; it just has the magic number in the base struct.
*/
-struct circuitmux_policy_data_s {
+struct circuitmux_policy_data_t {
uint32_t magic;
};
@@ -76,7 +76,7 @@ struct circuitmux_policy_data_s {
* specific data; it just has the magic number in the base struct.
*/
-struct circuitmux_policy_circ_data_s {
+struct circuitmux_policy_circ_data_t {
uint32_t magic;
};
@@ -158,5 +158,61 @@ void circuitmux_mark_destroyed_circids_usable(circuitmux_t *cmux,
MOCK_DECL(int, circuitmux_compare_muxes,
(circuitmux_t *cmux_1, circuitmux_t *cmux_2));
+#ifdef CIRCUITMUX_PRIVATE
+
+#include "core/or/destroy_cell_queue_st.h"
+
+/*
+ * Map of muxinfos for circuitmux_t to use; struct is defined below (name
+ * of struct must match HT_HEAD line).
+ */
+typedef HT_HEAD(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t)
+ chanid_circid_muxinfo_map_t;
+
+/*
+ * Structures for circuitmux.c
+ */
+
+struct circuitmux_t {
+ /* Keep count of attached, active circuits */
+ unsigned int n_circuits, n_active_circuits;
+
+ /* Total number of queued cells on all circuits */
+ unsigned int n_cells;
+
+ /*
+ * Map from (channel ID, circuit ID) pairs to circuit_muxinfo_t
+ */
+ chanid_circid_muxinfo_map_t *chanid_circid_map;
+
+ /** List of queued destroy cells */
+ destroy_cell_queue_t destroy_cell_queue;
+ /** Boolean: True iff the last cell to circuitmux_get_first_active_circuit
+ * returned the destroy queue. Used to force alternation between
+ * destroy/non-destroy cells.
+ *
+ * XXXX There is no reason to think that alternating is a particularly good
+ * approach -- it's just designed to prevent destroys from starving other
+ * cells completely.
+ */
+ unsigned int last_cell_was_destroy : 1;
+ /** Destroy counter: increment this when a destroy gets queued, decrement
+ * when we unqueue it, so we can test to make sure they don't starve.
+ */
+ int64_t destroy_ctr;
+
+ /*
+ * Circuitmux policy; if this is non-NULL, it can override the built-
+ * in round-robin active circuits behavior. This is how EWMA works in
+ * the new circuitmux_t world.
+ */
+ const circuitmux_policy_t *policy;
+
+ /* Policy-specific data */
+ circuitmux_policy_data_t *policy_data;
+};
+
+#endif /* defined(CIRCUITMUX_PRIVATE) */
+
#endif /* !defined(TOR_CIRCUITMUX_H) */
diff --git a/src/core/or/circuitmux_ewma.c b/src/core/or/circuitmux_ewma.c
index 07f83af0f1..b50f33528f 100644
--- a/src/core/or/circuitmux_ewma.c
+++ b/src/core/or/circuitmux_ewma.c
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -59,119 +59,6 @@
/** The natural logarithm of 0.5. */
#define LOG_ONEHALF -0.69314718055994529
-/*** EWMA structures ***/
-
-typedef struct cell_ewma_s cell_ewma_t;
-typedef struct ewma_policy_data_s ewma_policy_data_t;
-typedef struct ewma_policy_circ_data_s ewma_policy_circ_data_t;
-
-/**
- * The cell_ewma_t structure keeps track of how many cells a circuit has
- * transferred recently. It keeps an EWMA (exponentially weighted moving
- * average) of the number of cells flushed from the circuit queue onto a
- * connection in channel_flush_from_first_active_circuit().
- */
-
-struct cell_ewma_s {
- /** The last 'tick' at which we recalibrated cell_count.
- *
- * A cell sent at exactly the start of this tick has weight 1.0. Cells sent
- * since the start of this tick have weight greater than 1.0; ones sent
- * earlier have less weight. */
- unsigned int last_adjusted_tick;
- /** The EWMA of the cell count. */
- double cell_count;
- /** True iff this is the cell count for a circuit's previous
- * channel. */
- unsigned int is_for_p_chan : 1;
- /** The position of the circuit within the OR connection's priority
- * queue. */
- int heap_index;
-};
-
-struct ewma_policy_data_s {
- circuitmux_policy_data_t base_;
-
- /**
- * Priority queue of cell_ewma_t for circuits with queued cells waiting
- * for room to free up on the channel that owns this circuitmux. Kept
- * in heap order according to EWMA. This was formerly in channel_t, and
- * in or_connection_t before that.
- */
- smartlist_t *active_circuit_pqueue;
-
- /**
- * The tick on which the cell_ewma_ts in active_circuit_pqueue last had
- * their ewma values rescaled. This was formerly in channel_t, and in
- * or_connection_t before that.
- */
- unsigned int active_circuit_pqueue_last_recalibrated;
-};
-
-struct ewma_policy_circ_data_s {
- circuitmux_policy_circ_data_t base_;
-
- /**
- * The EWMA count for the number of cells flushed from this circuit
- * onto this circuitmux. Used to determine which circuit to flush
- * from next. This was formerly in circuit_t and or_circuit_t.
- */
- cell_ewma_t cell_ewma;
-
- /**
- * Pointer back to the circuit_t this is for; since we're separating
- * out circuit selection policy like this, we can't attach cell_ewma_t
- * to the circuit_t any more, so we can't use SUBTYPE_P directly to a
- * circuit_t like before; instead get it here.
- */
- circuit_t *circ;
-};
-
-#define EWMA_POL_DATA_MAGIC 0x2fd8b16aU
-#define EWMA_POL_CIRC_DATA_MAGIC 0x761e7747U
-
-/*** Downcasts for the above types ***/
-
-static ewma_policy_data_t *
-TO_EWMA_POL_DATA(circuitmux_policy_data_t *);
-
-static ewma_policy_circ_data_t *
-TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *);
-
-/**
- * Downcast a circuitmux_policy_data_t to an ewma_policy_data_t and assert
- * if the cast is impossible.
- */
-
-static inline ewma_policy_data_t *
-TO_EWMA_POL_DATA(circuitmux_policy_data_t *pol)
-{
- if (!pol) return NULL;
- else {
- tor_assertf(pol->magic == EWMA_POL_DATA_MAGIC,
- "Mismatch: %"PRIu32" != %"PRIu32,
- pol->magic, EWMA_POL_DATA_MAGIC);
- return DOWNCAST(ewma_policy_data_t, pol);
- }
-}
-
-/**
- * Downcast a circuitmux_policy_circ_data_t to an ewma_policy_circ_data_t
- * and assert if the cast is impossible.
- */
-
-static inline ewma_policy_circ_data_t *
-TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *pol)
-{
- if (!pol) return NULL;
- else {
- tor_assertf(pol->magic == EWMA_POL_CIRC_DATA_MAGIC,
- "Mismatch: %"PRIu32" != %"PRIu32,
- pol->magic, EWMA_POL_CIRC_DATA_MAGIC);
- return DOWNCAST(ewma_policy_circ_data_t, pol);
- }
-}
-
/*** Static declarations for circuitmux_ewma.c ***/
static void add_cell_ewma(ewma_policy_data_t *pol, cell_ewma_t *ewma);
diff --git a/src/core/or/circuitmux_ewma.h b/src/core/or/circuitmux_ewma.h
index b45ce1f916..e41cf9e0f0 100644
--- a/src/core/or/circuitmux_ewma.h
+++ b/src/core/or/circuitmux_ewma.h
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -22,9 +22,117 @@ void cmux_ewma_set_options(const or_options_t *options,
void circuitmux_ewma_free_all(void);
#ifdef CIRCUITMUX_EWMA_PRIVATE
+
+/*** EWMA structures ***/
+
+typedef struct cell_ewma_t cell_ewma_t;
+typedef struct ewma_policy_data_t ewma_policy_data_t;
+typedef struct ewma_policy_circ_data_t ewma_policy_circ_data_t;
+
+/**
+ * The cell_ewma_t structure keeps track of how many cells a circuit has
+ * transferred recently. It keeps an EWMA (exponentially weighted moving
+ * average) of the number of cells flushed from the circuit queue onto a
+ * connection in channel_flush_from_first_active_circuit().
+ */
+
+struct cell_ewma_t {
+ /** The last 'tick' at which we recalibrated cell_count.
+ *
+ * A cell sent at exactly the start of this tick has weight 1.0. Cells sent
+ * since the start of this tick have weight greater than 1.0; ones sent
+ * earlier have less weight. */
+ unsigned int last_adjusted_tick;
+ /** The EWMA of the cell count. */
+ double cell_count;
+ /** True iff this is the cell count for a circuit's previous
+ * channel. */
+ unsigned int is_for_p_chan : 1;
+ /** The position of the circuit within the OR connection's priority
+ * queue. */
+ int heap_index;
+};
+
+struct ewma_policy_data_t {
+ circuitmux_policy_data_t base_;
+
+ /**
+ * Priority queue of cell_ewma_t for circuits with queued cells waiting
+ * for room to free up on the channel that owns this circuitmux. Kept
+ * in heap order according to EWMA. This was formerly in channel_t, and
+ * in or_connection_t before that.
+ */
+ smartlist_t *active_circuit_pqueue;
+
+ /**
+ * The tick on which the cell_ewma_ts in active_circuit_pqueue last had
+ * their ewma values rescaled. This was formerly in channel_t, and in
+ * or_connection_t before that.
+ */
+ unsigned int active_circuit_pqueue_last_recalibrated;
+};
+
+struct ewma_policy_circ_data_t {
+ circuitmux_policy_circ_data_t base_;
+
+ /**
+ * The EWMA count for the number of cells flushed from this circuit
+ * onto this circuitmux. Used to determine which circuit to flush
+ * from next. This was formerly in circuit_t and or_circuit_t.
+ */
+ cell_ewma_t cell_ewma;
+
+ /**
+ * Pointer back to the circuit_t this is for; since we're separating
+ * out circuit selection policy like this, we can't attach cell_ewma_t
+ * to the circuit_t any more, so we can't use SUBTYPE_P directly to a
+ * circuit_t like before; instead get it here.
+ */
+ circuit_t *circ;
+};
+
+#define EWMA_POL_DATA_MAGIC 0x2fd8b16aU
+#define EWMA_POL_CIRC_DATA_MAGIC 0x761e7747U
+
+/*** Downcasts for the above types ***/
+
+/**
+ * Downcast a circuitmux_policy_data_t to an ewma_policy_data_t and assert
+ * if the cast is impossible.
+ */
+
+static inline ewma_policy_data_t *
+TO_EWMA_POL_DATA(circuitmux_policy_data_t *pol)
+{
+ if (!pol) return NULL;
+ else {
+ tor_assertf(pol->magic == EWMA_POL_DATA_MAGIC,
+ "Mismatch: %"PRIu32" != %"PRIu32,
+ pol->magic, EWMA_POL_DATA_MAGIC);
+ return DOWNCAST(ewma_policy_data_t, pol);
+ }
+}
+
+/**
+ * Downcast a circuitmux_policy_circ_data_t to an ewma_policy_circ_data_t
+ * and assert if the cast is impossible.
+ */
+
+static inline ewma_policy_circ_data_t *
+TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *pol)
+{
+ if (!pol) return NULL;
+ else {
+ tor_assertf(pol->magic == EWMA_POL_CIRC_DATA_MAGIC,
+ "Mismatch: %"PRIu32" != %"PRIu32,
+ pol->magic, EWMA_POL_CIRC_DATA_MAGIC);
+ return DOWNCAST(ewma_policy_circ_data_t, pol);
+ }
+}
+
STATIC unsigned cell_ewma_get_current_tick_and_fraction(double *remainder_out);
STATIC void cell_ewma_initialize_ticks(void);
-#endif
-#endif /* !defined(TOR_CIRCUITMUX_EWMA_H) */
+#endif /* defined(CIRCUITMUX_EWMA_PRIVATE) */
+#endif /* !defined(TOR_CIRCUITMUX_EWMA_H) */
diff --git a/src/core/or/circuitpadding.c b/src/core/or/circuitpadding.c
index 7f761fed6b..43f4a31624 100644
--- a/src/core/or/circuitpadding.c
+++ b/src/core/or/circuitpadding.c
@@ -116,6 +116,7 @@ STATIC smartlist_t *origin_padding_machines = NULL;
* runtime and as long as circuits are alive. */
STATIC smartlist_t *relay_padding_machines = NULL;
+#ifndef COCCI
/** Loop over the current padding state machines using <b>loop_var</b> as the
* loop variable. */
#define FOR_EACH_CIRCUIT_MACHINE_BEGIN(loop_var) \
@@ -130,6 +131,7 @@ STATIC smartlist_t *relay_padding_machines = NULL;
if (!(circ)->padding_info[loop_var]) \
continue;
#define FOR_EACH_ACTIVE_CIRCUIT_MACHINE_END } STMT_END ;
+#endif /* !defined(COCCI) */
/**
* Free the machineinfo at an index
@@ -686,7 +688,7 @@ circpad_distribution_sample(circpad_distribution_t dist)
case CIRCPAD_DIST_UNIFORM:
{
// param2 is upper bound, param1 is lower
- const struct uniform my_uniform = {
+ const struct uniform_t my_uniform = {
.base = UNIFORM(my_uniform),
.a = dist.param1,
.b = dist.param2,
@@ -696,7 +698,7 @@ circpad_distribution_sample(circpad_distribution_t dist)
case CIRCPAD_DIST_LOGISTIC:
{
/* param1 is Mu, param2 is sigma. */
- const struct logistic my_logistic = {
+ const struct logistic_t my_logistic = {
.base = LOGISTIC(my_logistic),
.mu = dist.param1,
.sigma = dist.param2,
@@ -706,7 +708,7 @@ circpad_distribution_sample(circpad_distribution_t dist)
case CIRCPAD_DIST_LOG_LOGISTIC:
{
/* param1 is Alpha, param2 is 1.0/Beta */
- const struct log_logistic my_log_logistic = {
+ const struct log_logistic_t my_log_logistic = {
.base = LOG_LOGISTIC(my_log_logistic),
.alpha = dist.param1,
.beta = dist.param2,
@@ -716,7 +718,7 @@ circpad_distribution_sample(circpad_distribution_t dist)
case CIRCPAD_DIST_GEOMETRIC:
{
/* param1 is 'p' (success probability) */
- const struct geometric my_geometric = {
+ const struct geometric_t my_geometric = {
.base = GEOMETRIC(my_geometric),
.p = dist.param1,
};
@@ -725,7 +727,7 @@ circpad_distribution_sample(circpad_distribution_t dist)
case CIRCPAD_DIST_WEIBULL:
{
/* param1 is k, param2 is Lambda */
- const struct weibull my_weibull = {
+ const struct weibull_t my_weibull = {
.base = WEIBULL(my_weibull),
.k = dist.param1,
.lambda = dist.param2,
@@ -735,7 +737,7 @@ circpad_distribution_sample(circpad_distribution_t dist)
case CIRCPAD_DIST_PARETO:
{
/* param1 is sigma, param2 is xi, no more params for mu so we use 0 */
- const struct genpareto my_genpareto = {
+ const struct genpareto_t my_genpareto = {
.base = GENPARETO(my_genpareto),
.mu = 0,
.sigma = dist.param1,
@@ -2179,8 +2181,8 @@ circpad_add_matching_machines(origin_circuit_t *on_circ,
circ->padding_machine[i] = NULL;
on_circ->padding_negotiation_failed = 1;
} else {
- /* Success. Don't try any more machines */
- return;
+ /* Success. Don't try any more machines on this index */
+ break;
}
}
} SMARTLIST_FOREACH_END(machine);
diff --git a/src/core/or/circuitpadding.h b/src/core/or/circuitpadding.h
index e9eb32c618..74b69a1c7a 100644
--- a/src/core/or/circuitpadding.h
+++ b/src/core/or/circuitpadding.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019, The Tor Project, Inc. */
+ * Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -301,7 +301,7 @@ typedef struct circpad_state_t {
* | | | | | | |
* | | | | | | |
* 0 +----+----+-----+-----+---------+---------------+
- * 0 100 200 350 500 1000 ∞ microseconds
+ * 0 100 200 350 500 1000 inf microseconds
*
* would be specified the following way:
* histogram_len = 6;
@@ -388,7 +388,7 @@ typedef struct circpad_state_t {
*
* States are allowed to transition to themselves, which means re-schedule
* a new padding timer. They are also allowed to temporarily "transition"
- * to the "IGNORE" and "CANCEL" pseudo-states. See #defines below
+ * to the "IGNORE" and "CANCEL" pseudo-states. See defines below
* for details on state behavior and meaning.
*/
circpad_statenum_t next_state[CIRCPAD_NUM_EVENTS];
diff --git a/src/core/or/circuitpadding_machines.c b/src/core/or/circuitpadding_machines.c
index 7220d657fc..98767f9e8f 100644
--- a/src/core/or/circuitpadding_machines.c
+++ b/src/core/or/circuitpadding_machines.c
@@ -5,8 +5,6 @@
* \file circuitpadding_machines.c
* \brief Circuit padding state machines
*
- * \detail
- *
* Introduce circuit padding machines that will be used by Tor circuits, as
* specified by proposal 302 "Hiding onion service clients using padding".
*
diff --git a/src/core/or/circuitstats.c b/src/core/or/circuitstats.c
index 7a7f3ca600..822e5bd308 100644
--- a/src/core/or/circuitstats.c
+++ b/src/core/or/circuitstats.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -29,7 +29,7 @@
#include "core/or/circuitbuild.h"
#include "core/or/circuitstats.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "feature/control/control_events.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "core/mainloop/mainloop.h"
diff --git a/src/core/or/circuitstats.h b/src/core/or/circuitstats.h
index 845d7b6722..52c9100f53 100644
--- a/src/core/or/circuitstats.h
+++ b/src/core/or/circuitstats.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -175,7 +175,7 @@ typedef struct {
} network_liveness_t;
/** Structure for circuit build times history */
-struct circuit_build_times_s {
+struct circuit_build_times_t {
/** The circular array of recorded build times in milliseconds */
build_time_t circuit_build_times[CBT_NCIRCUITS_TO_OBSERVE];
/** Current index in the circuit_build_times circular array */
diff --git a/src/core/or/circuituse.c b/src/core/or/circuituse.c
index 284e315f9c..37af449106 100644
--- a/src/core/or/circuituse.c
+++ b/src/core/or/circuituse.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -42,6 +42,7 @@
#include "feature/client/bridges.h"
#include "feature/client/circpathbias.h"
#include "feature/client/entrynodes.h"
+#include "feature/client/proxymode.h"
#include "feature/control/control_events.h"
#include "feature/dircommon/directory.h"
#include "feature/hs/hs_circuit.h"
@@ -774,16 +775,11 @@ circuit_expire_building(void)
if (!(TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out)) {
switch (victim->purpose) {
case CIRCUIT_PURPOSE_C_REND_READY:
- /* We only want to spare a rend circ if it has been specified in
- * an INTRODUCE1 cell sent to a hidden service. A circ's
- * pending_final_cpath field is non-NULL iff it is a rend circ
- * and we have tried to send an INTRODUCE1 cell specifying it.
- * Thus, if the pending_final_cpath field *is* NULL, then we
- * want to not spare it. */
- if (TO_ORIGIN_CIRCUIT(victim)->build_state &&
- TO_ORIGIN_CIRCUIT(victim)->build_state->pending_final_cpath ==
- NULL)
+ /* We only want to spare a rend circ iff it has been specified in an
+ * INTRODUCE1 cell sent to a hidden service. */
+ if (!hs_circ_is_rend_sent_in_intro1(CONST_TO_ORIGIN_CIRCUIT(victim))) {
break;
+ }
FALLTHROUGH;
case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED:
@@ -1964,23 +1960,61 @@ have_enough_path_info(int need_exit)
int
circuit_purpose_is_hidden_service(uint8_t purpose)
{
- if (purpose == CIRCUIT_PURPOSE_HS_VANGUARDS) {
- return 1;
- }
-
- /* Client-side purpose */
- if (purpose >= CIRCUIT_PURPOSE_C_HS_MIN_ &&
- purpose <= CIRCUIT_PURPOSE_C_HS_MAX_) {
- return 1;
- }
-
- /* Service-side purpose */
- if (purpose >= CIRCUIT_PURPOSE_S_HS_MIN_ &&
- purpose <= CIRCUIT_PURPOSE_S_HS_MAX_) {
- return 1;
- }
-
- return 0;
+ /* HS Vanguard purpose. */
+ if (circuit_purpose_is_hs_vanguards(purpose)) {
+ return 1;
+ }
+
+ /* Client-side purpose */
+ if (circuit_purpose_is_hs_client(purpose)) {
+ return 1;
+ }
+
+ /* Service-side purpose */
+ if (circuit_purpose_is_hs_service(purpose)) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/** Retrun true iff the given circuit is an HS client circuit. */
+bool
+circuit_purpose_is_hs_client(const uint8_t purpose)
+{
+ return (purpose >= CIRCUIT_PURPOSE_C_HS_MIN_ &&
+ purpose <= CIRCUIT_PURPOSE_C_HS_MAX_);
+}
+
+/** Retrun true iff the given circuit is an HS service circuit. */
+bool
+circuit_purpose_is_hs_service(const uint8_t purpose)
+{
+ return (purpose >= CIRCUIT_PURPOSE_S_HS_MIN_ &&
+ purpose <= CIRCUIT_PURPOSE_S_HS_MAX_);
+}
+
+/** Retrun true iff the given circuit is an HS Vanguards circuit. */
+bool
+circuit_purpose_is_hs_vanguards(const uint8_t purpose)
+{
+ return (purpose == CIRCUIT_PURPOSE_HS_VANGUARDS);
+}
+
+/** Retrun true iff the given circuit is an HS v2 circuit. */
+bool
+circuit_is_hs_v2(const circuit_t *circ)
+{
+ return (CIRCUIT_IS_ORIGIN(circ) &&
+ (CONST_TO_ORIGIN_CIRCUIT(circ)->rend_data != NULL));
+}
+
+/** Retrun true iff the given circuit is an HS v3 circuit. */
+bool
+circuit_is_hs_v3(const circuit_t *circ)
+{
+ return (CIRCUIT_IS_ORIGIN(circ) &&
+ (CONST_TO_ORIGIN_CIRCUIT(circ)->hs_ident != NULL));
}
/**
@@ -3085,7 +3119,7 @@ circuit_change_purpose(circuit_t *circ, uint8_t new_purpose)
/* Take specific actions if we are repurposing a hidden service circuit. */
if (circuit_purpose_is_hidden_service(circ->purpose) &&
!circuit_purpose_is_hidden_service(new_purpose)) {
- hs_circ_cleanup(circ);
+ hs_circ_cleanup_on_repurpose(circ);
}
}
diff --git a/src/core/or/circuituse.h b/src/core/or/circuituse.h
index 25588dbb11..95d36d6474 100644
--- a/src/core/or/circuituse.h
+++ b/src/core/or/circuituse.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -64,6 +64,15 @@ int hostname_in_track_host_exits(const or_options_t *options,
void mark_circuit_unusable_for_new_conns(origin_circuit_t *circ);
int circuit_purpose_is_hidden_service(uint8_t);
+
+/* Series of helper functions for hidden services. */
+bool circuit_purpose_is_hs_client(const uint8_t purpose);
+bool circuit_purpose_is_hs_service(const uint8_t purpose);
+bool circuit_purpose_is_hs_vanguards(const uint8_t purpose);
+
+bool circuit_is_hs_v2(const circuit_t *circ);
+bool circuit_is_hs_v3(const circuit_t *circ);
+
int circuit_should_use_vanguards(uint8_t);
void circuit_sent_valid_data(origin_circuit_t *circ, uint16_t relay_body_len);
void circuit_read_valid_data(origin_circuit_t *circ, uint16_t relay_body_len);
diff --git a/src/core/or/command.c b/src/core/or/command.c
index 1c97437769..9d946974bc 100644
--- a/src/core/or/command.c
+++ b/src/core/or/command.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -217,23 +217,6 @@ command_process_cell(channel_t *chan, cell_t *cell)
}
}
-/** Process an incoming var_cell from a channel; in the current protocol all
- * the var_cells are handshake-related and handled below the channel layer,
- * so this just logs a warning and drops the cell.
- */
-
-void
-command_process_var_cell(channel_t *chan, var_cell_t *var_cell)
-{
- tor_assert(chan);
- tor_assert(var_cell);
-
- log_info(LD_PROTOCOL,
- "Received unexpected var_cell above the channel layer of type %d"
- "; dropping it.",
- var_cell->command);
-}
-
/** Process a 'create' <b>cell</b> that just arrived from <b>chan</b>. Make a
* new circuit with the p_circ_id specified in cell. Put the circuit in state
* onionskin_pending, and pass the onionskin to the cpuworker. Circ will get
@@ -685,8 +668,7 @@ command_setup_channel(channel_t *chan)
tor_assert(chan);
channel_set_cell_handlers(chan,
- command_process_cell,
- command_process_var_cell);
+ command_process_cell);
}
/** Given a listener, install the right handler to process incoming
diff --git a/src/core/or/command.h b/src/core/or/command.h
index 8c90e1de6f..14ebb4a339 100644
--- a/src/core/or/command.h
+++ b/src/core/or/command.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,7 +15,6 @@
#include "core/or/channel.h"
void command_process_cell(channel_t *chan, cell_t *cell);
-void command_process_var_cell(channel_t *chan, var_cell_t *cell);
void command_setup_channel(channel_t *chan);
void command_setup_listener(channel_listener_t *chan_l);
diff --git a/src/core/or/connection_edge.c b/src/core/or/connection_edge.c
index 4f5f038e6c..37e83ba71e 100644
--- a/src/core/or/connection_edge.c
+++ b/src/core/or/connection_edge.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -1553,6 +1553,104 @@ consider_plaintext_ports(entry_connection_t *conn, uint16_t port)
return 0;
}
+/** Parse the given hostname in address. Returns true if the parsing was
+ * successful and type_out contains the type of the hostname. Else, false is
+ * returned which means it was not recognized and type_out is set to
+ * BAD_HOSTNAME.
+ *
+ * The possible recognized forms are (where true is returned):
+ *
+ * If address is of the form "y.onion" with a well-formed handle y:
+ * Put a NUL after y, lower-case it, and return ONION_V2_HOSTNAME or
+ * ONION_V3_HOSTNAME depending on the HS version.
+ *
+ * If address is of the form "x.y.onion" with a well-formed handle x:
+ * Drop "x.", put a NUL after y, lower-case it, and return
+ * ONION_V2_HOSTNAME or ONION_V3_HOSTNAME depending on the HS version.
+ *
+ * If address is of the form "y.onion" with a badly-formed handle y:
+ * Return BAD_HOSTNAME and log a message.
+ *
+ * If address is of the form "y.exit":
+ * Put a NUL after y and return EXIT_HOSTNAME.
+ *
+ * Otherwise:
+ * Return NORMAL_HOSTNAME and change nothing.
+ */
+STATIC bool
+parse_extended_hostname(char *address, hostname_type_t *type_out)
+{
+ char *s;
+ char *q;
+ char query[HS_SERVICE_ADDR_LEN_BASE32+1];
+
+ s = strrchr(address,'.');
+ if (!s) {
+ *type_out = NORMAL_HOSTNAME; /* no dot, thus normal */
+ goto success;
+ }
+ if (!strcmp(s+1,"exit")) {
+ *s = 0; /* NUL-terminate it */
+ *type_out = EXIT_HOSTNAME; /* .exit */
+ goto success;
+ }
+ if (strcmp(s+1,"onion")) {
+ *type_out = NORMAL_HOSTNAME; /* neither .exit nor .onion, thus normal */
+ goto success;
+ }
+
+ /* so it is .onion */
+ *s = 0; /* NUL-terminate it */
+ /* locate a 'sub-domain' component, in order to remove it */
+ q = strrchr(address, '.');
+ if (q == address) {
+ *type_out = BAD_HOSTNAME;
+ goto failed; /* reject sub-domain, as DNS does */
+ }
+ q = (NULL == q) ? address : q + 1;
+ if (strlcpy(query, q, HS_SERVICE_ADDR_LEN_BASE32+1) >=
+ HS_SERVICE_ADDR_LEN_BASE32+1) {
+ *type_out = BAD_HOSTNAME;
+ goto failed;
+ }
+ if (q != address) {
+ memmove(address, q, strlen(q) + 1 /* also get \0 */);
+ }
+ /* v2 onion address check. */
+ if (strlen(query) == REND_SERVICE_ID_LEN_BASE32) {
+ *type_out = ONION_V2_HOSTNAME;
+ if (rend_valid_v2_service_id(query)) {
+ goto success;
+ }
+ goto failed;
+ }
+
+ /* v3 onion address check. */
+ if (strlen(query) == HS_SERVICE_ADDR_LEN_BASE32) {
+ *type_out = ONION_V3_HOSTNAME;
+ if (hs_address_is_valid(query)) {
+ goto success;
+ }
+ goto failed;
+ }
+
+ /* Reaching this point, nothing was recognized. */
+ *type_out = BAD_HOSTNAME;
+ goto failed;
+
+ success:
+ return true;
+ failed:
+ /* otherwise, return to previous state and return 0 */
+ *s = '.';
+ const bool is_onion = (*type_out == ONION_V2_HOSTNAME) ||
+ (*type_out == ONION_V3_HOSTNAME);
+ log_warn(LD_APP, "Invalid %shostname %s; rejecting",
+ is_onion ? "onion " : "",
+ safe_str_client(address));
+ return false;
+}
+
/** How many times do we try connecting with an exit configured via
* TrackHostExits before concluding that it won't work any more and trying a
* different one? */
@@ -2020,16 +2118,15 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
const int automap = rr.automap;
const addressmap_entry_source_t exit_source = rr.exit_source;
- /* Now, we parse the address to see if it's an .onion or .exit or
- * other special address.
- */
- const hostname_type_t addresstype = parse_extended_hostname(socks->address);
-
/* Now see whether the hostname is bogus. This could happen because of an
* onion hostname whose format we don't recognize. */
- if (addresstype == BAD_HOSTNAME) {
+ hostname_type_t addresstype;
+ if (!parse_extended_hostname(socks->address, &addresstype)) {
control_event_client_status(LOG_WARN, "SOCKS_BAD_HOSTNAME HOSTNAME=%s",
escaped(socks->address));
+ if (addresstype == ONION_V3_HOSTNAME) {
+ conn->socks_request->socks_extended_error_code = SOCKS5_HS_BAD_ADDRESS;
+ }
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
return -1;
}
@@ -3522,11 +3619,17 @@ connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply,
size_t replylen, int endreason)
{
char buf[256];
- socks5_reply_status_t status =
- stream_end_reason_to_socks5_response(endreason);
+ socks5_reply_status_t status;
tor_assert(conn->socks_request); /* make sure it's an AP stream */
+ if (conn->socks_request->socks_use_extended_errors &&
+ conn->socks_request->socks_extended_error_code != 0) {
+ status = conn->socks_request->socks_extended_error_code;
+ } else {
+ status = stream_end_reason_to_socks5_response(endreason);
+ }
+
if (!SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)) {
control_event_stream_status(conn, status==SOCKS5_SUCCEEDED ?
STREAM_EVENT_SUCCEEDED : STREAM_EVENT_FAILED,
@@ -4306,68 +4409,6 @@ connection_ap_can_use_exit(const entry_connection_t *conn,
return 1;
}
-/** If address is of the form "y.onion" with a well-formed handle y:
- * Put a NUL after y, lower-case it, and return ONION_V2_HOSTNAME or
- * ONION_V3_HOSTNAME depending on the HS version.
- *
- * If address is of the form "x.y.onion" with a well-formed handle x:
- * Drop "x.", put a NUL after y, lower-case it, and return
- * ONION_V2_HOSTNAME or ONION_V3_HOSTNAME depending on the HS version.
- *
- * If address is of the form "y.onion" with a badly-formed handle y:
- * Return BAD_HOSTNAME and log a message.
- *
- * If address is of the form "y.exit":
- * Put a NUL after y and return EXIT_HOSTNAME.
- *
- * Otherwise:
- * Return NORMAL_HOSTNAME and change nothing.
- */
-hostname_type_t
-parse_extended_hostname(char *address)
-{
- char *s;
- char *q;
- char query[HS_SERVICE_ADDR_LEN_BASE32+1];
-
- s = strrchr(address,'.');
- if (!s)
- return NORMAL_HOSTNAME; /* no dot, thus normal */
- if (!strcmp(s+1,"exit")) {
- *s = 0; /* NUL-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 */
- /* locate a 'sub-domain' component, in order to remove it */
- q = strrchr(address, '.');
- if (q == address) {
- goto failed; /* reject sub-domain, as DNS does */
- }
- q = (NULL == q) ? address : q + 1;
- if (strlcpy(query, q, HS_SERVICE_ADDR_LEN_BASE32+1) >=
- HS_SERVICE_ADDR_LEN_BASE32+1)
- goto failed;
- if (q != address) {
- memmove(address, q, strlen(q) + 1 /* also get \0 */);
- }
- if (rend_valid_v2_service_id(query)) {
- return ONION_V2_HOSTNAME; /* success */
- }
- if (hs_address_is_valid(query)) {
- return ONION_V3_HOSTNAME;
- }
- failed:
- /* otherwise, return to previous state and return 0 */
- *s = '.';
- log_warn(LD_APP, "Invalid onion hostname %s; rejecting",
- safe_str_client(address));
- return BAD_HOSTNAME;
-}
-
/** Return true iff the (possibly NULL) <b>alen</b>-byte chunk of memory at
* <b>a</b> is equal to the (possibly NULL) <b>blen</b>-byte chunk of memory
* at <b>b</b>. */
diff --git a/src/core/or/connection_edge.h b/src/core/or/connection_edge.h
index e82b6bd765..11cb252935 100644
--- a/src/core/or/connection_edge.h
+++ b/src/core/or/connection_edge.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -71,6 +71,15 @@ entry_connection_t *EDGE_TO_ENTRY_CONN(edge_connection_t *);
#define connection_mark_unattached_ap(conn, endreason) \
connection_mark_unattached_ap_((conn), (endreason), __LINE__, SHORT_FILE__)
+/** Possible return values for parse_extended_hostname. */
+typedef enum hostname_type_t {
+ BAD_HOSTNAME,
+ EXIT_HOSTNAME,
+ NORMAL_HOSTNAME,
+ ONION_V2_HOSTNAME,
+ ONION_V3_HOSTNAME,
+} hostname_type_t;
+
MOCK_DECL(void,connection_mark_unattached_ap_,
(entry_connection_t *conn, int endreason,
int line, const char *file));
@@ -155,13 +164,6 @@ int connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
origin_circuit_t *circ,
crypt_path_t *cpath);
-/** Possible return values for parse_extended_hostname. */
-typedef enum hostname_type_t {
- NORMAL_HOSTNAME, ONION_V2_HOSTNAME, ONION_V3_HOSTNAME,
- EXIT_HOSTNAME, BAD_HOSTNAME
-} hostname_type_t;
-hostname_type_t parse_extended_hostname(char *address);
-
#if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
int get_pf_socket(void);
#endif
@@ -219,6 +221,8 @@ void half_edge_free_(struct half_edge_t *he);
#ifdef CONNECTION_EDGE_PRIVATE
+STATIC bool parse_extended_hostname(char *address, hostname_type_t *type_out);
+
/** A parsed BEGIN or BEGIN_DIR cell */
typedef struct begin_cell_t {
/** The address the client has asked us to connect to, or NULL if this is
diff --git a/src/core/or/connection_or.c b/src/core/or/connection_or.c
index 4c93351e31..5571d90f8f 100644
--- a/src/core/or/connection_or.c
+++ b/src/core/or/connection_or.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -27,7 +27,7 @@
* Define this so we get channel internal functions, since we're implementing
* part of a subclass (channel_tls_t).
*/
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define CONNECTION_OR_PRIVATE
#define ORCONN_EVENT_PRIVATE
#include "core/or/channel.h"
@@ -95,13 +95,6 @@ static unsigned int
connection_or_is_bad_for_new_circs(or_connection_t *or_conn);
static void connection_or_mark_bad_for_new_circs(or_connection_t *or_conn);
-/*
- * Call this when changing connection state, so notifications to the owning
- * channel can be handled.
- */
-
-static void connection_or_change_state(or_connection_t *conn, uint8_t state);
-
static void connection_or_check_canonicity(or_connection_t *conn,
int started_here);
@@ -457,8 +450,8 @@ connection_or_state_publish(const or_connection_t *conn, uint8_t state)
* be notified.
*/
-static void
-connection_or_change_state(or_connection_t *conn, uint8_t state)
+MOCK_IMPL(STATIC void,
+connection_or_change_state,(or_connection_t *conn, uint8_t state))
{
tor_assert(conn);
@@ -726,6 +719,19 @@ connection_or_finished_flushing(or_connection_t *conn)
switch (conn->base_.state) {
case OR_CONN_STATE_PROXY_HANDSHAKING:
+ /* PROXY_HAPROXY gets connected by receiving an ack. */
+ if (conn->proxy_type == PROXY_HAPROXY) {
+ tor_assert(TO_CONN(conn)->proxy_state == PROXY_HAPROXY_WAIT_FOR_FLUSH);
+ TO_CONN(conn)->proxy_state = PROXY_CONNECTED;
+
+ if (connection_tls_start_handshake(conn, 0) < 0) {
+ /* TLS handshaking error of some kind. */
+ connection_or_close_for_error(conn, 0);
+ return -1;
+ }
+ break;
+ }
+ break;
case OR_CONN_STATE_OPEN:
case OR_CONN_STATE_OR_HANDSHAKING_V2:
case OR_CONN_STATE_OR_HANDSHAKING_V3:
@@ -765,8 +771,9 @@ connection_or_finished_connecting(or_connection_t *or_conn)
return -1;
}
- connection_start_reading(conn);
connection_or_change_state(or_conn, OR_CONN_STATE_PROXY_HANDSHAKING);
+ connection_start_reading(conn);
+
return 0;
}
diff --git a/src/core/or/connection_or.h b/src/core/or/connection_or.h
index 272f536b83..90b21ad77b 100644
--- a/src/core/or/connection_or.h
+++ b/src/core/or/connection_or.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -134,7 +134,14 @@ void connection_or_group_set_badness_(smartlist_t *group, int force);
#ifdef CONNECTION_OR_PRIVATE
STATIC int should_connect_to_relay(const or_connection_t *or_conn);
STATIC void note_or_connect_failed(const or_connection_t *or_conn);
-#endif
+
+/*
+ * Call this when changing connection state, so notifications to the owning
+ * channel can be handled.
+ */
+MOCK_DECL(STATIC void,connection_or_change_state,
+ (or_connection_t *conn, uint8_t state));
+#endif /* defined(CONNECTION_OR_PRIVATE) */
#ifdef TOR_UNIT_TESTS
extern int certs_cell_ed25519_disabled_for_testing;
diff --git a/src/core/or/connection_st.h b/src/core/or/connection_st.h
index 1c42a56d6b..55d94d9451 100644
--- a/src/core/or/connection_st.h
+++ b/src/core/or/connection_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file connection_st.h
+ * @brief Base connection structure.
+ **/
+
#ifndef CONNECTION_ST_H
#define CONNECTION_ST_H
diff --git a/src/core/or/core_or.md b/src/core/or/core_or.md
new file mode 100644
index 0000000000..0b4d430a00
--- /dev/null
+++ b/src/core/or/core_or.md
@@ -0,0 +1,62 @@
+@dir core/or
+@brief core/or: **Onion routing happens here!**
+
+This is the central part of Tor that handles the core tasks of onion routing:
+building circuit, handling circuits, attaching circuit to streams, moving
+data around, and so forth.
+
+Some aspects of this module should probably be refactored into others.
+
+Notable files here include:
+
+`channel.c`
+: Generic channel implementation. Channels handle sending and receiving cells
+among tor nodes.
+
+`channeltls.c`
+: Channel implementation for TLS-based OR connections. Uses `connection_or.c`.
+
+`circuitbuild.c`
+: Code for constructing circuits and choosing their paths. (*Note*:
+this module could plausibly be split into handling the client side,
+the server side, and the path generation aspects of circuit building.)
+
+`circuitlist.c`
+: Code for maintaining and navigating the global list of circuits.
+
+`circuitmux.c`
+: Generic circuitmux implementation. A circuitmux handles deciding, for a
+particular channel, which circuit should write next.
+
+`circuitmux_ewma.c`
+: A circuitmux implementation based on the EWMA (exponentially
+weighted moving average) algorithm.
+
+`circuituse.c`
+: Code to actually send and receive data on circuits.
+
+`command.c`
+: Handles incoming cells on channels.
+
+`connection.c`
+: Generic and common connection tools, and implementation for the simpler
+connection types.
+
+`connection_edge.c`
+: Implementation for entry and exit connections.
+
+`connection_or.c`
+: Implementation for OR connections (the ones that send cells over TLS).
+
+`onion.c`
+: Generic code for generating and responding to CREATE and CREATED
+cells, and performing the appropriate onion handshakes. Also contains
+code to manage the server-side onion queue.
+
+`relay.c`
+: Handles particular types of relay cells, and provides code to receive,
+encrypt, route, and interpret relay cells.
+
+`scheduler.c`
+: Decides which channel/circuit pair is ready to receive the next cell.
+
diff --git a/src/core/or/cpath_build_state_st.h b/src/core/or/cpath_build_state_st.h
index 4572a10430..ee9a0d972c 100644
--- a/src/core/or/cpath_build_state_st.h
+++ b/src/core/or/cpath_build_state_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file cpath_build_state_st.h
+ * @brief Circuit-build-stse structure
+ **/
+
#ifndef CIRCUIT_BUILD_STATE_ST_ST_H
#define CIRCUIT_BUILD_STATE_ST_ST_H
@@ -35,4 +40,3 @@ struct cpath_build_state_t {
};
#endif /* !defined(CIRCUIT_BUILD_STATE_ST_ST_H) */
-
diff --git a/src/core/or/crypt_path.c b/src/core/or/crypt_path.c
index 9b7efc28bf..8f41540848 100644
--- a/src/core/or/crypt_path.c
+++ b/src/core/or/crypt_path.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, The Tor Project, Inc. */
+ * Copyright (c) 2019-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/crypt_path_reference_st.h b/src/core/or/crypt_path_reference_st.h
index 1827022b4e..71f9cb8c36 100644
--- a/src/core/or/crypt_path_reference_st.h
+++ b/src/core/or/crypt_path_reference_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file crypt_path_reference_st.h
+ * @brief reference-counting structure for crypt_path_t
+ **/
+
#ifndef CRYPT_PATH_REFERENCE_ST_H
#define CRYPT_PATH_REFERENCE_ST_H
@@ -20,4 +25,3 @@ struct crypt_path_reference_t {
};
#endif /* !defined(CRYPT_PATH_REFERENCE_ST_H) */
-
diff --git a/src/core/or/crypt_path_st.h b/src/core/or/crypt_path_st.h
index 249ac6aaa3..2b69728a6d 100644
--- a/src/core/or/crypt_path_st.h
+++ b/src/core/or/crypt_path_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file crypt_path_st.h
+ * @brief Path structures for origin circuits.
+ **/
+
#ifndef CRYPT_PATH_ST_H
#define CRYPT_PATH_ST_H
diff --git a/doc/HACKING/design/02-dataflow.md b/src/core/or/dataflow.md
index 39f21a908c..1098701780 100644
--- a/doc/HACKING/design/02-dataflow.md
+++ b/src/core/or/dataflow.md
@@ -1,5 +1,6 @@
+@tableofcontents
-## Data flow in the Tor process ##
+@page dataflow Data flow in the Tor process
We read bytes from the network, we write bytes to the network. For the
most part, the bytes we write correspond roughly to bytes we have read,
@@ -7,9 +8,7 @@ with bits of cryptography added in.
The rest is a matter of details.
-![Diagram of main data flows in Tor](./diagrams/02/02-dataflow.png "Diagram of main data flows in Tor")
-
-### Connections and buffers: reading, writing, and interpreting. ###
+### Connections and buffers: reading, writing, and interpreting.
At a low level, Tor's networking code is based on "connections". Each
connection represents an object that can send or receive network-like
@@ -79,7 +78,7 @@ wide variety of reasons, including:
* For some connection types, reading is disabled when the inbuf is
too full.
* Reading/writing is temporarily disabled on connections that have
- recently read/written enough data up to their bandwidth
+ recently read/written enough data up to their bandwidth
* Reading is disabled on connections when reading more data from them
would require that data to be buffered somewhere else that is
already full.
@@ -208,7 +207,7 @@ next channel in sequence with `append cell_to_circuit_queue()`. This
places the cell on a per-circuit queue for cells headed out on that
particular channel.
-### Sending cells on circuits: the complicated bit. ###
+### Sending cells on circuits: the complicated bit.
Relay cells are queued onto circuits from one of two (main) sources:
reading data from edge connections, and receiving a cell to be relayed
@@ -234,3 +233,4 @@ queue the next cell.
(This logic applies to outgoing relay cells only; incoming relay cells
are processed as they arrive.)
+
diff --git a/src/core/or/destroy_cell_queue_st.h b/src/core/or/destroy_cell_queue_st.h
index e917afc700..aa28289be5 100644
--- a/src/core/or/destroy_cell_queue_st.h
+++ b/src/core/or/destroy_cell_queue_st.h
@@ -1,12 +1,19 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file destroy_cell_queue_st.h
+ * @brief Destroy-cell queue structures
+ **/
+
#ifndef DESTROY_CELL_QUEUE_ST_H
#define DESTROY_CELL_QUEUE_ST_H
+#include "core/or/cell_queue_st.h"
+
/** A single queued destroy cell. */
struct destroy_cell_t {
TOR_SIMPLEQ_ENTRY(destroy_cell_t) next;
@@ -19,9 +26,8 @@ struct destroy_cell_t {
/** A queue of destroy cells on a channel. */
struct destroy_cell_queue_t {
/** Linked list of packed_cell_t */
- TOR_SIMPLEQ_HEAD(dcell_simpleq, destroy_cell_t) head;
+ TOR_SIMPLEQ_HEAD(dcell_simpleq_t, destroy_cell_t) head;
int n; /**< The number of cells in the queue. */
};
#endif /* !defined(DESTROY_CELL_QUEUE_ST_H) */
-
diff --git a/src/core/or/dos.c b/src/core/or/dos.c
index d06eaa6d05..5f99280030 100644
--- a/src/core/or/dos.c
+++ b/src/core/or/dos.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/*
@@ -15,6 +15,7 @@
#include "core/or/channel.h"
#include "core/or/connection_or.h"
#include "core/or/relay.h"
+#include "feature/hs/hs_dos.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodelist.h"
#include "feature/relay/routermode.h"
@@ -629,6 +630,7 @@ dos_log_heartbeat(void)
char *cc_msg = NULL;
char *single_hop_client_msg = NULL;
char *circ_stats_msg = NULL;
+ char *hs_dos_intro2_msg = NULL;
/* Stats number coming from relay.c append_cell_to_circuit_queue(). */
tor_asprintf(&circ_stats_msg,
@@ -654,17 +656,24 @@ dos_log_heartbeat(void)
num_single_hop_client_refused);
}
+ /* HS DoS stats. */
+ tor_asprintf(&hs_dos_intro2_msg,
+ " %" PRIu64 " INTRODUCE2 rejected.",
+ hs_dos_get_intro2_rejected_count());
+
log_notice(LD_HEARTBEAT,
- "DoS mitigation since startup:%s%s%s%s",
+ "DoS mitigation since startup:%s%s%s%s%s",
circ_stats_msg,
(cc_msg != NULL) ? cc_msg : " [cc not enabled]",
(conn_msg != NULL) ? conn_msg : " [conn not enabled]",
- (single_hop_client_msg != NULL) ? single_hop_client_msg : "");
+ (single_hop_client_msg != NULL) ? single_hop_client_msg : "",
+ (hs_dos_intro2_msg != NULL) ? hs_dos_intro2_msg : "");
tor_free(conn_msg);
tor_free(cc_msg);
tor_free(single_hop_client_msg);
tor_free(circ_stats_msg);
+ tor_free(hs_dos_intro2_msg);
return;
}
diff --git a/src/core/or/dos.h b/src/core/or/dos.h
index a46f65d767..b3eca058b8 100644
--- a/src/core/or/dos.h
+++ b/src/core/or/dos.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/*
diff --git a/src/core/or/edge_connection_st.h b/src/core/or/edge_connection_st.h
index 8922a3a9cf..9b2f031b9d 100644
--- a/src/core/or/edge_connection_st.h
+++ b/src/core/or/edge_connection_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file edge_connection_st.h
+ * @brief Edge-connection structure.
+ **/
+
#ifndef EDGE_CONNECTION_ST_H
#define EDGE_CONNECTION_ST_H
@@ -74,4 +79,3 @@ struct edge_connection_t {
};
#endif /* !defined(EDGE_CONNECTION_ST_H) */
-
diff --git a/src/core/or/entry_connection_st.h b/src/core/or/entry_connection_st.h
index e65c545d17..495ffd85dd 100644
--- a/src/core/or/entry_connection_st.h
+++ b/src/core/or/entry_connection_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file entry_connection_st.h
+ * @brief Entry connection structure.
+ **/
+
#ifndef ENTRY_CONNECTION_ST_H
#define ENTRY_CONNECTION_ST_H
@@ -97,4 +102,3 @@ struct entry_connection_t {
#define ENTRY_TO_EDGE_CONN(c) (&(((c))->edge_))
#endif /* !defined(ENTRY_CONNECTION_ST_H) */
-
diff --git a/src/core/or/entry_port_cfg_st.h b/src/core/or/entry_port_cfg_st.h
index b84838d44f..ef1095086d 100644
--- a/src/core/or/entry_port_cfg_st.h
+++ b/src/core/or/entry_port_cfg_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file entry_port_cfg_st.h
+ * @brief Configuration structure for client ports.
+ **/
+
#ifndef ENTRY_PORT_CFG_ST_H
#define ENTRY_PORT_CFG_ST_H
@@ -48,7 +53,9 @@ struct entry_port_cfg_t {
* do we prefer IPv6? */
unsigned int prefer_ipv6_virtaddr : 1;
+ /** For socks listeners: can we send back the extended SOCKS5 error code? */
+ unsigned int extended_socks5_codes : 1;
+
};
#endif /* !defined(ENTRY_PORT_CFG_ST_H) */
-
diff --git a/src/core/or/extend_info_st.h b/src/core/or/extend_info_st.h
index 7704ff16b5..a66ce24cfa 100644
--- a/src/core/or/extend_info_st.h
+++ b/src/core/or/extend_info_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file extend_info_st.h
+ * @brief Extend-info structure.
+ **/
+
#ifndef EXTEND_INFO_ST_H
#define EXTEND_INFO_ST_H
diff --git a/src/core/or/half_edge_st.h b/src/core/or/half_edge_st.h
index 1fe47ad3f1..c6b6e518fc 100644
--- a/src/core/or/half_edge_st.h
+++ b/src/core/or/half_edge_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file half_edge_st.h
+ * @brief Half-open connection structure.
+ **/
+
#ifndef HALF_EDGE_ST_H
#define HALF_EDGE_ST_H
@@ -31,4 +36,3 @@ typedef struct half_edge_t {
} half_edge_t;
#endif /* !defined(HALF_EDGE_ST_H) */
-
diff --git a/src/core/or/include.am b/src/core/or/include.am
new file mode 100644
index 0000000000..4dd251d2e4
--- /dev/null
+++ b/src/core/or/include.am
@@ -0,0 +1,98 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/core/or/address_set.c \
+ src/core/or/channel.c \
+ src/core/or/channelpadding.c \
+ src/core/or/channeltls.c \
+ src/core/or/circuitbuild.c \
+ src/core/or/circuitlist.c \
+ src/core/or/circuitmux.c \
+ src/core/or/circuitmux_ewma.c \
+ src/core/or/circuitpadding.c \
+ src/core/or/circuitpadding_machines.c \
+ src/core/or/circuitstats.c \
+ src/core/or/circuituse.c \
+ src/core/or/crypt_path.c \
+ src/core/or/command.c \
+ src/core/or/connection_edge.c \
+ src/core/or/connection_or.c \
+ src/core/or/dos.c \
+ src/core/or/onion.c \
+ src/core/or/ocirc_event.c \
+ src/core/or/or_periodic.c \
+ src/core/or/or_sys.c \
+ src/core/or/orconn_event.c \
+ src/core/or/policies.c \
+ src/core/or/protover.c \
+ src/core/or/protover_rust.c \
+ src/core/or/reasons.c \
+ src/core/or/relay.c \
+ src/core/or/scheduler.c \
+ src/core/or/scheduler_kist.c \
+ src/core/or/scheduler_vanilla.c \
+ src/core/or/sendme.c \
+ src/core/or/status.c \
+ src/core/or/versions.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/core/or/addr_policy_st.h \
+ src/core/or/address_set.h \
+ src/core/or/cell_queue_st.h \
+ src/core/or/cell_st.h \
+ src/core/or/channel.h \
+ src/core/or/channelpadding.h \
+ src/core/or/channeltls.h \
+ src/core/or/circuit_st.h \
+ src/core/or/circuitbuild.h \
+ src/core/or/circuitlist.h \
+ src/core/or/circuitmux.h \
+ src/core/or/circuitmux_ewma.h \
+ src/core/or/circuitstats.h \
+ src/core/or/circuitpadding.h \
+ src/core/or/circuitpadding_machines.h \
+ src/core/or/circuituse.h \
+ src/core/or/command.h \
+ src/core/or/connection_edge.h \
+ src/core/or/connection_or.h \
+ src/core/or/connection_st.h \
+ src/core/or/crypt_path.h \
+ src/core/or/cpath_build_state_st.h \
+ src/core/or/crypt_path_reference_st.h \
+ src/core/or/crypt_path_st.h \
+ src/core/or/destroy_cell_queue_st.h \
+ src/core/or/dos.h \
+ src/core/or/edge_connection_st.h \
+ src/core/or/half_edge_st.h \
+ src/core/or/entry_connection_st.h \
+ src/core/or/entry_port_cfg_st.h \
+ src/core/or/extend_info_st.h \
+ src/core/or/listener_connection_st.h \
+ src/core/or/onion.h \
+ src/core/or/or.h \
+ src/core/or/or_periodic.h \
+ src/core/or/or_sys.h \
+ src/core/or/orconn_event.h \
+ src/core/or/orconn_event_sys.h \
+ src/core/or/or_circuit_st.h \
+ src/core/or/or_connection_st.h \
+ src/core/or/or_handshake_certs_st.h \
+ src/core/or/or_handshake_state_st.h \
+ src/core/or/ocirc_event.h \
+ src/core/or/ocirc_event_sys.h \
+ src/core/or/origin_circuit_st.h \
+ src/core/or/policies.h \
+ src/core/or/port_cfg_st.h \
+ src/core/or/protover.h \
+ src/core/or/reasons.h \
+ src/core/or/relay.h \
+ src/core/or/relay_crypto_st.h \
+ src/core/or/scheduler.h \
+ src/core/or/sendme.h \
+ src/core/or/server_port_cfg_st.h \
+ src/core/or/socks_request_st.h \
+ src/core/or/status.h \
+ src/core/or/tor_version_st.h \
+ src/core/or/var_cell_st.h \
+ src/core/or/versions.h
diff --git a/src/core/or/listener_connection_st.h b/src/core/or/listener_connection_st.h
index 1250d9c9b4..78175ea061 100644
--- a/src/core/or/listener_connection_st.h
+++ b/src/core/or/listener_connection_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file listener_connection_st.h
+ * @brief Listener connection structure.
+ **/
+
#ifndef LISTENER_CONNECTION_ST_H
#define LISTENER_CONNECTION_ST_H
@@ -22,4 +27,3 @@ struct listener_connection_t {
};
#endif /* !defined(LISTENER_CONNECTION_ST_H) */
-
diff --git a/src/core/or/ocirc_event.c b/src/core/or/ocirc_event.c
index 3cb9147134..66992a0b5f 100644
--- a/src/core/or/ocirc_event.c
+++ b/src/core/or/ocirc_event.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/ocirc_event.h b/src/core/or/ocirc_event.h
index 8e9494874f..10307a3664 100644
--- a/src/core/or/ocirc_event.h
+++ b/src/core/or/ocirc_event.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/ocirc_event_sys.h b/src/core/or/ocirc_event_sys.h
index 61180496da..abb89b04a0 100644
--- a/src/core/or/ocirc_event_sys.h
+++ b/src/core/or/ocirc_event_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/**
* \file ocirc_event_sys.h
diff --git a/src/core/or/onion.c b/src/core/or/onion.c
index aeddedd807..21bda79914 100644
--- a/src/core/or/onion.c
+++ b/src/core/or/onion.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/onion.h b/src/core/or/onion.h
index bb0b5b8dfd..ff3083f374 100644
--- a/src/core/or/onion.h
+++ b/src/core/or/onion.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/or.h b/src/core/or/or.h
index 990cfacbc0..488a0fb09c 100644
--- a/src/core/or/or.h
+++ b/src/core/or/or.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -24,7 +24,6 @@
#include "lib/arch/bytes.h"
#include "lib/cc/compat_compiler.h"
-#include "lib/cc/torint.h"
#include "lib/container/map.h"
#include "lib/buf/buffers.h"
#include "lib/container/smartlist.h"
@@ -168,12 +167,13 @@ struct curve25519_public_key_t;
#define PROXY_CONNECT 1
#define PROXY_SOCKS4 2
#define PROXY_SOCKS5 3
-/* !!!! If there is ever a PROXY_* type over 3, we must grow the proxy_type
+#define PROXY_HAPROXY 4
+/* !!!! If there is ever a PROXY_* type over 7, we must grow the proxy_type
* field in or_connection_t */
/* Pluggable transport proxy type. Don't use this in or_connection_t,
* instead use the actual underlying proxy type (see above). */
-#define PROXY_PLUGGABLE 4
+#define PROXY_PLUGGABLE 5
/** How many circuits do we want simultaneously in-progress to handle
* a given stream? */
@@ -609,21 +609,21 @@ typedef uint32_t circid_t;
/** Identifies a stream on a circuit */
typedef uint16_t streamid_t;
-/* channel_t typedef; struct channel_s is in channel.h */
+/* channel_t typedef; struct channel_t is in channel.h */
-typedef struct channel_s channel_t;
+typedef struct channel_t channel_t;
-/* channel_listener_t typedef; struct channel_listener_s is in channel.h */
+/* channel_listener_t typedef; struct channel_listener_t is in channel.h */
-typedef struct channel_listener_s channel_listener_t;
+typedef struct channel_listener_t channel_listener_t;
/* TLS channel stuff */
-typedef struct channel_tls_s channel_tls_t;
+typedef struct channel_tls_t channel_tls_t;
-/* circuitmux_t typedef; struct circuitmux_s is in circuitmux.h */
+/* circuitmux_t typedef; struct circuitmux_t is in circuitmux.h */
-typedef struct circuitmux_s circuitmux_t;
+typedef struct circuitmux_t circuitmux_t;
typedef struct cell_t cell_t;
typedef struct var_cell_t var_cell_t;
@@ -1013,7 +1013,7 @@ typedef struct or_state_t or_state_t;
#define BW_MIN_WEIGHT_SCALE 1
#define BW_MAX_WEIGHT_SCALE INT32_MAX
-typedef struct circuit_build_times_s circuit_build_times_t;
+typedef struct circuit_build_times_t circuit_build_times_t;
/********************************* config.c ***************************/
diff --git a/src/core/or/or_circuit_st.h b/src/core/or/or_circuit_st.h
index f3eb861613..9bfe999728 100644
--- a/src/core/or/or_circuit_st.h
+++ b/src/core/or/or_circuit_st.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef OR_CIRCUIT_ST_H
@@ -27,7 +27,7 @@ struct or_circuit_t {
/** Pointer to a workqueue entry, if this circuit has given an onionskin to
* a cpuworker and is waiting for a response. Used to decide whether it is
* safe to free a circuit or if it is still in use by a cpuworker. */
- struct workqueue_entry_s *workqueue_entry;
+ struct workqueue_entry_t *workqueue_entry;
/** The circuit_id used in the previous (backward) hop of this circuit. */
circid_t p_circ_id;
diff --git a/src/core/or/or_connection_st.h b/src/core/or/or_connection_st.h
index 051fcd00d3..92956c2847 100644
--- a/src/core/or/or_connection_st.h
+++ b/src/core/or/or_connection_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file or_connection_st.h
+ * @brief OR connection structure.
+ **/
+
#ifndef OR_CONNECTION_ST_H
#define OR_CONNECTION_ST_H
@@ -58,7 +63,7 @@ struct or_connection_t {
/** True iff this is an outgoing connection. */
unsigned int is_outgoing:1;
- unsigned int proxy_type:2; /**< One of PROXY_NONE...PROXY_SOCKS5 */
+ unsigned int proxy_type:3; /**< One of PROXY_NONE...PROXY_HAPROXY */
unsigned int wide_circ_ids:1;
/** True iff this connection has had its bootstrap failure logged with
* control_event_bootstrap_problem. */
diff --git a/src/core/or/or_handshake_certs_st.h b/src/core/or/or_handshake_certs_st.h
index 9deb6d6d59..31755f04a1 100644
--- a/src/core/or/or_handshake_certs_st.h
+++ b/src/core/or/or_handshake_certs_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file or_handshake_certs_st.h
+ * @brief OR handshake certs structure
+ **/
+
#ifndef OR_HANDSHAKE_CERTS_ST
#define OR_HANDSHAKE_CERTS_ST
diff --git a/src/core/or/or_handshake_state_st.h b/src/core/or/or_handshake_state_st.h
index 472ce8a302..050404046d 100644
--- a/src/core/or/or_handshake_state_st.h
+++ b/src/core/or/or_handshake_state_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file or_handshake_state_st.h
+ * @brief OR handshake state structure
+ **/
+
#ifndef OR_HANDSHAKE_STATE_ST
#define OR_HANDSHAKE_STATE_ST
@@ -75,4 +80,3 @@ struct or_handshake_state_t {
};
#endif /* !defined(OR_HANDSHAKE_STATE_ST) */
-
diff --git a/src/core/or/or_periodic.c b/src/core/or/or_periodic.c
index fe28c99192..4dfdce14ca 100644
--- a/src/core/or/or_periodic.c
+++ b/src/core/or/or_periodic.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -20,11 +20,13 @@
#include "feature/relay/routermode.h"
+#ifndef COCCI
#define DECLARE_EVENT(name, roles, flags) \
static periodic_event_item_t name ## _event = \
PERIODIC_EVENT(name, \
PERIODIC_EVENT_ROLE_##roles, \
flags)
+#endif /* !defined(COCCI) */
#define FL(name) (PERIODIC_EVENT_FLAG_ ## name)
diff --git a/src/core/or/or_periodic.h b/src/core/or/or_periodic.h
index c2f47cf5ef..080573a838 100644
--- a/src/core/or/or_periodic.h
+++ b/src/core/or/or_periodic.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/or_sys.c b/src/core/or/or_sys.c
index 6f8c81a4df..394b7945e1 100644
--- a/src/core/or/or_sys.c
+++ b/src/core/or/or_sys.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/or_sys.h b/src/core/or/or_sys.h
index c37ef01858..3ae09f7b52 100644
--- a/src/core/or/or_sys.h
+++ b/src/core/or/or_sys.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/orconn_event.c b/src/core/or/orconn_event.c
index 86f112fc09..d0a06aa040 100644
--- a/src/core/or/orconn_event.c
+++ b/src/core/or/orconn_event.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/orconn_event.h b/src/core/or/orconn_event.h
index fb67a7d183..2653b20d6e 100644
--- a/src/core/or/orconn_event.h
+++ b/src/core/or/orconn_event.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/orconn_event_sys.h b/src/core/or/orconn_event_sys.h
index 9703b2e3d1..02f0b8116b 100644
--- a/src/core/or/orconn_event_sys.h
+++ b/src/core/or/orconn_event_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/**
* \file orconn_event_sys.h
diff --git a/src/core/or/origin_circuit_st.h b/src/core/or/origin_circuit_st.h
index 01bbc84ae2..79e250cd59 100644
--- a/src/core/or/origin_circuit_st.h
+++ b/src/core/or/origin_circuit_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file origin_circuit_st.h
+ * @brief Origin circuit structure.
+ **/
+
#ifndef ORIGIN_CIRCUIT_ST_H
#define ORIGIN_CIRCUIT_ST_H
diff --git a/src/core/or/policies.c b/src/core/or/policies.c
index 39a0817c85..4a69854deb 100644
--- a/src/core/or/policies.c
+++ b/src/core/or/policies.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -933,49 +933,6 @@ fascist_firewall_choose_address_ipv4h(uint32_t ipv4h_addr,
pref_ipv6, ap);
}
-/* Some microdescriptor consensus methods have no IPv6 addresses in rs: they
- * are in the microdescriptors. For these consensus methods, we can't rely on
- * the node's IPv6 address until its microdescriptor is available (when using
- * microdescs).
- * But for bridges, rewrite_node_address_for_bridge() updates node->ri with
- * the configured address, so we can trust bridge addresses.
- * (Bridges could gain an IPv6 address if their microdescriptor arrives, but
- * this will never be their preferred address: that is in the config.)
- * Returns true if the node needs a microdescriptor for its IPv6 address, and
- * false if the addresses in the node are already up-to-date.
- */
-static int
-node_awaiting_ipv6(const or_options_t* options, const node_t *node)
-{
- tor_assert(node);
-
- /* There's no point waiting for an IPv6 address if we'd never use it */
- if (!fascist_firewall_use_ipv6(options)) {
- return 0;
- }
-
- /* If the node has an IPv6 address, we're not waiting */
- if (node_has_ipv6_addr(node)) {
- return 0;
- }
-
- /* If the current consensus method and flavour has IPv6 addresses, we're not
- * waiting */
- if (networkstatus_consensus_has_ipv6(options)) {
- return 0;
- }
-
- /* Bridge clients never use the address from a bridge's md, so there's no
- * need to wait for it. */
- if (node_is_a_configured_bridge(node)) {
- return 0;
- }
-
- /* We are waiting if we_use_microdescriptors_for_circuits() and we have no
- * md. */
- return (!node->md && we_use_microdescriptors_for_circuits(options));
-}
-
/** Like fascist_firewall_choose_address_base(), but takes <b>rs</b>.
* Consults the corresponding node, then falls back to rs if node is NULL.
* This should only happen when there's no valid consensus, and rs doesn't
@@ -998,7 +955,7 @@ fascist_firewall_choose_address_rs(const routerstatus_t *rs,
const or_options_t *options = get_options();
const node_t *node = node_get_by_id(rs->identity_digest);
- if (node && !node_awaiting_ipv6(options, node)) {
+ if (node) {
fascist_firewall_choose_address_node(node, fw_connection, pref_only, ap);
} else {
/* There's no node-specific IPv6 preference, so use the generic IPv6
@@ -1111,17 +1068,6 @@ fascist_firewall_choose_address_node(const node_t *node,
}
node_assert_ok(node);
- /* Calling fascist_firewall_choose_address_node() when the node is missing
- * IPv6 information breaks IPv6-only clients.
- * If the node is a hard-coded fallback directory or authority, call
- * fascist_firewall_choose_address_rs() on the fake (hard-coded) routerstatus
- * for the node.
- * If it is not hard-coded, check that the node has a microdescriptor, full
- * descriptor (routerinfo), or is one of our configured bridges before
- * calling this function. */
- if (BUG(node_awaiting_ipv6(get_options(), node))) {
- return;
- }
const int pref_ipv6_node = (fw_connection == FIREWALL_OR_CONNECTION
? node_ipv6_or_preferred(node)
diff --git a/src/core/or/policies.h b/src/core/or/policies.h
index 3c46363c04..b9477b2db1 100644
--- a/src/core/or/policies.h
+++ b/src/core/or/policies.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/port_cfg_st.h b/src/core/or/port_cfg_st.h
index e9e82bb1de..064e679d78 100644
--- a/src/core/or/port_cfg_st.h
+++ b/src/core/or/port_cfg_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file port_cfg_st.h
+ * @brief Listener port configuration structure.
+ **/
+
#ifndef PORT_CFG_ST_H
#define PORT_CFG_ST_H
@@ -32,4 +37,3 @@ struct port_cfg_t {
};
#endif /* !defined(PORT_CFG_ST_H) */
-
diff --git a/src/core/or/protover.c b/src/core/or/protover.c
index 905c5e9ed3..2a0a06f951 100644
--- a/src/core/or/protover.c
+++ b/src/core/or/protover.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/protover.h b/src/core/or/protover.h
index af45a31aeb..9509f3e8a3 100644
--- a/src/core/or/protover.h
+++ b/src/core/or/protover.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/protover_rust.c b/src/core/or/protover_rust.c
index bc56ea11d0..f44746b6da 100644
--- a/src/core/or/protover_rust.c
+++ b/src/core/or/protover_rust.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/*
diff --git a/src/core/or/reasons.c b/src/core/or/reasons.c
index e21bfa670a..7da7843cab 100644
--- a/src/core/or/reasons.c
+++ b/src/core/or/reasons.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/reasons.h b/src/core/or/reasons.h
index c45a8bc38d..2e534aab73 100644
--- a/src/core/or/reasons.h
+++ b/src/core/or/reasons.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/relay.c b/src/core/or/relay.c
index f83d2365e4..82353e311f 100644
--- a/src/core/or/relay.c
+++ b/src/core/or/relay.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/relay.h b/src/core/or/relay.h
index 99f7553013..31bed0e01b 100644
--- a/src/core/or/relay.h
+++ b/src/core/or/relay.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -107,7 +107,7 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ,
STATIC int connected_cell_parse(const relay_header_t *rh, const cell_t *cell,
tor_addr_t *addr_out, int *ttl_out);
/** An address-and-ttl tuple as yielded by resolved_cell_parse */
-typedef struct address_ttl_s {
+typedef struct address_ttl_t {
tor_addr_t addr;
char *hostname;
int ttl;
diff --git a/src/core/or/relay_crypto_st.h b/src/core/or/relay_crypto_st.h
index 83bbd329a6..d92f486a90 100644
--- a/src/core/or/relay_crypto_st.h
+++ b/src/core/or/relay_crypto_st.h
@@ -1,13 +1,18 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file relay_crypto_st.h
+ * @brief Relay-cell encryption state structure.
+ **/
+
#ifndef RELAY_CRYPTO_ST_H
#define RELAY_CRYPTO_ST_H
-#define crypto_cipher_t aes_cnt_cipher
+#define crypto_cipher_t aes_cnt_cipher_t
struct crypto_cipher_t;
struct crypto_digest_t;
diff --git a/src/core/or/scheduler.c b/src/core/or/scheduler.c
index 0e3f0fe815..a3869c7ae3 100644
--- a/src/core/or/scheduler.c
+++ b/src/core/or/scheduler.c
@@ -1,18 +1,17 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
#include "app/config/config.h"
#include "lib/evloop/compat_libevent.h"
-#define SCHEDULER_PRIVATE_
+#define SCHEDULER_PRIVATE
#define SCHEDULER_KIST_PRIVATE
#include "core/or/scheduler.h"
#include "core/mainloop/mainloop.h"
#include "lib/buf/buffers.h"
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#include "core/or/channeltls.h"
-#include "lib/evloop/compat_libevent.h"
#include "core/or/or_connection_st.h"
diff --git a/src/core/or/scheduler.h b/src/core/or/scheduler.h
index 843be2603c..82df2b0b0f 100644
--- a/src/core/or/scheduler.h
+++ b/src/core/or/scheduler.h
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* * Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -40,7 +40,7 @@ typedef enum {
* doesn't create any state for itself, thus it has nothing to free when Tor
* is shutting down), then set that function pointer to NULL.
*/
-typedef struct scheduler_s {
+typedef struct scheduler_t {
/* Scheduler type. This is used for logging when the scheduler is switched
* during runtime. */
scheduler_types_t type;
@@ -136,7 +136,9 @@ MOCK_DECL(void, scheduler_channel_has_waiting_cells, (channel_t *chan));
* These functions are only visible to the scheduling system, the current
* scheduler implementation, and tests.
*****************************************************************************/
-#ifdef SCHEDULER_PRIVATE_
+#ifdef SCHEDULER_PRIVATE
+
+#include "ext/ht.h"
/*********************************
* Defined in scheduler.c
@@ -173,8 +175,8 @@ void scheduler_touch_channel(channel_t *chan);
/* Socket table entry which holds information of a channel's socket and kernel
* TCP information. Only used by KIST. */
-typedef struct socket_table_ent_s {
- HT_ENTRY(socket_table_ent_s) node;
+typedef struct socket_table_ent_t {
+ HT_ENTRY(socket_table_ent_t) node;
const channel_t *chan;
/* Amount written this scheduling run */
uint64_t written;
@@ -187,7 +189,7 @@ typedef struct socket_table_ent_s {
uint32_t notsent;
} socket_table_ent_t;
-typedef HT_HEAD(outbuf_table_s, outbuf_table_ent_s) outbuf_table_t;
+typedef HT_HEAD(outbuf_table_s, outbuf_table_ent_t) outbuf_table_t;
MOCK_DECL(int, channel_should_write_to_kernel,
(outbuf_table_t *table, channel_t *chan));
@@ -212,7 +214,6 @@ extern int32_t sched_run_interval;
scheduler_t *get_vanilla_scheduler(void);
-#endif /* defined(SCHEDULER_PRIVATE_) */
+#endif /* defined(SCHEDULER_PRIVATE) */
#endif /* !defined(TOR_SCHEDULER_H) */
-
diff --git a/src/core/or/scheduler_kist.c b/src/core/or/scheduler_kist.c
index 35b613cb8a..e56942be09 100644
--- a/src/core/or/scheduler_kist.c
+++ b/src/core/or/scheduler_kist.c
@@ -1,6 +1,11 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file scheduler_kist.c
+ * @brief Implements the KIST cell scheduler.
+ **/
+
#define SCHEDULER_KIST_PRIVATE
#include "core/or/or.h"
@@ -8,10 +13,10 @@
#include "app/config/config.h"
#include "core/mainloop/connection.h"
#include "feature/nodelist/networkstatus.h"
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#include "core/or/channel.h"
#include "core/or/channeltls.h"
-#define SCHEDULER_PRIVATE_
+#define SCHEDULER_PRIVATE
#include "core/or/scheduler.h"
#include "lib/math/fp.h"
@@ -46,13 +51,13 @@ socket_table_ent_eq(const socket_table_ent_t *a, const socket_table_ent_t *b)
return a->chan == b->chan;
}
-typedef HT_HEAD(socket_table_s, socket_table_ent_s) socket_table_t;
+typedef HT_HEAD(socket_table_s, socket_table_ent_t) socket_table_t;
static socket_table_t socket_table = HT_INITIALIZER();
-HT_PROTOTYPE(socket_table_s, socket_table_ent_s, node, socket_table_ent_hash,
+HT_PROTOTYPE(socket_table_s, socket_table_ent_t, node, socket_table_ent_hash,
socket_table_ent_eq)
-HT_GENERATE2(socket_table_s, socket_table_ent_s, node, socket_table_ent_hash,
+HT_GENERATE2(socket_table_s, socket_table_ent_t, node, socket_table_ent_hash,
socket_table_ent_eq, 0.6, tor_reallocarray, tor_free_)
/* outbuf_table hash table stuff. The outbuf_table keeps track of which
@@ -60,8 +65,8 @@ HT_GENERATE2(socket_table_s, socket_table_ent_s, node, socket_table_ent_hash,
* a write from outbuf to kernel periodically during a run and at the end of a
* run. */
-typedef struct outbuf_table_ent_s {
- HT_ENTRY(outbuf_table_ent_s) node;
+typedef struct outbuf_table_ent_t {
+ HT_ENTRY(outbuf_table_ent_t) node;
channel_t *chan;
} outbuf_table_ent_t;
@@ -77,9 +82,9 @@ outbuf_table_ent_eq(const outbuf_table_ent_t *a, const outbuf_table_ent_t *b)
return a->chan->global_identifier == b->chan->global_identifier;
}
-HT_PROTOTYPE(outbuf_table_s, outbuf_table_ent_s, node, outbuf_table_ent_hash,
+HT_PROTOTYPE(outbuf_table_s, outbuf_table_ent_t, node, outbuf_table_ent_hash,
outbuf_table_ent_eq)
-HT_GENERATE2(outbuf_table_s, outbuf_table_ent_s, node, outbuf_table_ent_hash,
+HT_GENERATE2(outbuf_table_s, outbuf_table_ent_t, node, outbuf_table_ent_hash,
outbuf_table_ent_eq, 0.6, tor_reallocarray, tor_free_)
/*****************************************************************************
diff --git a/src/core/or/scheduler_vanilla.c b/src/core/or/scheduler_vanilla.c
index 33536ae04b..d862ff8710 100644
--- a/src/core/or/scheduler_vanilla.c
+++ b/src/core/or/scheduler_vanilla.c
@@ -1,11 +1,16 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file scheduler_vanilla.c
+ * @brief "Vanilla" (pre-KIST) cell scheduler code.
+ **/
+
#include "core/or/or.h"
#include "app/config/config.h"
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#include "core/or/channel.h"
-#define SCHEDULER_PRIVATE_
+#define SCHEDULER_PRIVATE
#include "core/or/scheduler.h"
/*****************************************************************************
@@ -172,4 +177,3 @@ get_vanilla_scheduler(void)
{
return &vanilla_scheduler;
}
-
diff --git a/src/core/or/sendme.c b/src/core/or/sendme.c
index e61cf0c0f8..788f56088c 100644
--- a/src/core/or/sendme.c
+++ b/src/core/or/sendme.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2019, The Tor Project, Inc. */
+/* Copyright (c) 2019-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/sendme.h b/src/core/or/sendme.h
index 9d757ee435..05d37ec3bb 100644
--- a/src/core/or/sendme.h
+++ b/src/core/or/sendme.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2019, The Tor Project, Inc. */
+/* Copyright (c) 2019-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/server_port_cfg_st.h b/src/core/or/server_port_cfg_st.h
index 0738735c61..9a005eccdf 100644
--- a/src/core/or/server_port_cfg_st.h
+++ b/src/core/or/server_port_cfg_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file server_port_cfg_st.h
+ * @brief Cnfiguration structure for server ports.
+ **/
+
#ifndef SERVER_PORT_CFG_ST_H
#define SERVER_PORT_CFG_ST_H
@@ -17,4 +22,3 @@ struct server_port_cfg_t {
};
#endif /* !defined(SERVER_PORT_CFG_ST_H) */
-
diff --git a/src/core/or/socks_request_st.h b/src/core/or/socks_request_st.h
index 9fb941ff7e..4bcdb48b92 100644
--- a/src/core/or/socks_request_st.h
+++ b/src/core/or/socks_request_st.h
@@ -1,12 +1,19 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file socks_request_st.h
+ * @brief Client request structure.
+ **/
+
#ifndef SOCKS_REQUEST_ST_H
#define SOCKS_REQUEST_ST_H
+#include "lib/net/socks5_status.h"
+
#define MAX_SOCKS_REPLY_LEN 1024
#define SOCKS_NO_AUTH 0x00
@@ -58,6 +65,11 @@ struct socks_request_t {
* "username/password" authentication if both are offered. Used as input to
* parse_socks. */
unsigned int socks_prefer_no_auth : 1;
+ /** If set, we can send back the extended error code in the reply. */
+ unsigned int socks_use_extended_errors : 1;
+ /** If non zero, this contains the extended error code that should be used
+ * if the port was configured to use them. */
+ socks5_reply_status_t socks_extended_error_code;
/** Number of bytes in username; 0 if username is NULL */
size_t usernamelen;
diff --git a/src/core/or/status.c b/src/core/or/status.c
index 46494ca76c..f9f603f3b7 100644
--- a/src/core/or/status.c
+++ b/src/core/or/status.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/status.h b/src/core/or/status.h
index 3467501ebb..639f8cdf51 100644
--- a/src/core/or/status.h
+++ b/src/core/or/status.h
@@ -1,6 +1,11 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file status.h
+ * @brief Header for status.c
+ **/
+
#ifndef TOR_STATUS_H
#define TOR_STATUS_H
@@ -15,4 +20,3 @@ STATIC char *bytes_to_usage(uint64_t bytes);
#endif
#endif /* !defined(TOR_STATUS_H) */
-
diff --git a/src/core/or/tor_version_st.h b/src/core/or/tor_version_st.h
index c5bdcaf07b..46644c5eb8 100644
--- a/src/core/or/tor_version_st.h
+++ b/src/core/or/tor_version_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file tor_version_st.h
+ * @brief Parsed Tor version structure.
+ **/
+
#ifndef TOR_VERSION_ST_H
#define TOR_VERSION_ST_H
@@ -29,4 +34,3 @@ struct tor_version_t {
};
#endif /* !defined(TOR_VERSION_ST_H) */
-
diff --git a/src/core/or/var_cell_st.h b/src/core/or/var_cell_st.h
index 607c0d6c83..caf64c63a5 100644
--- a/src/core/or/var_cell_st.h
+++ b/src/core/or/var_cell_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file var_cell_st.h
+ * @brief Variable-length cell structure.
+ **/
+
#ifndef VAR_CELL_ST_H
#define VAR_CELL_ST_H
@@ -20,4 +25,3 @@ struct var_cell_t {
};
#endif /* !defined(VAR_CELL_ST_H) */
-
diff --git a/src/core/or/versions.c b/src/core/or/versions.c
index 2c32b529f7..a9a960d66e 100644
--- a/src/core/or/versions.c
+++ b/src/core/or/versions.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/versions.h b/src/core/or/versions.h
index 9aa7a0db87..75dc17f9c7 100644
--- a/src/core/or/versions.h
+++ b/src/core/or/versions.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/proto/.may_include b/src/core/proto/.may_include
index c1647a5cf9..a66c3f83a6 100644
--- a/src/core/proto/.may_include
+++ b/src/core/proto/.may_include
@@ -4,7 +4,11 @@ orconfig.h
lib/crypt_ops/*.h
lib/buf/*.h
+lib/malloc/*.h
+lib/string/*.h
+
+lib/net/address.h
trunnel/*.h
-core/proto/*.h \ No newline at end of file
+core/proto/*.h
diff --git a/src/core/proto/core_proto.md b/src/core/proto/core_proto.md
new file mode 100644
index 0000000000..ad43bc5846
--- /dev/null
+++ b/src/core/proto/core_proto.md
@@ -0,0 +1,6 @@
+@dir /core/proto
+@brief core/proto: Protocol encoding/decoding
+
+These functions should (but do not always) exist at a lower level than most
+of the rest of core.
+
diff --git a/src/core/proto/include.am b/src/core/proto/include.am
new file mode 100644
index 0000000000..726ef924cf
--- /dev/null
+++ b/src/core/proto/include.am
@@ -0,0 +1,18 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/core/proto/proto_cell.c \
+ src/core/proto/proto_control0.c \
+ src/core/proto/proto_ext_or.c \
+ src/core/proto/proto_haproxy.c \
+ src/core/proto/proto_http.c \
+ src/core/proto/proto_socks.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/core/proto/proto_cell.h \
+ src/core/proto/proto_control0.h \
+ src/core/proto/proto_ext_or.h \
+ src/core/proto/proto_haproxy.h \
+ src/core/proto/proto_http.h \
+ src/core/proto/proto_socks.h
diff --git a/src/core/proto/proto_cell.c b/src/core/proto/proto_cell.c
index 697fed29e1..5c1a2c24d7 100644
--- a/src/core/proto/proto_cell.c
+++ b/src/core/proto/proto_cell.c
@@ -1,9 +1,16 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file proto_cell.c
+ * @brief Decodes Tor cells from buffers.
+ **/
+/* Right now it only handles variable-length cells, but eventually
+ * we should refactor other cell-reading code into here. */
+
#include "core/or/or.h"
#include "lib/buf/buffers.h"
#include "core/proto/proto_cell.h"
@@ -83,4 +90,3 @@ fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto)
*out = result;
return 1;
}
-
diff --git a/src/core/proto/proto_cell.h b/src/core/proto/proto_cell.h
index 4f3982ea43..0e9cfbfed3 100644
--- a/src/core/proto/proto_cell.h
+++ b/src/core/proto/proto_cell.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file proto_cell.h
+ * @brief Header for proto_cell.c
+ **/
+
#ifndef TOR_PROTO_CELL_H
#define TOR_PROTO_CELL_H
@@ -14,4 +19,3 @@ int fetch_var_cell_from_buf(struct buf_t *buf, struct var_cell_t **out,
int linkproto);
#endif /* !defined(TOR_PROTO_CELL_H) */
-
diff --git a/src/core/proto/proto_control0.c b/src/core/proto/proto_control0.c
index d741f28f09..323b37c539 100644
--- a/src/core/proto/proto_control0.c
+++ b/src/core/proto/proto_control0.c
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file proto_control0.c
+ * @brief Code to detect the obsolete v0 control protocol.
+ **/
+
#include "core/or/or.h"
#include "lib/buf/buffers.h"
#include "core/proto/proto_control0.h"
@@ -23,4 +28,3 @@ peek_buf_has_control0_command(buf_t *buf)
}
return 0;
}
-
diff --git a/src/core/proto/proto_control0.h b/src/core/proto/proto_control0.h
index 162e513a1b..561bf00d19 100644
--- a/src/core/proto/proto_control0.h
+++ b/src/core/proto/proto_control0.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file proto_control0.h
+ * @brief Header for proto_control0.c
+ **/
+
#ifndef TOR_PROTO_CONTROL0_H
#define TOR_PROTO_CONTROL0_H
@@ -11,4 +16,3 @@ struct buf_t;
int peek_buf_has_control0_command(struct buf_t *buf);
#endif /* !defined(TOR_PROTO_CONTROL0_H) */
-
diff --git a/src/core/proto/proto_ext_or.c b/src/core/proto/proto_ext_or.c
index 4213bc14dd..23fc2393b7 100644
--- a/src/core/proto/proto_ext_or.c
+++ b/src/core/proto/proto_ext_or.c
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file proto_ext_or.c
+ * @brief Parsing/encoding for the extended OR protocol.
+ **/
+
#include "core/or/or.h"
#include "lib/buf/buffers.h"
#include "feature/relay/ext_orport.h"
@@ -37,4 +42,3 @@ fetch_ext_or_command_from_buf(buf_t *buf, ext_or_cmd_t **out)
buf_get_bytes(buf, (*out)->body, len);
return 1;
}
-
diff --git a/src/core/proto/proto_ext_or.h b/src/core/proto/proto_ext_or.h
index b2bc64af85..daac3e3eb7 100644
--- a/src/core/proto/proto_ext_or.h
+++ b/src/core/proto/proto_ext_or.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file proto_ext_or.h
+ * @brief Header for proto_ext_or.c
+ **/
+
#ifndef TOR_PROTO_EXT_OR_H
#define TOR_PROTO_EXT_OR_H
diff --git a/src/core/proto/proto_haproxy.c b/src/core/proto/proto_haproxy.c
new file mode 100644
index 0000000000..9129fc55bf
--- /dev/null
+++ b/src/core/proto/proto_haproxy.c
@@ -0,0 +1,45 @@
+/* Copyright (c) 2019-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define PROTO_HAPROXY_PRIVATE
+#include "lib/malloc/malloc.h"
+#include "lib/net/address.h"
+#include "lib/string/printf.h"
+#include "core/proto/proto_haproxy.h"
+
+/** Return a newly allocated PROXY header null-terminated string. Returns NULL
+ * if addr_port->addr is incompatible with the proxy protocol.
+ */
+char *
+haproxy_format_proxy_header_line(const tor_addr_port_t *addr_port)
+{
+ tor_assert(addr_port);
+
+ sa_family_t family = tor_addr_family(&addr_port->addr);
+ const char *family_string = NULL;
+ const char *src_addr_string = NULL;
+
+ switch (family) {
+ case AF_INET:
+ family_string = "TCP4";
+ src_addr_string = "0.0.0.0";
+ break;
+ case AF_INET6:
+ family_string = "TCP6";
+ src_addr_string = "::";
+ break;
+ default:
+ /* Unknown family. */
+ return NULL;
+ }
+
+ char *buf;
+ char addrbuf[TOR_ADDR_BUF_LEN];
+
+ tor_addr_to_str(addrbuf, &addr_port->addr, sizeof(addrbuf), 0);
+
+ tor_asprintf(&buf, "PROXY %s %s %s 0 %d\r\n", family_string, src_addr_string,
+ addrbuf, addr_port->port);
+
+ return buf;
+}
diff --git a/src/core/proto/proto_haproxy.h b/src/core/proto/proto_haproxy.h
new file mode 100644
index 0000000000..63c164e1a1
--- /dev/null
+++ b/src/core/proto/proto_haproxy.h
@@ -0,0 +1,12 @@
+/* Copyright (c) 2019-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_PROTO_HAPROXY_H
+#define TOR_PROTO_HAPROXY_H
+
+struct tor_addr_port_t;
+
+char *haproxy_format_proxy_header_line(
+ const struct tor_addr_port_t *addr_port);
+
+#endif /* !defined(TOR_PROTO_HAPROXY_H) */
diff --git a/src/core/proto/proto_http.c b/src/core/proto/proto_http.c
index 88c59ef561..ef4b897fcc 100644
--- a/src/core/proto/proto_http.c
+++ b/src/core/proto/proto_http.c
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file proto_http.c
+ * @brief Parse a subset of the HTTP protocol.
+ **/
+
#define PROTO_HTTP_PRIVATE
#include "core/or/or.h"
#include "lib/buf/buffers.h"
@@ -168,4 +173,3 @@ buf_http_find_content_length(const char *headers, size_t headerlen,
return ok ? 1 : -1;
}
-
diff --git a/src/core/proto/proto_http.h b/src/core/proto/proto_http.h
index cd70050205..e0c5135346 100644
--- a/src/core/proto/proto_http.h
+++ b/src/core/proto/proto_http.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file proto_http.h
+ * @brief Header for proto_http.c
+ **/
+
#ifndef TOR_PROTO_HTTP_H
#define TOR_PROTO_HTTP_H
@@ -21,4 +26,3 @@ STATIC int buf_http_find_content_length(const char *headers, size_t headerlen,
#endif
#endif /* !defined(TOR_PROTO_HTTP_H) */
-
diff --git a/src/core/proto/proto_socks.c b/src/core/proto/proto_socks.c
index c06e6b1a41..4f39d69d62 100644
--- a/src/core/proto/proto_socks.c
+++ b/src/core/proto/proto_socks.c
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file proto_socks.c
+ * @brief Implementations for SOCKS4 and SOCKS5 protocols.
+ **/
+
#include "core/or/or.h"
#include "feature/client/addressmap.h"
#include "lib/buf/buffers.h"
@@ -105,7 +110,7 @@ socks_request_free_(socks_request_t *req)
/**
* Parse a single SOCKS4 request from buffer <b>raw_data</b> of length
* <b>datalen</b> and update relevant fields of <b>req</b>. If SOCKS4a
- * request is detected, set <b>*is_socks4a<b> to true. Set <b>*drain_out</b>
+ * request is detected, set <b>*is_socks4a</b> to true. Set <b>*drain_out</b>
* to number of bytes we parsed so far.
*
* Return SOCKS_RESULT_DONE if parsing succeeded, SOCKS_RESULT_INVALID if
@@ -615,6 +620,7 @@ process_socks5_client_request(socks_request_t *req,
int safe_socks)
{
socks_result_t res = SOCKS_RESULT_DONE;
+ tor_addr_t tmpaddr;
if (req->command != SOCKS_COMMAND_CONNECT &&
req->command != SOCKS_COMMAND_RESOLVE &&
@@ -625,11 +631,10 @@ process_socks5_client_request(socks_request_t *req,
}
if (req->command == SOCKS_COMMAND_RESOLVE_PTR &&
- !string_is_valid_ipv4_address(req->address) &&
- !string_is_valid_ipv6_address(req->address)) {
+ tor_addr_parse(&tmpaddr, req->address) < 0) {
socks_request_set_socks5_error(req, SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED);
log_warn(LD_APP, "socks5 received RESOLVE_PTR command with "
- "hostname type. Rejecting.");
+ "a malformed address. Rejecting.");
res = SOCKS_RESULT_INVALID;
goto end;
diff --git a/src/core/proto/proto_socks.h b/src/core/proto/proto_socks.h
index 2a387bf848..f3af0d988e 100644
--- a/src/core/proto/proto_socks.h
+++ b/src/core/proto/proto_socks.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file proto_socks.h
+ * @brief Header for proto_socks.c
+ **/
+
#ifndef TOR_PROTO_SOCKS_H
#define TOR_PROTO_SOCKS_H
diff --git a/src/ext/ed25519/ref10/base.py b/src/ext/ed25519/ref10/base.py
index 84accc8580..3d477c5c39 100644
--- a/src/ext/ed25519/ref10/base.py
+++ b/src/ext/ed25519/ref10/base.py
@@ -1,3 +1,8 @@
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
b = 256
q = 2**255 - 19
l = 2**252 + 27742317777372353535851937790883648493
@@ -51,15 +56,15 @@ def radix255(x):
Bi = B
for i in range(32):
- print "{"
+ print("{")
Bij = Bi
for j in range(8):
- print " {"
- print " {",radix255(Bij[1]+Bij[0]),"},"
- print " {",radix255(Bij[1]-Bij[0]),"},"
- print " {",radix255(2*d*Bij[0]*Bij[1]),"},"
+ print(" {")
+ print(" {",radix255(Bij[1]+Bij[0]),"},")
+ print(" {",radix255(Bij[1]-Bij[0]),"},")
+ print(" {",radix255(2*d*Bij[0]*Bij[1]),"},")
Bij = edwards(Bij,Bi)
- print " },"
- print "},"
+ print(" },")
+ print("},")
for k in range(8):
Bi = edwards(Bi,Bi)
diff --git a/src/ext/ed25519/ref10/base2.py b/src/ext/ed25519/ref10/base2.py
index 5e4e8739d0..3f8e3d25d2 100644
--- a/src/ext/ed25519/ref10/base2.py
+++ b/src/ext/ed25519/ref10/base2.py
@@ -1,3 +1,8 @@
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
b = 256
q = 2**255 - 19
l = 2**252 + 27742317777372353535851937790883648493
@@ -52,9 +57,9 @@ def radix255(x):
Bi = B
for i in range(8):
- print " {"
- print " {",radix255(Bi[1]+Bi[0]),"},"
- print " {",radix255(Bi[1]-Bi[0]),"},"
- print " {",radix255(2*d*Bi[0]*Bi[1]),"},"
- print " },"
+ print(" {")
+ print(" {",radix255(Bi[1]+Bi[0]),"},")
+ print(" {",radix255(Bi[1]-Bi[0]),"},")
+ print(" {",radix255(2*d*Bi[0]*Bi[1]),"},")
+ print(" },")
Bi = edwards(B,edwards(B,Bi))
diff --git a/src/ext/ed25519/ref10/d.py b/src/ext/ed25519/ref10/d.py
index 8995bb86a3..5b875de666 100644
--- a/src/ext/ed25519/ref10/d.py
+++ b/src/ext/ed25519/ref10/d.py
@@ -1,3 +1,8 @@
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
q = 2**255 - 19
def expmod(b,e,m):
@@ -25,4 +30,4 @@ def radix255(x):
return result
d = -121665 * inv(121666)
-print radix255(d)
+print(radix255(d))
diff --git a/src/ext/ed25519/ref10/d2.py b/src/ext/ed25519/ref10/d2.py
index 79841758be..f59a1bc62a 100644
--- a/src/ext/ed25519/ref10/d2.py
+++ b/src/ext/ed25519/ref10/d2.py
@@ -1,3 +1,8 @@
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
q = 2**255 - 19
def expmod(b,e,m):
@@ -25,4 +30,4 @@ def radix255(x):
return result
d = -121665 * inv(121666)
-print radix255(d*2)
+print(radix255(d*2))
diff --git a/src/ext/ed25519/ref10/sqrtm1.py b/src/ext/ed25519/ref10/sqrtm1.py
index 9a47fbc12a..df9f26ee1d 100644
--- a/src/ext/ed25519/ref10/sqrtm1.py
+++ b/src/ext/ed25519/ref10/sqrtm1.py
@@ -1,3 +1,8 @@
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
q = 2**255 - 19
def expmod(b,e,m):
@@ -25,4 +30,4 @@ def radix255(x):
return result
I = expmod(2,(q-1)/4,q)
-print radix255(I)
+print(radix255(I))
diff --git a/src/ext/ht.h b/src/ext/ht.h
index 54e5eb7cba..9d4add1936 100644
--- a/src/ext/ht.h
+++ b/src/ext/ht.h
@@ -226,7 +226,8 @@ ht_string_hash(const char *s)
(x) = HT_NEXT(name, head, x))
#ifndef HT_NDEBUG
-#define HT_ASSERT_(x) tor_assert(x)
+#include "lib/err/torerr.h"
+#define HT_ASSERT_(x) raw_assert(x)
#else
#define HT_ASSERT_(x) (void)0
#endif
@@ -370,7 +371,8 @@ ht_string_hash(const char *s)
/* Return the next element in 'head' after 'elm', under the arbitrary \
* order used by HT_START. If there are no more elements, return \
* NULL. If 'elm' is to be removed from the table, you must call \
- * this function for the next value before you remove it. \
+ * this function for the next value before you remove it, or use \
+ * HT_NEXT_RMV instead. \
*/ \
ATTR_UNUSED static inline struct type ** \
name##_HT_NEXT(struct name *head, struct type **elm) \
@@ -392,6 +394,8 @@ ht_string_hash(const char *s)
return NULL; \
} \
} \
+ /* As HT_NEXT, but also remove the current element 'elm' from the \
+ * table. */ \
ATTR_UNUSED static inline struct type ** \
name##_HT_NEXT_RMV(struct name *head, struct type **elm) \
{ \
@@ -617,4 +621,3 @@ ht_string_hash(const char *s)
*/
#endif
-
diff --git a/src/ext/siphash.h b/src/ext/siphash.h
index 730e49937d..0207a959ff 100644
--- a/src/ext/siphash.h
+++ b/src/ext/siphash.h
@@ -1,6 +1,8 @@
#ifndef SIPHASH_H
#define SIPHASH_H
+#include <stdint.h>
+
struct sipkey {
uint64_t k0;
uint64_t k1;
diff --git a/src/ext/timeouts/timeout.h b/src/ext/timeouts/timeout.h
index 1ed309fd08..f1028bfc80 100644
--- a/src/ext/timeouts/timeout.h
+++ b/src/ext/timeouts/timeout.h
@@ -89,10 +89,10 @@ typedef uint64_t timeout_t;
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef TIMEOUT_CB_OVERRIDE
-struct timeout_cb {
+struct timeout_cb_t {
void (*fn)(void);
void *arg;
-}; /* struct timeout_cb */
+}; /* struct timeout_cb_t */
#endif
/*
@@ -125,7 +125,7 @@ struct timeout {
/* entry member for struct timeout_list lists */
#ifndef TIMEOUT_DISABLE_CALLBACKS
- struct timeout_cb callback;
+ struct timeout_cb_t callback;
/* optional callback information */
#endif
diff --git a/src/ext/tinytest_macros.h b/src/ext/tinytest_macros.h
index c3728d1fdd..6fc2cea2da 100644
--- a/src/ext/tinytest_macros.h
+++ b/src/ext/tinytest_macros.h
@@ -99,11 +99,11 @@
/* Assert b, but do not stop the test if b fails. Log msg on failure. */
#define tt_want_msg(b, msg) \
- tt_want_(b, msg, );
+ tt_want_(b, msg, )
/* Assert b and stop the test if b fails. Log msg on failure. */
#define tt_assert_msg(b, msg) \
- tt_want_(b, msg, TT_EXIT_TEST_FUNCTION);
+ tt_want_(b, msg, TT_EXIT_TEST_FUNCTION)
/* Assert b, but do not stop the test if b fails. */
#define tt_want(b) tt_want_msg( (b), "want("#b")")
diff --git a/src/feature/api/.may_include b/src/feature/api/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/api/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/api/feature_api.md b/src/feature/api/feature_api.md
new file mode 100644
index 0000000000..3065c000aa
--- /dev/null
+++ b/src/feature/api/feature_api.md
@@ -0,0 +1,2 @@
+@dir /feature/api
+@brief feature/api: In-process interface to starting/stopping Tor.
diff --git a/src/feature/api/include.am b/src/feature/api/include.am
new file mode 100644
index 0000000000..8d490458d4
--- /dev/null
+++ b/src/feature/api/include.am
@@ -0,0 +1,11 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/api/tor_api.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/api/tor_api_internal.h
+
+# This may someday want to be an installed file?
+noinst_HEADERS += src/feature/api/tor_api.h
diff --git a/src/feature/api/tor_api.c b/src/feature/api/tor_api.c
index e270c51ac9..531793301e 100644
--- a/src/feature/api/tor_api.c
+++ b/src/feature/api/tor_api.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/api/tor_api.h b/src/feature/api/tor_api.h
index cb84853a52..e9993bb0d5 100644
--- a/src/feature/api/tor_api.h
+++ b/src/feature/api/tor_api.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/api/tor_api_internal.h b/src/feature/api/tor_api_internal.h
index 60e0f3aa59..d52b2caf44 100644
--- a/src/feature/api/tor_api_internal.h
+++ b/src/feature/api/tor_api_internal.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file tor_api_internal.h
+ * @brief Internal declarations for in-process Tor API.
+ **/
+
#ifndef TOR_API_INTERNAL_H
#define TOR_API_INTERNAL_H
diff --git a/src/feature/client/.may_include b/src/feature/client/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/client/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/client/addressmap.c b/src/feature/client/addressmap.c
index c5a27ce8c6..1a6958d38c 100644
--- a/src/feature/client/addressmap.c
+++ b/src/feature/client/addressmap.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/client/addressmap.h b/src/feature/client/addressmap.h
index 9179aef1d0..7f1024e09a 100644
--- a/src/feature/client/addressmap.h
+++ b/src/feature/client/addressmap.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file addressmap.h
+ * @brief Header for addressmap.c
+ **/
+
#ifndef TOR_ADDRESSMAP_H
#define TOR_ADDRESSMAP_H
@@ -62,4 +67,3 @@ STATIC void get_random_virtual_addr(const virtual_addr_conf_t *conf,
#endif /* defined(ADDRESSMAP_PRIVATE) */
#endif /* !defined(TOR_ADDRESSMAP_H) */
-
diff --git a/src/feature/client/bridges.c b/src/feature/client/bridges.c
index f517876609..2b52a1173d 100644
--- a/src/feature/client/bridges.c
+++ b/src/feature/client/bridges.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/client/bridges.h b/src/feature/client/bridges.h
index 27b2750a45..174149cf97 100644
--- a/src/feature/client/bridges.h
+++ b/src/feature/client/bridges.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/client/circpathbias.c b/src/feature/client/circpathbias.c
index 60a52664f1..4ac5cb8fc9 100644
--- a/src/feature/client/circpathbias.c
+++ b/src/feature/client/circpathbias.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/client/circpathbias.h b/src/feature/client/circpathbias.h
index a9a8d18df2..88cc982dd4 100644
--- a/src/feature/client/circpathbias.h
+++ b/src/feature/client/circpathbias.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/client/dnsserv.c b/src/feature/client/dnsserv.c
index f9e436e88f..c1981ecde0 100644
--- a/src/feature/client/dnsserv.c
+++ b/src/feature/client/dnsserv.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/client/dnsserv.h b/src/feature/client/dnsserv.h
index fff1ed2adb..4011cb4e02 100644
--- a/src/feature/client/dnsserv.h
+++ b/src/feature/client/dnsserv.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/client/entrynodes.c b/src/feature/client/entrynodes.c
index 115d871843..148e6471ba 100644
--- a/src/feature/client/entrynodes.c
+++ b/src/feature/client/entrynodes.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -114,7 +114,7 @@
#include "core/or/or.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "app/config/statefile.h"
#include "core/mainloop/connection.h"
#include "core/mainloop/mainloop.h"
@@ -1038,7 +1038,7 @@ get_max_sample_size(guard_selection_t *gs,
* Return a smartlist of the all the guards that are not currently
* members of the sample (GUARDS - SAMPLED_GUARDS). The elements of
* this list are node_t pointers in the non-bridge case, and
- * bridge_info_t pointers in the bridge case. Set *<b>n_guards_out/b>
+ * bridge_info_t pointers in the bridge case. Set *<b>n_guards_out</b>
* to the number of guards that we found in GUARDS, including those
* that were already sampled.
*/
diff --git a/src/feature/client/entrynodes.h b/src/feature/client/entrynodes.h
index 4e5eb4e960..6eede2c8d4 100644
--- a/src/feature/client/entrynodes.h
+++ b/src/feature/client/entrynodes.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,7 +15,7 @@
#include "lib/container/handles.h"
/* Forward declare for guard_selection_t; entrynodes.c has the real struct */
-typedef struct guard_selection_s guard_selection_t;
+typedef struct guard_selection_t guard_selection_t;
/* Forward declare for entry_guard_t; the real declaration is private. */
typedef struct entry_guard_t entry_guard_t;
@@ -28,7 +28,7 @@ typedef struct circuit_guard_state_t circuit_guard_state_t;
private. */
typedef struct entry_guard_restriction_t entry_guard_restriction_t;
-/* Information about a guard's pathbias status.
+/** Information about a guard's pathbias status.
* These fields are used in circpathbias.c to try to detect entry
* nodes that are failing circuits at a suspicious frequency.
*/
@@ -210,7 +210,7 @@ typedef enum guard_selection_type_t {
* See the module documentation for entrynodes.c for more information
* about guard selection algorithms.
*/
-struct guard_selection_s {
+struct guard_selection_t {
/**
* The name for this guard-selection object. (Must not contain spaces).
*/
diff --git a/src/feature/client/feature_client.md b/src/feature/client/feature_client.md
new file mode 100644
index 0000000000..dd4bf78ec8
--- /dev/null
+++ b/src/feature/client/feature_client.md
@@ -0,0 +1,5 @@
+@dir /feature/client
+@brief feature/client: Client-specific code
+
+(There is also a bunch of client-specific code in other modules.)
+
diff --git a/src/feature/client/include.am b/src/feature/client/include.am
new file mode 100644
index 0000000000..53c9f047d4
--- /dev/null
+++ b/src/feature/client/include.am
@@ -0,0 +1,20 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/client/addressmap.c \
+ src/feature/client/bridges.c \
+ src/feature/client/circpathbias.c \
+ src/feature/client/dnsserv.c \
+ src/feature/client/entrynodes.c \
+ src/feature/client/proxymode.c \
+ src/feature/client/transports.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/client/addressmap.h \
+ src/feature/client/bridges.h \
+ src/feature/client/circpathbias.h \
+ src/feature/client/dnsserv.h \
+ src/feature/client/entrynodes.h \
+ src/feature/client/proxymode.h \
+ src/feature/client/transports.h
diff --git a/src/feature/client/proxymode.c b/src/feature/client/proxymode.c
new file mode 100644
index 0000000000..aa269ec7fb
--- /dev/null
+++ b/src/feature/client/proxymode.c
@@ -0,0 +1,32 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file proxymode.c
+ * @brief Determine whether we are trying to be a proxy.
+ **/
+
+#include "core/or/or.h"
+
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/port_cfg_st.h"
+#include "feature/client/proxymode.h"
+
+/** Return true iff we are trying to proxy client connections. */
+int
+proxy_mode(const or_options_t *options)
+{
+ (void)options;
+ SMARTLIST_FOREACH_BEGIN(get_configured_ports(), const port_cfg_t *, p) {
+ if (p->type == CONN_TYPE_AP_LISTENER ||
+ p->type == CONN_TYPE_AP_TRANS_LISTENER ||
+ p->type == CONN_TYPE_AP_DNS_LISTENER ||
+ p->type == CONN_TYPE_AP_NATD_LISTENER)
+ return 1;
+ } SMARTLIST_FOREACH_END(p);
+ return 0;
+}
diff --git a/src/feature/client/proxymode.h b/src/feature/client/proxymode.h
new file mode 100644
index 0000000000..30be08ff78
--- /dev/null
+++ b/src/feature/client/proxymode.h
@@ -0,0 +1,17 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file proxymode.h
+ * \brief Header file for proxymode.c.
+ **/
+
+#ifndef TOR_PROXYMODE_H
+#define TOR_PROXYMODE_H
+
+int proxy_mode(const or_options_t *options);
+
+#endif /* !defined(TOR_PROXYMODE_H) */
diff --git a/src/feature/client/transports.c b/src/feature/client/transports.c
index 3f731ac7d4..a8ea9781a4 100644
--- a/src/feature/client/transports.c
+++ b/src/feature/client/transports.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2019, The Tor Project, Inc. */
+/* Copyright (c) 2011-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -97,6 +97,8 @@
#include "core/or/circuitbuild.h"
#include "feature/client/transports.h"
#include "feature/relay/router.h"
+/* 31851: split the server transport code out of the client module */
+#include "feature/relay/transport_config.h"
#include "app/config/statefile.h"
#include "core/or/connection_or.h"
#include "feature/relay/ext_orport.h"
@@ -733,6 +735,9 @@ get_pt_proxy_uri(void)
const or_options_t *options = get_options();
char *uri = NULL;
+ /* XXX: Currently TCPProxy is not supported in TOR_PT_PROXY because
+ * there isn't a standard URI scheme for some proxy protocols, such as
+ * haproxy. */
if (options->Socks4Proxy || options->Socks5Proxy || options->HTTPSProxy) {
char addr[TOR_ADDR_BUF_LEN+1];
@@ -1279,7 +1284,7 @@ get_transport_options_for_server_proxy(const managed_proxy_t *mp)
string. */
SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, const char *, transport) {
smartlist_t *options_tmp_sl = NULL;
- options_tmp_sl = get_options_for_server_transport(transport);
+ options_tmp_sl = pt_get_options_for_server_transport(transport);
if (!options_tmp_sl)
continue;
@@ -1853,7 +1858,9 @@ managed_proxy_stderr_callback(process_t *process,
if (BUG(mp == NULL))
return;
- log_warn(LD_PT, "Managed proxy at '%s' reported: %s", mp->argv[0], line);
+ log_info(LD_PT,
+ "Managed proxy at '%s' reported via standard error: %s",
+ mp->argv[0], line);
}
/** Callback function that is called when our PT process terminates. The
diff --git a/src/feature/client/transports.h b/src/feature/client/transports.h
index 900dd9288e..1ed942c175 100644
--- a/src/feature/client/transports.h
+++ b/src/feature/client/transports.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/.may_include b/src/feature/control/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/control/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/control/btrack.c b/src/feature/control/btrack.c
index 3ce97dc855..874150ee13 100644
--- a/src/feature/control/btrack.c
+++ b/src/feature/control/btrack.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/btrack_circuit.c b/src/feature/control/btrack_circuit.c
index 2980c77ddc..be51b51046 100644
--- a/src/feature/control/btrack_circuit.c
+++ b/src/feature/control/btrack_circuit.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/btrack_circuit.h b/src/feature/control/btrack_circuit.h
index b326c22ccf..75699450c3 100644
--- a/src/feature/control/btrack_circuit.h
+++ b/src/feature/control/btrack_circuit.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/btrack_orconn.c b/src/feature/control/btrack_orconn.c
index 922b542a0c..104c8af230 100644
--- a/src/feature/control/btrack_orconn.c
+++ b/src/feature/control/btrack_orconn.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/btrack_orconn.h b/src/feature/control/btrack_orconn.h
index 07b1b755f3..8b3d8be37d 100644
--- a/src/feature/control/btrack_orconn.h
+++ b/src/feature/control/btrack_orconn.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/btrack_orconn_cevent.c b/src/feature/control/btrack_orconn_cevent.c
index a00eb042d5..d11be59280 100644
--- a/src/feature/control/btrack_orconn_cevent.c
+++ b/src/feature/control/btrack_orconn_cevent.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -45,6 +45,7 @@ using_proxy(const bt_orconn_t *bto)
case PROXY_CONNECT:
case PROXY_SOCKS4:
case PROXY_SOCKS5:
+ case PROXY_HAPROXY:
return true;
default:
return false;
diff --git a/src/feature/control/btrack_orconn_cevent.h b/src/feature/control/btrack_orconn_cevent.h
index afec55581e..8b2207721e 100644
--- a/src/feature/control/btrack_orconn_cevent.h
+++ b/src/feature/control/btrack_orconn_cevent.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/btrack_orconn_maps.c b/src/feature/control/btrack_orconn_maps.c
index e64bd3f0fe..0ef54237a8 100644
--- a/src/feature/control/btrack_orconn_maps.c
+++ b/src/feature/control/btrack_orconn_maps.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/btrack_orconn_maps.h b/src/feature/control/btrack_orconn_maps.h
index c2043fa153..c83b22b1e8 100644
--- a/src/feature/control/btrack_orconn_maps.h
+++ b/src/feature/control/btrack_orconn_maps.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/btrack_sys.h b/src/feature/control/btrack_sys.h
index 3f831d0640..5a157b7b54 100644
--- a/src/feature/control/btrack_sys.h
+++ b/src/feature/control/btrack_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/control.c b/src/feature/control/control.c
index ece5616907..ee1026359d 100644
--- a/src/feature/control/control.c
+++ b/src/feature/control/control.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/control.h b/src/feature/control/control.h
index 8d3595d2ed..7e72b2736b 100644
--- a/src/feature/control/control.h
+++ b/src/feature/control/control.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/control_auth.c b/src/feature/control/control_auth.c
index a574d07b33..b60623ab5c 100644
--- a/src/feature/control/control_auth.c
+++ b/src/feature/control/control_auth.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/control_auth.h b/src/feature/control/control_auth.h
index 246e18ccbc..d4c1dd78a7 100644
--- a/src/feature/control/control_auth.h
+++ b/src/feature/control/control_auth.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/control_bootstrap.c b/src/feature/control/control_bootstrap.c
index 098e24682e..2e78fad690 100644
--- a/src/feature/control/control_bootstrap.c
+++ b/src/feature/control/control_bootstrap.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/control_cmd.c b/src/feature/control/control_cmd.c
index 68d05abb73..8259c3b353 100644
--- a/src/feature/control/control_cmd.c
+++ b/src/feature/control/control_cmd.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,7 +13,7 @@
#include "core/or/or.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "app/main/main.h"
#include "core/mainloop/connection.h"
#include "core/or/circuitbuild.h"
@@ -26,6 +26,7 @@
#include "feature/control/control.h"
#include "feature/control/control_auth.h"
#include "feature/control/control_cmd.h"
+#include "feature/control/control_hs.h"
#include "feature/control/control_events.h"
#include "feature/control/control_getinfo.h"
#include "feature/control/control_proto.h"
@@ -288,26 +289,23 @@ handle_control_getconf(control_connection_t *conn,
const smartlist_t *questions = args->args;
smartlist_t *answers = smartlist_new();
smartlist_t *unrecognized = smartlist_new();
- char *msg = NULL;
- size_t msg_len;
const or_options_t *options = get_options();
- int i, len;
SMARTLIST_FOREACH_BEGIN(questions, const char *, q) {
if (!option_is_recognized(q)) {
- smartlist_add(unrecognized, (char*) q);
+ control_reply_add_printf(unrecognized, 552,
+ "Unrecognized configuration key \"%s\"", q);
} else {
config_line_t *answer = option_get_assignment(options,q);
if (!answer) {
const char *name = option_get_canonical_name(q);
- smartlist_add_asprintf(answers, "250-%s\r\n", name);
+ control_reply_add_one_kv(answers, 250, KV_OMIT_VALS, name, "");
}
while (answer) {
config_line_t *next;
- smartlist_add_asprintf(answers, "250-%s=%s\r\n",
- answer->key, answer->value);
-
+ control_reply_add_one_kv(answers, 250, KV_RAW, answer->key,
+ answer->value);
next = answer->next;
tor_free(answer->key);
tor_free(answer->value);
@@ -317,30 +315,16 @@ handle_control_getconf(control_connection_t *conn,
}
} SMARTLIST_FOREACH_END(q);
- if ((len = smartlist_len(unrecognized))) {
- for (i=0; i < len-1; ++i)
- control_printf_midreply(conn, 552,
- "Unrecognized configuration key \"%s\"",
- (char*)smartlist_get(unrecognized, i));
- control_printf_endreply(conn, 552,
- "Unrecognized configuration key \"%s\"",
- (char*)smartlist_get(unrecognized, len-1));
- } else if ((len = smartlist_len(answers))) {
- char *tmp = smartlist_get(answers, len-1);
- tor_assert(strlen(tmp)>4);
- tmp[3] = ' ';
- msg = smartlist_join_strings(answers, "", 0, &msg_len);
- connection_buf_add(msg, msg_len, TO_CONN(conn));
+ if (smartlist_len(unrecognized)) {
+ control_write_reply_lines(conn, unrecognized);
+ } else if (smartlist_len(answers)) {
+ control_write_reply_lines(conn, answers);
} else {
send_control_done(conn);
}
- SMARTLIST_FOREACH(answers, char *, cp, tor_free(cp));
- smartlist_free(answers);
- smartlist_free(unrecognized);
-
- tor_free(msg);
-
+ control_reply_free(answers);
+ control_reply_free(unrecognized);
return 0;
}
@@ -590,7 +574,7 @@ control_setconf_helper(control_connection_t *conn,
const unsigned flags =
CAL_CLEAR_FIRST | (use_defaults ? CAL_USE_DEFAULTS : 0);
- // We need a copy here, since confparse.c wants to canonicalize cases.
+ // We need a copy here, since confmgt.c wants to canonicalize cases.
config_line_t *lines = config_lines_dup(args->kwargs);
opt_err = options_trial_assign(lines, flags, &errstring);
@@ -1256,6 +1240,66 @@ static const control_cmd_syntax_t protocolinfo_syntax = {
.max_args = UINT_MAX
};
+/** Return a comma-separated list of authentication methods for
+ handle_control_protocolinfo(). Caller must free this string. */
+static char *
+get_authmethods(const or_options_t *options)
+{
+ int cookies = options->CookieAuthentication;
+ char *methods;
+ int passwd = (options->HashedControlPassword != NULL ||
+ options->HashedControlSessionPassword != NULL);
+ smartlist_t *mlist = smartlist_new();
+
+ if (cookies) {
+ smartlist_add(mlist, (char*)"COOKIE");
+ smartlist_add(mlist, (char*)"SAFECOOKIE");
+ }
+ if (passwd)
+ smartlist_add(mlist, (char*)"HASHEDPASSWORD");
+ if (!cookies && !passwd)
+ smartlist_add(mlist, (char*)"NULL");
+ methods = smartlist_join_strings(mlist, ",", 0, NULL);
+ smartlist_free(mlist);
+
+ return methods;
+}
+
+/** Return escaped cookie filename. Caller must free this string.
+ Return NULL if cookie authentication is disabled. */
+static char *
+get_esc_cfile(const or_options_t *options)
+{
+ char *cfile = NULL, *abs_cfile = NULL, *esc_cfile = NULL;
+
+ if (!options->CookieAuthentication)
+ return NULL;
+
+ cfile = get_controller_cookie_file_name();
+ abs_cfile = make_path_absolute(cfile);
+ esc_cfile = esc_for_log(abs_cfile);
+ tor_free(cfile);
+ tor_free(abs_cfile);
+ return esc_cfile;
+}
+
+/** Compose the auth methods line of a PROTOCOLINFO reply. */
+static void
+add_authmethods(smartlist_t *reply)
+{
+ const or_options_t *options = get_options();
+ char *methods = get_authmethods(options);
+ char *esc_cfile = get_esc_cfile(options);
+
+ control_reply_add_str(reply, 250, "AUTH");
+ control_reply_append_kv(reply, "METHODS", methods);
+ if (esc_cfile)
+ control_reply_append_kv(reply, "COOKIEFILE", esc_cfile);
+
+ tor_free(methods);
+ tor_free(esc_cfile);
+}
+
/** Called when we get a PROTOCOLINFO command: send back a reply. */
static int
handle_control_protocolinfo(control_connection_t *conn,
@@ -1263,6 +1307,7 @@ handle_control_protocolinfo(control_connection_t *conn,
{
const char *bad_arg = NULL;
const smartlist_t *args = cmd_args->args;
+ smartlist_t *reply = NULL;
conn->have_sent_protocolinfo = 1;
@@ -1280,45 +1325,17 @@ handle_control_protocolinfo(control_connection_t *conn,
/* Don't tolerate bad arguments when not authenticated. */
if (!STATE_IS_OPEN(TO_CONN(conn)->state))
connection_mark_for_close(TO_CONN(conn));
- goto done;
- } else {
- const or_options_t *options = get_options();
- int cookies = options->CookieAuthentication;
- char *cfile = get_controller_cookie_file_name();
- char *abs_cfile;
- char *esc_cfile;
- char *methods;
- abs_cfile = make_path_absolute(cfile);
- esc_cfile = esc_for_log(abs_cfile);
- {
- int passwd = (options->HashedControlPassword != NULL ||
- options->HashedControlSessionPassword != NULL);
- smartlist_t *mlist = smartlist_new();
- if (cookies) {
- smartlist_add(mlist, (char*)"COOKIE");
- smartlist_add(mlist, (char*)"SAFECOOKIE");
- }
- if (passwd)
- smartlist_add(mlist, (char*)"HASHEDPASSWORD");
- if (!cookies && !passwd)
- smartlist_add(mlist, (char*)"NULL");
- methods = smartlist_join_strings(mlist, ",", 0, NULL);
- smartlist_free(mlist);
- }
-
- control_write_midreply(conn, 250, "PROTOCOLINFO 1");
- control_printf_midreply(conn, 250, "AUTH METHODS=%s%s%s", methods,
- cookies?" COOKIEFILE=":"",
- cookies?esc_cfile:"");
- control_printf_midreply(conn, 250, "VERSION Tor=%s", escaped(VERSION));
- send_control_done(conn);
-
- tor_free(methods);
- tor_free(cfile);
- tor_free(abs_cfile);
- tor_free(esc_cfile);
+ return 0;
}
- done:
+ reply = smartlist_new();
+ control_reply_add_str(reply, 250, "PROTOCOLINFO 1");
+ add_authmethods(reply);
+ control_reply_add_str(reply, 250, "VERSION");
+ control_reply_append_kv(reply, "Tor", escaped(VERSION));
+ control_reply_add_done(reply);
+
+ control_write_reply_lines(conn, reply);
+ control_reply_free(reply);
return 0;
}
@@ -1970,6 +1987,7 @@ add_onion_helper_keyarg(const char *arg, int discard_pk,
decoded_key->v2 = pk;
*hs_version = HS_VERSION_TWO;
} else if (!strcasecmp(key_type_ed25519_v3, key_type)) {
+ /* parsing of private ed25519 key */
/* "ED25519-V3:<Base64 Blob>" - Loading a pre-existing ed25519 key. */
ed25519_secret_key_t *sk = tor_malloc_zero(sizeof(*sk));
if (base64_decode((char *) sk->seckey, sizeof(sk->seckey), key_blob,
@@ -2248,6 +2266,7 @@ typedef struct control_cmd_def_t {
*/
#define CMD_FL_WIPE (1u<<0)
+#ifndef COCCI
/** Macro: declare a command with a one-line argument, a given set of flags,
* and a syntax definition.
**/
@@ -2280,6 +2299,7 @@ typedef struct control_cmd_def_t {
0, \
&obsolete_syntax, \
}
+#endif /* !defined(COCCI) */
/**
* An array defining all the recognized controller commands.
@@ -2315,6 +2335,9 @@ static const control_cmd_def_t CONTROL_COMMANDS[] =
MULTLINE(hspost, 0),
ONE_LINE(add_onion, CMD_FL_WIPE),
ONE_LINE(del_onion, CMD_FL_WIPE),
+ ONE_LINE(onion_client_auth_add, CMD_FL_WIPE),
+ ONE_LINE(onion_client_auth_remove, 0),
+ ONE_LINE(onion_client_auth_view, 0),
};
/**
diff --git a/src/feature/control/control_cmd.h b/src/feature/control/control_cmd.h
index 4b6d54abe7..0ff0f0755f 100644
--- a/src/feature/control/control_cmd.h
+++ b/src/feature/control/control_cmd.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/control_cmd_args_st.h b/src/feature/control/control_cmd_args_st.h
index 8d7a4f55b3..e7d064c6fe 100644
--- a/src/feature/control/control_cmd_args_st.h
+++ b/src/feature/control/control_cmd_args_st.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/control_connection_st.h b/src/feature/control/control_connection_st.h
index c9164f03b3..9e410324e0 100644
--- a/src/feature/control/control_connection_st.h
+++ b/src/feature/control/control_connection_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file control_connection_st.h
+ * @brief Controller connection structure.
+ **/
+
#ifndef CONTROL_CONNECTION_ST_H
#define CONTROL_CONNECTION_ST_H
diff --git a/src/feature/control/control_events.c b/src/feature/control/control_events.c
index 8cf6d6de0b..916ccea875 100644
--- a/src/feature/control/control_events.c
+++ b/src/feature/control/control_events.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -38,6 +38,7 @@
#include "core/or/origin_circuit_st.h"
#include "lib/evloop/compat_libevent.h"
+#include "lib/encoding/confline.h"
static void flush_queued_events_cb(mainloop_event_t *event, void *arg);
static void control_get_bytes_rw_last_sec(uint64_t *r, uint64_t *w);
@@ -317,7 +318,7 @@ control_per_second_events(void)
/** Represents an event that's queued to be sent to one or more
* controllers. */
-typedef struct queued_event_s {
+typedef struct queued_event_t {
uint16_t event;
char *msg;
} queued_event_t;
@@ -833,13 +834,19 @@ control_event_stream_status(entry_connection_t *conn, stream_status_event_t tp,
circ = circuit_get_by_edge_conn(ENTRY_TO_EDGE_CONN(conn));
if (circ && CIRCUIT_IS_ORIGIN(circ))
origin_circ = TO_ORIGIN_CIRCUIT(circ);
- send_control_event(EVENT_STREAM_STATUS,
- "650 STREAM %"PRIu64" %s %lu %s%s%s%s\r\n",
+
+ {
+ char *conndesc = entry_connection_describe_status_for_controller(conn);
+ const char *sp = strlen(conndesc) ? " " : "";
+ send_control_event(EVENT_STREAM_STATUS,
+ "650 STREAM %"PRIu64" %s %lu %s%s%s%s%s%s\r\n",
(ENTRY_TO_CONN(conn)->global_identifier),
status,
origin_circ?
(unsigned long)origin_circ->global_identifier : 0ul,
- buf, reason_buf, addrport_buf, purpose);
+ buf, reason_buf, addrport_buf, purpose, sp, conndesc);
+ tor_free(conndesc);
+ }
/* XXX need to specify its intended exit, etc? */
@@ -1211,7 +1218,7 @@ control_event_circuit_cell_stats(void)
static int next_measurement_idx = 0;
/* number of entries set in n_measurements */
static int n_measurements = 0;
-static struct cached_bw_event_s {
+static struct cached_bw_event_t {
uint32_t n_read;
uint32_t n_written;
} cached_bw_events[N_BW_EVENTS_TO_CACHE];
@@ -1250,7 +1257,7 @@ get_bw_samples(void)
for (i = 0; i < n_measurements; ++i) {
tor_assert(0 <= idx && idx < N_BW_EVENTS_TO_CACHE);
- const struct cached_bw_event_s *bwe = &cached_bw_events[idx];
+ const struct cached_bw_event_t *bwe = &cached_bw_events[idx];
smartlist_add_asprintf(elements, "%u,%u",
(unsigned)bwe->n_read,
@@ -1641,13 +1648,17 @@ control_event_status(int type, int severity, const char *format, va_list args)
log_warn(LD_BUG, "Format string too long.");
return -1;
}
- tor_vasprintf(&user_buf, format, args);
+ if (tor_vasprintf(&user_buf, format, args)<0) {
+ log_warn(LD_BUG, "Failed to create user buffer.");
+ return -1;
+ }
send_control_event(type, "%s %s\r\n", format_buf, user_buf);
tor_free(user_buf);
return 0;
}
+#ifndef COCCI
#define CONTROL_EVENT_STATUS_BODY(event, sev) \
int r; \
do { \
@@ -1659,6 +1670,7 @@ control_event_status(int type, int severity, const char *format, va_list args)
r = control_event_status((event), (sev), format, ap); \
va_end(ap); \
} while (0)
+#endif /* !defined(COCCI) */
/** Format and send an EVENT_STATUS_GENERAL event whose main text is obtained
* by formatting the arguments using the printf-style <b>format</b>. */
@@ -1747,27 +1759,24 @@ control_event_guard(const char *nickname, const char *digest,
}
/** Called when a configuration option changes. This is generally triggered
- * by SETCONF requests and RELOAD/SIGHUP signals. The <b>elements</b> is
- * a smartlist_t containing (key, value, ...) pairs in sequence.
- * <b>value</b> can be NULL. */
-int
-control_event_conf_changed(const smartlist_t *elements)
+ * by SETCONF requests and RELOAD/SIGHUP signals. The <b>changes</b> are
+ * a linked list of configuration key-values.
+ * <b>changes</b> can be NULL, meaning "no changes".
+ */
+void
+control_event_conf_changed(const config_line_t *changes)
{
- int i;
char *result;
smartlist_t *lines;
- if (!EVENT_IS_INTERESTING(EVENT_CONF_CHANGED) ||
- smartlist_len(elements) == 0) {
- return 0;
+ if (!EVENT_IS_INTERESTING(EVENT_CONF_CHANGED) || !changes) {
+ return;
}
lines = smartlist_new();
- for (i = 0; i < smartlist_len(elements); i += 2) {
- char *k = smartlist_get(elements, i);
- char *v = smartlist_get(elements, i+1);
- if (v == NULL) {
- smartlist_add_asprintf(lines, "650-%s", k);
+ for (const config_line_t *line = changes; line; line = line->next) {
+ if (line->value == NULL) {
+ smartlist_add_asprintf(lines, "650-%s", line->key);
} else {
- smartlist_add_asprintf(lines, "650-%s=%s", k, v);
+ smartlist_add_asprintf(lines, "650-%s=%s", line->key, line->value);
}
}
result = smartlist_join_strings(lines, "\r\n", 0, NULL);
@@ -1776,7 +1785,6 @@ control_event_conf_changed(const smartlist_t *elements)
tor_free(result);
SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
smartlist_free(lines);
- return 0;
}
/** We just generated a new summary of which countries we've seen clients
diff --git a/src/feature/control/control_events.h b/src/feature/control/control_events.h
index 34986fdb89..74bbc0047d 100644
--- a/src/feature/control/control_events.h
+++ b/src/feature/control/control_events.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,6 +13,9 @@
#define TOR_CONTROL_EVENTS_H
#include "core/or/ocirc_event.h"
+#include "core/or/orconn_event.h"
+
+struct config_line_t;
/** Used to indicate the type of a CIRC_MINOR event passed to the controller.
* The various types are defined in control-spec.txt . */
@@ -21,8 +24,6 @@ typedef enum circuit_status_minor_event_t {
CIRC_MINOR_EVENT_CANNIBALIZED,
} circuit_status_minor_event_t;
-#include "core/or/orconn_event.h"
-
/** Used to indicate the type of a stream event passed to the controller.
* The various types are defined in control-spec.txt */
typedef enum stream_status_event_t {
@@ -157,7 +158,7 @@ int control_event_server_error(const char *format, ...)
int control_event_guard(const char *nickname, const char *digest,
const char *status);
-int control_event_conf_changed(const smartlist_t *elements);
+void control_event_conf_changed(const struct config_line_t *changes);
int control_event_buildtimeout_set(buildtimeout_set_event_t type,
const char *args);
int control_event_signal(uintptr_t signal);
diff --git a/src/feature/control/control_fmt.c b/src/feature/control/control_fmt.c
index e0e77eb2d0..d76e6ad8dd 100644
--- a/src/feature/control/control_fmt.c
+++ b/src/feature/control/control_fmt.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -165,6 +165,99 @@ circuit_describe_status_for_controller(origin_circuit_t *circ)
return rv;
}
+/** Allocate and return a description of <b>conn</b>'s current status. */
+char *
+entry_connection_describe_status_for_controller(const entry_connection_t *conn)
+{
+ char *rv;
+ smartlist_t *descparts = smartlist_new();
+
+ if (conn->socks_request != NULL) {
+ // Show username and/or password if available; used by IsolateSOCKSAuth.
+ if (conn->socks_request->usernamelen > 0) {
+ char* username_escaped = esc_for_log_len(conn->socks_request->username,
+ (size_t) conn->socks_request->usernamelen);
+ smartlist_add_asprintf(descparts, "SOCKS_USERNAME=%s",
+ username_escaped);
+ tor_free(username_escaped);
+ }
+ if (conn->socks_request->passwordlen > 0) {
+ char* password_escaped = esc_for_log_len(conn->socks_request->password,
+ (size_t) conn->socks_request->passwordlen);
+ smartlist_add_asprintf(descparts, "SOCKS_PASSWORD=%s",
+ password_escaped);
+ tor_free(password_escaped);
+ }
+
+ const char *client_protocol;
+ // Show the client protocol; used by IsolateClientProtocol.
+ switch (conn->socks_request->listener_type)
+ {
+ case CONN_TYPE_AP_LISTENER:
+ switch (conn->socks_request->socks_version)
+ {
+ case 4: client_protocol = "SOCKS4"; break;
+ case 5: client_protocol = "SOCKS5"; break;
+ default: client_protocol = "UNKNOWN";
+ }
+ break;
+ case CONN_TYPE_AP_TRANS_LISTENER: client_protocol = "TRANS"; break;
+ case CONN_TYPE_AP_NATD_LISTENER: client_protocol = "NATD"; break;
+ case CONN_TYPE_AP_DNS_LISTENER: client_protocol = "DNS"; break;
+ case CONN_TYPE_AP_HTTP_CONNECT_LISTENER:
+ client_protocol = "HTTPCONNECT"; break;
+ default: client_protocol = "UNKNOWN";
+ }
+ smartlist_add_asprintf(descparts, "CLIENT_PROTOCOL=%s",
+ client_protocol);
+ }
+
+ // Show newnym epoch; used for stream isolation when NEWNYM is used.
+ smartlist_add_asprintf(descparts, "NYM_EPOCH=%u",
+ conn->nym_epoch);
+
+ // Show session group; used for stream isolation of multiple listener ports.
+ smartlist_add_asprintf(descparts, "SESSION_GROUP=%d",
+ conn->entry_cfg.session_group);
+
+ // Show isolation flags.
+ smartlist_t *isoflaglist = smartlist_new();
+ char *isoflaglist_joined;
+ if (conn->entry_cfg.isolation_flags & ISO_DESTPORT) {
+ smartlist_add(isoflaglist, (void *)"DESTPORT");
+ }
+ if (conn->entry_cfg.isolation_flags & ISO_DESTADDR) {
+ smartlist_add(isoflaglist, (void *)"DESTADDR");
+ }
+ if (conn->entry_cfg.isolation_flags & ISO_SOCKSAUTH) {
+ smartlist_add(isoflaglist, (void *)"SOCKS_USERNAME");
+ smartlist_add(isoflaglist, (void *)"SOCKS_PASSWORD");
+ }
+ if (conn->entry_cfg.isolation_flags & ISO_CLIENTPROTO) {
+ smartlist_add(isoflaglist, (void *)"CLIENT_PROTOCOL");
+ }
+ if (conn->entry_cfg.isolation_flags & ISO_CLIENTADDR) {
+ smartlist_add(isoflaglist, (void *)"CLIENTADDR");
+ }
+ if (conn->entry_cfg.isolation_flags & ISO_SESSIONGRP) {
+ smartlist_add(isoflaglist, (void *)"SESSION_GROUP");
+ }
+ if (conn->entry_cfg.isolation_flags & ISO_NYM_EPOCH) {
+ smartlist_add(isoflaglist, (void *)"NYM_EPOCH");
+ }
+ isoflaglist_joined = smartlist_join_strings(isoflaglist, ",", 0, NULL);
+ smartlist_add_asprintf(descparts, "ISO_FIELDS=%s", isoflaglist_joined);
+ tor_free(isoflaglist_joined);
+ smartlist_free(isoflaglist);
+
+ rv = smartlist_join_strings(descparts, " ", 0, NULL);
+
+ SMARTLIST_FOREACH(descparts, char *, cp, tor_free(cp));
+ smartlist_free(descparts);
+
+ return rv;
+}
+
/** Return a longname the node whose identity is <b>id_digest</b>. If
* node_get_by_id() returns NULL, base 16 encoding of <b>id_digest</b> is
* returned instead.
diff --git a/src/feature/control/control_fmt.h b/src/feature/control/control_fmt.h
index 6446e37079..f3357cfc4e 100644
--- a/src/feature/control/control_fmt.h
+++ b/src/feature/control/control_fmt.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -17,6 +17,8 @@ int write_stream_target_to_buf(entry_connection_t *conn, char *buf,
void orconn_target_get_name(char *buf, size_t len,
or_connection_t *conn);
char *circuit_describe_status_for_controller(origin_circuit_t *circ);
+char *entry_connection_describe_status_for_controller(const
+ entry_connection_t *conn);
MOCK_DECL(const char *, node_describe_longname_by_id,(const char *id_digest));
diff --git a/src/feature/control/control_getinfo.c b/src/feature/control/control_getinfo.c
index 3e31bb9e8f..5dcc4b170d 100644
--- a/src/feature/control/control_getinfo.c
+++ b/src/feature/control/control_getinfo.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -34,6 +34,7 @@
#include "feature/dircache/dirserv.h"
#include "feature/dirclient/dirclient.h"
#include "feature/dirclient/dlstatus.h"
+#include "feature/dircommon/directory.h"
#include "feature/hibernate/hibernate.h"
#include "feature/hs/hs_cache.h"
#include "feature/hs_common/shared_random_client.h"
@@ -50,6 +51,7 @@
#include "feature/stats/geoip_stats.h"
#include "feature/stats/predict_ports.h"
#include "lib/version/torversion.h"
+#include "lib/encoding/kvline.h"
#include "core/or/entry_connection_st.h"
#include "core/or/or_connection_st.h"
@@ -325,6 +327,121 @@ getinfo_helper_current_time(control_connection_t *control_conn,
return 0;
}
+/** GETINFO helper for dumping different consensus flavors
+ * returns: 0 on success -1 on error. */
+STATIC int
+getinfo_helper_current_consensus(consensus_flavor_t flavor,
+ char** answer,
+ const char** errmsg)
+{
+ const char *flavor_name = networkstatus_get_flavor_name(flavor);
+ if (BUG(!strcmp(flavor_name, "??"))) {
+ *errmsg = "Internal error: unrecognized flavor name.";
+ return -1;
+ }
+ if (we_want_to_fetch_flavor(get_options(), flavor)) {
+ /** Check from the cache */
+ const cached_dir_t *consensus = dirserv_get_consensus(flavor_name);
+ if (consensus) {
+ *answer = tor_strdup(consensus->dir);
+ }
+ }
+ if (!*answer) { /* try loading it from disk */
+
+ tor_mmap_t *mapped = networkstatus_map_cached_consensus(flavor_name);
+ if (mapped) {
+ *answer = tor_memdup_nulterm(mapped->data, mapped->size);
+ tor_munmap_file(mapped);
+ }
+ if (!*answer) { /* generate an error */
+ *errmsg = "Could not open cached consensus. "
+ "Make sure FetchUselessDescriptors is set to 1.";
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/** Helper for getinfo_helper_dir.
+ *
+ * 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;
+ * - "/tor/server/all" for all the routerinfos we have, concatenated;
+ * - "/tor/server/fp/FP" where FP is a plus-separated sequence of
+ * hex identity digests; or
+ * - "/tor/server/d/D" where D is a plus-separated sequence
+ * of server descriptor digests, in hex.
+ *
+ * Return 0 if we found some matching descriptors, or -1 if we do not
+ * have any descriptors, no matching descriptors, or if we did not
+ * recognize the key (URL).
+ * If -1 is returned *<b>msg</b> will be set to an appropriate error
+ * message.
+ */
+static int
+controller_get_routerdescs(smartlist_t *descs_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(descs_out, &(r->cache_info)));
+ } else if (!strcmp(key, "/tor/server/authority")) {
+ const routerinfo_t *ri = router_get_my_routerinfo();
+ if (ri)
+ smartlist_add(descs_out, (void*) &(ri->cache_info));
+ } else if (!strcmpstart(key, "/tor/server/d/")) {
+ smartlist_t *digests = smartlist_new();
+ key += strlen("/tor/server/d/");
+ dir_split_resource_into_fingerprints(key, digests, NULL,
+ DSR_HEX|DSR_SORT_UNIQ);
+ SMARTLIST_FOREACH(digests, const char *, d,
+ {
+ signed_descriptor_t *sd = router_get_by_descriptor_digest(d);
+ if (sd)
+ smartlist_add(descs_out,sd);
+ });
+ SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
+ smartlist_free(digests);
+ } else if (!strcmpstart(key, "/tor/server/fp/")) {
+ smartlist_t *digests = smartlist_new();
+ time_t cutoff = time(NULL) - ROUTER_MAX_AGE_TO_PUBLISH;
+ key += strlen("/tor/server/fp/");
+ dir_split_resource_into_fingerprints(key, digests, NULL,
+ DSR_HEX|DSR_SORT_UNIQ);
+ SMARTLIST_FOREACH_BEGIN(digests, const char *, d) {
+ if (router_digest_is_me(d)) {
+ /* calling router_get_my_routerinfo() to make sure it exists */
+ const routerinfo_t *ri = router_get_my_routerinfo();
+ if (ri)
+ smartlist_add(descs_out, (void*) &(ri->cache_info));
+ } else {
+ const routerinfo_t *ri = router_get_by_id_digest(d);
+ /* Don't actually serve a descriptor that everyone will think is
+ * expired. This is an (ugly) workaround to keep buggy 0.1.1.10
+ * Tors from downloading descriptors that they will throw away.
+ */
+ if (ri && ri->cache_info.published_on > cutoff)
+ smartlist_add(descs_out, (void*) &(ri->cache_info));
+ }
+ } SMARTLIST_FOREACH_END(d);
+ SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
+ smartlist_free(digests);
+ } else {
+ *msg = "Key not recognized";
+ return -1;
+ }
+
+ if (!smartlist_len(descs_out)) {
+ *msg = "Servers unavailable";
+ return -1;
+ }
+ return 0;
+}
+
/** Implementation helper for GETINFO: knows the answers for questions about
* directory information. */
STATIC int
@@ -554,7 +671,7 @@ getinfo_helper_dir(control_connection_t *control_conn,
int res;
char *cp;
tor_asprintf(&url, "/tor/%s", question+4);
- res = dirserv_get_routerdescs(descs, url, &msg);
+ res = controller_get_routerdescs(descs, url, &msg);
if (res) {
log_warn(LD_CONTROL, "getinfo '%s': %s", question, msg);
smartlist_free(descs);
@@ -576,23 +693,18 @@ getinfo_helper_dir(control_connection_t *control_conn,
smartlist_free(descs);
} else if (!strcmpstart(question, "dir/status/")) {
*answer = tor_strdup("");
- } else if (!strcmp(question, "dir/status-vote/current/consensus")) { /* v3 */
- if (we_want_to_fetch_flavor(get_options(), FLAV_NS)) {
- const cached_dir_t *consensus = dirserv_get_consensus("ns");
- if (consensus)
- *answer = tor_strdup(consensus->dir);
+ } else if (!strcmp(question, "dir/status-vote/current/consensus")) {
+ int consensus_result = getinfo_helper_current_consensus(FLAV_NS,
+ answer, errmsg);
+ if (consensus_result < 0) {
+ return -1;
}
- if (!*answer) { /* try loading it from disk */
- tor_mmap_t *mapped = networkstatus_map_cached_consensus("ns");
- if (mapped) {
- *answer = tor_memdup_nulterm(mapped->data, mapped->size);
- tor_munmap_file(mapped);
- }
- if (!*answer) { /* generate an error */
- *errmsg = "Could not open cached consensus. "
- "Make sure FetchUselessDescriptors is set to 1.";
- return -1;
- }
+ } else if (!strcmp(question,
+ "dir/status-vote/current/consensus-microdesc")) {
+ int consensus_result = getinfo_helper_current_consensus(FLAV_MICRODESC,
+ answer, errmsg);
+ if (consensus_result < 0) {
+ return -1;
}
} else if (!strcmp(question, "network-status")) { /* v1 */
static int network_status_warned = 0;
@@ -1513,6 +1625,8 @@ static const getinfo_item_t getinfo_items[] = {
"v2 networkstatus docs as retrieved from a DirPort."),
ITEM("dir/status-vote/current/consensus", dir,
"v3 Networkstatus consensus as retrieved from a DirPort."),
+ ITEM("dir/status-vote/current/consensus-microdesc", dir,
+ "v3 Microdescriptor consensus as retrieved from a DirPort."),
ITEM("exit-policy/default", policies,
"The default value appended to the configured exit policy."),
ITEM("exit-policy/reject-private/default", policies,
@@ -1600,7 +1714,6 @@ handle_control_getinfo(control_connection_t *conn,
smartlist_t *answers = smartlist_new();
smartlist_t *unrecognized = smartlist_new();
char *ans = NULL;
- int i;
SMARTLIST_FOREACH_BEGIN(questions, const char *, q) {
const char *errmsg = NULL;
@@ -1612,43 +1725,33 @@ handle_control_getinfo(control_connection_t *conn,
goto done;
}
if (!ans) {
- if (errmsg) /* use provided error message */
- smartlist_add_strdup(unrecognized, errmsg);
- else /* use default error message */
- smartlist_add_asprintf(unrecognized, "Unrecognized key \"%s\"", q);
+ if (errmsg) {
+ /* use provided error message */
+ control_reply_add_str(unrecognized, 552, errmsg);
+ } else {
+ /* use default error message */
+ control_reply_add_printf(unrecognized, 552,
+ "Unrecognized key \"%s\"", q);
+ }
} else {
- smartlist_add_strdup(answers, q);
- smartlist_add(answers, ans);
+ control_reply_add_one_kv(answers, 250, KV_RAW, q, ans);
+ tor_free(ans);
}
} SMARTLIST_FOREACH_END(q);
- if (smartlist_len(unrecognized)) {
- /* control-spec section 2.3, mid-reply '-' or end of reply ' ' */
- for (i=0; i < smartlist_len(unrecognized)-1; ++i)
- control_write_midreply(conn, 552,
- (char *)smartlist_get(unrecognized, i));
+ control_reply_add_done(answers);
- control_write_endreply(conn, 552, (char *)smartlist_get(unrecognized, i));
+ if (smartlist_len(unrecognized)) {
+ control_write_reply_lines(conn, unrecognized);
+ /* If there were any unrecognized queries, don't write real answers */
goto done;
}
- for (i = 0; i < smartlist_len(answers); i += 2) {
- char *k = smartlist_get(answers, i);
- char *v = smartlist_get(answers, i+1);
- if (!strchr(v, '\n') && !strchr(v, '\r')) {
- control_printf_midreply(conn, 250, "%s=%s", k, v);
- } else {
- control_printf_datareply(conn, 250, "%s=", k);
- control_write_data(conn, v);
- }
- }
- send_control_done(conn);
+ control_write_reply_lines(conn, answers);
done:
- SMARTLIST_FOREACH(answers, char *, cp, tor_free(cp));
- smartlist_free(answers);
- SMARTLIST_FOREACH(unrecognized, char *, cp, tor_free(cp));
- smartlist_free(unrecognized);
+ control_reply_free(answers);
+ control_reply_free(unrecognized);
return 0;
}
diff --git a/src/feature/control/control_getinfo.h b/src/feature/control/control_getinfo.h
index 52978686d8..0ada49258e 100644
--- a/src/feature/control/control_getinfo.h
+++ b/src/feature/control/control_getinfo.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -48,6 +48,10 @@ STATIC int getinfo_helper_downloads(
control_connection_t *control_conn,
const char *question, char **answer,
const char **errmsg);
+STATIC int getinfo_helper_current_consensus(
+ consensus_flavor_t flavor,
+ char **answer,
+ const char **errmsg);
STATIC int getinfo_helper_dir(
control_connection_t *control_conn,
const char *question, char **answer,
diff --git a/src/feature/control/control_hs.c b/src/feature/control/control_hs.c
new file mode 100644
index 0000000000..f5b331de9a
--- /dev/null
+++ b/src/feature/control/control_hs.c
@@ -0,0 +1,342 @@
+/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2019-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file control_hs.c
+ *
+ * \brief Implement commands for Tor's control-socket interface that are
+ * related to onion services.
+ **/
+
+#include "core/or/or.h"
+#include "feature/control/control_cmd.h"
+#include "feature/control/control_hs.h"
+#include "feature/control/control_proto.h"
+#include "feature/hs/hs_client.h"
+#include "lib/encoding/confline.h"
+
+#include "feature/control/control_cmd_args_st.h"
+
+/** Parse the 'KeyType ":" PrivateKey' from <b>client_privkey_str</b> and store
+ * it into <b>privkey</b>. Use <b>conn</b> to output any errors if needed.
+ *
+ * Return 0 if all went well, -1 otherwise. */
+static int
+parse_private_key_from_control_port(const char *client_privkey_str,
+ curve25519_secret_key_t *privkey,
+ control_connection_t *conn)
+{
+ int retval = -1;
+ smartlist_t *key_args = smartlist_new();
+
+ tor_assert(privkey);
+
+ smartlist_split_string(key_args, client_privkey_str, ":",
+ SPLIT_IGNORE_BLANK, 0);
+ if (smartlist_len(key_args) != 2) {
+ control_printf_endreply(conn, 512, "Invalid key type/blob");
+ goto err;
+ }
+
+ const char *key_type = smartlist_get(key_args, 0);
+ const char *key_blob = smartlist_get(key_args, 1);
+
+ if (strcasecmp(key_type, "x25519")) {
+ control_printf_endreply(conn, 552,
+ "Unrecognized key type \"%s\"", key_type);
+ goto err;
+ }
+
+ if (base64_decode((char*)privkey->secret_key, sizeof(privkey->secret_key),
+ key_blob,
+ strlen(key_blob)) != sizeof(privkey->secret_key)) {
+ control_printf_endreply(conn, 512, "Failed to decode x25519 private key");
+ goto err;
+ }
+
+ if (fast_mem_is_zero((const char*)privkey->secret_key,
+ sizeof(privkey->secret_key))) {
+ control_printf_endreply(conn, 553,
+ "Invalid private key \"%s\"", key_blob);
+ goto err;
+ }
+
+ retval = 0;
+
+ err:
+ SMARTLIST_FOREACH(key_args, char *, c, tor_free(c));
+ smartlist_free(key_args);
+ return retval;
+}
+
+/** Syntax details for ONION_CLIENT_AUTH_ADD */
+const control_cmd_syntax_t onion_client_auth_add_syntax = {
+ .max_args = 2,
+ .accept_keywords = true,
+};
+
+/** Called when we get an ONION_CLIENT_AUTH_ADD command; parse the body, and
+ * register the new client-side client auth credentials:
+ * "ONION_CLIENT_AUTH_ADD" SP HSAddress
+ * SP KeyType ":" PrivateKeyBlob
+ * [SP "Type=" TYPE] CRLF
+ */
+int
+handle_control_onion_client_auth_add(control_connection_t *conn,
+ const control_cmd_args_t *args)
+{
+ int retval = -1;
+ smartlist_t *flags = smartlist_new();
+ hs_client_service_authorization_t *creds = NULL;
+
+ tor_assert(args);
+
+ int argc = smartlist_len(args->args);
+ /* We need at least 'HSAddress' and 'PrivateKeyBlob' */
+ if (argc < 2) {
+ control_printf_endreply(conn, 512,
+ "Incomplete ONION_CLIENT_AUTH_ADD command");
+ goto err;
+ }
+
+ creds = tor_malloc_zero(sizeof(hs_client_service_authorization_t));
+
+ const char *hsaddress = smartlist_get(args->args, 0);
+ if (!hs_address_is_valid(hsaddress)) {
+ control_printf_endreply(conn, 512, "Invalid v3 address \"%s\"",hsaddress);
+ goto err;
+ }
+ strlcpy(creds->onion_address, hsaddress, sizeof(creds->onion_address));
+
+ /* Parse the client private key */
+ const char *client_privkey = smartlist_get(args->args, 1);
+ if (parse_private_key_from_control_port(client_privkey,
+ &creds->enc_seckey, conn) < 0) {
+ goto err;
+ }
+
+ /* Now let's parse the remaining arguments (variable size) */
+ for (const config_line_t *line = args->kwargs; line; line = line->next) {
+ if (!strcasecmpstart(line->key, "Flags")) {
+ smartlist_split_string(flags, line->value, ",", SPLIT_IGNORE_BLANK, 0);
+ if (smartlist_len(flags) < 1) {
+ control_write_endreply(conn, 512, "Invalid 'Flags' argument");
+ goto err;
+ }
+ SMARTLIST_FOREACH_BEGIN(flags, const char *, flag) {
+ if (!strcasecmp(flag, "Permanent")) {
+ creds->flags |= CLIENT_AUTH_FLAG_IS_PERMANENT;
+ } else {
+ control_printf_endreply(conn, 512, "Invalid 'Flags' argument: %s",
+ escaped(flag));
+ goto err;
+ }
+ } SMARTLIST_FOREACH_END(flag);
+ }
+ }
+
+ hs_client_register_auth_status_t register_status;
+ /* Register the credential (register func takes ownership of cred.) */
+ register_status = hs_client_register_auth_credentials(creds);
+ switch (register_status) {
+ case REGISTER_FAIL_BAD_ADDRESS:
+ /* It's a bug because the service addr has already been validated above */
+ control_printf_endreply(conn, 512, "Invalid v3 address \"%s\"", hsaddress);
+ break;
+ case REGISTER_FAIL_PERMANENT_STORAGE:
+ control_printf_endreply(conn, 553, "Unable to store creds for \"%s\"",
+ hsaddress);
+ break;
+ case REGISTER_SUCCESS_ALREADY_EXISTS:
+ control_printf_endreply(conn, 251,"Client for onion existed and replaced");
+ break;
+ case REGISTER_SUCCESS_AND_DECRYPTED:
+ control_printf_endreply(conn, 252,"Registered client and decrypted desc");
+ break;
+ case REGISTER_SUCCESS:
+ control_printf_endreply(conn, 250, "OK");
+ break;
+ default:
+ tor_assert_nonfatal_unreached();
+ }
+
+ retval = 0;
+ goto done;
+
+ err:
+ client_service_authorization_free(creds);
+
+ done:
+ SMARTLIST_FOREACH(flags, char *, s, tor_free(s));
+ smartlist_free(flags);
+ return retval;
+}
+
+/** Syntax details for ONION_CLIENT_AUTH_REMOVE */
+const control_cmd_syntax_t onion_client_auth_remove_syntax = {
+ .max_args = 1,
+ .accept_keywords = true,
+};
+
+/** Called when we get an ONION_CLIENT_AUTH_REMOVE command; parse the body, and
+ * register the new client-side client auth credentials.
+ * "ONION_CLIENT_AUTH_REMOVE" SP HSAddress
+ */
+int
+handle_control_onion_client_auth_remove(control_connection_t *conn,
+ const control_cmd_args_t *args)
+{
+ int retval = -1;
+
+ tor_assert(args);
+
+ int argc = smartlist_len(args->args);
+ if (argc < 1) {
+ control_printf_endreply(conn, 512,
+ "Incomplete ONION_CLIENT_AUTH_REMOVE command");
+ goto err;
+ }
+
+ const char *hsaddress = smartlist_get(args->args, 0);
+ if (!hs_address_is_valid(hsaddress)) {
+ control_printf_endreply(conn, 512, "Invalid v3 address \"%s\"",hsaddress);
+ goto err;
+ }
+
+ hs_client_removal_auth_status_t removal_status;
+ removal_status = hs_client_remove_auth_credentials(hsaddress);
+ switch (removal_status) {
+ case REMOVAL_BAD_ADDRESS:
+ /* It's a bug because the service addr has already been validated above */
+ control_printf_endreply(conn, 512, "Invalid v3 address \"%s\"",hsaddress);
+ break;
+ case REMOVAL_SUCCESS_NOT_FOUND:
+ control_printf_endreply(conn, 251, "No credentials for \"%s\"",hsaddress);
+ break;
+ case REMOVAL_SUCCESS:
+ control_printf_endreply(conn, 250, "OK");
+ break;
+ default:
+ tor_assert_nonfatal_unreached();
+ }
+
+ retval = 0;
+
+ err:
+ return retval;
+}
+
+/** Helper: Return a newly allocated string with the encoding of client
+ * authorization credentials */
+static char *
+encode_client_auth_cred_for_control_port(
+ hs_client_service_authorization_t *cred)
+{
+ smartlist_t *control_line = smartlist_new();
+ char x25519_b64[128];
+ char *msg_str = NULL;
+
+ tor_assert(cred);
+
+ if (base64_encode(x25519_b64, sizeof(x25519_b64),
+ (char *)cred->enc_seckey.secret_key,
+ sizeof(cred->enc_seckey.secret_key), 0) < 0) {
+ tor_assert_nonfatal_unreached();
+ goto err;
+ }
+
+ smartlist_add_asprintf(control_line, "CLIENT %s x25519:%s",
+ cred->onion_address, x25519_b64);
+
+ if (cred->flags) { /* flags are also optional */
+ if (cred->flags & CLIENT_AUTH_FLAG_IS_PERMANENT) {
+ smartlist_add_asprintf(control_line, " Flags=Permanent");
+ }
+ }
+
+ /* Join all the components into a single string */
+ msg_str = smartlist_join_strings(control_line, "", 0, NULL);
+
+ err:
+ SMARTLIST_FOREACH(control_line, char *, cp, tor_free(cp));
+ smartlist_free(control_line);
+
+ return msg_str;
+}
+
+/** Syntax details for ONION_CLIENT_AUTH_VIEW */
+const control_cmd_syntax_t onion_client_auth_view_syntax = {
+ .max_args = 1,
+ .accept_keywords = true,
+};
+
+/** Called when we get an ONION_CLIENT_AUTH_VIEW command; parse the body, and
+ * register the new client-side client auth credentials.
+ * "ONION_CLIENT_AUTH_VIEW" [SP HSAddress] CRLF
+ */
+int
+handle_control_onion_client_auth_view(control_connection_t *conn,
+ const control_cmd_args_t *args)
+{
+ int retval = -1;
+ const char *hsaddress = NULL;
+ /* We are gonna put all the credential strings into a smartlist, and sort it
+ before printing, so that we can get a guaranteed order of printing. */
+ smartlist_t *creds_str_list = smartlist_new();
+
+ tor_assert(args);
+
+ int argc = smartlist_len(args->args);
+ if (argc >= 1) {
+ hsaddress = smartlist_get(args->args, 0);
+ if (!hs_address_is_valid(hsaddress)) {
+ control_printf_endreply(conn, 512, "Invalid v3 addr \"%s\"", hsaddress);
+ goto err;
+ }
+ }
+
+ if (hsaddress) {
+ control_printf_midreply(conn, 250, "ONION_CLIENT_AUTH_VIEW %s", hsaddress);
+ } else {
+ control_printf_midreply(conn, 250, "ONION_CLIENT_AUTH_VIEW");
+ }
+
+ /* Create an iterator out of the digest256map */
+ digest256map_t *client_auths = get_hs_client_auths_map();
+ digest256map_iter_t *itr = digest256map_iter_init(client_auths);
+ while (!digest256map_iter_done(itr)) {
+ const uint8_t *service_pubkey;
+ void *valp;
+ digest256map_iter_get(itr, &service_pubkey, &valp);
+ tor_assert(valp);
+ hs_client_service_authorization_t *cred = valp;
+
+ /* If a specific HS address was requested, only print creds for that one */
+ if (hsaddress && strcmp(cred->onion_address, hsaddress)) {
+ itr = digest256map_iter_next(client_auths, itr);
+ continue;
+ }
+
+ char *encoding_str = encode_client_auth_cred_for_control_port(cred);
+ tor_assert_nonfatal(encoding_str);
+ smartlist_add(creds_str_list, encoding_str);
+
+ itr = digest256map_iter_next(client_auths, itr);
+ }
+
+ /* We got everything: Now sort the strings and print them */
+ smartlist_sort_strings(creds_str_list);
+ SMARTLIST_FOREACH_BEGIN(creds_str_list, char *, c) {
+ control_printf_midreply(conn, 250, "%s", c);
+ } SMARTLIST_FOREACH_END(c);
+
+ send_control_done(conn);
+
+ retval = 0;
+
+ err:
+ SMARTLIST_FOREACH(creds_str_list, char *, cp, tor_free(cp));
+ smartlist_free(creds_str_list);
+ return retval;
+}
diff --git a/src/feature/control/control_hs.h b/src/feature/control/control_hs.h
new file mode 100644
index 0000000000..8a0cd6818d
--- /dev/null
+++ b/src/feature/control/control_hs.h
@@ -0,0 +1,34 @@
+/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2019-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file control_hs.c
+ *
+ * \brief Header file for control_hs.c.
+ **/
+
+#ifndef TOR_CONTROL_HS_H
+#define TOR_CONTROL_HS_H
+
+struct control_connection_t;
+struct control_cmd_syntax_t;
+struct control_cmd_args_t;
+
+extern const struct control_cmd_syntax_t onion_client_auth_add_syntax;
+extern const struct control_cmd_syntax_t onion_client_auth_remove_syntax;
+extern const struct control_cmd_syntax_t onion_client_auth_view_syntax;
+
+int
+handle_control_onion_client_auth_add(struct control_connection_t *conn,
+ const struct control_cmd_args_t *args);
+
+int
+handle_control_onion_client_auth_remove(struct control_connection_t *conn,
+ const struct control_cmd_args_t *args);
+
+int
+handle_control_onion_client_auth_view(struct control_connection_t *conn,
+ const struct control_cmd_args_t *args);
+
+#endif /* !defined(TOR_CONTROL_HS_H) */
diff --git a/src/feature/control/control_proto.c b/src/feature/control/control_proto.c
index 5dec87491d..98715ad9d5 100644
--- a/src/feature/control/control_proto.c
+++ b/src/feature/control/control_proto.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -22,6 +22,8 @@
#include "core/or/origin_circuit_st.h"
#include "core/or/socks_request_st.h"
#include "feature/control/control_connection_st.h"
+#include "lib/container/smartlist.h"
+#include "lib/encoding/kvline.h"
/** Append a NUL-terminated string <b>s</b> to the end of
* <b>conn</b>-\>outbuf.
@@ -275,3 +277,158 @@ control_write_data(control_connection_t *conn, const char *data)
connection_buf_add(esc, esc_len, TO_CONN(conn));
tor_free(esc);
}
+
+/** Write a single reply line to @a conn.
+ *
+ * @param conn control connection
+ * @param line control reply line to write
+ * @param lastone true if this is the last reply line of a multi-line reply
+ */
+void
+control_write_reply_line(control_connection_t *conn,
+ const control_reply_line_t *line, bool lastone)
+{
+ const config_line_t *kvline = line->kvline;
+ char *s = NULL;
+
+ if (strpbrk(kvline->value, "\r\n") != NULL) {
+ /* If a key-value pair needs to be encoded as CmdData, it can be
+ the only key-value pair in that reply line */
+ tor_assert(kvline->next == NULL);
+ control_printf_datareply(conn, line->code, "%s=", kvline->key);
+ control_write_data(conn, kvline->value);
+ return;
+ }
+ s = kvline_encode(kvline, line->flags);
+ if (lastone) {
+ control_write_endreply(conn, line->code, s);
+ } else {
+ control_write_midreply(conn, line->code, s);
+ }
+ tor_free(s);
+}
+
+/** Write a set of reply lines to @a conn.
+ *
+ * @param conn control connection
+ * @param lines smartlist of pointers to control_reply_line_t to write
+ */
+void
+control_write_reply_lines(control_connection_t *conn, smartlist_t *lines)
+{
+ bool lastone = false;
+
+ SMARTLIST_FOREACH_BEGIN(lines, control_reply_line_t *, line) {
+ if (line_sl_idx >= line_sl_len - 1)
+ lastone = true;
+ control_write_reply_line(conn, line, lastone);
+ } SMARTLIST_FOREACH_END(line);
+}
+
+/** Add a single key-value pair as a new reply line to a control reply
+ * line list.
+ *
+ * @param reply smartlist of pointers to control_reply_line_t
+ * @param code numeric control reply code
+ * @param flags kvline encoding flags
+ * @param key key
+ * @param val value
+ */
+void
+control_reply_add_one_kv(smartlist_t *reply, int code, int flags,
+ const char *key, const char *val)
+{
+ control_reply_line_t *line = tor_malloc_zero(sizeof(*line));
+
+ line->code = code;
+ line->flags = flags;
+ config_line_append(&line->kvline, key, val);
+ smartlist_add(reply, line);
+}
+
+/** Append a single key-value pair to last reply line in a control
+ * reply line list.
+ *
+ * @param reply smartlist of pointers to control_reply_line_t
+ * @param key key
+ * @param val value
+ */
+void
+control_reply_append_kv(smartlist_t *reply, const char *key, const char *val)
+{
+ int len = smartlist_len(reply);
+ control_reply_line_t *line;
+
+ tor_assert(len > 0);
+
+ line = smartlist_get(reply, len - 1);
+ config_line_append(&line->kvline, key, val);
+}
+
+/** Add new reply line consisting of the string @a s
+ *
+ * @param reply smartlist of pointers to control_reply_line_t
+ * @param code numeric control reply code
+ * @param s string containing the rest of the reply line
+ */
+void
+control_reply_add_str(smartlist_t *reply, int code, const char *s)
+{
+ control_reply_add_one_kv(reply, code, KV_OMIT_KEYS|KV_RAW, "", s);
+}
+
+/** Format a new reply line
+ *
+ * @param reply smartlist of pointers to control_reply_line_t
+ * @param code numeric control reply code
+ * @param fmt format string
+ */
+void
+control_reply_add_printf(smartlist_t *reply, int code, const char *fmt, ...)
+{
+ va_list ap;
+ char *buf = NULL;
+
+ va_start(ap, fmt);
+ (void)tor_vasprintf(&buf, fmt, ap);
+ va_end(ap);
+ control_reply_add_str(reply, code, buf);
+ tor_free(buf);
+}
+
+/** Add a "250 OK" line to a set of control reply lines */
+void
+control_reply_add_done(smartlist_t *reply)
+{
+ control_reply_add_str(reply, 250, "OK");
+}
+
+/** Free a control_reply_line_t. Don't call this directly; use the
+ * control_reply_line_free() macro instead. */
+void
+control_reply_line_free_(control_reply_line_t *line)
+{
+ if (!line)
+ return;
+ config_free_lines(line->kvline);
+ tor_free_(line);
+}
+
+/** Clear a smartlist of control_reply_line_t. Doesn't free the
+ * smartlist, but does free each individual line. */
+void
+control_reply_clear(smartlist_t *reply)
+{
+ SMARTLIST_FOREACH(reply, control_reply_line_t *, line,
+ control_reply_line_free(line));
+ smartlist_clear(reply);
+}
+
+/** Free a smartlist of control_reply_line_t. Don't call this
+ * directly; use the control_reply_free() macro instead. */
+void
+control_reply_free_(smartlist_t *reply)
+{
+ control_reply_clear(reply);
+ smartlist_free_(reply);
+}
diff --git a/src/feature/control/control_proto.h b/src/feature/control/control_proto.h
index 3182f3d415..4c32b820d1 100644
--- a/src/feature/control/control_proto.h
+++ b/src/feature/control/control_proto.h
@@ -1,17 +1,62 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file control_proto.h
* \brief Header file for control_proto.c.
+ *
+ * See @ref replylines for details about the key-value abstraction for
+ * generating reply lines.
**/
#ifndef TOR_CONTROL_PROTO_H
#define TOR_CONTROL_PROTO_H
+#include "lib/encoding/confline.h"
+
+/**
+ * @defgroup replylines Control reply lines
+ * @brief Key-value structures for control reply lines
+ *
+ * Control reply lines are config_line_t key-value structures with
+ * some additional information to help formatting, such as the numeric
+ * result code specified in the control protocol and flags affecting
+ * the way kvline_encode() formats the @a kvline.
+ *
+ * Generally, modules implementing control commands will work with
+ * smartlists of these structures, using functions like
+ * control_reply_add_str() for adding a reply line consisting of a
+ * single string, or control_reply_add_one_kv() and
+ * control_reply_append_kv() for composing a line containing one or
+ * more key-value pairs.
+ *
+ * @{
+ */
+/** @brief A reply line for the control protocol.
+ *
+ * This wraps config_line_t with some additional information that's
+ * useful when generating control reply lines.
+ */
+typedef struct control_reply_line_t {
+ int code; /**< numeric code */
+ int flags; /**< kvline encoding flags */
+ config_line_t *kvline; /**< kvline */
+} control_reply_line_t;
+
+void control_reply_line_free_(control_reply_line_t *line);
+/**
+ * @brief Free and null a control_reply_line_t
+ *
+ * @param line pointer to control_reply_line_t to free
+ */
+#define control_reply_line_free(line) \
+ FREE_AND_NULL(control_reply_line_t, \
+ control_reply_line_free_, (line))
+/** @} */
+
void connection_write_str_to_buf(const char *s, control_connection_t *conn);
void connection_printf_to_buf(control_connection_t *conn,
const char *format, ...)
@@ -45,4 +90,31 @@ void control_printf_datareply(control_connection_t *conn, int code,
CHECK_PRINTF(3, 4);
void control_write_data(control_connection_t *conn, const char *data);
+/** @addtogroup replylines
+ * @{
+ */
+void control_write_reply_line(control_connection_t *conn,
+ const control_reply_line_t *line, bool lastone);
+void control_write_reply_lines(control_connection_t *conn, smartlist_t *lines);
+
+void control_reply_add_one_kv(smartlist_t *reply, int code, int flags,
+ const char *key, const char *val);
+void control_reply_append_kv(smartlist_t *reply, const char *key,
+ const char *val);
+void control_reply_add_str(smartlist_t *reply, int code, const char *s);
+void control_reply_add_printf(smartlist_t *reply, int code,
+ const char *fmt, ...)
+ CHECK_PRINTF(3, 4);
+void control_reply_add_done(smartlist_t *reply);
+
+void control_reply_clear(smartlist_t *reply);
+void control_reply_free_(smartlist_t *reply);
+
+/** @brief Free and null a smartlist of control_reply_line_t.
+ *
+ * @param r pointer to smartlist_t of control_reply_line_t to free */
+#define control_reply_free(r) \
+ FREE_AND_NULL(smartlist_t, control_reply_free_, (r))
+/** @} */
+
#endif /* !defined(TOR_CONTROL_PROTO_H) */
diff --git a/src/feature/control/feature_control.md b/src/feature/control/feature_control.md
new file mode 100644
index 0000000000..9f1681ea91
--- /dev/null
+++ b/src/feature/control/feature_control.md
@@ -0,0 +1,8 @@
+@dir /feature/control
+@brief feature/control: Controller API.
+
+The Controller API is a text-based protocol that another program (or another
+thread, if you're running Tor in-process) can use to configure and control
+Tor while it is running. The current protocol is documented in
+[control-spec.txt](https://gitweb.torproject.org/torspec.git/tree/control-spec.txt).
+
diff --git a/src/feature/control/fmt_serverstatus.c b/src/feature/control/fmt_serverstatus.c
index 33c5ba1336..ed9ad95ce2 100644
--- a/src/feature/control/fmt_serverstatus.c
+++ b/src/feature/control/fmt_serverstatus.c
@@ -1,8 +1,13 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file fmt_serverstatus.c
+ * @brief Format relay info for a controller.
+ **/
+
#include "core/or/or.h"
#include "feature/control/fmt_serverstatus.h"
diff --git a/src/feature/control/fmt_serverstatus.h b/src/feature/control/fmt_serverstatus.h
index d9190cb7e1..9dd9fe125c 100644
--- a/src/feature/control/fmt_serverstatus.h
+++ b/src/feature/control/fmt_serverstatus.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/getinfo_geoip.c b/src/feature/control/getinfo_geoip.c
index d188725fa3..33019207e6 100644
--- a/src/feature/control/getinfo_geoip.c
+++ b/src/feature/control/getinfo_geoip.c
@@ -1,3 +1,12 @@
+/* Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file getinfo_geoip.c
+ * @brief GEOIP-related contoller GETINFO commands.
+ **/
#include "core/or/or.h"
#include "core/mainloop/connection.h"
diff --git a/src/feature/control/getinfo_geoip.h b/src/feature/control/getinfo_geoip.h
index 94759d0d18..5bc4b08414 100644
--- a/src/feature/control/getinfo_geoip.h
+++ b/src/feature/control/getinfo_geoip.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file getinfo_geoip.h
+ * @brief Header for getinfo_geoip.c
+ **/
+
#ifndef TOR_GETINFO_GEOIP_H
#define TOR_GETINFO_GEOIP_H
diff --git a/src/feature/control/include.am b/src/feature/control/include.am
new file mode 100644
index 0000000000..07094f23bb
--- /dev/null
+++ b/src/feature/control/include.am
@@ -0,0 +1,39 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/control/btrack.c \
+ src/feature/control/btrack_circuit.c \
+ src/feature/control/btrack_orconn.c \
+ src/feature/control/btrack_orconn_cevent.c \
+ src/feature/control/btrack_orconn_maps.c \
+ src/feature/control/control.c \
+ src/feature/control/control_auth.c \
+ src/feature/control/control_bootstrap.c \
+ src/feature/control/control_cmd.c \
+ src/feature/control/control_hs.c \
+ src/feature/control/control_events.c \
+ src/feature/control/control_fmt.c \
+ src/feature/control/control_getinfo.c \
+ src/feature/control/control_proto.c \
+ src/feature/control/fmt_serverstatus.c \
+ src/feature/control/getinfo_geoip.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/control/btrack_circuit.h \
+ src/feature/control/btrack_orconn.h \
+ src/feature/control/btrack_orconn_cevent.h \
+ src/feature/control/btrack_orconn_maps.h \
+ src/feature/control/btrack_sys.h \
+ src/feature/control/control.h \
+ src/feature/control/control_auth.h \
+ src/feature/control/control_cmd.h \
+ src/feature/control/control_hs.h \
+ src/feature/control/control_cmd_args_st.h \
+ src/feature/control/control_connection_st.h \
+ src/feature/control/control_events.h \
+ src/feature/control/control_fmt.h \
+ src/feature/control/control_getinfo.h \
+ src/feature/control/control_proto.h \
+ src/feature/control/fmt_serverstatus.h \
+ src/feature/control/getinfo_geoip.h
diff --git a/src/feature/dirauth/.may_include b/src/feature/dirauth/.may_include
new file mode 100644
index 0000000000..a9bb274699
--- /dev/null
+++ b/src/feature/dirauth/.may_include
@@ -0,0 +1,2 @@
+*.h
+feature/dirauth/*.inc
diff --git a/src/feature/dirauth/authmode.c b/src/feature/dirauth/authmode.c
index 29fcc6d1a9..0fde7bc679 100644
--- a/src/feature/dirauth/authmode.c
+++ b/src/feature/dirauth/authmode.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -26,6 +26,15 @@ authdir_mode(const or_options_t *options)
{
return options->AuthoritativeDir != 0;
}
+
+/* Return true iff we believe ourselves to be a v3 authoritative directory
+ * server. */
+int
+authdir_mode_v3(const or_options_t *options)
+{
+ return authdir_mode(options) && options->V3AuthoritativeDir != 0;
+}
+
/** Return true iff we are an authoritative directory server that is
* authoritative about receiving and serving descriptors of type
* <b>purpose</b> on its dirport.
diff --git a/src/feature/dirauth/authmode.h b/src/feature/dirauth/authmode.h
index bfd5f4dc04..6e6ba7f8ae 100644
--- a/src/feature/dirauth/authmode.h
+++ b/src/feature/dirauth/authmode.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,19 +14,13 @@
#ifdef HAVE_MODULE_DIRAUTH
int authdir_mode(const or_options_t *options);
+int authdir_mode_v3(const or_options_t *options);
int authdir_mode_handles_descs(const or_options_t *options, int purpose);
int authdir_mode_publishes_statuses(const or_options_t *options);
int authdir_mode_tests_reachability(const or_options_t *options);
int authdir_mode_bridge(const or_options_t *options);
-/* Return true iff we believe ourselves to be a v3 authoritative directory
- * server. */
-static inline int
-authdir_mode_v3(const or_options_t *options)
-{
- return authdir_mode(options) && options->V3AuthoritativeDir != 0;
-}
-
+/* Is the dirauth module enabled? */
#define have_module_dirauth() (1)
#else /* !defined(HAVE_MODULE_DIRAUTH) */
diff --git a/src/feature/dirauth/bridgeauth.c b/src/feature/dirauth/bridgeauth.c
index 4aaefc7a6d..b7bf3e4e04 100644
--- a/src/feature/dirauth/bridgeauth.c
+++ b/src/feature/dirauth/bridgeauth.c
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file bridgeauth.c
+ * @brief Bridge authority code
+ **/
+
#include "core/or/or.h"
#include "feature/dirauth/bridgeauth.h"
#include "feature/dirauth/voteflags.h"
diff --git a/src/feature/dirauth/bridgeauth.h b/src/feature/dirauth/bridgeauth.h
index 4905e9c3ee..382d1cfcb8 100644
--- a/src/feature/dirauth/bridgeauth.h
+++ b/src/feature/dirauth/bridgeauth.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file bridgeauth.h
+ * @brief Header for bridgeauth.c
+ **/
+
#ifndef TOR_DIRAUTH_BRIDGEAUTH_H
#define TOR_DIRAUTH_BRIDGEAUTH_H
diff --git a/src/feature/dirauth/bwauth.c b/src/feature/dirauth/bwauth.c
index e60c8b86bd..ff0c78f018 100644
--- a/src/feature/dirauth/bwauth.c
+++ b/src/feature/dirauth/bwauth.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,10 +13,12 @@
#include "feature/dirauth/bwauth.h"
#include "app/config/config.h"
+#include "feature/dirauth/dirauth_sys.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/routerlist.h"
#include "feature/dirparse/ns_parse.h"
+#include "feature/dirauth/dirauth_options_st.h"
#include "feature/nodelist/routerinfo_st.h"
#include "feature/nodelist/vote_routerstatus_st.h"
@@ -56,7 +58,7 @@ dirserv_get_last_n_measured_bws(void)
}
/** Measured bandwidth cache entry */
-typedef struct mbw_cache_entry_s {
+typedef struct mbw_cache_entry_t {
long mbw_kb;
time_t as_of;
} mbw_cache_entry_t;
@@ -182,7 +184,7 @@ dirserv_get_credible_bandwidth_kb(const routerinfo_t *ri)
/* Check if we have a measured bandwidth, and check the threshold if not */
if (!(dirserv_query_measured_bw_cache_kb(ri->cache_info.identity_digest,
&mbw_kb, NULL))) {
- threshold = get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised;
+ threshold = dirauth_get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised;
if (routers_with_measured_bw > threshold) {
/* Return zero for unmeasured bandwidth if we are above threshold */
bw_kb = 0;
diff --git a/src/feature/dirauth/bwauth.h b/src/feature/dirauth/bwauth.h
index 81c8affbd7..849c58e2fc 100644
--- a/src/feature/dirauth/bwauth.h
+++ b/src/feature/dirauth/bwauth.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirauth/dirauth_config.c b/src/feature/dirauth/dirauth_config.c
new file mode 100644
index 0000000000..ca16dc8424
--- /dev/null
+++ b/src/feature/dirauth/dirauth_config.c
@@ -0,0 +1,470 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file dirauth_config.c
+ * @brief Code to interpret the user's configuration of Tor's directory
+ * authority module.
+ **/
+
+#include "orconfig.h"
+#include "feature/dirauth/dirauth_config.h"
+
+#include "lib/encoding/confline.h"
+#include "lib/confmgt/confmgt.h"
+#include "lib/conf/confdecl.h"
+
+/* Required for dirinfo_type_t in or_options_t */
+#include "core/or/or.h"
+#include "app/config/config.h"
+
+#include "feature/dircommon/voting_schedule.h"
+#include "feature/stats/rephist.h"
+
+#include "feature/dirauth/authmode.h"
+#include "feature/dirauth/bwauth.h"
+#include "feature/dirauth/dirauth_periodic.h"
+#include "feature/dirauth/dirauth_sys.h"
+#include "feature/dirauth/dirvote.h"
+#include "feature/dirauth/guardfraction.h"
+#include "feature/dirauth/dirauth_options_st.h"
+
+/* Copied from config.c, we will refactor later in 29211. */
+#define REJECT(arg) \
+ STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
+#if defined(__GNUC__) && __GNUC__ <= 3
+#define COMPLAIN(args...) \
+ STMT_BEGIN log_warn(LD_CONFIG, args); STMT_END
+#else
+#define COMPLAIN(args, ...) \
+ STMT_BEGIN log_warn(LD_CONFIG, args, ##__VA_ARGS__); STMT_END
+#endif /* defined(__GNUC__) && __GNUC__ <= 3 */
+
+#define YES_IF_CHANGED_INT(opt) \
+ if (!CFG_EQ_INT(old_options, new_options, opt)) return 1;
+
+/** Return true iff we are configured to reject request under load for non
+ * relay connections. */
+bool
+dirauth_should_reject_requests_under_load(void)
+{
+ return !!dirauth_get_options()->AuthDirRejectRequestsUnderLoad;
+}
+
+/**
+ * Legacy validation/normalization function for the dirauth mode options in
+ * options. Uses old_options as the previous options.
+ *
+ * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
+ * on error.
+ */
+int
+options_validate_dirauth_mode(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ if (!authdir_mode(options))
+ return 0;
+
+ /* confirm that our address isn't broken, so we can complain now */
+ uint32_t tmp;
+ if (resolve_my_address(LOG_WARN, options, &tmp, NULL, NULL) < 0)
+ REJECT("Failed to resolve/guess local address. See logs for details.");
+
+ if (!options->ContactInfo && !options->TestingTorNetwork)
+ REJECT("Authoritative directory servers must set ContactInfo");
+
+ if (options->UseEntryGuards) {
+ log_info(LD_CONFIG, "Authoritative directory servers can't set "
+ "UseEntryGuards. Disabling.");
+ options->UseEntryGuards = 0;
+ }
+ if (!options->DownloadExtraInfo && authdir_mode_v3(options)) {
+ log_info(LD_CONFIG, "Authoritative directories always try to download "
+ "extra-info documents. Setting DownloadExtraInfo.");
+ options->DownloadExtraInfo = 1;
+ }
+ if (!(options->BridgeAuthoritativeDir ||
+ options->V3AuthoritativeDir))
+ REJECT("AuthoritativeDir is set, but none of "
+ "(Bridge/V3)AuthoritativeDir is set.");
+
+ /* If we have a v3bandwidthsfile and it's broken, complain on startup */
+ if (options->V3BandwidthsFile && !old_options) {
+ dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL, NULL,
+ NULL);
+ }
+ /* same for guardfraction file */
+ if (options->GuardfractionFile && !old_options) {
+ dirserv_read_guardfraction_file(options->GuardfractionFile, NULL);
+ }
+
+ if (!options->DirPort_set)
+ REJECT("Running as authoritative directory, but no DirPort set.");
+
+ if (!options->ORPort_set)
+ REJECT("Running as authoritative directory, but no ORPort set.");
+
+ if (options->ClientOnly)
+ REJECT("Running as authoritative directory, but ClientOnly also set.");
+
+ return 0;
+}
+
+/**
+ * Legacy validation/normalization function for the dirauth schedule options
+ * in options. Uses old_options as the previous options.
+ *
+ * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
+ * on error.
+ */
+int
+options_validate_dirauth_schedule(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ if (!authdir_mode_v3(options))
+ return 0;
+
+ if (options->V3AuthVoteDelay + options->V3AuthDistDelay >=
+ options->V3AuthVotingInterval/2) {
+ REJECT("V3AuthVoteDelay plus V3AuthDistDelay must be less than half "
+ "V3AuthVotingInterval");
+ }
+
+ if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS) {
+ if (options->TestingTorNetwork) {
+ if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS_TESTING) {
+ REJECT("V3AuthVoteDelay is way too low.");
+ } else {
+ COMPLAIN("V3AuthVoteDelay is very low. "
+ "This may lead to failure to vote for a consensus.");
+ }
+ } else {
+ REJECT("V3AuthVoteDelay is way too low.");
+ }
+ }
+
+ if (options->V3AuthDistDelay < MIN_DIST_SECONDS) {
+ if (options->TestingTorNetwork) {
+ if (options->V3AuthDistDelay < MIN_DIST_SECONDS_TESTING) {
+ REJECT("V3AuthDistDelay is way too low.");
+ } else {
+ COMPLAIN("V3AuthDistDelay is very low. "
+ "This may lead to missing votes in a consensus.");
+ }
+ } else {
+ REJECT("V3AuthDistDelay is way too low.");
+ }
+ }
+
+ if (options->V3AuthNIntervalsValid < 2)
+ REJECT("V3AuthNIntervalsValid must be at least 2.");
+
+ if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL) {
+ if (options->TestingTorNetwork) {
+ if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL_TESTING) {
+ /* Unreachable, covered by earlier checks */
+ REJECT("V3AuthVotingInterval is insanely low."); /* LCOV_EXCL_LINE */
+ } else {
+ COMPLAIN("V3AuthVotingInterval is very low. "
+ "This may lead to failure to synchronise for a consensus.");
+ }
+ } else {
+ REJECT("V3AuthVotingInterval is insanely low.");
+ }
+ } else if (options->V3AuthVotingInterval > 24*60*60) {
+ REJECT("V3AuthVotingInterval is insanely high.");
+ } else if (((24*60*60) % options->V3AuthVotingInterval) != 0) {
+ COMPLAIN("V3AuthVotingInterval does not divide evenly into 24 hours.");
+ }
+
+ return 0;
+}
+
+/**
+ * Legacy validation/normalization function for the dirauth testing options
+ * in options. Uses old_options as the previous options.
+ *
+ * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
+ * on error.
+ */
+int
+options_validate_dirauth_testing(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ if (!authdir_mode(options))
+ return 0;
+
+ if (!authdir_mode_v3(options))
+ return 0;
+
+ if (options->TestingV3AuthInitialVotingInterval
+ < MIN_VOTE_INTERVAL_TESTING_INITIAL) {
+ REJECT("TestingV3AuthInitialVotingInterval is insanely low.");
+ } else if (((30*60) % options->TestingV3AuthInitialVotingInterval) != 0) {
+ REJECT("TestingV3AuthInitialVotingInterval does not divide evenly into "
+ "30 minutes.");
+ }
+
+ if (options->TestingV3AuthInitialVoteDelay < MIN_VOTE_SECONDS_TESTING) {
+ REJECT("TestingV3AuthInitialVoteDelay is way too low.");
+ }
+
+ if (options->TestingV3AuthInitialDistDelay < MIN_DIST_SECONDS_TESTING) {
+ REJECT("TestingV3AuthInitialDistDelay is way too low.");
+ }
+
+ if (options->TestingV3AuthInitialVoteDelay +
+ options->TestingV3AuthInitialDistDelay >=
+ options->TestingV3AuthInitialVotingInterval) {
+ REJECT("TestingV3AuthInitialVoteDelay plus TestingV3AuthInitialDistDelay "
+ "must be less than TestingV3AuthInitialVotingInterval");
+ }
+
+ if (options->TestingV3AuthVotingStartOffset >
+ MIN(options->TestingV3AuthInitialVotingInterval,
+ options->V3AuthVotingInterval)) {
+ REJECT("TestingV3AuthVotingStartOffset is higher than the voting "
+ "interval.");
+ } else if (options->TestingV3AuthVotingStartOffset < 0) {
+ REJECT("TestingV3AuthVotingStartOffset must be non-negative.");
+ }
+
+ return 0;
+}
+
+/**
+ * Return true if changing the configuration from <b>old</b> to <b>new</b>
+ * affects the timing of the voting subsystem
+ */
+static int
+options_transition_affects_dirauth_timing(const or_options_t *old_options,
+ const or_options_t *new_options)
+{
+ tor_assert(old_options);
+ tor_assert(new_options);
+
+ if (authdir_mode_v3(old_options) != authdir_mode_v3(new_options))
+ return 1;
+ if (! authdir_mode_v3(new_options))
+ return 0;
+
+ YES_IF_CHANGED_INT(V3AuthVotingInterval);
+ YES_IF_CHANGED_INT(V3AuthVoteDelay);
+ YES_IF_CHANGED_INT(V3AuthDistDelay);
+ YES_IF_CHANGED_INT(TestingV3AuthInitialVotingInterval);
+ YES_IF_CHANGED_INT(TestingV3AuthInitialVoteDelay);
+ YES_IF_CHANGED_INT(TestingV3AuthInitialDistDelay);
+ YES_IF_CHANGED_INT(TestingV3AuthVotingStartOffset);
+
+ return 0;
+}
+
+/** Fetch the active option list, and take dirauth actions based on it. All of
+ * the things we do should survive being done repeatedly. If present,
+ * <b>old_options</b> contains the previous value of the options.
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_dirauth(const or_options_t *old_options)
+{
+ const or_options_t *options = get_options();
+
+ /* We may need to reschedule some dirauth stuff if our status changed. */
+ if (old_options) {
+ if (options_transition_affects_dirauth_timing(old_options, options)) {
+ voting_schedule_recalculate_timing(options, time(NULL));
+ reschedule_dirvote(options);
+ }
+ }
+
+ return 0;
+}
+
+/** Fetch the active option list, and take dirauth mtbf actions based on it.
+ * All of the things we do should survive being done repeatedly. If present,
+ * <b>old_options</b> contains the previous value of the options.
+ *
+ * Must be called immediately after a successful or_state_load().
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_dirauth_mtbf(const or_options_t *old_options)
+{
+ (void)old_options;
+
+ const or_options_t *options = get_options();
+ int running_tor = options->command == CMD_RUN_TOR;
+
+ if (!authdir_mode(options))
+ return 0;
+
+ /* Load dirauth state */
+ if (running_tor) {
+ rep_hist_load_mtbf_data(time(NULL));
+ }
+
+ return 0;
+}
+
+/** Fetch the active option list, and take dirauth statistics actions based
+ * on it. All of the things we do should survive being done repeatedly. If
+ * present, <b>old_options</b> contains the previous value of the options.
+ *
+ * Sets <b>*print_notice_out</b> if we enabled stats, and need to print
+ * a stats log using options_act_relay_stats_msg().
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_dirauth_stats(const or_options_t *old_options,
+ bool *print_notice_out)
+{
+ if (BUG(!print_notice_out))
+ return -1;
+
+ const or_options_t *options = get_options();
+
+ if (authdir_mode_bridge(options)) {
+ time_t now = time(NULL);
+ int print_notice = 0;
+
+ if (!old_options || !authdir_mode_bridge(old_options)) {
+ rep_hist_desc_stats_init(now);
+ print_notice = 1;
+ }
+ if (print_notice)
+ *print_notice_out = 1;
+ }
+
+ /* If we used to have statistics enabled but we just disabled them,
+ stop gathering them. */
+ if (old_options && authdir_mode_bridge(old_options) &&
+ !authdir_mode_bridge(options))
+ rep_hist_desc_stats_term();
+
+ return 0;
+}
+
+/**
+ * Make any necessary modifications to a dirauth_options_t that occur
+ * before validation. On success return 0; on failure return -1 and
+ * set *<b>msg_out</b> to a newly allocated error string.
+ **/
+static int
+dirauth_options_pre_normalize(void *arg, char **msg_out)
+{
+ dirauth_options_t *options = arg;
+ (void)msg_out;
+
+ if (!options->RecommendedClientVersions)
+ options->RecommendedClientVersions =
+ config_lines_dup(options->RecommendedVersions);
+ if (!options->RecommendedServerVersions)
+ options->RecommendedServerVersions =
+ config_lines_dup(options->RecommendedVersions);
+
+ if (config_ensure_bandwidth_cap(&options->AuthDirFastGuarantee,
+ "AuthDirFastGuarantee", msg_out) < 0)
+ return -1;
+ if (config_ensure_bandwidth_cap(&options->AuthDirGuardBWGuarantee,
+ "AuthDirGuardBWGuarantee", msg_out) < 0)
+ return -1;
+
+ return 0;
+}
+
+/**
+ * Check whether a dirauth_options_t is correct.
+ *
+ * On success return 0; on failure return -1 and set *<b>msg_out</b> to a
+ * newly allocated error string.
+ **/
+static int
+dirauth_options_validate(const void *arg, char **msg)
+{
+ const dirauth_options_t *options = arg;
+
+ if (options->VersioningAuthoritativeDirectory &&
+ (!options->RecommendedClientVersions ||
+ !options->RecommendedServerVersions)) {
+ REJECT("Versioning authoritative dir servers must set "
+ "Recommended*Versions.");
+ }
+
+ char *t;
+ /* Call these functions to produce warnings only. */
+ t = format_recommended_version_list(options->RecommendedClientVersions, 1);
+ tor_free(t);
+ t = format_recommended_version_list(options->RecommendedServerVersions, 1);
+ tor_free(t);
+
+ if (options->TestingAuthDirTimeToLearnReachability > 2*60*60) {
+ COMPLAIN("TestingAuthDirTimeToLearnReachability is insanely high.");
+ }
+
+ return 0;
+}
+
+/* Declare the options field table for dirauth_options */
+#define CONF_CONTEXT TABLE
+#include "feature/dirauth/dirauth_options.inc"
+#undef CONF_CONTEXT
+
+/** Magic number for dirauth_options_t. */
+#define DIRAUTH_OPTIONS_MAGIC 0x41757448
+
+/**
+ * Declare the configuration options for the dirauth module.
+ **/
+const config_format_t dirauth_options_fmt = {
+ .size = sizeof(dirauth_options_t),
+ .magic = { "dirauth_options_t",
+ DIRAUTH_OPTIONS_MAGIC,
+ offsetof(dirauth_options_t, magic) },
+ .vars = dirauth_options_t_vars,
+
+ .pre_normalize_fn = dirauth_options_pre_normalize,
+ .validate_fn = dirauth_options_validate
+};
diff --git a/src/feature/dirauth/dirauth_config.h b/src/feature/dirauth/dirauth_config.h
new file mode 100644
index 0000000000..9042ff8779
--- /dev/null
+++ b/src/feature/dirauth/dirauth_config.h
@@ -0,0 +1,91 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file dirauth_config.h
+ * @brief Header for feature/dirauth/dirauth_config.c
+ **/
+
+#ifndef TOR_FEATURE_DIRAUTH_DIRAUTH_CONFIG_H
+#define TOR_FEATURE_DIRAUTH_DIRAUTH_CONFIG_H
+
+struct or_options_t;
+
+#ifdef HAVE_MODULE_DIRAUTH
+
+#include "lib/cc/torint.h"
+
+int options_validate_dirauth_mode(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+int options_validate_dirauth_schedule(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+int options_validate_dirauth_testing(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+int options_act_dirauth(const struct or_options_t *old_options);
+int options_act_dirauth_mtbf(const struct or_options_t *old_options);
+int options_act_dirauth_stats(const struct or_options_t *old_options,
+ bool *print_notice_out);
+
+bool dirauth_should_reject_requests_under_load(void);
+
+extern const struct config_format_t dirauth_options_fmt;
+
+#else /* !defined(HAVE_MODULE_DIRAUTH) */
+
+/** When tor is compiled with the dirauth module disabled, it can't be
+ * configured as a directory authority.
+ *
+ * Returns -1 and sets msg to a newly allocated string, if AuthoritativeDir
+ * is set in options. Otherwise returns 0. */
+static inline int
+options_validate_dirauth_mode(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ /* Only check the primary option for now, #29211 will disable more
+ * options. */
+ if (options->AuthoritativeDir) {
+ /* REJECT() this configuration */
+ *msg = tor_strdup("This tor was built with dirauth mode disabled. "
+ "It can not be configured with AuthoritativeDir 1.");
+ return -1;
+ }
+
+ return 0;
+}
+
+#define options_validate_dirauth_schedule(old_options, options, msg) \
+ (((void)(old_options)),((void)(options)),((void)(msg)),0)
+#define options_validate_dirauth_testing(old_options, options, msg) \
+ (((void)(old_options)),((void)(options)),((void)(msg)),0)
+
+#define options_act_dirauth(old_options) \
+ (((void)(old_options)),0)
+#define options_act_dirauth_mtbf(old_options) \
+ (((void)(old_options)),0)
+
+static inline int
+options_act_dirauth_stats(const struct or_options_t *old_options,
+ bool *print_notice_out)
+{
+ (void)old_options;
+ *print_notice_out = 0;
+ return 0;
+}
+
+#define dirauth_should_reject_requests_under_load() (false)
+
+#endif /* defined(HAVE_MODULE_DIRAUTH) */
+
+#endif /* !defined(TOR_FEATURE_DIRAUTH_DIRAUTH_CONFIG_H) */
diff --git a/src/feature/dirauth/dirauth_options.inc b/src/feature/dirauth/dirauth_options.inc
new file mode 100644
index 0000000000..21f4996c39
--- /dev/null
+++ b/src/feature/dirauth/dirauth_options.inc
@@ -0,0 +1,105 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file dirauth_options.inc
+ * @brief Declare configuration options for the crypto_ops module.
+ **/
+
+/** Holds configuration about our directory authority options. */
+BEGIN_CONF_STRUCT(dirauth_options_t)
+
+/** If non-zero, always vote the Fast flag for any relay advertising
+ * this amount of capacity or more. */
+CONF_VAR(AuthDirFastGuarantee, MEMUNIT, 0, "100 KB")
+
+/** If non-zero, this advertised capacity or more is always sufficient
+ * to satisfy the bandwidth requirement for the Guard flag. */
+CONF_VAR(AuthDirGuardBWGuarantee, MEMUNIT, 0, "2 MB")
+
+/** Boolean: are we on IPv6? */
+CONF_VAR(AuthDirHasIPv6Connectivity, BOOL, 0, "0")
+
+/** True iff we should list bad exits, and vote for all other exits as
+ * good. */
+CONF_VAR(AuthDirListBadExits, BOOL, 0, "0")
+
+/** Do not permit more than this number of servers per IP address. */
+CONF_VAR(AuthDirMaxServersPerAddr, POSINT, 0, "2")
+
+/** Boolean: Do we enforce key-pinning? */
+CONF_VAR(AuthDirPinKeys, BOOL, 0, "1")
+
+/** Bool (default: 1): Switch for the shared random protocol. Only
+ * relevant to a directory authority. If off, the authority won't
+ * participate in the protocol. If on (default), a flag is added to the
+ * vote indicating participation. */
+CONF_VAR(AuthDirSharedRandomness, BOOL, 0, "1")
+
+/** Bool (default: 1): When testing routerinfos as a directory authority,
+ * do we enforce Ed25519 identity match? */
+/* NOTE: remove this option someday. */
+CONF_VAR(AuthDirTestEd25519LinkKeys, BOOL, 0, "1")
+
+/** Authority only: key=value pairs that we add to our networkstatus
+ * consensus vote on the 'params' line. */
+CONF_VAR(ConsensusParams, STRING, 0, NULL)
+
+/** Authority only: minimum number of measured bandwidths we must see
+ * before we only believe measured bandwidths to assign flags. */
+CONF_VAR(MinMeasuredBWsForAuthToIgnoreAdvertised, INT, 0, "500")
+
+/** As directory authority, accept hidden service directories after what
+ * time? */
+CONF_VAR(MinUptimeHidServDirectoryV2, INTERVAL, 0, "96 hours")
+
+/** Which versions of tor should we tell users to run? */
+CONF_VAR(RecommendedVersions, LINELIST, 0, NULL)
+
+/** Which versions of tor should we tell users to run on clients? */
+CONF_VAR(RecommendedClientVersions, LINELIST, 0, NULL)
+
+/** Which versions of tor should we tell users to run on relays? */
+CONF_VAR(RecommendedServerVersions, LINELIST, 0, NULL)
+
+/** If an authority has been around for less than this amount of time, it
+ * does not believe its reachability information is accurate. Only
+ * altered on testing networks. */
+CONF_VAR(TestingAuthDirTimeToLearnReachability, INTERVAL, 0, "30 minutes")
+
+ /** Relays in a testing network which should be voted Exit
+ * regardless of exit policy. */
+CONF_VAR(TestingDirAuthVoteExit, ROUTERSET, 0, NULL)
+CONF_VAR(TestingDirAuthVoteExitIsStrict, BOOL, 0, "0")
+
+/** Relays in a testing network which should be voted Guard
+ * regardless of uptime and bandwidth. */
+CONF_VAR(TestingDirAuthVoteGuard, ROUTERSET, 0, NULL)
+CONF_VAR(TestingDirAuthVoteGuardIsStrict, BOOL, 0, "0")
+
+/** Relays in a testing network which should be voted HSDir
+ * regardless of uptime and DirPort. */
+CONF_VAR(TestingDirAuthVoteHSDir, ROUTERSET, 0, NULL)
+CONF_VAR(TestingDirAuthVoteHSDirIsStrict, BOOL, 0, "0")
+
+/** Minimum value for the Exit flag threshold on testing networks. */
+CONF_VAR(TestingMinExitFlagThreshold, MEMUNIT, 0, "0")
+
+/** Minimum value for the Fast flag threshold on testing networks. */
+CONF_VAR(TestingMinFastFlagThreshold, MEMUNIT, 0, "0")
+
+/** Boolean: is this an authoritative directory that's willing to recommend
+ * versions? */
+CONF_VAR(VersioningAuthoritativeDirectory, BOOL, 0, "0")
+
+/** Boolean: Under bandwidth pressure, if set to 1, the authority will always
+ * answer directory requests from relays but will start sending 503 error code
+ * for the other connections. If set to 0, all connections are considered the
+ * same and the authority will try to answer them all regardless of bandwidth
+ * pressure or not. */
+CONF_VAR(AuthDirRejectRequestsUnderLoad, BOOL, 0, "1")
+
+END_CONF_STRUCT(dirauth_options_t)
diff --git a/src/feature/dirauth/dirauth_options_st.h b/src/feature/dirauth/dirauth_options_st.h
new file mode 100644
index 0000000000..02a498c054
--- /dev/null
+++ b/src/feature/dirauth/dirauth_options_st.h
@@ -0,0 +1,24 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file dirauth_options_st.h
+ * @brief Structure dirauth_options_t to hold directory authority options.
+ **/
+
+#ifndef TOR_FEATURE_DIRAUTH_DIRAUTH_OPTIONS_ST_H
+#define TOR_FEATURE_DIRAUTH_DIRAUTH_OPTIONS_ST_H
+
+#include "lib/conf/confdecl.h"
+#include "feature/nodelist/routerset.h"
+
+#define CONF_CONTEXT STRUCT
+#include "feature/dirauth/dirauth_options.inc"
+#undef CONF_CONTEXT
+
+typedef struct dirauth_options_t dirauth_options_t;
+
+#endif /* !defined(TOR_FEATURE_DIRAUTH_DIRAUTH_OPTIONS_ST_H) */
diff --git a/src/feature/dirauth/dirauth_periodic.c b/src/feature/dirauth/dirauth_periodic.c
index 02727d61b4..19e51c5a05 100644
--- a/src/feature/dirauth/dirauth_periodic.c
+++ b/src/feature/dirauth/dirauth_periodic.c
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dirauth_periodic.c
+ * @brief Peridoic events for directory authorities.
+ **/
+
#include "core/or/or.h"
#include "app/config/or_options_st.h"
@@ -18,11 +23,13 @@
#include "core/mainloop/periodic.h"
+#ifndef COCCI
#define DECLARE_EVENT(name, roles, flags) \
static periodic_event_item_t name ## _event = \
PERIODIC_EVENT(name, \
PERIODIC_EVENT_ROLE_##roles, \
flags)
+#endif /* !defined(COCCI) */
#define FL(name) (PERIODIC_EVENT_FLAG_##name)
diff --git a/src/feature/dirauth/dirauth_periodic.h b/src/feature/dirauth/dirauth_periodic.h
index 866fbd35de..ccdda92a77 100644
--- a/src/feature/dirauth/dirauth_periodic.h
+++ b/src/feature/dirauth/dirauth_periodic.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dirauth_periodic.h
+ * @brief Header for dirauth_periodic.c
+ **/
+
#ifndef DIRVOTE_PERIODIC_H
#define DIRVOTE_PERIODIC_H
diff --git a/src/feature/dirauth/dirauth_stub.c b/src/feature/dirauth/dirauth_stub.c
new file mode 100644
index 0000000000..15a195b0fb
--- /dev/null
+++ b/src/feature/dirauth/dirauth_stub.c
@@ -0,0 +1,33 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file dirauth_stub.c
+ * @brief Stub declarations for use when dirauth module is disabled.
+ **/
+
+#include "orconfig.h"
+#include "feature/dirauth/dirauth_sys.h"
+#include "lib/conf/conftypes.h"
+#include "lib/conf/confdecl.h"
+#include "lib/subsys/subsys.h"
+
+/* Declare the options field table for dirauth_options */
+#define CONF_CONTEXT STUB_TABLE
+#include "feature/dirauth/dirauth_options.inc"
+#undef CONF_CONTEXT
+
+static const config_format_t dirauth_options_stub_fmt = {
+ .vars = dirauth_options_t_vars,
+};
+
+const struct subsys_fns_t sys_dirauth = {
+ .name = "dirauth",
+ .supported = false,
+ .level = DIRAUTH_SUBSYS_LEVEL,
+
+ .options_format = &dirauth_options_stub_fmt
+};
diff --git a/src/feature/dirauth/dirauth_sys.c b/src/feature/dirauth/dirauth_sys.c
index e38d391300..56ac501e16 100644
--- a/src/feature/dirauth/dirauth_sys.c
+++ b/src/feature/dirauth/dirauth_sys.c
@@ -1,20 +1,31 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dirauth_sys.c
+ * @brief Directory authority subsystem declarations
+ **/
+
#include "core/or/or.h"
+#define DIRAUTH_SYS_PRIVATE
#include "feature/dirauth/bwauth.h"
#include "feature/dirauth/dirauth_sys.h"
#include "feature/dirauth/dirvote.h"
#include "feature/dirauth/dirauth_periodic.h"
#include "feature/dirauth/keypin.h"
#include "feature/dirauth/process_descs.h"
+#include "feature/dirauth/dirauth_config.h"
+
+#include "feature/dirauth/dirauth_options_st.h"
#include "lib/subsys/subsys.h"
+static const dirauth_options_t *global_dirauth_options;
+
static int
subsys_dirauth_initialize(void)
{
@@ -29,12 +40,31 @@ subsys_dirauth_shutdown(void)
dirvote_free_all();
dirserv_clear_measured_bw_cache();
keypin_close_journal();
+ global_dirauth_options = NULL;
+}
+
+const dirauth_options_t *
+dirauth_get_options(void)
+{
+ tor_assert(global_dirauth_options);
+ return global_dirauth_options;
+}
+
+STATIC int
+dirauth_set_options(void *arg)
+{
+ dirauth_options_t *opts = arg;
+ global_dirauth_options = opts;
+ return 0;
}
const struct subsys_fns_t sys_dirauth = {
.name = "dirauth",
.supported = true,
- .level = 70,
+ .level = DIRAUTH_SUBSYS_LEVEL,
.initialize = subsys_dirauth_initialize,
.shutdown = subsys_dirauth_shutdown,
+
+ .options_format = &dirauth_options_fmt,
+ .set_options = dirauth_set_options,
};
diff --git a/src/feature/dirauth/dirauth_sys.h b/src/feature/dirauth/dirauth_sys.h
index 4e9b6a2ab4..c512b91b33 100644
--- a/src/feature/dirauth/dirauth_sys.h
+++ b/src/feature/dirauth/dirauth_sys.h
@@ -1,12 +1,32 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dirauth_sys.h
+ * @brief Header for dirauth_sys.c
+ **/
+
#ifndef DIRAUTH_SYS_H
#define DIRAUTH_SYS_H
+struct dirauth_options_t;
+const struct dirauth_options_t *dirauth_get_options(void);
+
extern const struct subsys_fns_t sys_dirauth;
+/**
+ * Subsystem level for the directory-authority system.
+ *
+ * Defined here so that it can be shared between the real and stub
+ * definitions.
+ **/
+#define DIRAUTH_SUBSYS_LEVEL 70
+
+#ifdef DIRAUTH_SYS_PRIVATE
+STATIC int dirauth_set_options(void *arg);
+#endif
+
#endif /* !defined(DIRAUTH_SYS_H) */
diff --git a/src/feature/dirauth/dircollate.c b/src/feature/dirauth/dircollate.c
index 7992e3a85f..b35cb021ff 100644
--- a/src/feature/dirauth/dircollate.c
+++ b/src/feature/dirauth/dircollate.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -32,8 +32,8 @@ static void dircollator_collate_by_ed25519(dircollator_t *dc);
/** Hashtable entry mapping a pair of digests (actually an ed25519 key and an
* RSA SHA1 digest) to an array of vote_routerstatus_t. */
-typedef struct ddmap_entry_s {
- HT_ENTRY(ddmap_entry_s) node;
+typedef struct ddmap_entry_t {
+ HT_ENTRY(ddmap_entry_t) node;
/** A SHA1-RSA1024 identity digest and Ed25519 identity key,
* concatenated. (If there is no ed25519 identity key, there is no
* entry in this table.) */
@@ -89,9 +89,9 @@ ddmap_entry_set_digests(ddmap_entry_t *ent,
memcpy(ent->d + DIGEST_LEN, ed25519, DIGEST256_LEN);
}
-HT_PROTOTYPE(double_digest_map, ddmap_entry_s, node, ddmap_entry_hash,
+HT_PROTOTYPE(double_digest_map, ddmap_entry_t, node, ddmap_entry_hash,
ddmap_entry_eq)
-HT_GENERATE2(double_digest_map, ddmap_entry_s, node, ddmap_entry_hash,
+HT_GENERATE2(double_digest_map, ddmap_entry_t, node, ddmap_entry_hash,
ddmap_entry_eq, 0.6, tor_reallocarray, tor_free_)
/** Helper: add a single vote_routerstatus_t <b>vrs</b> to the collator
diff --git a/src/feature/dirauth/dircollate.h b/src/feature/dirauth/dircollate.h
index 754a094817..90c6bddad5 100644
--- a/src/feature/dirauth/dircollate.h
+++ b/src/feature/dirauth/dircollate.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,7 +15,7 @@
#include "lib/testsupport/testsupport.h"
#include "core/or/or.h"
-typedef struct dircollator_s dircollator_t;
+typedef struct dircollator_t dircollator_t;
dircollator_t *dircollator_new(int n_votes, int n_authorities);
void dircollator_free_(dircollator_t *obj);
@@ -30,11 +30,11 @@ vote_routerstatus_t **dircollator_get_votes_for_router(dircollator_t *dc,
int idx);
#ifdef DIRCOLLATE_PRIVATE
-struct ddmap_entry_s;
-typedef HT_HEAD(double_digest_map, ddmap_entry_s) double_digest_map_t;
+struct ddmap_entry_t;
+typedef HT_HEAD(double_digest_map, ddmap_entry_t) double_digest_map_t;
/** A dircollator keeps track of all the routerstatus entries in a
* set of networkstatus votes, and matches them by an appropriate rule. */
-struct dircollator_s {
+struct dircollator_t {
/** True iff we have run the collation algorithm. */
int is_collated;
/** The total number of votes that we received. */
diff --git a/src/feature/dirauth/dirvote.c b/src/feature/dirauth/dirvote.c
index 043bbfc227..e230815ca3 100644
--- a/src/feature/dirauth/dirvote.c
+++ b/src/feature/dirauth/dirvote.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define DIRVOTE_PRIVATE
@@ -41,10 +41,12 @@
#include "feature/dirauth/dirvote.h"
#include "feature/dirauth/authmode.h"
#include "feature/dirauth/shared_random_state.h"
+#include "feature/dirauth/dirauth_sys.h"
#include "feature/nodelist/authority_cert_st.h"
#include "feature/dircache/cached_dir_st.h"
#include "feature/dirclient/dir_server_st.h"
+#include "feature/dirauth/dirauth_options_st.h"
#include "feature/nodelist/document_signature_st.h"
#include "feature/nodelist/microdesc_st.h"
#include "feature/nodelist/networkstatus_st.h"
@@ -382,7 +384,6 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key,
rsf = routerstatus_format_entry(&vrs->status,
vrs->version, vrs->protocols,
NS_V3_VOTE,
- ROUTERSTATUS_FORMAT_NO_CONSENSUS_METHOD,
vrs);
if (rsf)
smartlist_add(chunks, rsf);
@@ -1538,14 +1539,11 @@ networkstatus_compute_consensus(smartlist_t *votes,
consensus_method = MAX_SUPPORTED_CONSENSUS_METHOD;
}
- if (consensus_method >= MIN_METHOD_FOR_INIT_BW_WEIGHTS_ONE) {
+ {
/* It's smarter to initialize these weights to 1, so that later on,
* we can't accidentally divide by zero. */
G = M = E = D = 1;
T = 4;
- } else {
- /* ...but originally, they were set to zero. */
- G = M = E = D = T = 0;
}
/* Compute medians of time-related things, and figure out how many
@@ -2246,7 +2244,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
/* Okay!! Now we can write the descriptor... */
/* First line goes into "buf". */
buf = routerstatus_format_entry(&rs_out, NULL, NULL,
- rs_format, consensus_method, NULL);
+ rs_format, NULL);
if (buf)
smartlist_add(chunks, buf);
}
@@ -2266,8 +2264,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
smartlist_add_strdup(chunks, chosen_version);
}
smartlist_add_strdup(chunks, "\n");
- if (chosen_protocol_list &&
- consensus_method >= MIN_METHOD_FOR_RS_PROTOCOLS) {
+ if (chosen_protocol_list) {
smartlist_add_asprintf(chunks, "pr %s\n", chosen_protocol_list);
}
/* Now the weight line. */
@@ -2530,9 +2527,12 @@ compute_consensus_package_lines(smartlist_t *votes)
* any new signatures in <b>src_voter_list</b> that should be added to
* <b>target</b>. (A signature should be added if we have no signature for that
* voter in <b>target</b> yet, or if we have no verifiable signature and the
- * new signature is verifiable.) Return the number of signatures added or
- * changed, or -1 if the document signed by <b>sigs</b> isn't the same
- * document as <b>target</b>. */
+ * new signature is verifiable.)
+ *
+ * Return the number of signatures added or changed, or -1 if the document
+ * signatures are invalid. Sets *<b>msg_out</b> to a string constant
+ * describing the signature status.
+ */
STATIC int
networkstatus_add_detached_signatures(networkstatus_t *target,
ns_detached_signatures_t *sigs,
@@ -3567,6 +3567,14 @@ dirvote_add_signatures_to_pending_consensus(
return r;
}
+/** Helper: we just got the <b>detached_signatures_body</b> sent to us as
+ * signatures on the currently pending consensus. Add them to the pending
+ * consensus (if we have one).
+ *
+ * Set *<b>msg</b> to a string constant describing the status, regardless of
+ * success or failure.
+ *
+ * Return negative on failure, nonnegative on success. */
static int
dirvote_add_signatures_to_all_pending_consensuses(
const char *detached_signatures_body,
@@ -3629,7 +3637,12 @@ dirvote_add_signatures_to_all_pending_consensuses(
/** Helper: we just got the <b>detached_signatures_body</b> sent to us as
* signatures on the currently pending consensus. Add them to the pending
* consensus (if we have one); otherwise queue them until we have a
- * consensus. Return negative on failure, nonnegative on success. */
+ * consensus.
+ *
+ * Set *<b>msg</b> to a string constant describing the status, regardless of
+ * success or failure.
+ *
+ * Return negative on failure, nonnegative on success. */
int
dirvote_add_signatures(const char *detached_signatures_body,
const char *source,
@@ -3803,13 +3816,6 @@ dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method)
smartlist_add_asprintf(chunks, "ntor-onion-key %s", kbuf);
}
- /* We originally put a lines in the micrdescriptors, but then we worked out
- * that we needed them in the microdesc consensus. See #20916. */
- if (consensus_method < MIN_METHOD_FOR_NO_A_LINES_IN_MICRODESC &&
- !tor_addr_is_null(&ri->ipv6_addr) && ri->ipv6_orport)
- smartlist_add_asprintf(chunks, "a %s\n",
- fmt_addrport(&ri->ipv6_addr, ri->ipv6_orport));
-
if (family) {
if (consensus_method < MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS) {
smartlist_add_asprintf(chunks, "family %s\n", family);
@@ -3915,8 +3921,7 @@ static const struct consensus_method_range_t {
int low;
int high;
} microdesc_consensus_methods[] = {
- {MIN_SUPPORTED_CONSENSUS_METHOD, MIN_METHOD_FOR_NO_A_LINES_IN_MICRODESC - 1},
- {MIN_METHOD_FOR_NO_A_LINES_IN_MICRODESC,
+ {MIN_SUPPORTED_CONSENSUS_METHOD,
MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS - 1},
{MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS,
MAX_SUPPORTED_CONSENSUS_METHOD},
@@ -4228,7 +4233,7 @@ compare_routerinfo_by_ip_and_bw_(const void **a, const void **b)
static digestmap_t *
get_possible_sybil_list(const smartlist_t *routers)
{
- const or_options_t *options = get_options();
+ const dirauth_options_t *options = dirauth_get_options();
digestmap_t *omit_as_sybil;
smartlist_t *routers_by_ip = smartlist_new();
uint32_t last_addr;
@@ -4417,6 +4422,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
authority_cert_t *cert)
{
const or_options_t *options = get_options();
+ const dirauth_options_t *d_options = dirauth_get_options();
networkstatus_t *v3_out = NULL;
uint32_t addr;
char *hostname = NULL, *client_versions = NULL, *server_versions = NULL;
@@ -4424,7 +4430,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
smartlist_t *routers, *routerstatuses;
char identity_digest[DIGEST_LEN];
char signing_key_digest[DIGEST_LEN];
- int listbadexits = options->AuthDirListBadExits;
+ const int listbadexits = d_options->AuthDirListBadExits;
routerlist_t *rl = router_get_routerlist();
time_t now = time(NULL);
time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
@@ -4456,11 +4462,11 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
hostname = tor_dup_ip(addr);
}
- if (options->VersioningAuthoritativeDir) {
+ if (d_options->VersioningAuthoritativeDirectory) {
client_versions =
- format_recommended_version_list(options->RecommendedClientVersions, 0);
+ format_recommended_version_list(d_options->RecommendedClientVersions, 0);
server_versions =
- format_recommended_version_list(options->RecommendedServerVersions, 0);
+ format_recommended_version_list(d_options->RecommendedServerVersions, 0);
}
contact = get_options()->ContactInfo;
@@ -4661,10 +4667,10 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
smartlist_add_strdup(v3_out->known_flags, "BadExit");
smartlist_sort_strings(v3_out->known_flags);
- if (options->ConsensusParams) {
+ if (d_options->ConsensusParams) {
v3_out->net_params = smartlist_new();
smartlist_split_string(v3_out->net_params,
- options->ConsensusParams, NULL, 0, 0);
+ d_options->ConsensusParams, NULL, 0, 0);
smartlist_sort_strings(v3_out->net_params);
}
v3_out->bw_file_headers = bw_file_headers;
diff --git a/src/feature/dirauth/dirvote.h b/src/feature/dirauth/dirvote.h
index b7df33a3a9..675f4ee148 100644
--- a/src/feature/dirauth/dirvote.h
+++ b/src/feature/dirauth/dirvote.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -49,36 +49,12 @@
#define MIN_VOTE_INTERVAL_TESTING_INITIAL \
((MIN_VOTE_SECONDS_TESTING)+(MIN_DIST_SECONDS_TESTING)+1)
-/* A placeholder for routerstatus_format_entry() when the consensus method
- * argument is not applicable. */
-#define ROUTERSTATUS_FORMAT_NO_CONSENSUS_METHOD 0
-
/** The lowest consensus method that we currently support. */
-#define MIN_SUPPORTED_CONSENSUS_METHOD 25
+#define MIN_SUPPORTED_CONSENSUS_METHOD 28
/** The highest consensus method that we currently support. */
#define MAX_SUPPORTED_CONSENSUS_METHOD 29
-/** Lowest consensus method where authorities vote on required/recommended
- * protocols. */
-#define MIN_METHOD_FOR_RECOMMENDED_PROTOCOLS 25
-
-/** Lowest consensus method where authorities add protocols to routerstatus
- * entries. */
-#define MIN_METHOD_FOR_RS_PROTOCOLS 25
-
-/** Lowest consensus method where authorities initialize bandwidth weights to 1
- * instead of 0. See #14881 */
-#define MIN_METHOD_FOR_INIT_BW_WEIGHTS_ONE 26
-
-/** Lowest consensus method where the microdesc consensus contains relay IPv6
- * addresses. See #23826 and #20916. */
-#define MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS 27
-
-/** Lowest consensus method where microdescriptors do not contain relay IPv6
- * addresses. See #23828 and #20916. */
-#define MIN_METHOD_FOR_NO_A_LINES_IN_MICRODESC 28
-
/**
* Lowest consensus method where microdescriptor lines are put in canonical
* form for improved compressibility and ease of storage. See proposal 298.
@@ -186,7 +162,7 @@ dirvote_add_signatures(const char *detached_signatures_body,
{
(void) detached_signatures_body;
(void) source;
- (void) msg_out;
+ *msg_out = "No directory authority support";
/* If the dirauth module is disabled, this should NEVER be called else we
* failed to safeguard the dirauth module. */
tor_assert_nonfatal_unreached();
diff --git a/src/feature/dirauth/dsigs_parse.c b/src/feature/dirauth/dsigs_parse.c
index c5c8e18866..d0bb931814 100644
--- a/src/feature/dirauth/dsigs_parse.c
+++ b/src/feature/dirauth/dsigs_parse.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirauth/dsigs_parse.h b/src/feature/dirauth/dsigs_parse.h
index 0cc53072f8..b25e3e0b28 100644
--- a/src/feature/dirauth/dsigs_parse.h
+++ b/src/feature/dirauth/dsigs_parse.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirauth/feature_dirauth.md b/src/feature/dirauth/feature_dirauth.md
new file mode 100644
index 0000000000..b152b94894
--- /dev/null
+++ b/src/feature/dirauth/feature_dirauth.md
@@ -0,0 +1,9 @@
+@dir /feature/dirauth
+@brief feature/dirauth: Directory authority implementation.
+
+This module handles running Tor as a directory authority.
+
+The directory protocol is specified in
+[dir-spec.txt](https://gitweb.torproject.org/torspec.git/tree/dir-spec.txt).
+
+
diff --git a/src/feature/dirauth/guardfraction.c b/src/feature/dirauth/guardfraction.c
index d1a7f194d4..40189ce494 100644
--- a/src/feature/dirauth/guardfraction.c
+++ b/src/feature/dirauth/guardfraction.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirauth/guardfraction.h b/src/feature/dirauth/guardfraction.h
index 9f01ded838..c10fd9b7bb 100644
--- a/src/feature/dirauth/guardfraction.h
+++ b/src/feature/dirauth/guardfraction.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -16,7 +16,7 @@
STATIC int
dirserv_read_guardfraction_file_from_str(const char *guardfraction_file_str,
smartlist_t *vote_routerstatuses);
-#endif /* defined(DIRSERV_PRIVATE) */
+#endif
int dirserv_read_guardfraction_file(const char *fname,
smartlist_t *vote_routerstatuses);
diff --git a/src/feature/dirauth/include.am b/src/feature/dirauth/include.am
new file mode 100644
index 0000000000..2ef629ae35
--- /dev/null
+++ b/src/feature/dirauth/include.am
@@ -0,0 +1,52 @@
+
+# The Directory Authority module.
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+MODULE_DIRAUTH_SOURCES = \
+ src/feature/dirauth/authmode.c \
+ src/feature/dirauth/bridgeauth.c \
+ src/feature/dirauth/bwauth.c \
+ src/feature/dirauth/dirauth_config.c \
+ src/feature/dirauth/dirauth_periodic.c \
+ src/feature/dirauth/dirauth_sys.c \
+ src/feature/dirauth/dircollate.c \
+ src/feature/dirauth/dirvote.c \
+ src/feature/dirauth/dsigs_parse.c \
+ src/feature/dirauth/guardfraction.c \
+ src/feature/dirauth/keypin.c \
+ src/feature/dirauth/process_descs.c \
+ src/feature/dirauth/reachability.c \
+ src/feature/dirauth/recommend_pkg.c \
+ src/feature/dirauth/shared_random.c \
+ src/feature/dirauth/shared_random_state.c \
+ src/feature/dirauth/voteflags.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/dirauth/authmode.h \
+ src/feature/dirauth/bridgeauth.h \
+ src/feature/dirauth/bwauth.h \
+ src/feature/dirauth/dirauth_config.h \
+ src/feature/dirauth/dirauth_options.inc \
+ src/feature/dirauth/dirauth_options_st.h \
+ src/feature/dirauth/dirauth_periodic.h \
+ src/feature/dirauth/dirauth_sys.h \
+ src/feature/dirauth/dircollate.h \
+ src/feature/dirauth/dirvote.h \
+ src/feature/dirauth/dsigs_parse.h \
+ src/feature/dirauth/guardfraction.h \
+ src/feature/dirauth/keypin.h \
+ src/feature/dirauth/ns_detached_signatures_st.h \
+ src/feature/dirauth/reachability.h \
+ src/feature/dirauth/recommend_pkg.h \
+ src/feature/dirauth/process_descs.h \
+ src/feature/dirauth/shared_random.h \
+ src/feature/dirauth/shared_random_state.h \
+ src/feature/dirauth/vote_microdesc_hash_st.h \
+ src/feature/dirauth/voteflags.h
+
+if BUILD_MODULE_DIRAUTH
+LIBTOR_APP_A_SOURCES += $(MODULE_DIRAUTH_SOURCES)
+else
+LIBTOR_APP_A_STUB_SOURCES += src/feature/dirauth/dirauth_stub.c
+endif
diff --git a/src/feature/dirauth/keypin.c b/src/feature/dirauth/keypin.c
index 316b7d6c2f..edf5ba5833 100644
--- a/src/feature/dirauth/keypin.c
+++ b/src/feature/dirauth/keypin.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,8 +15,6 @@
#include "lib/cc/torint.h"
#include "lib/crypt_ops/crypto_digest.h"
#include "lib/crypt_ops/crypto_format.h"
-#include "lib/crypt_ops/crypto_format.h"
-#include "lib/ctime/di_ops.h"
#include "lib/ctime/di_ops.h"
#include "lib/encoding/binascii.h"
#include "lib/encoding/time_fmt.h"
diff --git a/src/feature/dirauth/keypin.h b/src/feature/dirauth/keypin.h
index 1de84f6d4a..881f010f0e 100644
--- a/src/feature/dirauth/keypin.h
+++ b/src/feature/dirauth/keypin.h
@@ -1,6 +1,11 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file keypin.h
+ * @brief Header for keypin.c
+ **/
+
#ifndef TOR_KEYPIN_H
#define TOR_KEYPIN_H
@@ -40,6 +45,8 @@ int keypin_check_lone_rsa(const uint8_t *rsa_id_digest);
#ifdef KEYPIN_PRIVATE
+#include "ext/ht.h"
+
/**
* In-memory representation of a key-pinning table entry.
*/
diff --git a/src/feature/dirauth/ns_detached_signatures_st.h b/src/feature/dirauth/ns_detached_signatures_st.h
index 61d20b7525..f409431ec1 100644
--- a/src/feature/dirauth/ns_detached_signatures_st.h
+++ b/src/feature/dirauth/ns_detached_signatures_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file ns_detached_signatures_st.h
+ * @brief Detached consensus signatures structure.
+ **/
+
#ifndef NS_DETACHED_SIGNATURES_ST_H
#define NS_DETACHED_SIGNATURES_ST_H
@@ -19,4 +24,3 @@ struct ns_detached_signatures_t {
};
#endif /* !defined(NS_DETACHED_SIGNATURES_ST_H) */
-
diff --git a/src/feature/dirauth/process_descs.c b/src/feature/dirauth/process_descs.c
index 71e3195c01..5025d0ae39 100644
--- a/src/feature/dirauth/process_descs.c
+++ b/src/feature/dirauth/process_descs.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,17 +12,21 @@
* them make those decisions.
**/
+#define PROCESS_DESCS_PRIVATE
+
#include "core/or/or.h"
#include "feature/dirauth/process_descs.h"
#include "app/config/config.h"
#include "core/or/policies.h"
#include "core/or/versions.h"
+#include "feature/dirauth/dirauth_sys.h"
#include "feature/dirauth/keypin.h"
#include "feature/dirauth/reachability.h"
#include "feature/dirclient/dlstatus.h"
#include "feature/dircommon/directory.h"
#include "feature/nodelist/describe.h"
+#include "feature/nodelist/microdesc.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodelist.h"
#include "feature/nodelist/routerinfo.h"
@@ -32,46 +36,28 @@
#include "feature/relay/router.h"
#include "core/or/tor_version_st.h"
+#include "feature/dirauth/dirauth_options_st.h"
#include "feature/nodelist/extrainfo_st.h"
#include "feature/nodelist/node_st.h"
+#include "feature/nodelist/microdesc_st.h"
#include "feature/nodelist/routerinfo_st.h"
#include "feature/nodelist/routerstatus_st.h"
+#include "feature/nodelist/vote_routerstatus_st.h"
#include "lib/encoding/confline.h"
+#include "lib/crypt_ops/crypto_format.h"
/** How far in the future do we allow a router to get? (seconds) */
#define ROUTER_ALLOW_SKEW (60*60*12)
static void directory_remove_invalid(void);
-struct authdir_config_t;
static was_router_added_t dirserv_add_extrainfo(extrainfo_t *ei,
const char **msg);
static uint32_t
-dirserv_get_status_impl(const char *fp, const char *nickname,
- uint32_t addr, uint16_t or_port,
- const char *platform, const char **msg,
- int severity);
-
-/* 1 Historically used to indicate Named */
-#define FP_INVALID 2 /**< Believed invalid. */
-#define FP_REJECT 4 /**< We will not publish this router. */
-/* 8 Historically used to avoid using this as a dir. */
-#define FP_BADEXIT 16 /**< We'll tell clients not to use this as an exit. */
-/* 32 Historically used to indicade Unnamed */
-
-/** Target of status_by_digest map. */
-typedef uint32_t router_status_t;
-
-static void add_fingerprint_to_dir(const char *fp,
- struct authdir_config_t *list,
- router_status_t add_status);
-
-/** List of nickname-\>identity fingerprint mappings for all the routers
- * that we name. Used to prevent router impersonation. */
-typedef struct authdir_config_t {
- strmap_t *fp_by_name; /**< Map from lc nickname to fingerprint. */
- digestmap_t *status_by_digest; /**< Map from digest to router_status_t. */
-} authdir_config_t;
+dirserv_get_status_impl(const char *id_digest,
+ const ed25519_public_key_t *ed25519_public_key,
+ const char *nickname, uint32_t addr, uint16_t or_port,
+ const char *platform, const char **msg, int severity);
/** Should be static; exposed for testing. */
static authdir_config_t *fingerprint_list = NULL;
@@ -83,20 +69,39 @@ authdir_config_new(void)
authdir_config_t *list = tor_malloc_zero(sizeof(authdir_config_t));
list->fp_by_name = strmap_new();
list->status_by_digest = digestmap_new();
+ list->status_by_digest256 = digest256map_new();
return list;
}
+#ifdef TOR_UNIT_TESTS
+
+/** Initialize fingerprint_list to a new authdir_config_t. Used for tests. */
+void
+authdir_init_fingerprint_list(void)
+{
+ fingerprint_list = authdir_config_new();
+}
+
+/* Return the current fingerprint_list. Used for tests. */
+authdir_config_t *
+authdir_return_fingerprint_list(void)
+{
+ return fingerprint_list;
+}
+
+#endif /* defined(TOR_UNIT_TESTS) */
+
/** Add the fingerprint <b>fp</b> to the smartlist of fingerprint_entry_t's
* <b>list</b>, or-ing the currently set status flags with
* <b>add_status</b>.
*/
-/* static */ void
-add_fingerprint_to_dir(const char *fp, authdir_config_t *list,
- router_status_t add_status)
+int
+add_rsa_fingerprint_to_dir(const char *fp, authdir_config_t *list,
+ rtr_flags_t add_status)
{
char *fingerprint;
char d[DIGEST_LEN];
- router_status_t *status;
+ rtr_flags_t *status;
tor_assert(fp);
tor_assert(list);
@@ -107,24 +112,52 @@ add_fingerprint_to_dir(const char *fp, authdir_config_t *list,
log_warn(LD_DIRSERV, "Couldn't decode fingerprint \"%s\"",
escaped(fp));
tor_free(fingerprint);
- return;
+ return -1;
}
status = digestmap_get(list->status_by_digest, d);
if (!status) {
- status = tor_malloc_zero(sizeof(router_status_t));
+ status = tor_malloc_zero(sizeof(rtr_flags_t));
digestmap_set(list->status_by_digest, d, status);
}
tor_free(fingerprint);
*status |= add_status;
- return;
+ return 0;
+}
+
+/** Add the ed25519 key <b>edkey</b> to the smartlist of fingerprint_entry_t's
+ * <b>list</b>, or-ing the currently set status flags with <b>add_status</b>.
+ * Return -1 if we were unable to decode the key, else return 0.
+ */
+int
+add_ed25519_to_dir(const ed25519_public_key_t *edkey, authdir_config_t *list,
+ rtr_flags_t add_status)
+{
+ rtr_flags_t *status;
+
+ tor_assert(edkey);
+ tor_assert(list);
+
+ if (ed25519_validate_pubkey(edkey) < 0) {
+ log_warn(LD_DIRSERV, "Invalid ed25519 key \"%s\"", ed25519_fmt(edkey));
+ return -1;
+ }
+
+ status = digest256map_get(list->status_by_digest256, edkey->pubkey);
+ if (!status) {
+ status = tor_malloc_zero(sizeof(rtr_flags_t));
+ digest256map_set(list->status_by_digest256, edkey->pubkey, status);
+ }
+
+ *status |= add_status;
+ return 0;
}
/** Add the fingerprint for this OR to the global list of recognized
* identity key fingerprints. */
int
-dirserv_add_own_fingerprint(crypto_pk_t *pk)
+dirserv_add_own_fingerprint(crypto_pk_t *pk, const ed25519_public_key_t *edkey)
{
char fp[FINGERPRINT_LEN+1];
if (crypto_pk_get_fingerprint(pk, fp, 0)<0) {
@@ -133,7 +166,14 @@ dirserv_add_own_fingerprint(crypto_pk_t *pk)
}
if (!fingerprint_list)
fingerprint_list = authdir_config_new();
- add_fingerprint_to_dir(fp, fingerprint_list, 0);
+ if (add_rsa_fingerprint_to_dir(fp, fingerprint_list, 0) < 0) {
+ log_err(LD_BUG, "Error adding RSA fingerprint");
+ return -1;
+ }
+ if (add_ed25519_to_dir(edkey, fingerprint_list, 0) < 0) {
+ log_err(LD_BUG, "Error adding ed25519 key");
+ return -1;
+ }
return 0;
}
@@ -174,27 +214,46 @@ dirserv_load_fingerprint_file(void)
fingerprint_list_new = authdir_config_new();
for (list=front; list; list=list->next) {
- char digest_tmp[DIGEST_LEN];
- router_status_t add_status = 0;
+ rtr_flags_t add_status = 0;
nickname = list->key; fingerprint = list->value;
tor_strstrip(fingerprint, " "); /* remove spaces */
- if (strlen(fingerprint) != HEX_DIGEST_LEN ||
- base16_decode(digest_tmp, sizeof(digest_tmp),
- fingerprint, HEX_DIGEST_LEN) != sizeof(digest_tmp)) {
- log_notice(LD_CONFIG,
- "Invalid fingerprint (nickname '%s', "
- "fingerprint %s). Skipping.",
- nickname, fingerprint);
- continue;
- }
+
+ /* Determine what we should do with the relay with the nickname field. */
if (!strcasecmp(nickname, "!reject")) {
- add_status = FP_REJECT;
+ add_status = RTR_REJECT;
} else if (!strcasecmp(nickname, "!badexit")) {
- add_status = FP_BADEXIT;
+ add_status = RTR_BADEXIT;
} else if (!strcasecmp(nickname, "!invalid")) {
- add_status = FP_INVALID;
+ add_status = RTR_INVALID;
+ }
+
+ /* Check if fingerprint is RSA or ed25519 by verifying it. */
+ int ed25519_not_ok = -1, rsa_not_ok = -1;
+
+ /* Attempt to add the RSA key. */
+ if (strlen(fingerprint) == HEX_DIGEST_LEN) {
+ rsa_not_ok = add_rsa_fingerprint_to_dir(fingerprint,
+ fingerprint_list_new,
+ add_status);
+ }
+
+ /* Check ed25519 key. We check the size to prevent buffer overflows.
+ * If valid, attempt to add it, */
+ ed25519_public_key_t ed25519_pubkey_tmp;
+ if (strlen(fingerprint) == BASE64_DIGEST256_LEN) {
+ if (!digest256_from_base64((char *) ed25519_pubkey_tmp.pubkey,
+ fingerprint)) {
+ ed25519_not_ok = add_ed25519_to_dir(&ed25519_pubkey_tmp,
+ fingerprint_list_new, add_status);
+ }
+ }
+
+ /* If both keys are invalid (or missing), log and skip. */
+ if (ed25519_not_ok && rsa_not_ok) {
+ log_warn(LD_CONFIG, "Invalid fingerprint (nickname '%s', "
+ "fingerprint %s). Skipping.", nickname, fingerprint);
+ continue;
}
- add_fingerprint_to_dir(fingerprint, fingerprint_list_new, add_status);
}
config_free_lines(front);
@@ -225,26 +284,33 @@ dirserv_load_fingerprint_file(void)
*
* Return the appropriate router status.
*
- * If the status is 'FP_REJECT' and <b>msg</b> is provided, set
- * *<b>msg</b> to an explanation of why. */
+ * If the status is 'RTR_REJECT' and <b>msg</b> is provided, set
+ * *<b>msg</b> to a string constant explaining why. */
uint32_t
dirserv_router_get_status(const routerinfo_t *router, const char **msg,
int severity)
{
char d[DIGEST_LEN];
- const int key_pinning = get_options()->AuthDirPinKeys;
+ const int key_pinning = dirauth_get_options()->AuthDirPinKeys;
+ uint32_t r;
+ ed25519_public_key_t *signing_key = NULL;
if (crypto_pk_get_digest(router->identity_pkey, d)) {
log_warn(LD_BUG,"Error computing fingerprint");
if (msg)
*msg = "Bug: Error computing fingerprint";
- return FP_REJECT;
+ return RTR_REJECT;
}
- /* Check for the more common reasons to reject a router first. */
- const uint32_t r = dirserv_get_status_impl(d, router->nickname,
- router->addr, router->or_port,
- router->platform, msg, severity);
+ /* First, check for the more common reasons to reject a router. */
+ if (router->cache_info.signing_key_cert) {
+ /* This has an ed25519 identity key. */
+ signing_key = &router->cache_info.signing_key_cert->signing_key;
+ }
+ r = dirserv_get_status_impl(d, signing_key, router->nickname, router->addr,
+ router->or_port, router->platform, msg,
+ severity);
+
if (r)
return r;
@@ -259,7 +325,7 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg,
"key.", router_describe(router));
if (msg)
*msg = "Missing ntor curve25519 onion key. Please upgrade!";
- return FP_REJECT;
+ return RTR_REJECT;
}
if (router->cache_info.signing_key_cert) {
@@ -275,7 +341,7 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg,
if (msg) {
*msg = "Ed25519 identity key or RSA identity key has changed.";
}
- return FP_REJECT;
+ return RTR_REJECT;
}
}
} else {
@@ -292,7 +358,7 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg,
if (msg) {
*msg = "Ed25519 identity key has disappeared.";
}
- return FP_REJECT;
+ return RTR_REJECT;
}
#endif /* defined(DISABLE_DISABLING_ED25519) */
}
@@ -304,15 +370,17 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg,
/** Return true if there is no point in downloading the router described by
* <b>rs</b> because this directory would reject it. */
int
-dirserv_would_reject_router(const routerstatus_t *rs)
+dirserv_would_reject_router(const routerstatus_t *rs,
+ const vote_routerstatus_t *vrs)
{
uint32_t res;
+ struct ed25519_public_key_t pk;
+ memcpy(&pk.pubkey, vrs->ed25519_id, ED25519_PUBKEY_LEN);
- res = dirserv_get_status_impl(rs->identity_digest, rs->nickname,
- rs->addr, rs->or_port,
- NULL, NULL, LOG_DEBUG);
+ res = dirserv_get_status_impl(rs->identity_digest, &pk, rs->nickname,
+ rs->addr, rs->or_port, NULL, NULL, LOG_DEBUG);
- return (res & FP_REJECT) != 0;
+ return (res & RTR_REJECT) != 0;
}
/**
@@ -331,22 +399,21 @@ dirserv_rejects_tor_version(const char *platform,
static const char please_upgrade_string[] =
"Tor version is insecure or unsupported. Please upgrade!";
- /* Versions before Tor 0.2.9 are unsupported. Versions between 0.2.9.0 and
- * 0.2.9.4 suffer from bug #20499, where relays don't keep their consensus
- * up to date */
- if (!tor_version_as_new_as(platform,"0.2.9.5-alpha")) {
+ /* Versions before Tor 0.3.5 are unsupported.
+ *
+ * Also, reject unstable versions of 0.3.5, since (as of this writing)
+ * they are almost none of the network. */
+ if (!tor_version_as_new_as(platform,"0.3.5.7")) {
if (msg)
*msg = please_upgrade_string;
return true;
}
- /* Series between Tor 0.3.0 and 0.3.4 inclusive are unsupported, and some
- * have bug #27841, which makes them broken as intro points. Reject them.
- *
- * Also reject unstable versions of 0.3.5, since (as of this writing)
- * they are almost none of the network. */
- if (tor_version_as_new_as(platform,"0.3.0.0-alpha-dev") &&
- !tor_version_as_new_as(platform,"0.3.5.7")) {
+ /* Series between Tor 0.3.6 and 0.4.1.4-rc inclusive are unsupported.
+ * Reject them. 0.3.6.0-alpha-dev only existed for a short time, before
+ * it was renamed to 0.4.0.0-alpha-dev. */
+ if (tor_version_as_new_as(platform,"0.3.6.0-alpha-dev") &&
+ !tor_version_as_new_as(platform,"0.4.1.5")) {
if (msg) {
*msg = please_upgrade_string;
}
@@ -357,19 +424,20 @@ dirserv_rejects_tor_version(const char *platform,
}
/** Helper: As dirserv_router_get_status, but takes the router fingerprint
- * (hex, no spaces), nickname, address (used for logging only), IP address, OR
- * port and platform (logging only) as arguments.
+ * (hex, no spaces), ed25519 key, nickname, address (used for logging only),
+ * IP address, OR port and platform (logging only) as arguments.
*
* Log messages at 'severity'. (There's not much point in
* logging that we're rejecting servers we'll not download.)
*/
static uint32_t
-dirserv_get_status_impl(const char *id_digest, const char *nickname,
- uint32_t addr, uint16_t or_port,
+dirserv_get_status_impl(const char *id_digest,
+ const ed25519_public_key_t *ed25519_public_key,
+ const char *nickname, uint32_t addr, uint16_t or_port,
const char *platform, const char **msg, int severity)
{
uint32_t result = 0;
- router_status_t *status_by_digest;
+ rtr_flags_t *status_by_digest;
if (!fingerprint_list)
fingerprint_list = authdir_config_new();
@@ -384,13 +452,13 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname,
if (msg) {
*msg = "Malformed platform string.";
}
- return FP_REJECT;
+ return RTR_REJECT;
}
}
/* Check whether the version is obsolete, broken, insecure, etc... */
if (platform && dirserv_rejects_tor_version(platform, msg)) {
- return FP_REJECT;
+ return RTR_REJECT;
}
status_by_digest = digestmap_get(fingerprint_list->status_by_digest,
@@ -398,23 +466,30 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname,
if (status_by_digest)
result |= *status_by_digest;
- if (result & FP_REJECT) {
+ if (ed25519_public_key) {
+ status_by_digest = digest256map_get(fingerprint_list->status_by_digest256,
+ ed25519_public_key->pubkey);
+ if (status_by_digest)
+ result |= *status_by_digest;
+ }
+
+ if (result & RTR_REJECT) {
if (msg)
- *msg = "Fingerprint is marked rejected -- if you think this is a "
- "mistake please set a valid email address in ContactInfo and "
- "send an email to bad-relays@lists.torproject.org mentioning "
- "your fingerprint(s)?";
- return FP_REJECT;
- } else if (result & FP_INVALID) {
+ *msg = "Fingerprint and/or ed25519 identity is marked rejected -- if "
+ "you think this is a mistake please set a valid email address "
+ "in ContactInfo and send an email to "
+ "bad-relays@lists.torproject.org mentioning your fingerprint(s)?";
+ return RTR_REJECT;
+ } else if (result & RTR_INVALID) {
if (msg)
- *msg = "Fingerprint is marked invalid";
+ *msg = "Fingerprint and/or ed25519 identity is marked invalid";
}
if (authdir_policy_badexit_address(addr, or_port)) {
log_fn(severity, LD_DIRSERV,
"Marking '%s' as bad exit because of address '%s'",
nickname, fmt_addr32(addr));
- result |= FP_BADEXIT;
+ result |= RTR_BADEXIT;
}
if (!authdir_policy_permits_address(addr, or_port)) {
@@ -425,13 +500,13 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname,
"mistake please set a valid email address in ContactInfo and "
"send an email to bad-relays@lists.torproject.org mentioning "
"your address(es) and fingerprint(s)?";
- return FP_REJECT;
+ return RTR_REJECT;
}
if (!authdir_policy_valid_address(addr, or_port)) {
log_fn(severity, LD_DIRSERV,
"Not marking '%s' valid because of address '%s'",
nickname, fmt_addr32(addr));
- result |= FP_INVALID;
+ result |= RTR_INVALID;
}
return result;
@@ -446,6 +521,7 @@ dirserv_free_fingerprint_list(void)
strmap_free(fingerprint_list->fp_by_name, tor_free_);
digestmap_free(fingerprint_list->status_by_digest, tor_free_);
+ digest256map_free(fingerprint_list->status_by_digest256, tor_free_);
tor_free(fingerprint_list);
}
@@ -487,7 +563,8 @@ dirserv_router_has_valid_address(routerinfo_t *ri)
/** Check whether we, as a directory server, want to accept <b>ri</b>. If so,
* set its is_valid,running fields and return 0. Otherwise, return -1.
*
- * If the router is rejected, set *<b>msg</b> to an explanation of why.
+ * If the router is rejected, set *<b>msg</b> to a string constant explining
+ * why.
*
* If <b>complain</b> then explain at log-level 'notice' why we refused
* a descriptor; else explain at log-level 'info'.
@@ -501,7 +578,7 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
int severity = (complain && ri->contact_info) ? LOG_NOTICE : LOG_INFO;
uint32_t status = dirserv_router_get_status(ri, msg, severity);
tor_assert(msg);
- if (status & FP_REJECT)
+ if (status & RTR_REJECT)
return -1; /* msg is already set. */
/* Is there too much clock skew? */
@@ -537,7 +614,7 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
return -1;
}
- *valid_out = ! (status & FP_INVALID);
+ *valid_out = ! (status & RTR_INVALID);
return 0;
}
@@ -549,8 +626,8 @@ void
dirserv_set_node_flags_from_authoritative_status(node_t *node,
uint32_t authstatus)
{
- node->is_valid = (authstatus & FP_INVALID) ? 0 : 1;
- node->is_bad_exit = (authstatus & FP_BADEXIT) ? 1 : 0;
+ node->is_valid = (authstatus & RTR_INVALID) ? 0 : 1;
+ node->is_bad_exit = (authstatus & RTR_BADEXIT) ? 1 : 0;
}
/** True iff <b>a</b> is more severe than <b>b</b>. */
@@ -653,7 +730,8 @@ dirserv_add_multiple_descriptors(const char *desc, size_t desclen,
* That means the caller must not access <b>ri</b> after this function
* returns, since it might have been freed.
*
- * Return the status of the operation.
+ * Return the status of the operation, and set *<b>msg</b> to a string
+ * constant describing the status.
*
* This function is only called when fresh descriptors are posted, not when
* we re-load the cache.
@@ -666,7 +744,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
char *desc, *nickname;
const size_t desclen = ri->cache_info.signed_descriptor_len +
ri->cache_info.annotations_len;
- const int key_pinning = get_options()->AuthDirPinKeys;
+ const int key_pinning = dirauth_get_options()->AuthDirPinKeys;
*msg = NULL;
/* If it's too big, refuse it now. Otherwise we'll cache it all over the
@@ -864,21 +942,21 @@ directory_remove_invalid(void)
continue;
r = dirserv_router_get_status(ent, &msg, LOG_INFO);
description = router_describe(ent);
- if (r & FP_REJECT) {
+ if (r & RTR_REJECT) {
log_info(LD_DIRSERV, "Router %s is now rejected: %s",
description, msg?msg:"");
routerlist_remove(rl, ent, 0, time(NULL));
continue;
}
- if (bool_neq((r & FP_INVALID), !node->is_valid)) {
+ if (bool_neq((r & RTR_INVALID), !node->is_valid)) {
log_info(LD_DIRSERV, "Router '%s' is now %svalid.", description,
- (r&FP_INVALID) ? "in" : "");
- node->is_valid = (r&FP_INVALID)?0:1;
+ (r&RTR_INVALID) ? "in" : "");
+ node->is_valid = (r&RTR_INVALID)?0:1;
}
- if (bool_neq((r & FP_BADEXIT), node->is_bad_exit)) {
+ if (bool_neq((r & RTR_BADEXIT), node->is_bad_exit)) {
log_info(LD_DIRSERV, "Router '%s' is now a %s exit", description,
- (r & FP_BADEXIT) ? "bad" : "good");
- node->is_bad_exit = (r&FP_BADEXIT) ? 1: 0;
+ (r & RTR_BADEXIT) ? "bad" : "good");
+ node->is_bad_exit = (r&RTR_BADEXIT) ? 1: 0;
}
} SMARTLIST_FOREACH_END(node);
diff --git a/src/feature/dirauth/process_descs.h b/src/feature/dirauth/process_descs.h
index e504daa7b7..1461ab697d 100644
--- a/src/feature/dirauth/process_descs.h
+++ b/src/feature/dirauth/process_descs.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,6 +15,48 @@
// for was_router_added_t.
#include "feature/nodelist/routerlist.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+
+struct authdir_config_t;
+
+/** Target of status_by_digest map. */
+typedef uint32_t rtr_flags_t;
+
+int add_rsa_fingerprint_to_dir(const char *fp, struct authdir_config_t *list,
+ rtr_flags_t add_status);
+
+int add_ed25519_to_dir(const ed25519_public_key_t *edkey,
+ struct authdir_config_t *list,
+ rtr_flags_t add_status);
+
+/** List of nickname-\>identity fingerprint mappings for all the routers
+ * that we name. Used to prevent router impersonation. */
+typedef struct authdir_config_t {
+ strmap_t *fp_by_name; /**< Map from lc nickname to fingerprint. */
+ digestmap_t *status_by_digest; /**< Map from digest to router_status_t. */
+ digest256map_t *status_by_digest256; /**< Map from digest256 to
+ * router_status_t. */
+} authdir_config_t;
+
+#if defined(PROCESS_DESCS_PRIVATE) || defined(TOR_UNIT_TESTS)
+
+/* 1 Historically used to indicate Named */
+#define RTR_INVALID 2 /**< Believed invalid. */
+#define RTR_REJECT 4 /**< We will not publish this router. */
+/* 8 Historically used to avoid using this as a dir. */
+#define RTR_BADEXIT 16 /**< We'll tell clients not to use this as an exit. */
+/* 32 Historically used to indicade Unnamed */
+
+#endif /* defined(PROCESS_DESCS_PRIVATE) || defined(TOR_UNIT_TESTS) */
+
+#ifdef TOR_UNIT_TESTS
+
+void authdir_init_fingerprint_list(void);
+
+authdir_config_t *authdir_return_fingerprint_list(void);
+
+#endif /* defined(TOR_UNIT_TESTS) */
+
void dirserv_free_fingerprint_list(void);
#ifdef HAVE_MODULE_DIRAUTH
@@ -28,11 +70,13 @@ enum was_router_added_t dirserv_add_descriptor(routerinfo_t *ri,
const char **msg,
const char *source);
-int dirserv_would_reject_router(const routerstatus_t *rs);
+int dirserv_would_reject_router(const routerstatus_t *rs,
+ const vote_routerstatus_t *vrs);
int authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
int complain,
int *valid_out);
-int dirserv_add_own_fingerprint(crypto_pk_t *pk);
+int dirserv_add_own_fingerprint(crypto_pk_t *pk,
+ const ed25519_public_key_t *edkey);
uint32_t dirserv_router_get_status(const routerinfo_t *router,
const char **msg,
int severity);
@@ -54,7 +98,7 @@ dirserv_add_multiple_descriptors(const char *desc, size_t desclen,
(void)desclen;
(void)purpose;
(void)source;
- (void)msg;
+ *msg = "No directory authority support";
return (enum was_router_added_t)0;
}
static inline enum was_router_added_t
@@ -63,14 +107,16 @@ dirserv_add_descriptor(routerinfo_t *ri,
const char *source)
{
(void)ri;
- (void)msg;
(void)source;
+ *msg = "No directory authority support";
return (enum was_router_added_t)0;
}
static inline int
-dirserv_would_reject_router(const routerstatus_t *rs)
+dirserv_would_reject_router(const routerstatus_t *rs,
+ const vote_routerstatus_t *vrs)
{
(void)rs;
+ (void)vrs;
return 0;
}
static inline int
@@ -79,15 +125,16 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
int *valid_out)
{
(void)ri;
- (void)msg;
(void)complain;
- (void)valid_out;
+ *msg = "No directory authority support";
+ *valid_out = 0;
return 0;
}
static inline int
-dirserv_add_own_fingerprint(crypto_pk_t *pk)
+dirserv_add_own_fingerprint(crypto_pk_t *pk, const ed25519_public_key_t *edkey)
{
(void)pk;
+ (void)edkey;
return 0;
}
static inline uint32_t
@@ -96,8 +143,9 @@ dirserv_router_get_status(const routerinfo_t *router,
int severity)
{
(void)router;
- (void)msg;
(void)severity;
+ if (msg)
+ *msg = "No directory authority support";
return 0;
}
static inline void
diff --git a/src/feature/dirauth/reachability.c b/src/feature/dirauth/reachability.c
index 883b692cbb..65fa27ed80 100644
--- a/src/feature/dirauth/reachability.c
+++ b/src/feature/dirauth/reachability.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -17,6 +17,7 @@
#include "core/or/channeltls.h"
#include "core/or/command.h"
#include "feature/dirauth/authmode.h"
+#include "feature/dirauth/dirauth_sys.h"
#include "feature/nodelist/describe.h"
#include "feature/nodelist/nodelist.h"
#include "feature/nodelist/routerinfo.h"
@@ -24,6 +25,7 @@
#include "feature/nodelist/torcert.h"
#include "feature/stats/rephist.h"
+#include "feature/dirauth/dirauth_options_st.h"
#include "feature/nodelist/node_st.h"
#include "feature/nodelist/routerinfo_st.h"
#include "feature/nodelist/routerlist_st.h"
@@ -53,7 +55,7 @@ dirserv_orconn_tls_done(const tor_addr_t *addr,
ri = node->ri;
- if (get_options()->AuthDirTestEd25519LinkKeys &&
+ if (dirauth_get_options()->AuthDirTestEd25519LinkKeys &&
node_supports_ed25519_link_authentication(node, 1) &&
ri->cache_info.signing_key_cert) {
/* We allow the node to have an ed25519 key if we haven't been told one in
@@ -125,7 +127,7 @@ dirserv_should_launch_reachability_test(const routerinfo_t *ri,
void
dirserv_single_reachability_test(time_t now, routerinfo_t *router)
{
- const or_options_t *options = get_options();
+ const dirauth_options_t *dirauth_options = dirauth_get_options();
channel_t *chan = NULL;
const node_t *node = NULL;
tor_addr_t router_addr;
@@ -136,7 +138,7 @@ dirserv_single_reachability_test(time_t now, routerinfo_t *router)
node = node_get_by_id(router->cache_info.identity_digest);
tor_assert(node);
- if (options->AuthDirTestEd25519LinkKeys &&
+ if (dirauth_options->AuthDirTestEd25519LinkKeys &&
node_supports_ed25519_link_authentication(node, 1) &&
router->cache_info.signing_key_cert) {
ed_id_key = &router->cache_info.signing_key_cert->signing_key;
@@ -154,7 +156,7 @@ dirserv_single_reachability_test(time_t now, routerinfo_t *router)
if (chan) command_setup_channel(chan);
/* Possible IPv6. */
- if (get_options()->AuthDirHasIPv6Connectivity == 1 &&
+ if (dirauth_get_options()->AuthDirHasIPv6Connectivity == 1 &&
!tor_addr_is_null(&router->ipv6_addr)) {
char addrstr[TOR_ADDR_BUF_LEN];
log_debug(LD_OR, "Testing reachability of %s at %s:%u.",
diff --git a/src/feature/dirauth/reachability.h b/src/feature/dirauth/reachability.h
index 46d0e7ee2e..19448a67f3 100644
--- a/src/feature/dirauth/reachability.h
+++ b/src/feature/dirauth/reachability.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -24,10 +24,10 @@
#define REACHABILITY_TEST_CYCLE_PERIOD \
(REACHABILITY_TEST_INTERVAL*REACHABILITY_MODULO_PER_TEST)
+#ifdef HAVE_MODULE_DIRAUTH
void dirserv_single_reachability_test(time_t now, routerinfo_t *router);
void dirserv_test_reachability(time_t now);
-#ifdef HAVE_MODULE_DIRAUTH
int dirserv_should_launch_reachability_test(const routerinfo_t *ri,
const routerinfo_t *ri_old);
void dirserv_orconn_tls_done(const tor_addr_t *addr,
@@ -35,25 +35,16 @@ void dirserv_orconn_tls_done(const tor_addr_t *addr,
const char *digest_rcvd,
const struct ed25519_public_key_t *ed_id_rcvd);
#else /* !defined(HAVE_MODULE_DIRAUTH) */
-static inline int
-dirserv_should_launch_reachability_test(const routerinfo_t *ri,
- const routerinfo_t *ri_old)
-{
- (void)ri;
- (void)ri_old;
- return 0;
-}
-static inline void
-dirserv_orconn_tls_done(const tor_addr_t *addr,
- uint16_t or_port,
- const char *digest_rcvd,
- const struct ed25519_public_key_t *ed_id_rcvd)
-{
- (void)addr;
- (void)or_port;
- (void)digest_rcvd;
- (void)ed_id_rcvd;
-}
+#define dirserv_single_reachability_test(now, router) \
+ (((void)(now)),((void)(router)))
+#define dirserv_test_reachability(now) \
+ (((void)(now)))
+
+#define dirserv_should_launch_reachability_test(ri, ri_old) \
+ (((void)(ri)),((void)(ri_old)),0)
+#define dirserv_orconn_tls_done(addr, or_port, digest_rcvd, ed_id_rcvd) \
+ (((void)(addr)),((void)(or_port)),((void)(digest_rcvd)), \
+ ((void)(ed_id_rcvd)))
#endif /* defined(HAVE_MODULE_DIRAUTH) */
#endif /* !defined(TOR_REACHABILITY_H) */
diff --git a/src/feature/dirauth/recommend_pkg.c b/src/feature/dirauth/recommend_pkg.c
index 0456ff8463..84254566c6 100644
--- a/src/feature/dirauth/recommend_pkg.c
+++ b/src/feature/dirauth/recommend_pkg.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirauth/recommend_pkg.h b/src/feature/dirauth/recommend_pkg.h
index af17e945e8..dcd9f8be8a 100644
--- a/src/feature/dirauth/recommend_pkg.h
+++ b/src/feature/dirauth/recommend_pkg.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirauth/shared_random.c b/src/feature/dirauth/shared_random.c
index a45f0a29c3..48e2147ea6 100644
--- a/src/feature/dirauth/shared_random.c
+++ b/src/feature/dirauth/shared_random.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -90,7 +90,7 @@
#include "core/or/or.h"
#include "feature/dirauth/shared_random.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_util.h"
#include "feature/nodelist/networkstatus.h"
@@ -103,23 +103,25 @@
#include "feature/dirauth/dirvote.h"
#include "feature/dirauth/authmode.h"
+#include "feature/dirauth/dirauth_sys.h"
+#include "feature/dirauth/dirauth_options_st.h"
#include "feature/nodelist/authority_cert_st.h"
#include "feature/nodelist/networkstatus_st.h"
-/* String prefix of shared random values in votes/consensuses. */
+/** String prefix of shared random values in votes/consensuses. */
static const char previous_srv_str[] = "shared-rand-previous-value";
static const char current_srv_str[] = "shared-rand-current-value";
static const char commit_ns_str[] = "shared-rand-commit";
static const char sr_flag_ns_str[] = "shared-rand-participate";
-/* The value of the consensus param AuthDirNumSRVAgreements found in the
+/** The value of the consensus param AuthDirNumSRVAgreements found in the
* vote. This is set once the consensus creation subsystem requests the
* SRV(s) that should be put in the consensus. We use this value to decide
* if we keep or not an SRV. */
static int32_t num_srv_agreements_from_vote;
-/* Return a heap allocated copy of the SRV <b>orig</b>. */
+/** Return a heap allocated copy of the SRV <b>orig</b>. */
sr_srv_t *
sr_srv_dup(const sr_srv_t *orig)
{
@@ -135,7 +137,7 @@ sr_srv_dup(const sr_srv_t *orig)
return duplicate;
}
-/* Allocate a new commit object and initializing it with <b>rsa_identity</b>
+/** Allocate a new commit object and initializing it with <b>rsa_identity</b>
* that MUST be provided. The digest algorithm is set to the default one
* that is supported. The rest is uninitialized. This never returns NULL. */
static sr_commit_t *
@@ -153,7 +155,7 @@ commit_new(const char *rsa_identity)
return commit;
}
-/* Issue a log message describing <b>commit</b>. */
+/** Issue a log message describing <b>commit</b>. */
static void
commit_log(const sr_commit_t *commit)
{
@@ -166,7 +168,7 @@ commit_log(const sr_commit_t *commit)
commit->reveal_ts, safe_str(commit->encoded_reveal));
}
-/* Make sure that the commitment and reveal information in <b>commit</b>
+/** Make sure that the commitment and reveal information in <b>commit</b>
* match. If they match return 0, return -1 otherwise. This function MUST be
* used everytime we receive a new reveal value. Furthermore, the commit
* object MUST have a reveal value and the hash of the reveal value. */
@@ -220,7 +222,7 @@ verify_commit_and_reveal(const sr_commit_t *commit)
return -1;
}
-/* Return true iff the commit contains an encoded reveal value. */
+/** Return true iff the commit contains an encoded reveal value. */
STATIC int
commit_has_reveal_value(const sr_commit_t *commit)
{
@@ -228,7 +230,7 @@ commit_has_reveal_value(const sr_commit_t *commit)
sizeof(commit->encoded_reveal));
}
-/* Parse the encoded commit. The format is:
+/** Parse the encoded commit. The format is:
* base64-encode( TIMESTAMP || H(REVEAL) )
*
* If successfully decoded and parsed, commit is updated and 0 is returned.
@@ -283,7 +285,7 @@ commit_decode(const char *encoded, sr_commit_t *commit)
return -1;
}
-/* Parse the b64 blob at <b>encoded</b> containing reveal information and
+/** Parse the b64 blob at <b>encoded</b> containing reveal information and
* store the information in-place in <b>commit</b>. Return 0 on success else
* a negative value. */
STATIC int
@@ -333,7 +335,7 @@ reveal_decode(const char *encoded, sr_commit_t *commit)
return -1;
}
-/* Encode a reveal element using a given commit object to dst which is a
+/** Encode a reveal element using a given commit object to dst which is a
* buffer large enough to put the base64-encoded reveal construction. The
* format is as follow:
* REVEAL = base64-encode( TIMESTAMP || H(RN) )
@@ -362,7 +364,7 @@ reveal_encode(const sr_commit_t *commit, char *dst, size_t len)
return ret;
}
-/* Encode the given commit object to dst which is a buffer large enough to
+/** Encode the given commit object to dst which is a buffer large enough to
* put the base64-encoded commit. The format is as follow:
* COMMIT = base64-encode( TIMESTAMP || H(H(RN)) )
* Return base64 encoded length on success else a negative value.
@@ -388,14 +390,14 @@ commit_encode(const sr_commit_t *commit, char *dst, size_t len)
return base64_encode(dst, len, buf, sizeof(buf), 0);
}
-/* Cleanup both our global state and disk state. */
+/** Cleanup both our global state and disk state. */
static void
sr_cleanup(void)
{
sr_state_free_all();
}
-/* Using <b>commit</b>, return a newly allocated string containing the commit
+/** Using <b>commit</b>, return a newly allocated string containing the commit
* information that should be used during SRV calculation. It's the caller
* responsibility to free the memory. Return NULL if this is not a commit to be
* used for SRV calculation. */
@@ -414,7 +416,7 @@ get_srv_element_from_commit(const sr_commit_t *commit)
return element;
}
-/* Return a srv object that is built with the construction:
+/** Return a srv object that is built with the construction:
* SRV = SHA3-256("shared-random" | INT_8(reveal_num) |
* INT_4(version) | HASHED_REVEALS | previous_SRV)
* This function cannot fail. */
@@ -456,7 +458,7 @@ generate_srv(const char *hashed_reveals, uint64_t reveal_num,
return srv;
}
-/* Compare reveal values and return the result. This should exclusively be
+/** Compare reveal values and return the result. This should exclusively be
* used by smartlist_sort(). */
static int
compare_reveal_(const void **_a, const void **_b)
@@ -466,7 +468,7 @@ compare_reveal_(const void **_a, const void **_b)
sizeof(a->hashed_reveal));
}
-/* Given <b>commit</b> give the line that we should place in our votes.
+/** Given <b>commit</b> give the line that we should place in our votes.
* It's the responsibility of the caller to free the string. */
static char *
get_vote_line_from_commit(const sr_commit_t *commit, sr_phase_t phase)
@@ -506,7 +508,7 @@ get_vote_line_from_commit(const sr_commit_t *commit, sr_phase_t phase)
return vote_line;
}
-/* Return a heap allocated string that contains the given <b>srv</b> string
+/** Return a heap allocated string that contains the given <b>srv</b> string
* representation formatted for a networkstatus document using the
* <b>key</b> as the start of the line. This doesn't return NULL. */
static char *
@@ -524,7 +526,7 @@ srv_to_ns_string(const sr_srv_t *srv, const char *key)
return srv_str;
}
-/* Given the previous SRV and the current SRV, return a heap allocated
+/** Given the previous SRV and the current SRV, return a heap allocated
* string with their data that could be put in a vote or a consensus. Caller
* must free the returned string. Return NULL if no SRVs were provided. */
static char *
@@ -557,7 +559,7 @@ get_ns_str_from_sr_values(const sr_srv_t *prev_srv, const sr_srv_t *cur_srv)
return srv_str;
}
-/* Return 1 iff the two commits have the same commitment values. This
+/** Return 1 iff the two commits have the same commitment values. This
* function does not care about reveal values. */
STATIC int
commitments_are_the_same(const sr_commit_t *commit_one,
@@ -572,7 +574,7 @@ commitments_are_the_same(const sr_commit_t *commit_one,
return 1;
}
-/* We just received a commit from the vote of authority with
+/** We just received a commit from the vote of authority with
* <b>identity_digest</b>. Return 1 if this commit is authorititative that
* is, it belongs to the authority that voted it. Else return 0 if not. */
STATIC int
@@ -586,7 +588,7 @@ commit_is_authoritative(const sr_commit_t *commit,
sizeof(commit->rsa_identity));
}
-/* Decide if the newly received <b>commit</b> should be kept depending on
+/** Decide if the newly received <b>commit</b> should be kept depending on
* the current phase and state of the protocol. The <b>voter_key</b> is the
* RSA identity key fingerprint of the authority's vote from which the
* commit comes from. The <b>phase</b> is the phase we should be validating
@@ -705,7 +707,7 @@ should_keep_commit(const sr_commit_t *commit, const char *voter_key,
return 0;
}
-/* We are in reveal phase and we found a valid and verified <b>commit</b> in
+/** We are in reveal phase and we found a valid and verified <b>commit</b> in
* a vote that contains reveal values that we could use. Update the commit
* we have in our state. Never call this with an unverified commit. */
STATIC void
@@ -726,7 +728,7 @@ save_commit_during_reveal_phase(const sr_commit_t *commit)
sr_state_copy_reveal_info(saved_commit, commit);
}
-/* Save <b>commit</b> to our persistent state. Depending on the current
+/** Save <b>commit</b> to our persistent state. Depending on the current
* phase, different actions are taken. Steals reference of <b>commit</b>.
* The commit object MUST be valid and verified before adding it to the
* state. */
@@ -751,7 +753,7 @@ save_commit_to_state(sr_commit_t *commit)
}
}
-/* Return 1 if we should we keep an SRV voted by <b>n_agreements</b> auths.
+/** Return 1 if we should we keep an SRV voted by <b>n_agreements</b> auths.
* Return 0 if we should ignore it. */
static int
should_keep_srv(int n_agreements)
@@ -781,7 +783,7 @@ should_keep_srv(int n_agreements)
return 1;
}
-/* Helper: compare two DIGEST256_LEN digests. */
+/** Helper: compare two DIGEST256_LEN digests. */
static int
compare_srvs_(const void **_a, const void **_b)
{
@@ -789,7 +791,7 @@ compare_srvs_(const void **_a, const void **_b)
return tor_memcmp(a->value, b->value, sizeof(a->value));
}
-/* Return the most frequent member of the sorted list of DIGEST256_LEN
+/** Return the most frequent member of the sorted list of DIGEST256_LEN
* digests in <b>sl</b> with the count of that most frequent element. */
static sr_srv_t *
smartlist_get_most_frequent_srv(const smartlist_t *sl, int *count_out)
@@ -806,7 +808,7 @@ compare_srv_(const void **_a, const void **_b)
sizeof(a->value));
}
-/* Using a list of <b>votes</b>, return the SRV object from them that has
+/** Using a list of <b>votes</b>, return the SRV object from them that has
* been voted by the majority of dirauths. If <b>current</b> is set, we look
* for the current SRV value else the previous one. The returned pointer is
* an object located inside a vote. NULL is returned if no appropriate value
@@ -868,7 +870,7 @@ get_majority_srv_from_votes(const smartlist_t *votes, int current)
return the_srv;
}
-/* Free a commit object. */
+/** Free a commit object. */
void
sr_commit_free_(sr_commit_t *commit)
{
@@ -880,7 +882,7 @@ sr_commit_free_(sr_commit_t *commit)
tor_free(commit);
}
-/* Generate the commitment/reveal value for the protocol run starting at
+/** Generate the commitment/reveal value for the protocol run starting at
* <b>timestamp</b>. <b>my_rsa_cert</b> is our authority RSA certificate. */
sr_commit_t *
sr_generate_our_commit(time_t timestamp, const authority_cert_t *my_rsa_cert)
@@ -937,7 +939,8 @@ sr_generate_our_commit(time_t timestamp, const authority_cert_t *my_rsa_cert)
return NULL;
}
-/* Compute the shared random value based on the active commits in our state. */
+/** Compute the shared random value based on the active commits in our
+ * state. */
void
sr_compute_srv(void)
{
@@ -1010,7 +1013,7 @@ sr_compute_srv(void)
tor_free(reveals);
}
-/* Parse a commit from a vote or from our disk state and return a newly
+/** Parse a commit from a vote or from our disk state and return a newly
* allocated commit object. NULL is returned on error.
*
* The commit's data is in <b>args</b> and the order matters very much:
@@ -1082,7 +1085,7 @@ sr_parse_commit(const smartlist_t *args)
return NULL;
}
-/* Called when we are done parsing a vote by <b>voter_key</b> that might
+/** Called when we are done parsing a vote by <b>voter_key</b> that might
* contain some useful <b>commits</b>. Find if any of them should be kept
* and update our state accordingly. Once done, the list of commitments will
* be empty. */
@@ -1120,7 +1123,7 @@ sr_handle_received_commits(smartlist_t *commits, crypto_pk_t *voter_key)
} SMARTLIST_FOREACH_END(commit);
}
-/* Return a heap-allocated string containing commits that should be put in
+/** Return a heap-allocated string containing commits that should be put in
* the votes. It's the responsibility of the caller to free the string.
* This always return a valid string, either empty or with line(s). */
char *
@@ -1129,7 +1132,7 @@ sr_get_string_for_vote(void)
char *vote_str = NULL;
digestmap_t *state_commits;
smartlist_t *chunks = smartlist_new();
- const or_options_t *options = get_options();
+ const dirauth_options_t *options = dirauth_get_options();
/* Are we participating in the protocol? */
if (!options->AuthDirSharedRandomness) {
@@ -1178,7 +1181,7 @@ sr_get_string_for_vote(void)
return vote_str;
}
-/* Return a heap-allocated string that should be put in the consensus and
+/** Return a heap-allocated string that should be put in the consensus and
* contains the shared randomness values. It's the responsibility of the
* caller to free the string. NULL is returned if no SRV(s) available.
*
@@ -1194,7 +1197,7 @@ sr_get_string_for_consensus(const smartlist_t *votes,
int32_t num_srv_agreements)
{
char *srv_str;
- const or_options_t *options = get_options();
+ const dirauth_options_t *options = dirauth_get_options();
tor_assert(votes);
@@ -1222,7 +1225,7 @@ sr_get_string_for_consensus(const smartlist_t *votes,
return NULL;
}
-/* We just computed a new <b>consensus</b>. Update our state with the SRVs
+/** We just computed a new <b>consensus</b>. Update our state with the SRVs
* from the consensus (might be NULL as well). Register the SRVs in our SR
* state and prepare for the upcoming protocol round. */
void
@@ -1261,7 +1264,7 @@ sr_act_post_consensus(const networkstatus_t *consensus)
sr_state_update(voting_schedule_get_next_valid_after_time());
}
-/* Initialize shared random subsystem. This MUST be called early in the boot
+/** Initialize shared random subsystem. This MUST be called early in the boot
* process of tor. Return 0 on success else -1 on error. */
int
sr_init(int save_to_disk)
@@ -1269,7 +1272,7 @@ sr_init(int save_to_disk)
return sr_state_init(save_to_disk, 1);
}
-/* Save our state to disk and cleanup everything. */
+/** Save our state to disk and cleanup everything. */
void
sr_save_and_cleanup(void)
{
@@ -1279,7 +1282,7 @@ sr_save_and_cleanup(void)
#ifdef TOR_UNIT_TESTS
-/* Set the global value of number of SRV agreements so the test can play
+/** Set the global value of number of SRV agreements so the test can play
* along by calling specific functions that don't parse the votes prior for
* the AuthDirNumSRVAgreements value. */
void
diff --git a/src/feature/dirauth/shared_random.h b/src/feature/dirauth/shared_random.h
index 7ff9f15512..c4e259dcdb 100644
--- a/src/feature/dirauth/shared_random.h
+++ b/src/feature/dirauth/shared_random.h
@@ -1,86 +1,88 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_SHARED_RANDOM_H
#define TOR_SHARED_RANDOM_H
-/*
- * This file contains ABI/API of the shared random protocol defined in
+/**
+ * \file shared_random.h
+ *
+ * \brief This file contains ABI/API of the shared random protocol defined in
* proposal #250. Every public functions and data structure are namespaced
* with "sr_" which stands for shared random.
*/
#include "core/or/or.h"
-/* Protocol version */
+/** Protocol version */
#define SR_PROTO_VERSION 1
-/* Default digest algorithm. */
+/** Default digest algorithm. */
#define SR_DIGEST_ALG DIGEST_SHA3_256
-/* Invariant token in the SRV calculation. */
+/** Invariant token in the SRV calculation. */
#define SR_SRV_TOKEN "shared-random"
-/* Don't count the NUL terminated byte even though the TOKEN has it. */
+/** Don't count the NUL terminated byte even though the TOKEN has it. */
#define SR_SRV_TOKEN_LEN (sizeof(SR_SRV_TOKEN) - 1)
-/* Length of the random number (in bytes). */
+/** Length of the random number (in bytes). */
#define SR_RANDOM_NUMBER_LEN 32
-/* Size of a decoded commit value in a vote or state. It's a hash and a
+/** Size of a decoded commit value in a vote or state. It's a hash and a
* timestamp. It adds up to 40 bytes. */
#define SR_COMMIT_LEN (sizeof(uint64_t) + DIGEST256_LEN)
-/* Size of a decoded reveal value from a vote or state. It's a 64 bit
+/** Size of a decoded reveal value from a vote or state. It's a 64 bit
* timestamp and the hashed random number. This adds up to 40 bytes. */
#define SR_REVEAL_LEN (sizeof(uint64_t) + DIGEST256_LEN)
-/* Size of SRV message length. The construction is has follow:
+/** Size of SRV message length. The construction is has follow:
* "shared-random" | INT_8(reveal_num) | INT_4(version) | PREV_SRV */
#define SR_SRV_MSG_LEN \
(SR_SRV_TOKEN_LEN + sizeof(uint64_t) + sizeof(uint32_t) + DIGEST256_LEN)
-/* Length of base64 encoded commit NOT including the NUL terminated byte.
+/** Length of base64 encoded commit NOT including the NUL terminated byte.
* Formula is taken from base64_encode_size. This adds up to 56 bytes. */
#define SR_COMMIT_BASE64_LEN (BASE64_LEN(SR_COMMIT_LEN))
-/* Length of base64 encoded reveal NOT including the NUL terminated byte.
+/** Length of base64 encoded reveal NOT including the NUL terminated byte.
* Formula is taken from base64_encode_size. This adds up to 56 bytes. */
#define SR_REVEAL_BASE64_LEN (BASE64_LEN(SR_REVEAL_LEN))
-/* Length of base64 encoded shared random value. It's 32 bytes long so 44
+/** Length of base64 encoded shared random value. It's 32 bytes long so 44
* bytes from the base64_encode_size formula. That includes the '='
* character at the end. */
#define SR_SRV_VALUE_BASE64_LEN (BASE64_LEN(DIGEST256_LEN))
-/* Assert if commit valid flag is not set. */
+/** Assert if commit valid flag is not set. */
#define ASSERT_COMMIT_VALID(c) tor_assert((c)->valid)
-/* Protocol phase. */
+/** Protocol phase. */
typedef enum {
- /* Commitment phase */
+ /** Commitment phase */
SR_PHASE_COMMIT = 1,
- /* Reveal phase */
+ /** Reveal phase */
SR_PHASE_REVEAL = 2,
} sr_phase_t;
-/* A shared random value (SRV). */
+/** A shared random value (SRV). */
typedef struct sr_srv_t {
- /* The number of reveal values used to derive this SRV. */
+ /** The number of reveal values used to derive this SRV. */
uint64_t num_reveals;
- /* The actual value. This is the stored result of SHA3-256. */
+ /** The actual value. This is the stored result of SHA3-256. */
uint8_t value[DIGEST256_LEN];
} sr_srv_t;
-/* A commit (either ours or from another authority). */
+/** A commit (either ours or from another authority). */
typedef struct sr_commit_t {
- /* Hashing algorithm used. */
+ /** Hashing algorithm used. */
digest_algorithm_t alg;
- /* Indicate if this commit has been verified thus valid. */
+ /** Indicate if this commit has been verified thus valid. */
unsigned int valid:1;
/* Commit owner info */
- /* The RSA identity key of the authority and its base16 representation,
+ /** The RSA identity key of the authority and its base16 representation,
* which includes the NUL terminated byte. */
char rsa_identity[DIGEST_LEN];
char rsa_identity_hex[HEX_DIGEST_LEN + 1];
/* Commitment information */
- /* Timestamp of reveal. Correspond to TIMESTAMP. */
+ /** Timestamp of reveal. Correspond to TIMESTAMP. */
uint64_t reveal_ts;
/* H(REVEAL) as found in COMMIT message. */
char hashed_reveal[DIGEST256_LEN];
@@ -89,13 +91,13 @@ typedef struct sr_commit_t {
/* Reveal information */
- /* H(RN) which is what we used as the random value for this commit. We
+ /** H(RN) which is what we used as the random value for this commit. We
* don't use the raw bytes since those are sent on the network thus
* avoiding possible information leaks of our PRNG. */
uint8_t random_number[SR_RANDOM_NUMBER_LEN];
- /* Timestamp of commit. Correspond to TIMESTAMP. */
+ /** Timestamp of commit. Correspond to TIMESTAMP. */
uint64_t commit_ts;
- /* This is the whole reveal message. We use it during verification */
+ /** This is the whole reveal message. We use it during verification */
char encoded_reveal[SR_REVEAL_BASE64_LEN + 1];
} sr_commit_t;
@@ -191,4 +193,3 @@ void set_num_srv_agreements(int32_t value);
#endif /* TOR_UNIT_TESTS */
#endif /* !defined(TOR_SHARED_RANDOM_H) */
-
diff --git a/src/feature/dirauth/shared_random_state.c b/src/feature/dirauth/shared_random_state.c
index 4078d6a24a..cfbfa4ec5b 100644
--- a/src/feature/dirauth/shared_random_state.c
+++ b/src/feature/dirauth/shared_random_state.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,7 +12,7 @@
#include "core/or/or.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "lib/crypt_ops/crypto_util.h"
#include "feature/dirauth/dirvote.h"
#include "feature/nodelist/networkstatus.h"
@@ -26,18 +26,18 @@
#include "app/config/or_state_st.h"
-/* Default filename of the shared random state on disk. */
+/** Default filename of the shared random state on disk. */
static const char default_fname[] = "sr-state";
-/* String representation of a protocol phase. */
+/** String representation of a protocol phase. */
static const char *phase_str[] = { "unknown", "commit", "reveal" };
-/* Our shared random protocol state. There is only one possible state per
+/** Our shared random protocol state. There is only one possible state per
* protocol run so this is the global state which is reset at every run once
* the shared random value has been computed. */
static sr_state_t *sr_state = NULL;
-/* Representation of our persistent state on disk. The sr_state above
+/** Representation of our persistent state on disk. The sr_state above
* contains the data parsed from this state. When we save to disk, we
* translate the sr_state to this sr_disk_state. */
static sr_disk_state_t *sr_disk_state = NULL;
@@ -56,14 +56,10 @@ DUMMY_TYPECHECK_INSTANCE(sr_disk_state_t);
#define V(member,conftype,initvalue) \
VAR(#member, conftype, member, initvalue)
-/* Our persistent state magic number. */
+/** Our persistent state magic number. */
#define SR_DISK_STATE_MAGIC 0x98AB1254
-static int
-disk_state_validate_cb(void *old_state, void *state, void *default_state,
- int from_setconf, char **msg);
-
-/* Array of variables that are saved to disk as a persistent state. */
+/** Array of variables that are saved to disk as a persistent state. */
static const config_var_t state_vars[] = {
V(Version, POSINT, "0"),
V(TorVersion, STRING, NULL),
@@ -78,7 +74,7 @@ static const config_var_t state_vars[] = {
END_OF_CONFIG_VARS
};
-/* "Extra" variable in the state that receives lines we can't parse. This
+/** "Extra" variable in the state that receives lines we can't parse. This
* lets us preserve options from versions of Tor newer than us. */
static const struct_member_t state_extra_var = {
.name = "__extra",
@@ -86,24 +82,19 @@ static const struct_member_t state_extra_var = {
.offset = offsetof(sr_disk_state_t, ExtraLines),
};
-/* Configuration format of sr_disk_state_t. */
+/** Configuration format of sr_disk_state_t. */
static const config_format_t state_format = {
- sizeof(sr_disk_state_t),
- {
+ .size = sizeof(sr_disk_state_t),
+ .magic = {
"sr_disk_state_t",
SR_DISK_STATE_MAGIC,
offsetof(sr_disk_state_t, magic_),
},
- NULL,
- NULL,
- state_vars,
- disk_state_validate_cb,
- NULL,
- &state_extra_var,
- -1,
+ .vars = state_vars,
+ .extra = &state_extra_var,
};
-/* Global configuration manager for the shared-random state file */
+/** Global configuration manager for the shared-random state file */
static config_mgr_t *shared_random_state_mgr = NULL;
/** Return the configuration manager for the shared-random state file. */
@@ -119,7 +110,7 @@ get_srs_mgr(void)
static void state_query_del_(sr_state_object_t obj_type, void *data);
-/* Return a string representation of a protocol phase. */
+/** Return a string representation of a protocol phase. */
STATIC const char *
get_phase_str(sr_phase_t phase)
{
@@ -137,7 +128,7 @@ get_phase_str(sr_phase_t phase)
return the_string;
}
-/* Return the time we should expire the state file created at <b>now</b>.
+/** Return the time we should expire the state file created at <b>now</b>.
* We expire the state file in the beginning of the next protocol run. */
STATIC time_t
get_state_valid_until_time(time_t now)
@@ -168,7 +159,7 @@ get_state_valid_until_time(time_t now)
return valid_until;
}
-/* Given the consensus 'valid-after' time, return the protocol phase we should
+/** Given the consensus 'valid-after' time, return the protocol phase we should
* be in. */
STATIC sr_phase_t
get_sr_protocol_phase(time_t valid_after)
@@ -188,7 +179,7 @@ get_sr_protocol_phase(time_t valid_after)
}
}
-/* Add the given <b>commit</b> to <b>state</b>. It MUST be a valid commit
+/** Add the given <b>commit</b> to <b>state</b>. It MUST be a valid commit
* and there shouldn't be a commit from the same authority in the state
* already else verification hasn't been done prior. This takes ownership of
* the commit once in our state. */
@@ -213,7 +204,7 @@ commit_add_to_state(sr_commit_t *commit, sr_state_t *state)
}
}
-/* Helper: deallocate a commit object. (Used with digestmap_free(), which
+/** Helper: deallocate a commit object. (Used with digestmap_free(), which
* requires a function pointer whose argument is void *). */
static void
commit_free_(void *p)
@@ -224,7 +215,7 @@ commit_free_(void *p)
#define state_free(val) \
FREE_AND_NULL(sr_state_t, state_free_, (val))
-/* Free a state that was allocated with state_new(). */
+/** Free a state that was allocated with state_new(). */
static void
state_free_(sr_state_t *state)
{
@@ -238,7 +229,7 @@ state_free_(sr_state_t *state)
tor_free(state);
}
-/* Allocate an sr_state_t object and returns it. If no <b>fname</b>, the
+/** Allocate an sr_state_t object and returns it. If no <b>fname</b>, the
* default file name is used. This function does NOT initialize the state
* timestamp, phase or shared random value. NULL is never returned. */
static sr_state_t *
@@ -257,7 +248,7 @@ state_new(const char *fname, time_t now)
return new_state;
}
-/* Set our global state pointer with the one given. */
+/** Set our global state pointer with the one given. */
static void
state_set(sr_state_t *state)
{
@@ -271,7 +262,7 @@ state_set(sr_state_t *state)
#define disk_state_free(val) \
FREE_AND_NULL(sr_disk_state_t, disk_state_free_, (val))
-/* Free an allocated disk state. */
+/** Free an allocated disk state. */
static void
disk_state_free_(sr_disk_state_t *state)
{
@@ -281,7 +272,7 @@ disk_state_free_(sr_disk_state_t *state)
config_free(get_srs_mgr(), state);
}
-/* Allocate a new disk state, initialize it and return it. */
+/** Allocate a new disk state, initialize it and return it. */
static sr_disk_state_t *
disk_state_new(time_t now)
{
@@ -297,7 +288,7 @@ disk_state_new(time_t now)
return new_state;
}
-/* Set our global disk state with the given state. */
+/** Set our global disk state with the given state. */
static void
disk_state_set(sr_disk_state_t *state)
{
@@ -308,7 +299,7 @@ disk_state_set(sr_disk_state_t *state)
sr_disk_state = state;
}
-/* Return -1 if the disk state is invalid (something in there that we can't or
+/** Return -1 if the disk state is invalid (something in there that we can't or
* shouldn't use). Return 0 if everything checks out. */
static int
disk_state_validate(const sr_disk_state_t *state)
@@ -343,25 +334,7 @@ disk_state_validate(const sr_disk_state_t *state)
return -1;
}
-/* Validate the disk state (NOP for now). */
-static int
-disk_state_validate_cb(void *old_state, void *state, void *default_state,
- int from_setconf, char **msg)
-{
- /* We don't use these; only options do. */
- (void) from_setconf;
- (void) default_state;
- (void) old_state;
-
- /* This is called by config_dump which is just before we are about to
- * write it to disk. At that point, our global memory state has been
- * copied to the disk state so it's fair to assume it's trustable. */
- (void) state;
- (void) msg;
- return 0;
-}
-
-/* Parse the Commit line(s) in the disk state and translate them to the
+/** Parse the Commit line(s) in the disk state and translate them to the
* the memory state. Return 0 on success else -1 on error. */
static int
disk_state_parse_commits(sr_state_t *state,
@@ -416,7 +389,7 @@ disk_state_parse_commits(sr_state_t *state,
return -1;
}
-/* Parse a share random value line from the disk state and save it to dst
+/** Parse a share random value line from the disk state and save it to dst
* which is an allocated srv object. Return 0 on success else -1. */
static int
disk_state_parse_srv(const char *value, sr_srv_t *dst)
@@ -451,7 +424,7 @@ disk_state_parse_srv(const char *value, sr_srv_t *dst)
return ret;
}
-/* Parse both SharedRandCurrentValue and SharedRandPreviousValue line from
+/** Parse both SharedRandCurrentValue and SharedRandPreviousValue line from
* the state. Return 0 on success else -1. */
static int
disk_state_parse_sr_values(sr_state_t *state,
@@ -502,7 +475,7 @@ disk_state_parse_sr_values(sr_state_t *state,
return -1;
}
-/* Parse the given disk state and set a newly allocated state. On success,
+/** Parse the given disk state and set a newly allocated state. On success,
* return that state else NULL. */
static sr_state_t *
disk_state_parse(const sr_disk_state_t *new_disk_state)
@@ -536,7 +509,7 @@ disk_state_parse(const sr_disk_state_t *new_disk_state)
return NULL;
}
-/* From a valid commit object and an allocated config line, set the line's
+/** From a valid commit object and an allocated config line, set the line's
* value to the state string representation of a commit. */
static void
disk_state_put_commit_line(const sr_commit_t *commit, config_line_t *line)
@@ -563,7 +536,7 @@ disk_state_put_commit_line(const sr_commit_t *commit, config_line_t *line)
}
}
-/* From a valid srv object and an allocated config line, set the line's
+/** From a valid srv object and an allocated config line, set the line's
* value to the state string representation of a shared random value. */
static void
disk_state_put_srv_line(const sr_srv_t *srv, config_line_t *line)
@@ -581,7 +554,7 @@ disk_state_put_srv_line(const sr_srv_t *srv, config_line_t *line)
tor_asprintf(&line->value, "%" PRIu64 " %s", srv->num_reveals, encoded);
}
-/* Reset disk state that is free allocated memory and zeroed the object. */
+/** Reset disk state that is free allocated memory and zeroed the object. */
static void
disk_state_reset(void)
{
@@ -600,7 +573,7 @@ disk_state_reset(void)
sr_disk_state->TorVersion = tor_strdup(get_version());
}
-/* Update our disk state based on our global SR state. */
+/** Update our disk state based on our global SR state. */
static void
disk_state_update(void)
{
@@ -644,7 +617,7 @@ disk_state_update(void)
} DIGESTMAP_FOREACH_END;
}
-/* Load state from disk and put it into our disk state. If the state passes
+/** Load state from disk and put it into our disk state. If the state passes
* validation, our global state will be updated with it. Return 0 on
* success. On error, -EINVAL is returned if the state on disk did contained
* something malformed or is unreadable. -ENOENT is returned indicating that
@@ -662,7 +635,7 @@ disk_state_load_from_disk(void)
return ret;
}
-/* Helper for disk_state_load_from_disk(). */
+/** Helper for disk_state_load_from_disk(). */
STATIC int
disk_state_load_from_disk_impl(const char *fname)
{
@@ -724,7 +697,7 @@ disk_state_load_from_disk_impl(const char *fname)
return ret;
}
-/* Save the disk state to disk but before that update it from the current
+/** Save the disk state to disk but before that update it from the current
* state so we always have the latest. Return 0 on success else -1. */
static int
disk_state_save_to_disk(void)
@@ -768,7 +741,7 @@ disk_state_save_to_disk(void)
return ret;
}
-/* Reset our state to prepare for a new protocol run. Once this returns, all
+/** Reset our state to prepare for a new protocol run. Once this returns, all
* commits in the state will be removed and freed. */
STATIC void
reset_state_for_new_protocol_run(time_t valid_after)
@@ -789,7 +762,7 @@ reset_state_for_new_protocol_run(time_t valid_after)
sr_state_delete_commits();
}
-/* This is the first round of the new protocol run starting at
+/** This is the first round of the new protocol run starting at
* <b>valid_after</b>. Do the necessary housekeeping. */
STATIC void
new_protocol_run(time_t valid_after)
@@ -823,7 +796,7 @@ new_protocol_run(time_t valid_after)
}
}
-/* Return 1 iff the <b>next_phase</b> is a phase transition from the current
+/** Return 1 iff the <b>next_phase</b> is a phase transition from the current
* phase that is it's different. */
STATIC int
is_phase_transition(sr_phase_t next_phase)
@@ -831,7 +804,7 @@ is_phase_transition(sr_phase_t next_phase)
return sr_state->phase != next_phase;
}
-/* Helper function: return a commit using the RSA fingerprint of the
+/** Helper function: return a commit using the RSA fingerprint of the
* authority or NULL if no such commit is known. */
static sr_commit_t *
state_query_get_commit(const char *rsa_fpr)
@@ -840,7 +813,7 @@ state_query_get_commit(const char *rsa_fpr)
return digestmap_get(sr_state->commits, rsa_fpr);
}
-/* Helper function: This handles the GET state action using an
+/** Helper function: This handles the GET state action using an
* <b>obj_type</b> and <b>data</b> needed for the action. */
static void *
state_query_get_(sr_state_object_t obj_type, const void *data)
@@ -875,7 +848,7 @@ state_query_get_(sr_state_object_t obj_type, const void *data)
return obj;
}
-/* Helper function: This handles the PUT state action using an
+/** Helper function: This handles the PUT state action using an
* <b>obj_type</b> and <b>data</b> needed for the action.
* PUT frees the previous data before replacing it, if needed. */
static void
@@ -928,7 +901,7 @@ state_query_put_(sr_state_object_t obj_type, void *data)
}
}
-/* Helper function: This handles the DEL_ALL state action using an
+/** Helper function: This handles the DEL_ALL state action using an
* <b>obj_type</b> and <b>data</b> needed for the action. */
static void
state_query_del_all_(sr_state_object_t obj_type)
@@ -957,7 +930,7 @@ state_query_del_all_(sr_state_object_t obj_type)
}
}
-/* Helper function: This handles the DEL state action using an
+/** Helper function: This handles the DEL state action using an
* <b>obj_type</b> and <b>data</b> needed for the action. */
static void
state_query_del_(sr_state_object_t obj_type, void *data)
@@ -983,7 +956,7 @@ state_query_del_(sr_state_object_t obj_type, void *data)
}
}
-/* Query state using an <b>action</b> for an object type <b>obj_type</b>.
+/** Query state using an <b>action</b> for an object type <b>obj_type</b>.
* The <b>data</b> pointer needs to point to an object that the action needs
* to use and if anything is required to be returned, it is stored in
* <b>out</b>.
@@ -1025,7 +998,7 @@ state_query(sr_state_action_t action, sr_state_object_t obj_type,
}
}
-/* Delete the current SRV value from the state freeing it and the value is set
+/** Delete the current SRV value from the state freeing it and the value is set
* to NULL meaning empty. */
STATIC void
state_del_current_srv(void)
@@ -1033,7 +1006,7 @@ state_del_current_srv(void)
state_query(SR_STATE_ACTION_DEL, SR_STATE_OBJ_CURSRV, NULL, NULL);
}
-/* Delete the previous SRV value from the state freeing it and the value is
+/** Delete the previous SRV value from the state freeing it and the value is
* set to NULL meaning empty. */
STATIC void
state_del_previous_srv(void)
@@ -1041,7 +1014,7 @@ state_del_previous_srv(void)
state_query(SR_STATE_ACTION_DEL, SR_STATE_OBJ_PREVSRV, NULL, NULL);
}
-/* Rotate SRV value by setting the previous SRV to the current SRV, and
+/** Rotate SRV value by setting the previous SRV to the current SRV, and
* clearing the current SRV. */
STATIC void
state_rotate_srv(void)
@@ -1054,7 +1027,7 @@ state_rotate_srv(void)
sr_state_set_current_srv(NULL);
}
-/* Set valid after time in the our state. */
+/** Set valid after time in the our state. */
void
sr_state_set_valid_after(time_t valid_after)
{
@@ -1062,7 +1035,7 @@ sr_state_set_valid_after(time_t valid_after)
(void *) &valid_after, NULL);
}
-/* Return the phase we are currently in according to our state. */
+/** Return the phase we are currently in according to our state. */
sr_phase_t
sr_state_get_phase(void)
{
@@ -1072,7 +1045,7 @@ sr_state_get_phase(void)
return *(sr_phase_t *) ptr;
}
-/* Return the previous SRV value from our state. Value CAN be NULL.
+/** Return the previous SRV value from our state. Value CAN be NULL.
* The state object owns the SRV, so the calling code should not free the SRV.
* Use sr_srv_dup() if you want to keep a copy of the SRV. */
const sr_srv_t *
@@ -1084,7 +1057,7 @@ sr_state_get_previous_srv(void)
return srv;
}
-/* Set the current SRV value from our state. Value CAN be NULL. The srv
+/** Set the current SRV value from our state. Value CAN be NULL. The srv
* object ownership is transferred to the state object. */
void
sr_state_set_previous_srv(const sr_srv_t *srv)
@@ -1093,7 +1066,7 @@ sr_state_set_previous_srv(const sr_srv_t *srv)
NULL);
}
-/* Return the current SRV value from our state. Value CAN be NULL.
+/** Return the current SRV value from our state. Value CAN be NULL.
* The state object owns the SRV, so the calling code should not free the SRV.
* Use sr_srv_dup() if you want to keep a copy of the SRV. */
const sr_srv_t *
@@ -1105,7 +1078,7 @@ sr_state_get_current_srv(void)
return srv;
}
-/* Set the current SRV value from our state. Value CAN be NULL. The srv
+/** Set the current SRV value from our state. Value CAN be NULL. The srv
* object ownership is transferred to the state object. */
void
sr_state_set_current_srv(const sr_srv_t *srv)
@@ -1114,7 +1087,7 @@ sr_state_set_current_srv(const sr_srv_t *srv)
NULL);
}
-/* Clean all the SRVs in our state. */
+/** Clean all the SRVs in our state. */
void
sr_state_clean_srvs(void)
{
@@ -1123,7 +1096,7 @@ sr_state_clean_srvs(void)
state_del_current_srv();
}
-/* Return a pointer to the commits map from our state. CANNOT be NULL. */
+/** Return a pointer to the commits map from our state. CANNOT be NULL. */
digestmap_t *
sr_state_get_commits(void)
{
@@ -1134,7 +1107,7 @@ sr_state_get_commits(void)
return commits;
}
-/* Update the current SR state as needed for the upcoming voting round at
+/** Update the current SR state as needed for the upcoming voting round at
* <b>valid_after</b>. */
void
sr_state_update(time_t valid_after)
@@ -1198,7 +1171,7 @@ sr_state_update(time_t valid_after)
}
}
-/* Return commit object from the given authority digest <b>rsa_identity</b>.
+/** Return commit object from the given authority digest <b>rsa_identity</b>.
* Return NULL if not found. */
sr_commit_t *
sr_state_get_commit(const char *rsa_identity)
@@ -1212,7 +1185,7 @@ sr_state_get_commit(const char *rsa_identity)
return commit;
}
-/* Add <b>commit</b> to the permanent state. The commit object ownership is
+/** Add <b>commit</b> to the permanent state. The commit object ownership is
* transferred to the state so the caller MUST not free it. */
void
sr_state_add_commit(sr_commit_t *commit)
@@ -1227,14 +1200,14 @@ sr_state_add_commit(sr_commit_t *commit)
sr_commit_get_rsa_fpr(commit));
}
-/* Remove all commits from our state. */
+/** Remove all commits from our state. */
void
sr_state_delete_commits(void)
{
state_query(SR_STATE_ACTION_DEL_ALL, SR_STATE_OBJ_COMMIT, NULL, NULL);
}
-/* Copy the reveal information from <b>commit</b> into <b>saved_commit</b>.
+/** Copy the reveal information from <b>commit</b> into <b>saved_commit</b>.
* This <b>saved_commit</b> MUST come from our current SR state. Once modified,
* the disk state is updated. */
void
@@ -1255,7 +1228,7 @@ sr_state_copy_reveal_info(sr_commit_t *saved_commit, const sr_commit_t *commit)
sr_commit_get_rsa_fpr(saved_commit));
}
-/* Set the fresh SRV flag from our state. This doesn't need to trigger a
+/** Set the fresh SRV flag from our state. This doesn't need to trigger a
* disk state synchronization so we directly change the state. */
void
sr_state_set_fresh_srv(void)
@@ -1263,7 +1236,7 @@ sr_state_set_fresh_srv(void)
sr_state->is_srv_fresh = 1;
}
-/* Unset the fresh SRV flag from our state. This doesn't need to trigger a
+/** Unset the fresh SRV flag from our state. This doesn't need to trigger a
* disk state synchronization so we directly change the state. */
void
sr_state_unset_fresh_srv(void)
@@ -1271,14 +1244,14 @@ sr_state_unset_fresh_srv(void)
sr_state->is_srv_fresh = 0;
}
-/* Return the value of the fresh SRV flag. */
+/** Return the value of the fresh SRV flag. */
unsigned int
sr_state_srv_is_fresh(void)
{
return sr_state->is_srv_fresh;
}
-/* Cleanup and free our disk and memory state. */
+/** Cleanup and free our disk and memory state. */
void
sr_state_free_all(void)
{
@@ -1290,7 +1263,7 @@ sr_state_free_all(void)
config_mgr_free(shared_random_state_mgr);
}
-/* Save our current state in memory to disk. */
+/** Save our current state in memory to disk. */
void
sr_state_save(void)
{
@@ -1298,7 +1271,7 @@ sr_state_save(void)
state_query(SR_STATE_ACTION_SAVE, 0, NULL, NULL);
}
-/* Return 1 iff the state has been initialized that is it exists in memory.
+/** Return 1 iff the state has been initialized that is it exists in memory.
* Return 0 otherwise. */
int
sr_state_is_initialized(void)
@@ -1306,7 +1279,7 @@ sr_state_is_initialized(void)
return sr_state == NULL ? 0 : 1;
}
-/* Initialize the disk and memory state.
+/** Initialize the disk and memory state.
*
* If save_to_disk is set to 1, the state is immediately saved to disk after
* creation else it's not thus only kept in memory.
@@ -1369,7 +1342,7 @@ sr_state_init(int save_to_disk, int read_from_disk)
#ifdef TOR_UNIT_TESTS
-/* Set the current phase of the protocol. Used only by unit tests. */
+/** Set the current phase of the protocol. Used only by unit tests. */
void
set_sr_phase(sr_phase_t phase)
{
@@ -1378,7 +1351,7 @@ set_sr_phase(sr_phase_t phase)
sr_state->phase = phase;
}
-/* Get the SR state. Used only by unit tests */
+/** Get the SR state. Used only by unit tests */
sr_state_t *
get_sr_state(void)
{
diff --git a/src/feature/dirauth/shared_random_state.h b/src/feature/dirauth/shared_random_state.h
index 08f999f9d4..3a34bcc3e7 100644
--- a/src/feature/dirauth/shared_random_state.h
+++ b/src/feature/dirauth/shared_random_state.h
@@ -1,12 +1,17 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file shared_random_state.h
+ * @brief Header for shared_random_state.c
+ **/
+
#ifndef TOR_SHARED_RANDOM_STATE_H
#define TOR_SHARED_RANDOM_STATE_H
#include "feature/dirauth/shared_random.h"
-/* Action that can be performed on the state for any objects. */
+/** Action that can be performed on the state for any objects. */
typedef enum {
SR_STATE_ACTION_GET = 1,
SR_STATE_ACTION_PUT = 2,
@@ -15,52 +20,53 @@ typedef enum {
SR_STATE_ACTION_SAVE = 5,
} sr_state_action_t;
-/* Object in the state that can be queried through the state API. */
+/** Object in the state that can be queried through the state API. */
typedef enum {
- /* Will return a single commit using an authority identity key. */
+ /** Will return a single commit using an authority identity key. */
SR_STATE_OBJ_COMMIT,
- /* Returns the entire list of commits from the state. */
+ /** Returns the entire list of commits from the state. */
SR_STATE_OBJ_COMMITS,
- /* Return the current SRV object pointer. */
+ /** Return the current SRV object pointer. */
SR_STATE_OBJ_CURSRV,
- /* Return the previous SRV object pointer. */
+ /** Return the previous SRV object pointer. */
SR_STATE_OBJ_PREVSRV,
- /* Return the phase. */
+ /** Return the phase. */
SR_STATE_OBJ_PHASE,
- /* Get or Put the valid after time. */
+ /** Get or Put the valid after time. */
SR_STATE_OBJ_VALID_AFTER,
} sr_state_object_t;
-/* State of the protocol. It's also saved on disk in fname. This data
+/** State of the protocol. It's also saved on disk in fname. This data
* structure MUST be synchronized at all time with the one on disk. */
typedef struct sr_state_t {
- /* Filename of the state file on disk. */
+ /** Filename of the state file on disk. */
char *fname;
- /* Version of the protocol. */
+ /** Version of the protocol. */
uint32_t version;
- /* The valid-after of the voting period we have prepared the state for. */
+ /** The valid-after of the voting period we have prepared the state for. */
time_t valid_after;
- /* Until when is this state valid? */
+ /** Until when is this state valid? */
time_t valid_until;
- /* Protocol phase. */
+ /** Protocol phase. */
sr_phase_t phase;
- /* Number of runs completed. */
+ /** Number of runs completed. */
uint64_t n_protocol_runs;
- /* The number of commitment rounds we've performed in this protocol run. */
+ /** The number of commitment rounds we've performed in this protocol run. */
unsigned int n_commit_rounds;
- /* The number of reveal rounds we've performed in this protocol run. */
+ /** The number of reveal rounds we've performed in this protocol run. */
unsigned int n_reveal_rounds;
- /* A map of all the received commitments for this protocol run. This is
+ /** A map of all the received commitments for this protocol run. This is
* indexed by authority RSA identity digest. */
digestmap_t *commits;
- /* Current and previous shared random value. */
+ /** Current shared random value. */
sr_srv_t *previous_srv;
+ /** Previous shared random value. */
sr_srv_t *current_srv;
- /* Indicate if the state contains an SRV that was _just_ generated. This is
+ /** Indicate if the state contains an SRV that was _just_ generated. This is
* used during voting so that we know whether to use the super majority rule
* or not when deciding on keeping it for the consensus. It is _always_ set
* to 0 post consensus.
@@ -73,22 +79,22 @@ typedef struct sr_state_t {
unsigned int is_srv_fresh:1;
} sr_state_t;
-/* Persistent state of the protocol, as saved to disk. */
+/** Persistent state of the protocol, as saved to disk. */
typedef struct sr_disk_state_t {
uint32_t magic_;
- /* Version of the protocol. */
+ /** Version of the protocol. */
int Version;
- /* Version of our running tor. */
+ /** Version of our running tor. */
char *TorVersion;
- /* Creation time of this state */
+ /** Creation time of this state */
time_t ValidAfter;
- /* State valid until? */
+ /** State valid until? */
time_t ValidUntil;
- /* All commits seen that are valid. */
+ /** All commits seen that are valid. */
struct config_line_t *Commit;
- /* Previous and current shared random value. */
+ /** Previous and current shared random value. */
struct config_line_t *SharedRandValues;
- /* Extra Lines for configuration we might not know. */
+ /** Extra Lines for configuration we might not know. */
struct config_line_t *ExtraLines;
} sr_disk_state_t;
diff --git a/src/feature/dirauth/vote_microdesc_hash_st.h b/src/feature/dirauth/vote_microdesc_hash_st.h
index 7869f92b4f..7f8ebf7fd7 100644
--- a/src/feature/dirauth/vote_microdesc_hash_st.h
+++ b/src/feature/dirauth/vote_microdesc_hash_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file vote_microdesc_hash_st.h
+ * @brief Microdescriptor-hash voting strcture.
+ **/
+
#ifndef VOTE_MICRODESC_HASH_ST_H
#define VOTE_MICRODESC_HASH_ST_H
@@ -19,4 +24,3 @@ struct vote_microdesc_hash_t {
};
#endif /* !defined(VOTE_MICRODESC_HASH_ST_H) */
-
diff --git a/src/feature/dirauth/voteflags.c b/src/feature/dirauth/voteflags.c
index f552af98c4..477eb6f0b7 100644
--- a/src/feature/dirauth/voteflags.c
+++ b/src/feature/dirauth/voteflags.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -18,6 +18,7 @@
#include "core/or/policies.h"
#include "feature/dirauth/bwauth.h"
#include "feature/dirauth/reachability.h"
+#include "feature/dirauth/dirauth_sys.h"
#include "feature/hibernate/hibernate.h"
#include "feature/nodelist/dirlist.h"
#include "feature/nodelist/networkstatus.h"
@@ -27,6 +28,7 @@
#include "feature/relay/router.h"
#include "feature/stats/rephist.h"
+#include "feature/dirauth/dirauth_options_st.h"
#include "feature/nodelist/node_st.h"
#include "feature/nodelist/routerinfo_st.h"
#include "feature/nodelist/routerlist_st.h"
@@ -145,7 +147,7 @@ router_is_active(const routerinfo_t *ri, const node_t *node, time_t now)
* if TestingTorNetwork, and TestingMinExitFlagThreshold is non-zero */
if (!ri->bandwidthcapacity) {
if (get_options()->TestingTorNetwork) {
- if (get_options()->TestingMinExitFlagThreshold > 0) {
+ if (dirauth_get_options()->TestingMinExitFlagThreshold > 0) {
/* If we're in a TestingTorNetwork, and TestingMinExitFlagThreshold is,
* then require bandwidthcapacity */
return 0;
@@ -175,14 +177,14 @@ dirserv_thinks_router_is_hs_dir(const routerinfo_t *router,
long uptime;
/* If we haven't been running for at least
- * get_options()->MinUptimeHidServDirectoryV2 seconds, we can't
+ * MinUptimeHidServDirectoryV2 seconds, we can't
* have accurate data telling us a relay has been up for at least
* that long. We also want to allow a bit of slack: Reachability
* tests aren't instant. If we haven't been running long enough,
* trust the relay. */
if (get_uptime() >
- get_options()->MinUptimeHidServDirectoryV2 * 1.1)
+ dirauth_get_options()->MinUptimeHidServDirectoryV2 * 1.1)
uptime = MIN(rep_hist_get_uptime(router->cache_info.identity_digest, now),
real_uptime(router, now));
else
@@ -191,7 +193,7 @@ dirserv_thinks_router_is_hs_dir(const routerinfo_t *router,
return (router->wants_to_be_hs_dir &&
router->supports_tunnelled_dir_requests &&
node->is_stable && node->is_fast &&
- uptime >= get_options()->MinUptimeHidServDirectoryV2 &&
+ uptime >= dirauth_get_options()->MinUptimeHidServDirectoryV2 &&
router_is_active(router, node, now));
}
@@ -214,9 +216,10 @@ router_counts_toward_thresholds(const node_t *node, time_t now,
dirserv_has_measured_bw(node->identity);
uint64_t min_bw_kb = ABSOLUTE_MIN_BW_VALUE_TO_CONSIDER_KB;
const or_options_t *options = get_options();
+ const dirauth_options_t *dirauth_options = dirauth_get_options();
if (options->TestingTorNetwork) {
- min_bw_kb = (int64_t)options->TestingMinExitFlagThreshold / 1000;
+ min_bw_kb = (int64_t)dirauth_options->TestingMinExitFlagThreshold / 1000;
}
return node->ri && router_is_active(node->ri, node, now) &&
@@ -242,11 +245,12 @@ dirserv_compute_performance_thresholds(digestmap_t *omit_as_sybil)
const smartlist_t *nodelist;
time_t now = time(NULL);
const or_options_t *options = get_options();
+ const dirauth_options_t *dirauth_options = dirauth_get_options();
/* Require mbw? */
int require_mbw =
(dirserv_get_last_n_measured_bws() >
- options->MinMeasuredBWsForAuthToIgnoreAdvertised) ? 1 : 0;
+ dirauth_options->MinMeasuredBWsForAuthToIgnoreAdvertised) ? 1 : 0;
/* initialize these all here, in case there are no routers */
stable_uptime = 0;
@@ -338,7 +342,7 @@ dirserv_compute_performance_thresholds(digestmap_t *omit_as_sybil)
ABSOLUTE_MIN_VALUE_FOR_FAST_FLAG,
INT32_MAX);
if (options->TestingTorNetwork) {
- min_fast = (int32_t)options->TestingMinFastFlagThreshold;
+ min_fast = (int32_t)dirauth_options->TestingMinFastFlagThreshold;
}
max_fast = networkstatus_get_param(NULL, "FastFlagMaxThreshold",
INT32_MAX, min_fast, INT32_MAX);
@@ -352,9 +356,11 @@ dirserv_compute_performance_thresholds(digestmap_t *omit_as_sybil)
}
/* Protect sufficiently fast nodes from being pushed out of the set
* of Fast nodes. */
- if (options->AuthDirFastGuarantee &&
- fast_bandwidth_kb > options->AuthDirFastGuarantee/1000)
- fast_bandwidth_kb = (uint32_t)options->AuthDirFastGuarantee/1000;
+ {
+ const uint64_t fast_opt = dirauth_get_options()->AuthDirFastGuarantee;
+ if (fast_opt && fast_bandwidth_kb > fast_opt / 1000)
+ fast_bandwidth_kb = (uint32_t)(fast_opt / 1000);
+ }
/* Now that we have a time-known that 7/8 routers are known longer than,
* fill wfus with the wfu of every such "familiar" router. */
@@ -428,7 +434,7 @@ dirserv_get_flag_thresholds_line(void)
{
char *result=NULL;
const int measured_threshold =
- get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised;
+ dirauth_get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised;
const int enough_measured_bw =
dirserv_get_last_n_measured_bws() > measured_threshold;
@@ -455,8 +461,9 @@ dirserv_get_flag_thresholds_line(void)
int
running_long_enough_to_decide_unreachable(void)
{
- return time_of_process_start
- + get_options()->TestingAuthDirTimeToLearnReachability < approx_time();
+ const dirauth_options_t *opts = dirauth_get_options();
+ return time_of_process_start +
+ opts->TestingAuthDirTimeToLearnReachability < approx_time();
}
/** Each server needs to have passed a reachability test no more
@@ -481,6 +488,7 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
*/
int answer;
const or_options_t *options = get_options();
+ const dirauth_options_t *dirauth_options = dirauth_get_options();
node_t *node = node_get_mutable_by_id(router->cache_info.identity_digest);
tor_assert(node);
@@ -507,7 +515,7 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
IPv6 OR port since that'd kill all dual stack relays until a
majority of the dir auths have IPv6 connectivity. */
answer = (now < node->last_reachable + REACHABLE_TIMEOUT &&
- (options->AuthDirHasIPv6Connectivity != 1 ||
+ (dirauth_options->AuthDirHasIPv6Connectivity != 1 ||
tor_addr_is_null(&router->ipv6_addr) ||
now < node->last_reachable6 + REACHABLE_TIMEOUT));
}
@@ -538,7 +546,7 @@ static int
should_publish_node_ipv6(const node_t *node, const routerinfo_t *ri,
time_t now)
{
- const or_options_t *options = get_options();
+ const dirauth_options_t *options = dirauth_get_options();
return options->AuthDirHasIPv6Connectivity == 1 &&
!tor_addr_is_null(&ri->ipv6_addr) &&
@@ -571,10 +579,10 @@ dirauth_set_routerstatus_from_routerinfo(routerstatus_t *rs,
set_routerstatus_from_routerinfo(rs, node, ri);
/* Override rs->is_possible_guard. */
+ const uint64_t bw_opt = dirauth_get_options()->AuthDirGuardBWGuarantee;
if (node->is_fast && node->is_stable &&
ri->supports_tunnelled_dir_requests &&
- ((options->AuthDirGuardBWGuarantee &&
- routerbw_kb >= options->AuthDirGuardBWGuarantee/1000) ||
+ ((bw_opt && routerbw_kb >= bw_opt / 1000) ||
routerbw_kb >= MIN(guard_bandwidth_including_exits_kb,
guard_bandwidth_excluding_exits_kb))) {
long tk = rep_hist_get_weighted_time_known(
@@ -612,9 +620,9 @@ dirauth_set_routerstatus_from_routerinfo(routerstatus_t *rs,
STATIC void
dirserv_set_routerstatus_testing(routerstatus_t *rs)
{
- const or_options_t *options = get_options();
+ const dirauth_options_t *options = dirauth_get_options();
- tor_assert(options->TestingTorNetwork);
+ tor_assert(get_options()->TestingTorNetwork);
if (routerset_contains_routerstatus(options->TestingDirAuthVoteExit,
rs, 0)) {
diff --git a/src/feature/dirauth/voteflags.h b/src/feature/dirauth/voteflags.h
index c4f36e7817..91f3854573 100644
--- a/src/feature/dirauth/voteflags.h
+++ b/src/feature/dirauth/voteflags.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dircache/.may_include b/src/feature/dircache/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/dircache/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/dircache/cached_dir_st.h b/src/feature/dircache/cached_dir_st.h
index a28802f905..ede1d028da 100644
--- a/src/feature/dircache/cached_dir_st.h
+++ b/src/feature/dircache/cached_dir_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file cached_dir_st.h
+ * @brief Cached large directory object structure.
+ **/
+
#ifndef CACHED_DIR_ST_H
#define CACHED_DIR_ST_H
@@ -22,4 +27,3 @@ struct cached_dir_t {
};
#endif /* !defined(CACHED_DIR_ST_H) */
-
diff --git a/src/feature/dircache/conscache.c b/src/feature/dircache/conscache.c
index 2ec9981c03..ceba410a5f 100644
--- a/src/feature/dircache/conscache.c
+++ b/src/feature/dircache/conscache.c
@@ -1,6 +1,11 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file conscache.c
+ * @brief Consensus and diff on-disk cache.
+ **/
+
#include "core/or/or.h"
#include "app/config/config.h"
@@ -133,7 +138,7 @@ consensus_cache_may_overallocate(consensus_cache_t *cache)
*/
int
consensus_cache_register_with_sandbox(consensus_cache_t *cache,
- struct sandbox_cfg_elem **cfg)
+ struct sandbox_cfg_elem_t **cfg)
{
#ifdef MUST_UNMAP_TO_UNLINK
/* Our Linux sandbox doesn't support huge file lists like the one that would
@@ -246,7 +251,7 @@ consensus_cache_find_first(consensus_cache_t *cache,
}
/**
- * Given a <b>cache</b>, add every entry to <b>out<b> for which
+ * Given a <b>cache</b>, add every entry to <b>out</b> for which
* <b>key</b>=<b>value</b>. If <b>key</b> is NULL, add every entry.
*
* Do not add any entry that has been marked for removal.
diff --git a/src/feature/dircache/conscache.h b/src/feature/dircache/conscache.h
index d848e57617..ace5908e40 100644
--- a/src/feature/dircache/conscache.h
+++ b/src/feature/dircache/conscache.h
@@ -1,6 +1,11 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file conscache.h
+ * @brief Header for conscache.c
+ **/
+
#ifndef TOR_CONSCACHE_H
#define TOR_CONSCACHE_H
@@ -9,6 +14,8 @@
typedef struct consensus_cache_entry_t consensus_cache_entry_t;
typedef struct consensus_cache_t consensus_cache_t;
+struct config_line_t;
+
HANDLE_DECL(consensus_cache_entry, consensus_cache_entry_t, )
#define consensus_cache_entry_handle_free(h) \
FREE_AND_NULL(consensus_cache_entry_handle_t, \
@@ -18,10 +25,10 @@ consensus_cache_t *consensus_cache_open(const char *subdir, int max_entries);
void consensus_cache_free_(consensus_cache_t *cache);
#define consensus_cache_free(cache) \
FREE_AND_NULL(consensus_cache_t, consensus_cache_free_, (cache))
-struct sandbox_cfg_elem;
+struct sandbox_cfg_elem_t;
int consensus_cache_may_overallocate(consensus_cache_t *cache);
int consensus_cache_register_with_sandbox(consensus_cache_t *cache,
- struct sandbox_cfg_elem **cfg);
+ struct sandbox_cfg_elem_t **cfg);
void consensus_cache_unmap_lazy(consensus_cache_t *cache, time_t cutoff);
void consensus_cache_delete_pending(consensus_cache_t *cache,
int force);
diff --git a/src/feature/dircache/consdiffmgr.c b/src/feature/dircache/consdiffmgr.c
index 397efa0341..8445b8f986 100644
--- a/src/feature/dircache/consdiffmgr.c
+++ b/src/feature/dircache/consdiffmgr.c
@@ -1,8 +1,8 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file consdiffmsr.c
+ * \file consdiffmgr.c
*
* \brief consensus diff manager functions
*
@@ -844,7 +844,7 @@ consdiffmgr_configure(const consdiff_cfg_t *cfg)
* operations that the consensus diff manager will need.
*/
int
-consdiffmgr_register_with_sandbox(struct sandbox_cfg_elem **cfg)
+consdiffmgr_register_with_sandbox(struct sandbox_cfg_elem_t **cfg)
{
return consensus_cache_register_with_sandbox(cdm_cache_get(), cfg);
}
@@ -1293,7 +1293,7 @@ typedef struct compressed_result_t {
/**
* Compress the bytestring <b>input</b> of length <b>len</b> using the
- * <n>n_methods</b> compression methods listed in the array <b>methods</b>.
+ * <b>n_methods</b> compression methods listed in the array <b>methods</b>.
*
* For each successful compression, set the fields in the <b>results_out</b>
* array in the position corresponding to the compression method. Use
diff --git a/src/feature/dircache/consdiffmgr.h b/src/feature/dircache/consdiffmgr.h
index b1b3323b6c..27b8165e94 100644
--- a/src/feature/dircache/consdiffmgr.h
+++ b/src/feature/dircache/consdiffmgr.h
@@ -1,6 +1,11 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file consdiffmgr.h
+ * @brief Header for consdiffmgr.c
+ **/
+
#ifndef TOR_CONSDIFFMGR_H
#define TOR_CONSDIFFMGR_H
@@ -55,23 +60,25 @@ void consdiffmgr_rescan(void);
int consdiffmgr_cleanup(void);
void consdiffmgr_enable_background_compression(void);
void consdiffmgr_configure(const consdiff_cfg_t *cfg);
-struct sandbox_cfg_elem;
-int consdiffmgr_register_with_sandbox(struct sandbox_cfg_elem **cfg);
+struct sandbox_cfg_elem_t;
+int consdiffmgr_register_with_sandbox(struct sandbox_cfg_elem_t **cfg);
void consdiffmgr_free_all(void);
int consdiffmgr_validate(void);
#ifdef CONSDIFFMGR_PRIVATE
+struct consensus_cache_t;
+struct consensus_cache_entry_t;
STATIC unsigned n_diff_compression_methods(void);
STATIC unsigned n_consensus_compression_methods(void);
-STATIC consensus_cache_t *cdm_cache_get(void);
-STATIC consensus_cache_entry_t *cdm_cache_lookup_consensus(
+STATIC struct consensus_cache_t *cdm_cache_get(void);
+STATIC struct consensus_cache_entry_t *cdm_cache_lookup_consensus(
consensus_flavor_t flavor, time_t valid_after);
STATIC int cdm_entry_get_sha3_value(uint8_t *digest_out,
- consensus_cache_entry_t *ent,
+ struct consensus_cache_entry_t *ent,
const char *label);
STATIC int uncompress_or_set_ptr(const char **out, size_t *outlen,
char **owned_out,
- consensus_cache_entry_t *ent);
+ struct consensus_cache_entry_t *ent);
#endif /* defined(CONSDIFFMGR_PRIVATE) */
#ifdef TOR_UNIT_TESTS
diff --git a/src/feature/dircache/dircache.c b/src/feature/dircache/dircache.c
index 59cdcc5e02..3b8775968a 100644
--- a/src/feature/dircache/dircache.c
+++ b/src/feature/dircache/dircache.c
@@ -1,8 +1,13 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dircache.c
+ * @brief Cache directories and serve them to clients.
+ **/
+
#define DIRCACHE_PRIVATE
#include "core/or/or.h"
@@ -23,6 +28,7 @@
#include "feature/nodelist/authcert.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/routerlist.h"
+#include "feature/relay/relay_config.h"
#include "feature/relay/routermode.h"
#include "feature/rend/rendcache.h"
#include "feature/stats/geoip_stats.h"
@@ -328,7 +334,7 @@ typedef struct get_handler_args_t {
* an arguments structure, and must return 0 on success or -1 if we should
* close the connection.
**/
-typedef struct url_table_ent_s {
+typedef struct url_table_ent_t {
const char *string;
int is_prefix;
int (*handler)(dir_connection_t *conn, const get_handler_args_t *args);
@@ -473,7 +479,7 @@ static int
handle_get_frontpage(dir_connection_t *conn, const get_handler_args_t *args)
{
(void) args; /* unused */
- const char *frontpage = get_dirportfrontpage();
+ const char *frontpage = relay_get_dirportfrontpage();
if (frontpage) {
size_t dlen;
@@ -560,7 +566,7 @@ parse_one_diff_hash(uint8_t *digest, const char *hex, const char *location,
}
/** If there is an X-Or-Diff-From-Consensus header included in <b>headers</b>,
- * set <b>digest_out<b> to a new smartlist containing every 256-bit
+ * set <b>digest_out</b> to a new smartlist containing every 256-bit
* hex-encoded digest listed in that header and return 0. Otherwise return
* -1. */
static int
@@ -1378,7 +1384,7 @@ handle_get_hs_descriptor_v2(dir_connection_t *conn,
return 0;
}
-/** Helper function for GET /tor/hs/3/<z>. Only for version 3.
+/** Helper function for GET `/tor/hs/3/...`. Only for version 3.
*/
STATIC int
handle_get_hs_descriptor_v3(dir_connection_t *conn,
diff --git a/src/feature/dircache/dircache.h b/src/feature/dircache/dircache.h
index de0d205f6a..d6392e2d42 100644
--- a/src/feature/dircache/dircache.h
+++ b/src/feature/dircache/dircache.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dircache/dircache_stub.c b/src/feature/dircache/dircache_stub.c
new file mode 100644
index 0000000000..87811597d1
--- /dev/null
+++ b/src/feature/dircache/dircache_stub.c
@@ -0,0 +1,78 @@
+/* Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file dircache_stub.c
+ * @brief Stub declarations for use when dircache module is disabled.
+ **/
+
+#include "core/or/or.h"
+#include "feature/dircache/consdiffmgr.h"
+#include "feature/dircache/dircache.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/dircommon/dir_connection_st.h"
+
+int
+directory_handle_command(dir_connection_t *conn)
+{
+ (void) conn;
+ tor_assert_nonfatal_unreached_once();
+ return -1;
+}
+
+int
+connection_dirserv_flushed_some(dir_connection_t *conn)
+{
+ (void) conn;
+ tor_assert_nonfatal_unreached_once();
+ return -1;
+}
+
+void
+dir_conn_clear_spool(dir_connection_t *conn)
+{
+ if (!conn)
+ return;
+ tor_assert_nonfatal_once(conn->spool == NULL);
+}
+
+void
+consdiffmgr_enable_background_compression(void)
+{
+}
+
+int
+consdiffmgr_add_consensus(const char *consensus,
+ size_t consensus_len,
+ const networkstatus_t *as_parsed)
+{
+ (void)consensus;
+ (void)consensus_len;
+ (void)as_parsed;
+ return 0;
+}
+
+int
+consdiffmgr_register_with_sandbox(struct sandbox_cfg_elem_t **cfg)
+{
+ (void)cfg;
+ return 0;
+}
+
+int
+consdiffmgr_cleanup(void)
+{
+ return 0;
+}
+
+void
+consdiffmgr_free_all(void)
+{
+}
+
+void
+dirserv_free_all(void)
+{
+}
diff --git a/src/feature/dircache/dirserv.c b/src/feature/dircache/dirserv.c
index 79400bf15f..fb8db879a4 100644
--- a/src/feature/dircache/dirserv.c
+++ b/src/feature/dircache/dirserv.c
@@ -1,9 +1,8 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#define DIRSERV_PRIVATE
#include "core/or/or.h"
#include "app/config/config.h"
@@ -69,55 +68,7 @@ static cached_dir_t *lookup_cached_dir_by_fp(const uint8_t *fp);
/********************************************************************/
/* A set of functions to answer questions about how we'd like to behave
- * as a directory mirror/client. */
-
-/** Return 1 if we fetch our directory material directly from the
- * authorities, rather than from a mirror. */
-int
-directory_fetches_from_authorities(const or_options_t *options)
-{
- const routerinfo_t *me;
- uint32_t addr;
- int refuseunknown;
- if (options->FetchDirInfoEarly)
- return 1;
- if (options->BridgeRelay == 1)
- return 0;
- if (server_mode(options) &&
- router_pick_published_address(options, &addr, 1) < 0)
- return 1; /* we don't know our IP address; ask an authority. */
- refuseunknown = ! router_my_exit_policy_is_reject_star() &&
- should_refuse_unknown_exits(options);
- if (!dir_server_mode(options) && !refuseunknown)
- return 0;
- if (!server_mode(options) || !advertised_server_mode())
- return 0;
- me = router_get_my_routerinfo();
- if (!me || (!me->supports_tunnelled_dir_requests && !refuseunknown))
- return 0; /* if we don't service directory requests, return 0 too */
- return 1;
-}
-
-/** Return 1 if we should fetch new networkstatuses, descriptors, etc
- * on the "mirror" schedule rather than the "client" schedule.
- */
-int
-directory_fetches_dir_info_early(const or_options_t *options)
-{
- return directory_fetches_from_authorities(options);
-}
-
-/** Return 1 if we should fetch new networkstatuses, descriptors, etc
- * on a very passive schedule -- waiting long enough for ordinary clients
- * to probably have the info we want. These would include bridge users,
- * and maybe others in the future e.g. if a Tor client uses another Tor
- * client as a directory guard.
- */
-int
-directory_fetches_dir_info_later(const or_options_t *options)
-{
- return options->UseBridges != 0;
-}
+ * as a directory mirror */
/** Return true iff we want to serve certificates for authorities
* that we don't acknowledge as authorities ourself.
@@ -161,19 +112,6 @@ directory_permits_begindir_requests(const or_options_t *options)
return options->BridgeRelay != 0 || dir_server_mode(options);
}
-/** Return 1 if we have no need to fetch new descriptors. This generally
- * happens when we're not a dir cache and we haven't built any circuits
- * lately.
- */
-int
-directory_too_idle_to_fetch_descriptors(const or_options_t *options,
- time_t now)
-{
- return !directory_caches_dir_info(options) &&
- !options->FetchUselessDescriptors &&
- rep_hist_circbuilding_dormant(now);
-}
-
/********************************************************************/
/** Map from flavor name to the cached_dir_t for the v3 consensuses that we're
@@ -259,14 +197,45 @@ dirserv_set_cached_consensus_networkstatus(const char *networkstatus,
/** Return the latest downloaded consensus networkstatus in encoded, signed,
* optionally compressed format, suitable for sending to clients. */
-cached_dir_t *
-dirserv_get_consensus(const char *flavor_name)
+MOCK_IMPL(cached_dir_t *,
+dirserv_get_consensus,(const char *flavor_name))
{
if (!cached_consensuses)
return NULL;
return strmap_get(cached_consensuses, flavor_name);
}
+/** As dir_split_resource_into_fingerprints, but instead fills
+ * <b>spool_out</b> with a list of spoolable_resource_t for the resource
+ * identified through <b>source</b>. */
+int
+dir_split_resource_into_spoolable(const char *resource,
+ dir_spool_source_t source,
+ smartlist_t *spool_out,
+ int *compressed_out,
+ int flags)
+{
+ smartlist_t *fingerprints = smartlist_new();
+
+ tor_assert(flags & (DSR_HEX|DSR_BASE64));
+ const size_t digest_len =
+ (flags & DSR_DIGEST256) ? DIGEST256_LEN : DIGEST_LEN;
+
+ int r = dir_split_resource_into_fingerprints(resource, fingerprints,
+ compressed_out, flags);
+ /* This is not a very efficient implementation XXXX */
+ SMARTLIST_FOREACH_BEGIN(fingerprints, uint8_t *, digest) {
+ spooled_resource_t *spooled =
+ spooled_resource_new(source, digest, digest_len);
+ if (spooled)
+ smartlist_add(spool_out, spooled);
+ tor_free(digest);
+ } SMARTLIST_FOREACH_END(digest);
+
+ smartlist_free(fingerprints);
+ return r;
+}
+
/** As dirserv_get_routerdescs(), but instead of getting signed_descriptor_t
* pointers, adds copies of digests to fps_out, and doesn't use the
* /tor/server/ prefix. For a /d/ request, adds descriptor digests; for other
@@ -333,87 +302,6 @@ dirserv_get_routerdesc_spool(smartlist_t *spool_out,
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;
- * - "/tor/server/all" for all the routerinfos we have, concatenated;
- * - "/tor/server/fp/FP" where FP is a plus-separated sequence of
- * hex identity digests; or
- * - "/tor/server/d/D" where D is a plus-separated sequence
- * of server descriptor digests, in hex.
- *
- * Return 0 if we found some matching descriptors, or -1 if we do not
- * have any descriptors, no matching descriptors, or if we did not
- * recognize the key (URL).
- * If -1 is returned *<b>msg</b> will be set to an appropriate error
- * message.
- *
- * XXXX rename this function. It's only called from the controller.
- * XXXX in fact, refactor this function, merging as much as possible.
- */
-int
-dirserv_get_routerdescs(smartlist_t *descs_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(descs_out, &(r->cache_info)));
- } else if (!strcmp(key, "/tor/server/authority")) {
- const routerinfo_t *ri = router_get_my_routerinfo();
- if (ri)
- smartlist_add(descs_out, (void*) &(ri->cache_info));
- } else if (!strcmpstart(key, "/tor/server/d/")) {
- smartlist_t *digests = smartlist_new();
- key += strlen("/tor/server/d/");
- dir_split_resource_into_fingerprints(key, digests, NULL,
- DSR_HEX|DSR_SORT_UNIQ);
- SMARTLIST_FOREACH(digests, const char *, d,
- {
- signed_descriptor_t *sd = router_get_by_descriptor_digest(d);
- if (sd)
- smartlist_add(descs_out,sd);
- });
- SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
- smartlist_free(digests);
- } else if (!strcmpstart(key, "/tor/server/fp/")) {
- smartlist_t *digests = smartlist_new();
- time_t cutoff = time(NULL) - ROUTER_MAX_AGE_TO_PUBLISH;
- key += strlen("/tor/server/fp/");
- dir_split_resource_into_fingerprints(key, digests, NULL,
- DSR_HEX|DSR_SORT_UNIQ);
- SMARTLIST_FOREACH_BEGIN(digests, const char *, d) {
- if (router_digest_is_me(d)) {
- /* calling router_get_my_routerinfo() to make sure it exists */
- const routerinfo_t *ri = router_get_my_routerinfo();
- if (ri)
- smartlist_add(descs_out, (void*) &(ri->cache_info));
- } else {
- const routerinfo_t *ri = router_get_by_id_digest(d);
- /* Don't actually serve a descriptor that everyone will think is
- * expired. This is an (ugly) workaround to keep buggy 0.1.1.10
- * Tors from downloading descriptors that they will throw away.
- */
- if (ri && ri->cache_info.published_on > cutoff)
- smartlist_add(descs_out, (void*) &(ri->cache_info));
- }
- } SMARTLIST_FOREACH_END(d);
- SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
- smartlist_free(digests);
- } else {
- *msg = "Key not recognized";
- return -1;
- }
-
- if (!smartlist_len(descs_out)) {
- *msg = "Servers unavailable";
- return -1;
- }
- return 0;
-}
-
/* ==========
* Spooling code.
* ========== */
diff --git a/src/feature/dircache/dirserv.h b/src/feature/dircache/dirserv.h
index 7f944459da..73a64b1b7e 100644
--- a/src/feature/dircache/dirserv.h
+++ b/src/feature/dircache/dirserv.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -73,29 +73,52 @@ typedef struct spooled_resource_t {
int connection_dirserv_flushed_some(dir_connection_t *conn);
-int directory_fetches_from_authorities(const or_options_t *options);
-int directory_fetches_dir_info_early(const or_options_t *options);
-int directory_fetches_dir_info_later(const or_options_t *options);
+enum dir_spool_source_t;
+int dir_split_resource_into_spoolable(const char *resource,
+ enum dir_spool_source_t source,
+ smartlist_t *spool_out,
+ int *compressed_out,
+ int flags);
+
+#ifdef HAVE_MODULE_DIRCACHE
+/** Is the dircache module enabled? */
+#define have_module_dircache() (1)
int directory_caches_unknown_auth_certs(const or_options_t *options);
int directory_caches_dir_info(const or_options_t *options);
int directory_permits_begindir_requests(const or_options_t *options);
-int directory_too_idle_to_fetch_descriptors(const or_options_t *options,
- time_t now);
-
-cached_dir_t *dirserv_get_consensus(const char *flavor_name);
+MOCK_DECL(cached_dir_t *, dirserv_get_consensus, (const char *flavor_name));
void dirserv_set_cached_consensus_networkstatus(const char *consensus,
size_t consensus_len,
const char *flavor_name,
const common_digests_t *digests,
const uint8_t *sha3_as_signed,
time_t published);
+#else /* !defined(HAVE_MODULE_DIRCACHE) */
+#define have_module_dircache() (0)
+#define directory_caches_unknown_auth_certs(opt) \
+ ((void)(opt), 0)
+#define directory_caches_dir_info(opt) \
+ ((void)(opt), 0)
+#define directory_permits_begindir_requests(opt) \
+ ((void)(opt), 0)
+#define dirserv_get_consensus(flav) \
+ ((void)(flav), NULL)
+#define dirserv_set_cached_consensus_networkstatus(a,b,c,d,e,f) \
+ STMT_BEGIN { \
+ (void)(a); \
+ (void)(b); \
+ (void)(c); \
+ (void)(d); \
+ (void)(e); \
+ (void)(f); \
+ } STMT_END
+#endif /* defined(HAVE_MODULE_DIRCACHE) */
+
void dirserv_clear_old_networkstatuses(time_t cutoff);
int dirserv_get_routerdesc_spool(smartlist_t *spools_out, const char *key,
dir_spool_source_t source,
int conn_is_encrypted,
const char **msg_out);
-int dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
- const char **msg);
void dirserv_free_all(void);
void cached_dir_decref(cached_dir_t *d);
diff --git a/src/feature/dircache/feature_dircache.md b/src/feature/dircache/feature_dircache.md
new file mode 100644
index 0000000000..97734f2a34
--- /dev/null
+++ b/src/feature/dircache/feature_dircache.md
@@ -0,0 +1,6 @@
+@dir /feature/dircache
+@brief feature/dircache: Run as a directory cache server
+
+This module handles the directory caching functionality that all relays may
+provide, for serving cached directory objects to objects.
+
diff --git a/src/feature/dircache/include.am b/src/feature/dircache/include.am
new file mode 100644
index 0000000000..ab162565f7
--- /dev/null
+++ b/src/feature/dircache/include.am
@@ -0,0 +1,21 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+MODULE_DIRCACHE_SOURCES = \
+ src/feature/dircache/conscache.c \
+ src/feature/dircache/consdiffmgr.c \
+ src/feature/dircache/dircache.c \
+ src/feature/dircache/dirserv.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/dircache/cached_dir_st.h \
+ src/feature/dircache/conscache.h \
+ src/feature/dircache/consdiffmgr.h \
+ src/feature/dircache/dircache.h \
+ src/feature/dircache/dirserv.h
+
+if BUILD_MODULE_DIRCACHE
+LIBTOR_APP_A_SOURCES += $(MODULE_DIRCACHE_SOURCES)
+else
+LIBTOR_APP_A_STUB_SOURCES += src/feature/dircache/dircache_stub.c
+endif
diff --git a/src/feature/dirclient/.may_include b/src/feature/dirclient/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/dirclient/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/dirclient/dir_server_st.h b/src/feature/dirclient/dir_server_st.h
index 8e35532435..37fa3148a7 100644
--- a/src/feature/dirclient/dir_server_st.h
+++ b/src/feature/dirclient/dir_server_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dir_server_st.h
+ * @brief Trusted/fallback directory server structure.
+ **/
+
#ifndef DIR_SERVER_ST_H
#define DIR_SERVER_ST_H
diff --git a/src/feature/dirclient/dirclient.c b/src/feature/dirclient/dirclient.c
index fa82bdc1e7..1200c3c562 100644
--- a/src/feature/dirclient/dirclient.c
+++ b/src/feature/dirclient/dirclient.c
@@ -1,8 +1,13 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dirclient.c
+ * @brief Download directory information
+ **/
+
#define DIRCLIENT_PRIVATE
#include "core/or/or.h"
@@ -20,6 +25,7 @@
#include "feature/dirauth/shared_random.h"
#include "feature/dircache/dirserv.h"
#include "feature/dirclient/dirclient.h"
+#include "feature/dirclient/dirclient_modes.h"
#include "feature/dirclient/dlstatus.h"
#include "feature/dircommon/consdiff.h"
#include "feature/dircommon/directory.h"
@@ -448,7 +454,7 @@ directory_get_from_dirserver,(
{
const routerstatus_t *rs = NULL;
const or_options_t *options = get_options();
- int prefer_authority = (directory_fetches_from_authorities(options)
+ int prefer_authority = (dirclient_fetches_from_authorities(options)
|| want_authority == DL_WANT_AUTHORITY);
int require_authority = 0;
int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose,
@@ -667,7 +673,7 @@ directory_choose_address_routerstatus(const routerstatus_t *status,
if (indirection == DIRIND_DIRECT_CONN ||
indirection == DIRIND_ANON_DIRPORT ||
(indirection == DIRIND_ONEHOP
- && !directory_must_use_begindir(options))) {
+ && !dirclient_must_use_begindir(options))) {
fascist_firewall_choose_address_rs(status, FIREWALL_DIR_CONNECTION, 0,
use_dir_ap);
have_dir = tor_addr_port_is_valid_ap(use_dir_ap, 0);
@@ -866,16 +872,6 @@ connection_dir_download_cert_failed(dir_connection_t *conn, int status)
update_certificate_downloads(time(NULL));
}
-/* Should this tor instance only use begindir for all its directory requests?
- */
-int
-directory_must_use_begindir(const or_options_t *options)
-{
- /* Clients, onion services, and bridges must use begindir,
- * relays and authorities do not have to */
- return !public_server_mode(options);
-}
-
/** Evaluate the situation and decide if we should use an encrypted
* "begindir-style" connection for this directory request.
* 0) If there is no DirPort, yes.
@@ -927,7 +923,7 @@ directory_command_should_use_begindir(const or_options_t *options,
}
/* Reasons why we want to avoid using begindir */
if (indirection == DIRIND_ONEHOP) {
- if (!directory_must_use_begindir(options)) {
+ if (!dirclient_must_use_begindir(options)) {
*reason = "in relay mode";
return 0;
}
@@ -1289,7 +1285,7 @@ directory_initiate_request,(directory_request_t *request))
/* use encrypted begindir connections for everything except relays
* this provides better protection for directory fetches */
- if (!use_begindir && directory_must_use_begindir(options)) {
+ if (!use_begindir && dirclient_must_use_begindir(options)) {
log_warn(LD_BUG, "Client could not use begindir connection: %s",
begindir_reason ? begindir_reason : "(NULL)");
return;
@@ -2728,62 +2724,7 @@ handle_response_fetch_hsdesc_v3(dir_connection_t *conn,
log_info(LD_REND,"Received v3 hsdesc (body size %d, status %d (%s))",
(int)body_len, status_code, escaped(reason));
- switch (status_code) {
- case 200:
- /* We got something: Try storing it in the cache. */
- if (hs_cache_store_as_client(body, &conn->hs_ident->identity_pk) < 0) {
- log_info(LD_REND, "Failed to store hidden service descriptor");
- /* Fire control port FAILED event. */
- hs_control_desc_event_failed(conn->hs_ident, conn->identity_digest,
- "BAD_DESC");
- hs_control_desc_event_content(conn->hs_ident, conn->identity_digest,
- NULL);
- } else {
- log_info(LD_REND, "Stored hidden service descriptor successfully.");
- TO_CONN(conn)->purpose = DIR_PURPOSE_HAS_FETCHED_HSDESC;
- hs_client_desc_has_arrived(conn->hs_ident);
- /* Fire control port RECEIVED event. */
- hs_control_desc_event_received(conn->hs_ident, conn->identity_digest);
- hs_control_desc_event_content(conn->hs_ident, conn->identity_digest,
- body);
- }
- break;
- case 404:
- /* Not there. We'll retry when connection_about_to_close_connection()
- * tries to clean this conn up. */
- log_info(LD_REND, "Fetching hidden service v3 descriptor not found: "
- "Retrying at another directory.");
- /* Fire control port FAILED event. */
- hs_control_desc_event_failed(conn->hs_ident, conn->identity_digest,
- "NOT_FOUND");
- hs_control_desc_event_content(conn->hs_ident, conn->identity_digest,
- NULL);
- break;
- case 400:
- log_warn(LD_REND, "Fetching v3 hidden service descriptor failed: "
- "http status 400 (%s). Dirserver didn't like our "
- "query? Retrying at another directory.",
- escaped(reason));
- /* Fire control port FAILED event. */
- hs_control_desc_event_failed(conn->hs_ident, conn->identity_digest,
- "QUERY_REJECTED");
- hs_control_desc_event_content(conn->hs_ident, conn->identity_digest,
- NULL);
- break;
- default:
- log_warn(LD_REND, "Fetching v3 hidden service descriptor failed: "
- "http status %d (%s) response unexpected from HSDir server "
- "'%s:%d'. Retrying at another directory.",
- status_code, escaped(reason), TO_CONN(conn)->address,
- TO_CONN(conn)->port);
- /* Fire control port FAILED event. */
- hs_control_desc_event_failed(conn->hs_ident, conn->identity_digest,
- "UNEXPECTED");
- hs_control_desc_event_content(conn->hs_ident, conn->identity_digest,
- NULL);
- break;
- }
-
+ hs_client_dir_fetch_done(conn, reason, body, status_code);
return 0;
}
@@ -3143,7 +3084,7 @@ dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
{
char digest[DIGEST_LEN];
time_t now = time(NULL);
- int server = directory_fetches_from_authorities(get_options());
+ int server = dirclient_fetches_from_authorities(get_options());
if (!was_descriptor_digests) {
if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
tor_assert(!was_extrainfo);
@@ -3188,7 +3129,7 @@ dir_microdesc_download_failed(smartlist_t *failed,
routerstatus_t *rs;
download_status_t *dls;
time_t now = time(NULL);
- int server = directory_fetches_from_authorities(get_options());
+ int server = dirclient_fetches_from_authorities(get_options());
if (! consensus)
return;
diff --git a/src/feature/dirclient/dirclient.h b/src/feature/dirclient/dirclient.h
index be4374c7cf..08209721bb 100644
--- a/src/feature/dirclient/dirclient.h
+++ b/src/feature/dirclient/dirclient.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -41,8 +41,6 @@ typedef enum {
DIRIND_ANON_DIRPORT,
} dir_indirection_t;
-int directory_must_use_begindir(const or_options_t *options);
-
/**
* A directory_request_t describes the information about a directory request
* at the client side. It describes what we're going to ask for, which
diff --git a/src/feature/dirclient/dirclient_modes.c b/src/feature/dirclient/dirclient_modes.c
new file mode 100644
index 0000000000..23fd1a2f6e
--- /dev/null
+++ b/src/feature/dirclient/dirclient_modes.c
@@ -0,0 +1,95 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file dirclient_modes.c
+ * @brief Functions to answer questions about how we'd like to behave
+ * as a directory client
+ **/
+
+#include "orconfig.h"
+
+#include "core/or/or.h"
+
+#include "feature/dirclient/dirclient_modes.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
+#include "feature/stats/predict_ports.h"
+
+#include "app/config/or_options_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+
+/* Should this tor instance only use begindir for all its directory requests?
+ */
+int
+dirclient_must_use_begindir(const or_options_t *options)
+{
+ /* Clients, onion services, and bridges must use begindir,
+ * relays and authorities do not have to */
+ return !public_server_mode(options);
+}
+
+/** Return 1 if we fetch our directory material directly from the
+ * authorities, rather than from a mirror. */
+int
+dirclient_fetches_from_authorities(const or_options_t *options)
+{
+ const routerinfo_t *me;
+ uint32_t addr;
+ int refuseunknown;
+ if (options->FetchDirInfoEarly)
+ return 1;
+ if (options->BridgeRelay == 1)
+ return 0;
+ if (server_mode(options) &&
+ router_pick_published_address(options, &addr, 1) < 0)
+ return 1; /* we don't know our IP address; ask an authority. */
+ refuseunknown = ! router_my_exit_policy_is_reject_star() &&
+ should_refuse_unknown_exits(options);
+ if (!dir_server_mode(options) && !refuseunknown)
+ return 0;
+ if (!server_mode(options) || !advertised_server_mode())
+ return 0;
+ me = router_get_my_routerinfo();
+ if (!me || (!me->supports_tunnelled_dir_requests && !refuseunknown))
+ return 0; /* if we don't service directory requests, return 0 too */
+ return 1;
+}
+
+/** Return 1 if we should fetch new networkstatuses, descriptors, etc
+ * on the "mirror" schedule rather than the "client" schedule.
+ */
+int
+dirclient_fetches_dir_info_early(const or_options_t *options)
+{
+ return dirclient_fetches_from_authorities(options);
+}
+
+/** Return 1 if we should fetch new networkstatuses, descriptors, etc
+ * on a very passive schedule -- waiting long enough for ordinary clients
+ * to probably have the info we want. These would include bridge users,
+ * and maybe others in the future e.g. if a Tor client uses another Tor
+ * client as a directory guard.
+ */
+int
+dirclient_fetches_dir_info_later(const or_options_t *options)
+{
+ return options->UseBridges != 0;
+}
+
+/** Return 1 if we have no need to fetch new descriptors. This generally
+ * happens when we're not a dir cache and we haven't built any circuits
+ * lately.
+ */
+int
+dirclient_too_idle_to_fetch_descriptors(const or_options_t *options,
+ time_t now)
+{
+ return !directory_caches_dir_info(options) &&
+ !options->FetchUselessDescriptors &&
+ rep_hist_circbuilding_dormant(now);
+}
diff --git a/src/feature/dirclient/dirclient_modes.h b/src/feature/dirclient/dirclient_modes.h
new file mode 100644
index 0000000000..c402207724
--- /dev/null
+++ b/src/feature/dirclient/dirclient_modes.h
@@ -0,0 +1,24 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file dirclient_modes.h
+ * @brief Header for feature/dirclient/dirclient_modes.c
+ **/
+
+#ifndef TOR_FEATURE_DIRCLIENT_DIRCLIENT_MODES_H
+#define TOR_FEATURE_DIRCLIENT_DIRCLIENT_MODES_H
+
+struct or_options_t;
+
+int dirclient_must_use_begindir(const or_options_t *options);
+int dirclient_fetches_from_authorities(const struct or_options_t *options);
+int dirclient_fetches_dir_info_early(const struct or_options_t *options);
+int dirclient_fetches_dir_info_later(const struct or_options_t *options);
+int dirclient_too_idle_to_fetch_descriptors(const struct or_options_t *options,
+ time_t now);
+
+#endif /* !defined(TOR_FEATURE_DIRCLIENT_DIRCLIENT_MODES_H) */
diff --git a/src/feature/dirclient/dlstatus.c b/src/feature/dirclient/dlstatus.c
index 0842a2c676..ab3fbb8577 100644
--- a/src/feature/dirclient/dlstatus.c
+++ b/src/feature/dirclient/dlstatus.c
@@ -1,8 +1,13 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dlstatus.c
+ * @brief Track status and retry schedule of a downloadable object.
+ **/
+
#define DLSTATUS_PRIVATE
#include "core/or/or.h"
diff --git a/src/feature/dirclient/dlstatus.h b/src/feature/dirclient/dlstatus.h
index 681712b059..e5c8b756c4 100644
--- a/src/feature/dirclient/dlstatus.h
+++ b/src/feature/dirclient/dlstatus.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirclient/download_status_st.h b/src/feature/dirclient/download_status_st.h
index 39a5ad2860..92efcb44d0 100644
--- a/src/feature/dirclient/download_status_st.h
+++ b/src/feature/dirclient/download_status_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file download_status_st.h
+ * @brief Directory download status/schedule structure.
+ **/
+
#ifndef DOWNLOAD_STATUS_ST_H
#define DOWNLOAD_STATUS_ST_H
@@ -62,4 +67,3 @@ struct download_status_t {
};
#endif /* !defined(DOWNLOAD_STATUS_ST_H) */
-
diff --git a/src/feature/dirclient/feature_dirclient.md b/src/feature/dirclient/feature_dirclient.md
new file mode 100644
index 0000000000..5c7ee964d3
--- /dev/null
+++ b/src/feature/dirclient/feature_dirclient.md
@@ -0,0 +1,7 @@
+@dir /feature/dirclient
+@brief feature/dirclient: Directory client implementation.
+
+The code here is used by all Tor instances that need to download directory
+information. Currently, that is all of them, since even authorities need to
+launch downloads to learn about relays that other authorities have listed.
+
diff --git a/src/feature/dirclient/include.am b/src/feature/dirclient/include.am
new file mode 100644
index 0000000000..24cae9eedd
--- /dev/null
+++ b/src/feature/dirclient/include.am
@@ -0,0 +1,14 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/dirclient/dirclient.c \
+ src/feature/dirclient/dirclient_modes.c \
+ src/feature/dirclient/dlstatus.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/dirclient/dir_server_st.h \
+ src/feature/dirclient/dirclient.h \
+ src/feature/dirclient/dirclient_modes.h \
+ src/feature/dirclient/dlstatus.h \
+ src/feature/dirclient/download_status_st.h
diff --git a/src/feature/dircommon/.may_include b/src/feature/dircommon/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/dircommon/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/dircommon/consdiff.c b/src/feature/dircommon/consdiff.c
index 8e93953f73..e42378c44c 100644
--- a/src/feature/dircommon/consdiff.c
+++ b/src/feature/dircommon/consdiff.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2014, Daniel Martí
- * Copyright (c) 2014-2019, The Tor Project, Inc. */
+ * Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -530,10 +530,12 @@ typedef struct router_id_iterator_t {
cdline_t hash;
} router_id_iterator_t;
+#ifndef COCCI
/**
* Initializer for a router_id_iterator_t.
*/
#define ROUTER_ID_ITERATOR_INIT { { NULL, 0 }, { NULL, 0 } }
+#endif /* !defined(COCCI) */
/** Given an index *<b>idxp</b> into the consensus at <b>cons</b>, advance
* the index to the next router line ("r ...") in the consensus, or to
@@ -570,7 +572,7 @@ find_next_router_line(const smartlist_t *cons,
/** Pre-process a consensus in <b>cons</b> (represented as a list of cdline_t)
* to remove the signatures from it. If the footer is removed, return a
* cdline_t containing a delete command to delete the footer, allocated in
- * <b>area</>. If no footer is removed, return NULL.
+ * <b>area</b>. If no footer is removed, return NULL.
*
* We remove the signatures here because they are not themselves signed, and
* as such there might be different encodings for them.
@@ -1048,7 +1050,7 @@ consdiff_gen_diff(const smartlist_t *cons1,
if (smartlist_len(cons2) == smartlist_len(ed_cons2)) {
SMARTLIST_FOREACH_BEGIN(cons2, const cdline_t *, line1) {
const cdline_t *line2 = smartlist_get(ed_cons2, line1_sl_idx);
- if (! lines_eq(line1, line2) ) {
+ if (!lines_eq(line1, line2)) {
cons2_eq = 0;
break;
}
diff --git a/src/feature/dircommon/consdiff.h b/src/feature/dircommon/consdiff.h
index b63fcb2cc6..c2dcb6da24 100644
--- a/src/feature/dircommon/consdiff.h
+++ b/src/feature/dircommon/consdiff.h
@@ -1,7 +1,12 @@
/* Copyright (c) 2014, Daniel Martí
- * Copyright (c) 2014-2019, The Tor Project, Inc. */
+ * Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file consdiff.h
+ * @brief Header for consdiff.c
+ **/
+
#ifndef TOR_CONSDIFF_H
#define TOR_CONSDIFF_H
diff --git a/src/feature/dircommon/dir_connection_st.h b/src/feature/dircommon/dir_connection_st.h
index a858560c29..12230e6741 100644
--- a/src/feature/dircommon/dir_connection_st.h
+++ b/src/feature/dircommon/dir_connection_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dir_connection_st.h
+ * @brief Client/server directory connection structure.
+ **/
+
#ifndef DIR_CONNECTION_ST_H
#define DIR_CONNECTION_ST_H
@@ -23,7 +28,9 @@ struct dir_connection_t {
* fingerprints.
**/
char *requested_resource;
- unsigned int dirconn_direct:1; /**< Is this dirconn direct, or via Tor? */
+ /** Is this dirconn direct, or via a multi-hop Tor circuit?
+ * Direct connections can use the DirPort, or BEGINDIR over the ORPort. */
+ unsigned int dirconn_direct:1;
/** If we're fetching descriptors, what router purpose shall we assign
* to them? */
diff --git a/src/feature/dircommon/directory.c b/src/feature/dircommon/directory.c
index 8e5b413326..b177fe5201 100644
--- a/src/feature/dircommon/directory.c
+++ b/src/feature/dircommon/directory.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
@@ -702,34 +702,3 @@ dir_split_resource_into_fingerprints(const char *resource,
smartlist_free(fp_tmp);
return 0;
}
-
-/** As dir_split_resource_into_fingerprints, but instead fills
- * <b>spool_out</b> with a list of spoolable_resource_t for the resource
- * identified through <b>source</b>. */
-int
-dir_split_resource_into_spoolable(const char *resource,
- dir_spool_source_t source,
- smartlist_t *spool_out,
- int *compressed_out,
- int flags)
-{
- smartlist_t *fingerprints = smartlist_new();
-
- tor_assert(flags & (DSR_HEX|DSR_BASE64));
- const size_t digest_len =
- (flags & DSR_DIGEST256) ? DIGEST256_LEN : DIGEST_LEN;
-
- int r = dir_split_resource_into_fingerprints(resource, fingerprints,
- compressed_out, flags);
- /* This is not a very efficient implementation XXXX */
- SMARTLIST_FOREACH_BEGIN(fingerprints, uint8_t *, digest) {
- spooled_resource_t *spooled =
- spooled_resource_new(source, digest, digest_len);
- if (spooled)
- smartlist_add(spool_out, spooled);
- tor_free(digest);
- } SMARTLIST_FOREACH_END(digest);
-
- smartlist_free(fingerprints);
- return r;
-}
diff --git a/src/feature/dircommon/directory.h b/src/feature/dircommon/directory.h
index 4fc743ad3d..0f26cdeff9 100644
--- a/src/feature/dircommon/directory.h
+++ b/src/feature/dircommon/directory.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -108,12 +108,6 @@ void connection_dir_about_to_close(dir_connection_t *dir_conn);
int dir_split_resource_into_fingerprints(const char *resource,
smartlist_t *fp_out, int *compressed_out,
int flags);
-enum dir_spool_source_t;
-int dir_split_resource_into_spoolable(const char *resource,
- enum dir_spool_source_t source,
- smartlist_t *spool_out,
- int *compressed_out,
- int flags);
int dir_split_resource_into_fingerprint_pairs(const char *res,
smartlist_t *pairs_out);
char *directory_dump_request_log(void);
diff --git a/src/feature/dircommon/feature_dircommon.md b/src/feature/dircommon/feature_dircommon.md
new file mode 100644
index 0000000000..359049ecd8
--- /dev/null
+++ b/src/feature/dircommon/feature_dircommon.md
@@ -0,0 +1,7 @@
+@dir /feature/dircommon
+@brief feature/dircommon: Directory client and server shared code
+
+This module has the code that directory clients (anybody who download
+information about relays) and directory servers (anybody who serves such
+information) share in common.
+
diff --git a/src/feature/dircommon/fp_pair.c b/src/feature/dircommon/fp_pair.c
index 284600df77..8b55896ba8 100644
--- a/src/feature/dircommon/fp_pair.c
+++ b/src/feature/dircommon/fp_pair.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -22,14 +22,14 @@
/* Define fp_pair_map_t structures */
-struct fp_pair_map_entry_s {
- HT_ENTRY(fp_pair_map_entry_s) node;
+struct fp_pair_map_entry_t {
+ HT_ENTRY(fp_pair_map_entry_t) node;
void *val;
fp_pair_t key;
};
-struct fp_pair_map_s {
- HT_HEAD(fp_pair_map_impl, fp_pair_map_entry_s) head;
+struct fp_pair_map_t {
+ HT_HEAD(fp_pair_map_impl, fp_pair_map_entry_t) head;
};
/*
@@ -56,9 +56,9 @@ fp_pair_map_entry_hash(const fp_pair_map_entry_t *a)
* Hash table functions for fp_pair_map_t
*/
-HT_PROTOTYPE(fp_pair_map_impl, fp_pair_map_entry_s, node,
+HT_PROTOTYPE(fp_pair_map_impl, fp_pair_map_entry_t, node,
fp_pair_map_entry_hash, fp_pair_map_entries_eq)
-HT_GENERATE2(fp_pair_map_impl, fp_pair_map_entry_s, node,
+HT_GENERATE2(fp_pair_map_impl, fp_pair_map_entry_t, node,
fp_pair_map_entry_hash, fp_pair_map_entries_eq,
0.6, tor_reallocarray_, tor_free_)
diff --git a/src/feature/dircommon/fp_pair.h b/src/feature/dircommon/fp_pair.h
index 5041583e88..ae71ea7b71 100644
--- a/src/feature/dircommon/fp_pair.h
+++ b/src/feature/dircommon/fp_pair.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -19,8 +19,8 @@ typedef struct {
* Declare fp_pair_map_t functions and structs
*/
-typedef struct fp_pair_map_entry_s fp_pair_map_entry_t;
-typedef struct fp_pair_map_s fp_pair_map_t;
+typedef struct fp_pair_map_entry_t fp_pair_map_entry_t;
+typedef struct fp_pair_map_t fp_pair_map_t;
typedef fp_pair_map_entry_t *fp_pair_map_iter_t;
fp_pair_map_t * fp_pair_map_new(void);
diff --git a/src/feature/dircommon/include.am b/src/feature/dircommon/include.am
new file mode 100644
index 0000000000..f0f0323d12
--- /dev/null
+++ b/src/feature/dircommon/include.am
@@ -0,0 +1,16 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/dircommon/consdiff.c \
+ src/feature/dircommon/directory.c \
+ src/feature/dircommon/fp_pair.c \
+ src/feature/dircommon/voting_schedule.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/dircommon/consdiff.h \
+ src/feature/dircommon/dir_connection_st.h \
+ src/feature/dircommon/directory.h \
+ src/feature/dircommon/fp_pair.h \
+ src/feature/dircommon/vote_timing_st.h \
+ src/feature/dircommon/voting_schedule.h
diff --git a/src/feature/dircommon/vote_timing_st.h b/src/feature/dircommon/vote_timing_st.h
index 814a325314..103d950f86 100644
--- a/src/feature/dircommon/vote_timing_st.h
+++ b/src/feature/dircommon/vote_timing_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file vote_timing_st.h
+ * @brief Directory voting schedule structure.
+ **/
+
#ifndef VOTE_TIMING_ST_H
#define VOTE_TIMING_ST_H
@@ -21,4 +26,3 @@ struct vote_timing_t {
};
#endif /* !defined(VOTE_TIMING_ST_H) */
-
diff --git a/src/feature/dircommon/voting_schedule.c b/src/feature/dircommon/voting_schedule.c
index 5576ec69f7..389f7f6b5d 100644
--- a/src/feature/dircommon/voting_schedule.c
+++ b/src/feature/dircommon/voting_schedule.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -8,7 +8,6 @@
* tor. The full feature is built as part of the dirauth module.
**/
-#define VOTING_SCHEDULE_PRIVATE
#include "feature/dircommon/voting_schedule.h"
#include "core/or/or.h"
diff --git a/src/feature/dircommon/voting_schedule.h b/src/feature/dircommon/voting_schedule.h
index d78c7ee2da..e4c6210087 100644
--- a/src/feature/dircommon/voting_schedule.h
+++ b/src/feature/dircommon/voting_schedule.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -26,15 +26,15 @@ typedef struct {
/** When do we publish the consensus? */
time_t interval_starts;
- /* True iff we have generated and distributed our vote. */
+ /** True iff we have generated and distributed our vote. */
int have_voted;
- /* True iff we've requested missing votes. */
+ /** True iff we've requested missing votes. */
int have_fetched_missing_votes;
- /* True iff we have built a consensus and sent the signatures around. */
+ /** True iff we have built a consensus and sent the signatures around. */
int have_built_consensus;
- /* True iff we've fetched missing signatures. */
+ /** True iff we've fetched missing signatures. */
int have_fetched_missing_signatures;
- /* True iff we have published our consensus. */
+ /** True iff we have published our consensus. */
int have_published_consensus;
/* True iff this voting schedule was set on demand meaning not through the
@@ -62,4 +62,3 @@ time_t voting_schedule_get_start_of_next_interval(time_t now,
time_t voting_schedule_get_next_valid_after_time(void);
#endif /* !defined(TOR_VOTING_SCHEDULE_H) */
-
diff --git a/src/feature/dirparse/.may_include b/src/feature/dirparse/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/dirparse/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/dirparse/authcert_members.h b/src/feature/dirparse/authcert_members.h
new file mode 100644
index 0000000000..c6755bb629
--- /dev/null
+++ b/src/feature/dirparse/authcert_members.h
@@ -0,0 +1,29 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file authcert_members.h
+ *
+ * @brief List of tokens common to V3 authority certificates and V3
+ * consensuses.
+ **/
+
+#ifndef TOR_AUTHCERT_MEMBERS_H
+#define TOR_AUTHCERT_MEMBERS_H
+
+#define AUTHCERT_MEMBERS \
+ T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, \
+ GE(1), NO_OBJ ), \
+ T1("dir-identity-key", K_DIR_IDENTITY_KEY, NO_ARGS, NEED_KEY ),\
+ T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ),\
+ T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ),\
+ T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),\
+ T1("dir-key-crosscert", K_DIR_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),\
+ T1("dir-key-certification", K_DIR_KEY_CERTIFICATION,\
+ NO_ARGS, NEED_OBJ),\
+ T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ)
+
+#endif /* !defined(TOR_AUTHCERT_MEMBERS_H) */
diff --git a/src/feature/dirparse/authcert_members.i b/src/feature/dirparse/authcert_members.i
deleted file mode 100644
index 08cffca97a..0000000000
--- a/src/feature/dirparse/authcert_members.i
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * List of tokens common to V3 authority certificates and V3 consensuses.
- */
- T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION,
- GE(1), NO_OBJ ),
- T1("dir-identity-key", K_DIR_IDENTITY_KEY, NO_ARGS, NEED_KEY ),
- T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ),
- T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ),
- T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),
- T1("dir-key-crosscert", K_DIR_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),
- T1("dir-key-certification", K_DIR_KEY_CERTIFICATION,
- NO_ARGS, NEED_OBJ),
- T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ),
diff --git a/src/feature/dirparse/authcert_parse.c b/src/feature/dirparse/authcert_parse.c
index 8ba5a53981..3d42119b94 100644
--- a/src/feature/dirparse/authcert_parse.c
+++ b/src/feature/dirparse/authcert_parse.c
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file authcert_parse.c
+ * @brief Authority certificate parsing.
+ **/
+
#include "core/or/or.h"
#include "feature/dirparse/authcert_parse.h"
#include "feature/dirparse/parsecommon.h"
@@ -13,10 +18,11 @@
#include "lib/memarea/memarea.h"
#include "feature/nodelist/authority_cert_st.h"
+#include "feature/dirparse/authcert_members.h"
/** List of tokens recognized in V3 authority certificates. */
static token_rule_t dir_key_certificate_table[] = {
-#include "feature/dirparse/authcert_members.i"
+ AUTHCERT_MEMBERS,
T1("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
END_OF_TABLE
};
diff --git a/src/feature/dirparse/authcert_parse.h b/src/feature/dirparse/authcert_parse.h
index 800631c3de..7f6dd1c02f 100644
--- a/src/feature/dirparse/authcert_parse.h
+++ b/src/feature/dirparse/authcert_parse.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirparse/feature_dirparse.md b/src/feature/dirparse/feature_dirparse.md
new file mode 100644
index 0000000000..e4b34668ba
--- /dev/null
+++ b/src/feature/dirparse/feature_dirparse.md
@@ -0,0 +1,8 @@
+@dir /feature/dirparse
+@brief feature/dirparse: Parsing Tor directory objects
+
+We define a number of "directory objects" in
+[dir-spec.txt](https://gitweb.torproject.org/torspec.git/tree/dir-spec.txt),
+all of them using a common line-oriented meta-format. This module is used by
+other parts of Tor to parse them.
+
diff --git a/src/feature/dirparse/include.am b/src/feature/dirparse/include.am
new file mode 100644
index 0000000000..edca04f6f7
--- /dev/null
+++ b/src/feature/dirparse/include.am
@@ -0,0 +1,25 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/dirparse/authcert_parse.c \
+ src/feature/dirparse/microdesc_parse.c \
+ src/feature/dirparse/ns_parse.c \
+ src/feature/dirparse/parsecommon.c \
+ src/feature/dirparse/policy_parse.c \
+ src/feature/dirparse/routerparse.c \
+ src/feature/dirparse/sigcommon.c \
+ src/feature/dirparse/signing.c \
+ src/feature/dirparse/unparseable.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/dirparse/authcert_members.h \
+ src/feature/dirparse/authcert_parse.h \
+ src/feature/dirparse/microdesc_parse.h \
+ src/feature/dirparse/ns_parse.h \
+ src/feature/dirparse/parsecommon.h \
+ src/feature/dirparse/policy_parse.h \
+ src/feature/dirparse/routerparse.h \
+ src/feature/dirparse/sigcommon.h \
+ src/feature/dirparse/signing.h \
+ src/feature/dirparse/unparseable.h
diff --git a/src/feature/dirparse/microdesc_parse.c b/src/feature/dirparse/microdesc_parse.c
index 4bb4db7821..c2eabeb404 100644
--- a/src/feature/dirparse/microdesc_parse.c
+++ b/src/feature/dirparse/microdesc_parse.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -164,7 +164,7 @@ microdesc_extract_body(microdesc_t *md,
/**
* Parse a microdescriptor which begins at <b>s</b> and ends at
- * <b>start_of_next_microdesc. Store its fields into <b>md</b>. Use
+ * <b>start_of_next_microdesc</b>. Store its fields into <b>md</b>. Use
* <b>where</b> for generating log information. If <b>allow_annotations</b>
* is true, then one or more annotations may precede the microdescriptor body
* proper. Use <b>area</b> for memory management, clearing it when done.
diff --git a/src/feature/dirparse/microdesc_parse.h b/src/feature/dirparse/microdesc_parse.h
index 95af85544a..e81126b8cd 100644
--- a/src/feature/dirparse/microdesc_parse.h
+++ b/src/feature/dirparse/microdesc_parse.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirparse/ns_parse.c b/src/feature/dirparse/ns_parse.c
index d5405e6464..4d9b6e6e73 100644
--- a/src/feature/dirparse/ns_parse.c
+++ b/src/feature/dirparse/ns_parse.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -36,6 +36,7 @@
#include "feature/nodelist/networkstatus_st.h"
#include "feature/nodelist/networkstatus_voter_info_st.h"
#include "feature/nodelist/vote_routerstatus_st.h"
+#include "feature/dirparse/authcert_members.h"
#undef log
#include <math.h>
@@ -84,7 +85,7 @@ static token_rule_t networkstatus_token_table[] = {
T01("required-relay-protocols", K_REQUIRED_RELAY_PROTOCOLS,
CONCAT_ARGS, NO_OBJ ),
-#include "feature/dirparse/authcert_members.i"
+ AUTHCERT_MEMBERS,
T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
T1( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
diff --git a/src/feature/dirparse/ns_parse.h b/src/feature/dirparse/ns_parse.h
index 0cf2cc88d0..6a1ea85c92 100644
--- a/src/feature/dirparse/ns_parse.h
+++ b/src/feature/dirparse/ns_parse.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirparse/parsecommon.c b/src/feature/dirparse/parsecommon.c
index c22ed186b8..ab465c4d7f 100644
--- a/src/feature/dirparse/parsecommon.c
+++ b/src/feature/dirparse/parsecommon.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirparse/parsecommon.h b/src/feature/dirparse/parsecommon.h
index ef74925b26..4db9a89f13 100644
--- a/src/feature/dirparse/parsecommon.h
+++ b/src/feature/dirparse/parsecommon.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirparse/policy_parse.c b/src/feature/dirparse/policy_parse.c
index 7562ae409b..28cd174686 100644
--- a/src/feature/dirparse/policy_parse.c
+++ b/src/feature/dirparse/policy_parse.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,7 +9,7 @@
* \brief Code to parse address policies.
**/
-#define EXPOSE_ROUTERDESC_TOKEN_TABLE
+#define ROUTERDESC_TOKEN_TABLE_PRIVATE
#include "core/or/or.h"
diff --git a/src/feature/dirparse/policy_parse.h b/src/feature/dirparse/policy_parse.h
index e09ee5559f..7764069e66 100644
--- a/src/feature/dirparse/policy_parse.h
+++ b/src/feature/dirparse/policy_parse.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirparse/routerparse.c b/src/feature/dirparse/routerparse.c
index f78c46f186..f476beec66 100644
--- a/src/feature/dirparse/routerparse.c
+++ b/src/feature/dirparse/routerparse.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -50,7 +50,7 @@
* </ul>
**/
-#define EXPOSE_ROUTERDESC_TOKEN_TABLE
+#define ROUTERDESC_TOKEN_TABLE_PRIVATE
#include "core/or/or.h"
#include "app/config/config.h"
diff --git a/src/feature/dirparse/routerparse.h b/src/feature/dirparse/routerparse.h
index f9a13f2168..519044e9b0 100644
--- a/src/feature/dirparse/routerparse.h
+++ b/src/feature/dirparse/routerparse.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -40,7 +40,8 @@ int find_single_ipv6_orport(const smartlist_t *list,
void routerparse_init(void);
void routerparse_free_all(void);
-#ifdef EXPOSE_ROUTERDESC_TOKEN_TABLE
+#ifdef ROUTERDESC_TOKEN_TABLE_PRIVATE
+#include "feature/dirparse/parsecommon.h"
extern const struct token_rule_t routerdesc_token_table[];
#endif
diff --git a/src/feature/dirparse/sigcommon.c b/src/feature/dirparse/sigcommon.c
index 2019e09918..8b970d7d1f 100644
--- a/src/feature/dirparse/sigcommon.c
+++ b/src/feature/dirparse/sigcommon.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirparse/sigcommon.h b/src/feature/dirparse/sigcommon.h
index b6b34e8f62..c2ed9df494 100644
--- a/src/feature/dirparse/sigcommon.h
+++ b/src/feature/dirparse/sigcommon.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirparse/signing.c b/src/feature/dirparse/signing.c
index 3ab40c3807..e420e5b6b9 100644
--- a/src/feature/dirparse/signing.c
+++ b/src/feature/dirparse/signing.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirparse/signing.h b/src/feature/dirparse/signing.h
index 8b119b4eb2..7ca34bb14a 100644
--- a/src/feature/dirparse/signing.h
+++ b/src/feature/dirparse/signing.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirparse/unparseable.c b/src/feature/dirparse/unparseable.c
index 941b5a1f6d..98b68f90bb 100644
--- a/src/feature/dirparse/unparseable.c
+++ b/src/feature/dirparse/unparseable.c
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file unparseable.c
+ * @brief Dump unparseable objects to disk.
+ **/
+
#define UNPARSEABLE_PRIVATE
#include "core/or/or.h"
diff --git a/src/feature/dirparse/unparseable.h b/src/feature/dirparse/unparseable.h
index 36c6b5a1ec..cff91c82cc 100644
--- a/src/feature/dirparse/unparseable.h
+++ b/src/feature/dirparse/unparseable.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/feature.md b/src/feature/feature.md
new file mode 100644
index 0000000000..acc3487e55
--- /dev/null
+++ b/src/feature/feature.md
@@ -0,0 +1,7 @@
+@dir /feature
+@brief feature: domain-specific modules
+
+The "feature" directory has modules that Tor uses only for a particular
+role or service, such as maintaining/using an onion service, operating as a
+relay or a client, or being a directory authority.
+
diff --git a/src/feature/hibernate/.may_include b/src/feature/hibernate/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/hibernate/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/hibernate/feature_hibernate.md b/src/feature/hibernate/feature_hibernate.md
new file mode 100644
index 0000000000..0eb5ffea0d
--- /dev/null
+++ b/src/feature/hibernate/feature_hibernate.md
@@ -0,0 +1,14 @@
+@dir /feature/hibernate
+@brief feature/hibernate: Bandwidth accounting and hibernation (!)
+
+This module implements two features that are only somewhat related, and
+should probably be separated in the future. One feature is bandwidth
+accounting (making sure we use no more than so many gigabytes in a day) and
+hibernation (avoiding network activity while we have used up all/most of our
+configured gigabytes). The other feature is clean shutdown, where we stop
+accepting new connections for a while and give the old ones time to close.
+
+The two features are related only in the sense that "soft hibernation" (being
+almost out of ) is very close to the "shutting down" state. But it would be
+better in the long run to make the two completely separate.
+
diff --git a/src/feature/hibernate/hibernate.c b/src/feature/hibernate/hibernate.c
index f7847d9a16..82c33659aa 100644
--- a/src/feature/hibernate/hibernate.c
+++ b/src/feature/hibernate/hibernate.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/hibernate/hibernate.h b/src/feature/hibernate/hibernate.h
index 2e245f6ab1..2383658b20 100644
--- a/src/feature/hibernate/hibernate.h
+++ b/src/feature/hibernate/hibernate.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/hibernate/include.am b/src/feature/hibernate/include.am
new file mode 100644
index 0000000000..355e591392
--- /dev/null
+++ b/src/feature/hibernate/include.am
@@ -0,0 +1,8 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/hibernate/hibernate.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/hibernate/hibernate.h
diff --git a/src/feature/hs/.may_include b/src/feature/hs/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/hs/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/hs/feature_hs.md b/src/feature/hs/feature_hs.md
new file mode 100644
index 0000000000..299d07e014
--- /dev/null
+++ b/src/feature/hs/feature_hs.md
@@ -0,0 +1,8 @@
+@dir /feature/hs
+@brief feature/hs: v3 (current) onion service protocol
+
+This directory implements the v3 onion service protocol,
+as specified in
+[rend-spec-v3.txt](https://gitweb.torproject.org/torspec.git/tree/rend-spec-v3.txt).
+
+
diff --git a/src/feature/hs/hs_cache.c b/src/feature/hs/hs_cache.c
index 9817113b23..44cd2505fd 100644
--- a/src/feature/hs/hs_cache.c
+++ b/src/feature/hs/hs_cache.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -27,12 +27,27 @@
static int cached_client_descriptor_has_expired(time_t now,
const hs_cache_client_descriptor_t *cached_desc);
+/** Helper function: Return true iff the cache entry has a decrypted
+ * descriptor.
+ *
+ * A NULL desc object in the entry means that we were not able to decrypt the
+ * descriptor because we are likely lacking client authorization. It is still
+ * a valid entry but some operations can't be done without the decrypted
+ * descriptor thus this function MUST be used to safe guard access to the
+ * decrypted desc object. */
+static inline bool
+entry_has_decrypted_descriptor(const hs_cache_client_descriptor_t *entry)
+{
+ tor_assert(entry);
+ return (entry->desc != NULL);
+}
+
/********************** Directory HS cache ******************/
-/* Directory descriptor cache. Map indexed by blinded key. */
+/** Directory descriptor cache. Map indexed by blinded key. */
static digest256map_t *hs_cache_v3_dir;
-/* Remove a given descriptor from our cache. */
+/** Remove a given descriptor from our cache. */
static void
remove_v3_desc_as_dir(const hs_cache_dir_descriptor_t *desc)
{
@@ -40,7 +55,7 @@ remove_v3_desc_as_dir(const hs_cache_dir_descriptor_t *desc)
digest256map_remove(hs_cache_v3_dir, desc->key);
}
-/* Store a given descriptor in our cache. */
+/** Store a given descriptor in our cache. */
static void
store_v3_desc_as_dir(hs_cache_dir_descriptor_t *desc)
{
@@ -48,7 +63,7 @@ store_v3_desc_as_dir(hs_cache_dir_descriptor_t *desc)
digest256map_set(hs_cache_v3_dir, desc->key, desc);
}
-/* Query our cache and return the entry or NULL if not found. */
+/** Query our cache and return the entry or NULL if not found. */
static hs_cache_dir_descriptor_t *
lookup_v3_desc_as_dir(const uint8_t *key)
{
@@ -59,7 +74,7 @@ lookup_v3_desc_as_dir(const uint8_t *key)
#define cache_dir_desc_free(val) \
FREE_AND_NULL(hs_cache_dir_descriptor_t, cache_dir_desc_free_, (val))
-/* Free a directory descriptor object. */
+/** Free a directory descriptor object. */
static void
cache_dir_desc_free_(hs_cache_dir_descriptor_t *desc)
{
@@ -71,7 +86,7 @@ cache_dir_desc_free_(hs_cache_dir_descriptor_t *desc)
tor_free(desc);
}
-/* Helper function: Use by the free all function using the digest256map
+/** Helper function: Use by the free all function using the digest256map
* interface to cache entries. */
static void
cache_dir_desc_free_void(void *ptr)
@@ -79,7 +94,7 @@ cache_dir_desc_free_void(void *ptr)
cache_dir_desc_free_(ptr);
}
-/* Create a new directory cache descriptor object from a encoded descriptor.
+/** Create a new directory cache descriptor object from a encoded descriptor.
* On success, return the heap-allocated cache object, otherwise return NULL if
* we can't decode the descriptor. */
static hs_cache_dir_descriptor_t *
@@ -109,7 +124,7 @@ cache_dir_desc_new(const char *desc)
return NULL;
}
-/* Return the size of a cache entry in bytes. */
+/** Return the size of a cache entry in bytes. */
static size_t
cache_get_dir_entry_size(const hs_cache_dir_descriptor_t *entry)
{
@@ -117,7 +132,7 @@ cache_get_dir_entry_size(const hs_cache_dir_descriptor_t *entry)
+ strlen(entry->encoded_desc));
}
-/* Try to store a valid version 3 descriptor in the directory cache. Return 0
+/** Try to store a valid version 3 descriptor in the directory cache. Return 0
* on success else a negative value is returned indicating that we have a
* newer version in our cache. On error, caller is responsible to free the
* given descriptor desc. */
@@ -167,7 +182,7 @@ cache_store_v3_as_dir(hs_cache_dir_descriptor_t *desc)
return -1;
}
-/* Using the query which is the base64 encoded blinded key of a version 3
+/** Using the query which is the base64 encoded blinded key of a version 3
* descriptor, lookup in our directory cache the entry. If found, 1 is
* returned and desc_out is populated with a newly allocated string being the
* encoded descriptor. If not found, 0 is returned and desc_out is untouched.
@@ -202,7 +217,7 @@ cache_lookup_v3_as_dir(const char *query, const char **desc_out)
return -1;
}
-/* Clean the v3 cache by removing any entry that has expired using the
+/** Clean the v3 cache by removing any entry that has expired using the
* <b>global_cutoff</b> value. If <b>global_cutoff</b> is 0, the cleaning
* process will use the lifetime found in the plaintext data section. Return
* the number of bytes cleaned. */
@@ -252,7 +267,7 @@ cache_clean_v3_as_dir(time_t now, time_t global_cutoff)
return bytes_removed;
}
-/* Given an encoded descriptor, store it in the directory cache depending on
+/** Given an encoded descriptor, store it in the directory cache depending on
* which version it is. Return a negative value on error. On success, 0 is
* returned. */
int
@@ -287,7 +302,7 @@ hs_cache_store_as_dir(const char *desc)
return -1;
}
-/* Using the query, lookup in our directory cache the entry. If found, 1 is
+/** Using the query, lookup in our directory cache the entry. If found, 1 is
* returned and desc_out is populated with a newly allocated string being
* the encoded descriptor. If not found, 0 is returned and desc_out is
* untouched. On error, a negative value is returned and desc_out is
@@ -312,7 +327,7 @@ hs_cache_lookup_as_dir(uint32_t version, const char *query,
return found;
}
-/* Clean all directory caches using the current time now. */
+/** Clean all directory caches using the current time now. */
void
hs_cache_clean_as_dir(time_t now)
{
@@ -329,23 +344,38 @@ hs_cache_clean_as_dir(time_t now)
/********************** Client-side HS cache ******************/
-/* Client-side HS descriptor cache. Map indexed by service identity key. */
+/** Client-side HS descriptor cache. Map indexed by service identity key. */
static digest256map_t *hs_cache_v3_client;
-/* Client-side introduction point state cache. Map indexed by service public
+/** Client-side introduction point state cache. Map indexed by service public
* identity key (onion address). It contains hs_cache_client_intro_state_t
* objects all related to a specific service. */
static digest256map_t *hs_cache_client_intro_state;
-/* Return the size of a client cache entry in bytes. */
+/** Return the size of a client cache entry in bytes. */
static size_t
cache_get_client_entry_size(const hs_cache_client_descriptor_t *entry)
{
- return sizeof(*entry) +
- strlen(entry->encoded_desc) + hs_desc_obj_size(entry->desc);
+ size_t size = 0;
+
+ if (entry == NULL) {
+ goto end;
+ }
+ size += sizeof(*entry);
+
+ if (entry->encoded_desc) {
+ size += strlen(entry->encoded_desc);
+ }
+
+ if (entry_has_decrypted_descriptor(entry)) {
+ size += hs_desc_obj_size(entry->desc);
+ }
+
+ end:
+ return size;
}
-/* Remove a given descriptor from our cache. */
+/** Remove a given descriptor from our cache. */
static void
remove_v3_desc_as_client(const hs_cache_client_descriptor_t *desc)
{
@@ -355,7 +385,7 @@ remove_v3_desc_as_client(const hs_cache_client_descriptor_t *desc)
rend_cache_decrement_allocation(cache_get_client_entry_size(desc));
}
-/* Store a given descriptor in our cache. */
+/** Store a given descriptor in our cache. */
static void
store_v3_desc_as_client(hs_cache_client_descriptor_t *desc)
{
@@ -365,7 +395,7 @@ store_v3_desc_as_client(hs_cache_client_descriptor_t *desc)
rend_cache_increment_allocation(cache_get_client_entry_size(desc));
}
-/* Query our cache and return the entry or NULL if not found or if expired. */
+/** Query our cache and return the entry or NULL if not found or if expired. */
STATIC hs_cache_client_descriptor_t *
lookup_v3_desc_as_client(const uint8_t *key)
{
@@ -388,15 +418,17 @@ lookup_v3_desc_as_client(const uint8_t *key)
return cached_desc;
}
-/* Parse the encoded descriptor in <b>desc_str</b> using
- * <b>service_identity_pk<b> to decrypt it first.
+/** Parse the encoded descriptor in <b>desc_str</b> using
+ * <b>service_identity_pk</b> to decrypt it first.
*
* If everything goes well, allocate and return a new
* hs_cache_client_descriptor_t object. In case of error, return NULL. */
static hs_cache_client_descriptor_t *
cache_client_desc_new(const char *desc_str,
- const ed25519_public_key_t *service_identity_pk)
+ const ed25519_public_key_t *service_identity_pk,
+ hs_desc_decode_status_t *decode_status_out)
{
+ hs_desc_decode_status_t ret;
hs_descriptor_t *desc = NULL;
hs_cache_client_descriptor_t *client_desc = NULL;
@@ -404,10 +436,24 @@ cache_client_desc_new(const char *desc_str,
tor_assert(service_identity_pk);
/* Decode the descriptor we just fetched. */
- if (hs_client_decode_descriptor(desc_str, service_identity_pk, &desc) < 0) {
+ ret = hs_client_decode_descriptor(desc_str, service_identity_pk, &desc);
+ if (ret != HS_DESC_DECODE_OK &&
+ ret != HS_DESC_DECODE_NEED_CLIENT_AUTH &&
+ ret != HS_DESC_DECODE_BAD_CLIENT_AUTH) {
+ /* In the case of a missing or bad client authorization, we'll keep the
+ * descriptor in the cache because those credentials can arrive later. */
goto end;
}
- tor_assert(desc);
+ /* Make sure we do have a descriptor if decoding was successful. */
+ if (ret == HS_DESC_DECODE_OK) {
+ tor_assert(desc);
+ } else {
+ if (BUG(desc != NULL)) {
+ /* We are not suppose to have a descriptor if the decoding code is not
+ * indicating success. Just in case, bail early to recover. */
+ goto end;
+ }
+ }
/* All is good: make a cache object for this descriptor */
client_desc = tor_malloc_zero(sizeof(hs_cache_client_descriptor_t));
@@ -420,6 +466,9 @@ cache_client_desc_new(const char *desc_str,
client_desc->encoded_desc = tor_strdup(desc_str);
end:
+ if (decode_status_out) {
+ *decode_status_out = ret;
+ }
return client_desc;
}
@@ -448,7 +497,7 @@ cache_client_desc_free_void(void *ptr)
cache_client_desc_free(desc);
}
-/* Return a newly allocated and initialized hs_cache_intro_state_t object. */
+/** Return a newly allocated and initialized hs_cache_intro_state_t object. */
static hs_cache_intro_state_t *
cache_intro_state_new(void)
{
@@ -460,21 +509,21 @@ cache_intro_state_new(void)
#define cache_intro_state_free(val) \
FREE_AND_NULL(hs_cache_intro_state_t, cache_intro_state_free_, (val))
-/* Free an hs_cache_intro_state_t object. */
+/** Free an hs_cache_intro_state_t object. */
static void
cache_intro_state_free_(hs_cache_intro_state_t *state)
{
tor_free(state);
}
-/* Helper function: used by the free all function. */
+/** Helper function: used by the free all function. */
static void
cache_intro_state_free_void(void *state)
{
cache_intro_state_free_(state);
}
-/* Return a newly allocated and initialized hs_cache_client_intro_state_t
+/** Return a newly allocated and initialized hs_cache_client_intro_state_t
* object. */
static hs_cache_client_intro_state_t *
cache_client_intro_state_new(void)
@@ -488,7 +537,7 @@ cache_client_intro_state_new(void)
FREE_AND_NULL(hs_cache_client_intro_state_t, \
cache_client_intro_state_free_, (val))
-/* Free a cache_client_intro_state object. */
+/** Free a cache_client_intro_state object. */
static void
cache_client_intro_state_free_(hs_cache_client_intro_state_t *cache)
{
@@ -499,14 +548,14 @@ cache_client_intro_state_free_(hs_cache_client_intro_state_t *cache)
tor_free(cache);
}
-/* Helper function: used by the free all function. */
+/** Helper function: used by the free all function. */
static void
cache_client_intro_state_free_void(void *entry)
{
cache_client_intro_state_free_(entry);
}
-/* For the given service identity key service_pk and an introduction
+/** For the given service identity key service_pk and an introduction
* authentication key auth_key, lookup the intro state object. Return 1 if
* found and put it in entry if not NULL. Return 0 if not found and entry is
* untouched. */
@@ -541,7 +590,7 @@ cache_client_intro_state_lookup(const ed25519_public_key_t *service_pk,
return 0;
}
-/* Note the given failure in state. */
+/** Note the given failure in state. */
static void
cache_client_intro_state_note(hs_cache_intro_state_t *state,
rend_intro_point_failure_t failure)
@@ -563,7 +612,7 @@ cache_client_intro_state_note(hs_cache_intro_state_t *state,
}
}
-/* For the given service identity key service_pk and an introduction
+/** For the given service identity key service_pk and an introduction
* authentication key auth_key, add an entry in the client intro state cache
* If no entry exists for the service, it will create one. If state is non
* NULL, it will point to the new intro state entry. */
@@ -597,7 +646,7 @@ cache_client_intro_state_add(const ed25519_public_key_t *service_pk,
}
}
-/* Remove every intro point state entry from cache that has been created
+/** Remove every intro point state entry from cache that has been created
* before or at the cutoff. */
static void
cache_client_intro_state_clean(time_t cutoff,
@@ -614,7 +663,7 @@ cache_client_intro_state_clean(time_t cutoff,
} DIGEST256MAP_FOREACH_END;
}
-/* Return true iff no intro points are in this cache. */
+/** Return true iff no intro points are in this cache. */
static int
cache_client_intro_state_is_empty(const hs_cache_client_intro_state_t *cache)
{
@@ -635,9 +684,25 @@ cache_store_as_client(hs_cache_client_descriptor_t *client_desc)
tor_assert(client_desc);
/* Check if we already have a descriptor from this HS in cache. If we do,
- * check if this descriptor is newer than the cached one */
+ * check if this descriptor is newer than the cached one only if we have a
+ * decoded descriptor. We do keep non-decoded descriptor that requires
+ * client authorization. */
cache_entry = lookup_v3_desc_as_client(client_desc->key.pubkey);
if (cache_entry != NULL) {
+ /* If the current or the new cache entry don't have a decrypted descriptor
+ * (missing client authorization), we always replace the current one with
+ * the new one. Reason is that we can't inspect the revision counter
+ * within the plaintext data so we blindly replace. */
+ if (!entry_has_decrypted_descriptor(cache_entry) ||
+ !entry_has_decrypted_descriptor(client_desc)) {
+ remove_v3_desc_as_client(cache_entry);
+ cache_client_desc_free(cache_entry);
+ goto store;
+ }
+
+ /* From this point on, we know that the decrypted descriptor is in the
+ * current entry and new object thus safe to access. */
+
/* If we have an entry in our cache that has a revision counter greater
* than the one we just fetched, discard the one we fetched. */
if (cache_entry->desc->plaintext_data.revision_counter >
@@ -657,6 +722,7 @@ cache_store_as_client(hs_cache_client_descriptor_t *client_desc)
cache_client_desc_free(cache_entry);
}
+ store:
/* Store descriptor in cache */
store_v3_desc_as_client(client_desc);
@@ -664,7 +730,7 @@ cache_store_as_client(hs_cache_client_descriptor_t *client_desc)
return 0;
}
-/* Return true iff the cached client descriptor at <b>cached_desc</b has
+/** Return true iff the cached client descriptor at <b>cached_desc</b> has
* expired. */
static int
cached_client_descriptor_has_expired(time_t now,
@@ -687,7 +753,7 @@ cached_client_descriptor_has_expired(time_t now,
return 0;
}
-/* clean the client cache using now as the current time. Return the total size
+/** clean the client cache using now as the current time. Return the total size
* of removed bytes from the cache. */
static size_t
cache_clean_v3_as_client(time_t now)
@@ -710,11 +776,15 @@ cache_clean_v3_as_client(time_t now)
MAP_DEL_CURRENT(key);
entry_size = cache_get_client_entry_size(entry);
bytes_removed += entry_size;
+
/* We just removed an old descriptor. We need to close all intro circuits
- * so we don't have leftovers that can be selected while lacking a
- * descriptor. We leave the rendezvous circuits opened because they could
- * be in use. */
- hs_client_close_intro_circuits_from_desc(entry->desc);
+ * if the descriptor is decrypted so we don't have leftovers that can be
+ * selected while lacking a descriptor. Circuits are selected by intro
+ * authentication key thus we need the descriptor. We leave the rendezvous
+ * circuits opened because they could be in use. */
+ if (entry_has_decrypted_descriptor(entry)) {
+ hs_client_close_intro_circuits_from_desc(entry->desc);
+ }
/* Entry is not in the cache anymore, destroy it. */
cache_client_desc_free(entry);
/* Update our OOM. We didn't use the remove() function because we are in
@@ -752,7 +822,9 @@ hs_cache_lookup_encoded_as_client(const ed25519_public_key_t *key)
}
/** Public API: Given the HS ed25519 identity public key in <b>key</b>, return
- * its HS descriptor if it's stored in our cache, or NULL if not. */
+ * its HS descriptor if it's stored in our cache, or NULL if not or if the
+ * descriptor was never decrypted. The later can happen if we are waiting for
+ * client authorization to be added. */
const hs_descriptor_t *
hs_cache_lookup_as_client(const ed25519_public_key_t *key)
{
@@ -761,27 +833,41 @@ hs_cache_lookup_as_client(const ed25519_public_key_t *key)
tor_assert(key);
cached_desc = lookup_v3_desc_as_client(key->pubkey);
- if (cached_desc) {
- tor_assert(cached_desc->desc);
+ if (cached_desc && entry_has_decrypted_descriptor(cached_desc)) {
return cached_desc->desc;
}
return NULL;
}
-/** Public API: Given an encoded descriptor, store it in the client HS
- * cache. Return -1 on error, 0 on success .*/
-int
+/** Public API: Given an encoded descriptor, store it in the client HS cache.
+ * Return a decode status which changes how we handle the SOCKS connection
+ * depending on its value:
+ *
+ * HS_DESC_DECODE_OK: Returned on success. Descriptor was properly decoded
+ * and is now stored.
+ *
+ * HS_DESC_DECODE_NEED_CLIENT_AUTH: Client authorization is needed but the
+ * descriptor was still stored.
+ *
+ * HS_DESC_DECODE_BAD_CLIENT_AUTH: Client authorization for this descriptor
+ * was not usable but the descriptor was
+ * still stored.
+ *
+ * Any other codes means indicate where the error occured and the descriptor
+ * was not stored. */
+hs_desc_decode_status_t
hs_cache_store_as_client(const char *desc_str,
const ed25519_public_key_t *identity_pk)
{
+ hs_desc_decode_status_t ret;
hs_cache_client_descriptor_t *client_desc = NULL;
tor_assert(desc_str);
tor_assert(identity_pk);
/* Create client cache descriptor object */
- client_desc = cache_client_desc_new(desc_str, identity_pk);
+ client_desc = cache_client_desc_new(desc_str, identity_pk, &ret);
if (!client_desc) {
log_warn(LD_GENERAL, "HSDesc parsing failed!");
log_debug(LD_GENERAL, "Failed to parse HSDesc: %s.", escaped(desc_str));
@@ -790,17 +876,54 @@ hs_cache_store_as_client(const char *desc_str,
/* Push it to the cache */
if (cache_store_as_client(client_desc) < 0) {
+ ret = HS_DESC_DECODE_GENERIC_ERROR;
goto err;
}
- return 0;
+ return ret;
err:
cache_client_desc_free(client_desc);
- return -1;
+ return ret;
}
-/* Clean all client caches using the current time now. */
+/** Remove and free a client cache descriptor entry for the given onion
+ * service ed25519 public key. If the descriptor is decoded, the intro
+ * circuits are closed if any.
+ *
+ * This does nothing if no descriptor exists for the given key. */
+void
+hs_cache_remove_as_client(const ed25519_public_key_t *key)
+{
+ hs_cache_client_descriptor_t *cached_desc = NULL;
+
+ tor_assert(key);
+
+ cached_desc = lookup_v3_desc_as_client(key->pubkey);
+ if (!cached_desc) {
+ return;
+ }
+ /* If we have a decrypted/decoded descriptor, attempt to close its
+ * introduction circuit(s). We shouldn't have circuit(s) without a
+ * descriptor else it will lead to a failure. */
+ if (entry_has_decrypted_descriptor(cached_desc)) {
+ hs_client_close_intro_circuits_from_desc(cached_desc->desc);
+ }
+ /* Remove and free. */
+ remove_v3_desc_as_client(cached_desc);
+ cache_client_desc_free(cached_desc);
+
+ /* Logging. */
+ {
+ char key_b64[BASE64_DIGEST256_LEN + 1];
+ digest256_to_base64(key_b64, (const char *) key);
+ log_info(LD_REND, "Onion service v3 descriptor '%s' removed "
+ "from client cache",
+ safe_str_client(key_b64));
+ }
+}
+
+/** Clean all client caches using the current time now. */
void
hs_cache_clean_as_client(time_t now)
{
@@ -811,7 +934,7 @@ hs_cache_clean_as_client(time_t now)
cache_clean_v3_as_client(now);
}
-/* Purge the client descriptor cache. */
+/** Purge the client descriptor cache. */
void
hs_cache_purge_as_client(void)
{
@@ -828,7 +951,7 @@ hs_cache_purge_as_client(void)
log_info(LD_REND, "Hidden service client descriptor cache purged.");
}
-/* For a given service identity public key and an introduction authentication
+/** For a given service identity public key and an introduction authentication
* key, note the given failure in the client intro state cache. */
void
hs_cache_client_intro_state_note(const ed25519_public_key_t *service_pk,
@@ -850,7 +973,7 @@ hs_cache_client_intro_state_note(const ed25519_public_key_t *service_pk,
cache_client_intro_state_note(entry, failure);
}
-/* For a given service identity public key and an introduction authentication
+/** For a given service identity public key and an introduction authentication
* key, return true iff it is present in the failure cache. */
const hs_cache_intro_state_t *
hs_cache_client_intro_state_find(const ed25519_public_key_t *service_pk,
@@ -861,7 +984,7 @@ hs_cache_client_intro_state_find(const ed25519_public_key_t *service_pk,
return state;
}
-/* Cleanup the client introduction state cache. */
+/** Cleanup the client introduction state cache. */
void
hs_cache_client_intro_state_clean(time_t now)
{
@@ -881,7 +1004,7 @@ hs_cache_client_intro_state_clean(time_t now)
} DIGEST256MAP_FOREACH_END;
}
-/* Purge the client introduction state cache. */
+/** Purge the client introduction state cache. */
void
hs_cache_client_intro_state_purge(void)
{
@@ -895,9 +1018,41 @@ hs_cache_client_intro_state_purge(void)
"cache purged.");
}
+/* This is called when new client authorization was added to the global state.
+ * It attemps to decode the descriptor of the given service identity key.
+ *
+ * Return true if decoding was successful else false. */
+bool
+hs_cache_client_new_auth_parse(const ed25519_public_key_t *service_pk)
+{
+ bool ret = false;
+ hs_cache_client_descriptor_t *cached_desc = NULL;
+
+ tor_assert(service_pk);
+
+ if (!hs_cache_v3_client) {
+ return false;
+ }
+
+ cached_desc = lookup_v3_desc_as_client(service_pk->pubkey);
+ if (cached_desc == NULL || entry_has_decrypted_descriptor(cached_desc)) {
+ /* No entry for that service or the descriptor is already decoded. */
+ goto end;
+ }
+
+ /* Attempt a decode. If we are successful, inform the caller. */
+ if (hs_client_decode_descriptor(cached_desc->encoded_desc, service_pk,
+ &cached_desc->desc) == HS_DESC_DECODE_OK) {
+ ret = true;
+ }
+
+ end:
+ return ret;
+}
+
/**************** Generics *********************************/
-/* Do a round of OOM cleanup on all directory caches. Return the amount of
+/** Do a round of OOM cleanup on all directory caches. Return the amount of
* removed bytes. It is possible that the returned value is lower than
* min_remove_bytes if the caches get emptied out so the caller should be
* aware of this. */
@@ -951,7 +1106,7 @@ hs_cache_handle_oom(time_t now, size_t min_remove_bytes)
return bytes_removed;
}
-/* Return the maximum size of a v3 HS descriptor. */
+/** Return the maximum size of a v3 HS descriptor. */
unsigned int
hs_cache_get_max_descriptor_size(void)
{
@@ -960,7 +1115,7 @@ hs_cache_get_max_descriptor_size(void)
HS_DESC_MAX_LEN, 1, INT32_MAX);
}
-/* Initialize the hidden service cache subsystem. */
+/** Initialize the hidden service cache subsystem. */
void
hs_cache_init(void)
{
@@ -975,7 +1130,7 @@ hs_cache_init(void)
hs_cache_client_intro_state = digest256map_new();
}
-/* Cleanup the hidden service cache subsystem. */
+/** Cleanup the hidden service cache subsystem. */
void
hs_cache_free_all(void)
{
diff --git a/src/feature/hs/hs_cache.h b/src/feature/hs/hs_cache.h
index 079d31d437..bb3c77f224 100644
--- a/src/feature/hs/hs_cache.h
+++ b/src/feature/hs/hs_cache.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -18,47 +18,47 @@
struct ed25519_public_key_t;
-/* This is the maximum time an introduction point state object can stay in the
+/** This is the maximum time an introduction point state object can stay in the
* client cache in seconds (2 mins or 120 seconds). */
#define HS_CACHE_CLIENT_INTRO_STATE_MAX_AGE (2 * 60)
-/* Introduction point state. */
+/** Introduction point state. */
typedef struct hs_cache_intro_state_t {
- /* When this entry was created and put in the cache. */
+ /** When this entry was created and put in the cache. */
time_t created_ts;
- /* Did it suffered a generic error? */
+ /** Did it suffered a generic error? */
unsigned int error : 1;
- /* Did it timed out? */
+ /** Did it timed out? */
unsigned int timed_out : 1;
- /* How many times we tried to reached it and it was unreachable. */
+ /** How many times we tried to reached it and it was unreachable. */
uint32_t unreachable_count;
} hs_cache_intro_state_t;
typedef struct hs_cache_client_intro_state_t {
- /* Contains hs_cache_intro_state_t object indexed by introduction point
+ /** Contains hs_cache_intro_state_t object indexed by introduction point
* authentication key. */
digest256map_t *intro_points;
} hs_cache_client_intro_state_t;
-/* Descriptor representation on the directory side which is a subset of
+/** Descriptor representation on the directory side which is a subset of
* information that the HSDir can decode and serve it. */
typedef struct hs_cache_dir_descriptor_t {
- /* This object is indexed using the blinded pubkey located in the plaintext
+ /** This object is indexed using the blinded pubkey located in the plaintext
* data which is populated only once the descriptor has been successfully
* decoded and validated. This simply points to that pubkey. */
const uint8_t *key;
- /* When does this entry has been created. Used to expire entries. */
+ /** When does this entry has been created. Used to expire entries. */
time_t created_ts;
- /* Descriptor plaintext information. Obviously, we can't decrypt the
+ /** Descriptor plaintext information. Obviously, we can't decrypt the
* encrypted part of the descriptor. */
hs_desc_plaintext_data_t *plaintext_data;
- /* Encoded descriptor which is basically in text form. It's a NUL terminated
+ /** Encoded descriptor which is basically in text form. It's a NUL terminated
* string thus safe to strlen(). */
char *encoded_desc;
} hs_cache_dir_descriptor_t;
@@ -83,8 +83,9 @@ const hs_descriptor_t *
hs_cache_lookup_as_client(const struct ed25519_public_key_t *key);
const char *
hs_cache_lookup_encoded_as_client(const struct ed25519_public_key_t *key);
-int hs_cache_store_as_client(const char *desc_str,
- const struct ed25519_public_key_t *identity_pk);
+hs_desc_decode_status_t hs_cache_store_as_client(const char *desc_str,
+ const struct ed25519_public_key_t *identity_pk);
+void hs_cache_remove_as_client(const struct ed25519_public_key_t *key);
void hs_cache_clean_as_client(time_t now);
void hs_cache_purge_as_client(void);
@@ -99,24 +100,28 @@ const hs_cache_intro_state_t *hs_cache_client_intro_state_find(
void hs_cache_client_intro_state_clean(time_t now);
void hs_cache_client_intro_state_purge(void);
+bool hs_cache_client_new_auth_parse(const ed25519_public_key_t *service_pk);
+
#ifdef HS_CACHE_PRIVATE
#include "lib/crypt_ops/crypto_ed25519.h"
/** Represents a locally cached HS descriptor on a hidden service client. */
typedef struct hs_cache_client_descriptor_t {
- /* This object is indexed using the service identity public key */
+ /** This object is indexed using the service identity public key */
struct ed25519_public_key_t key;
- /* When will this entry expire? We expire cached client descriptors in the
+ /** When will this entry expire? We expire cached client descriptors in the
* start of the next time period, since that's when clients need to start
* using the next blinded key of the service. */
time_t expiration_ts;
- /* The cached descriptor, this object is the owner. It can't be NULL. A
- * cache object without a valid descriptor is not possible. */
+ /** The cached decoded descriptor, this object is the owner. This can be
+ * NULL if the descriptor couldn't be decoded due to missing or bad client
+ * authorization. It can be decoded later from the encoded_desc object if
+ * the proper client authorization is given tor. */
hs_descriptor_t *desc;
- /* Encoded descriptor in string form. Can't be NULL. */
+ /** Encoded descriptor in string form. Can't be NULL. */
char *encoded_desc;
} hs_cache_client_descriptor_t;
diff --git a/src/feature/hs/hs_cell.c b/src/feature/hs/hs_cell.c
index df59f73c1b..52bd663200 100644
--- a/src/feature/hs/hs_cell.c
+++ b/src/feature/hs/hs_cell.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -24,7 +24,7 @@
#include "trunnel/hs/cell_introduce1.h"
#include "trunnel/hs/cell_rendezvous.h"
-/* Compute the MAC of an INTRODUCE cell in mac_out. The encoded_cell param is
+/** Compute the MAC of an INTRODUCE cell in mac_out. The encoded_cell param is
* the cell content up to the ENCRYPTED section of length encoded_cell_len.
* The encrypted param is the start of the ENCRYPTED section of length
* encrypted_len. The mac_key is the key needed for the computation of the MAC
@@ -67,7 +67,7 @@ compute_introduce_mac(const uint8_t *encoded_cell, size_t encoded_cell_len,
memwipe(mac_msg, 0, sizeof(mac_msg));
}
-/* From a set of keys, subcredential and the ENCRYPTED section of an
+/** From a set of keys, subcredential and the ENCRYPTED section of an
* INTRODUCE2 cell, return a newly allocated intro cell keys structure.
* Finally, the client public key is copied in client_pk. On error, return
* NULL. */
@@ -101,7 +101,7 @@ get_introduce2_key_material(const ed25519_public_key_t *auth_key,
return keys;
}
-/* Using the given encryption key, decrypt the encrypted_section of length
+/** Using the given encryption key, decrypt the encrypted_section of length
* encrypted_section_len of an INTRODUCE2 cell and return a newly allocated
* buffer containing the decrypted data. On decryption failure, NULL is
* returned. */
@@ -136,7 +136,7 @@ decrypt_introduce2(const uint8_t *enc_key, const uint8_t *encrypted_section,
return decrypted;
}
-/* Given a pointer to the decrypted data of the ENCRYPTED section of an
+/** Given a pointer to the decrypted data of the ENCRYPTED section of an
* INTRODUCE2 cell of length decrypted_len, parse and validate the cell
* content. Return a newly allocated cell structure or NULL on error. The
* circuit and service object are only used for logging purposes. */
@@ -188,7 +188,7 @@ parse_introduce2_encrypted(const uint8_t *decrypted_data,
return NULL;
}
-/* Build a legacy ESTABLISH_INTRO cell with the given circuit nonce and RSA
+/** Build a legacy ESTABLISH_INTRO cell with the given circuit nonce and RSA
* encryption key. The encoded cell is put in cell_out that MUST at least be
* of the size of RELAY_PAYLOAD_SIZE. Return the encoded cell length on
* success else a negative value and cell_out is untouched. */
@@ -210,7 +210,7 @@ build_legacy_establish_intro(const char *circ_nonce, crypto_pk_t *enc_key,
return cell_len;
}
-/* Parse an INTRODUCE2 cell from payload of size payload_len for the given
+/** Parse an INTRODUCE2 cell from payload of size payload_len for the given
* service and circuit which are used only for logging purposes. The resulting
* parsed cell is put in cell_ptr_out.
*
@@ -249,7 +249,7 @@ parse_introduce2_cell(const hs_service_t *service,
return -1;
}
-/* Set the onion public key onion_pk in cell, the encrypted section of an
+/** Set the onion public key onion_pk in cell, the encrypted section of an
* INTRODUCE1 cell. */
static void
introduce1_set_encrypted_onion_key(trn_cell_introduce_encrypted_t *cell,
@@ -266,7 +266,7 @@ introduce1_set_encrypted_onion_key(trn_cell_introduce_encrypted_t *cell,
trn_cell_introduce_encrypted_getlen_onion_key(cell));
}
-/* Set the link specifiers in lspecs in cell, the encrypted section of an
+/** Set the link specifiers in lspecs in cell, the encrypted section of an
* INTRODUCE1 cell. */
static void
introduce1_set_encrypted_link_spec(trn_cell_introduce_encrypted_t *cell,
@@ -286,7 +286,7 @@ introduce1_set_encrypted_link_spec(trn_cell_introduce_encrypted_t *cell,
trn_cell_introduce_encrypted_add_nspecs(cell, ls));
}
-/* Set padding in the enc_cell only if needed that is the total length of both
+/** Set padding in the enc_cell only if needed that is the total length of both
* sections are below the mininum required for an INTRODUCE1 cell. */
static void
introduce1_set_encrypted_padding(const trn_cell_introduce1_t *cell,
@@ -306,7 +306,7 @@ introduce1_set_encrypted_padding(const trn_cell_introduce1_t *cell,
}
}
-/* Encrypt the ENCRYPTED payload and encode it in the cell using the enc_cell
+/** Encrypt the ENCRYPTED payload and encode it in the cell using the enc_cell
* and the INTRODUCE1 data.
*
* This can't fail but it is very important that the caller sets every field
@@ -394,7 +394,7 @@ introduce1_encrypt_and_encode(trn_cell_introduce1_t *cell,
tor_free(encrypted);
}
-/* Using the INTRODUCE1 data, setup the ENCRYPTED section in cell. This means
+/** Using the INTRODUCE1 data, setup the ENCRYPTED section in cell. This means
* set it, encrypt it and encode it. */
static void
introduce1_set_encrypted(trn_cell_introduce1_t *cell,
@@ -435,7 +435,7 @@ introduce1_set_encrypted(trn_cell_introduce1_t *cell,
trn_cell_introduce_encrypted_free(enc_cell);
}
-/* Set the authentication key in the INTRODUCE1 cell from the given data. */
+/** Set the authentication key in the INTRODUCE1 cell from the given data. */
static void
introduce1_set_auth_key(trn_cell_introduce1_t *cell,
const hs_cell_introduce1_data_t *data)
@@ -451,7 +451,7 @@ introduce1_set_auth_key(trn_cell_introduce1_t *cell,
data->auth_pk->pubkey, trn_cell_introduce1_getlen_auth_key(cell));
}
-/* Set the legacy ID field in the INTRODUCE1 cell from the given data. */
+/** Set the legacy ID field in the INTRODUCE1 cell from the given data. */
static void
introduce1_set_legacy_id(trn_cell_introduce1_t *cell,
const hs_cell_introduce1_data_t *data)
@@ -473,7 +473,7 @@ introduce1_set_legacy_id(trn_cell_introduce1_t *cell,
}
}
-/* Build and add to the given DoS cell extension the given parameter type and
+/** Build and add to the given DoS cell extension the given parameter type and
* value. */
static void
build_establish_intro_dos_param(trn_cell_extension_dos_t *dos_ext,
@@ -493,7 +493,7 @@ build_establish_intro_dos_param(trn_cell_extension_dos_t *dos_ext,
/* Not freeing the trunnel object because it is now owned by dos_ext. */
}
-/* Build the DoS defense cell extension and put it in the given extensions
+/** Build the DoS defense cell extension and put it in the given extensions
* object. Return 0 on success, -1 on failure. (Right now, failure is only
* possible if there is a bug.) */
static int
@@ -568,7 +568,7 @@ build_establish_intro_dos_extension(const hs_service_config_t *service_config,
/* Public API */
/* ========== */
-/* Allocate and build all the ESTABLISH_INTRO cell extension. The given
+/** Allocate and build all the ESTABLISH_INTRO cell extension. The given
* extensions pointer is always set to a valid cell extension object. */
STATIC trn_cell_extension_t *
build_establish_intro_extensions(const hs_service_config_t *service_config,
@@ -599,7 +599,7 @@ build_establish_intro_extensions(const hs_service_config_t *service_config,
return extensions;
}
-/* Build an ESTABLISH_INTRO cell with the given circuit nonce and intro point
+/** Build an ESTABLISH_INTRO cell with the given circuit nonce and intro point
* object. The encoded cell is put in cell_out that MUST at least be of the
* size of RELAY_PAYLOAD_SIZE. Return the encoded cell length on success else
* a negative value and cell_out is untouched. This function also supports
@@ -725,7 +725,7 @@ hs_cell_build_establish_intro(const char *circ_nonce,
return cell_len;
}
-/* Parse the INTRO_ESTABLISHED cell in the payload of size payload_len. If we
+/** Parse the INTRO_ESTABLISHED cell in the payload of size payload_len. If we
* are successful at parsing it, return the length of the parsed cell else a
* negative value on error. */
ssize_t
@@ -747,7 +747,7 @@ hs_cell_parse_intro_established(const uint8_t *payload, size_t payload_len)
return ret;
}
-/* Parse the INTRODUCE2 cell using data which contains everything we need to
+/** Parse the INTRODUCE2 cell using data which contains everything we need to
* do so and contains the destination buffers of information we extract and
* compute from the cell. Return 0 on success else a negative value. The
* service and circ are only used for logging purposes. */
@@ -908,7 +908,7 @@ hs_cell_parse_introduce2(hs_cell_introduce2_data_t *data,
return ret;
}
-/* Build a RENDEZVOUS1 cell with the given rendezvous cookie and handshake
+/** Build a RENDEZVOUS1 cell with the given rendezvous cookie and handshake
* info. The encoded cell is put in cell_out and the length of the data is
* returned. This can't fail. */
ssize_t
@@ -942,7 +942,7 @@ hs_cell_build_rendezvous1(const uint8_t *rendezvous_cookie,
return cell_len;
}
-/* Build an INTRODUCE1 cell from the given data. The encoded cell is put in
+/** Build an INTRODUCE1 cell from the given data. The encoded cell is put in
* cell_out which must be of at least size RELAY_PAYLOAD_SIZE. On success, the
* encoded length is returned else a negative value and the content of
* cell_out should be ignored. */
@@ -983,7 +983,7 @@ hs_cell_build_introduce1(const hs_cell_introduce1_data_t *data,
return cell_len;
}
-/* Build an ESTABLISH_RENDEZVOUS cell from the given rendezvous_cookie. The
+/** Build an ESTABLISH_RENDEZVOUS cell from the given rendezvous_cookie. The
* encoded cell is put in cell_out which must be of at least
* RELAY_PAYLOAD_SIZE. On success, the encoded length is returned and the
* caller should clear up the content of the cell.
@@ -1000,7 +1000,7 @@ hs_cell_build_establish_rendezvous(const uint8_t *rendezvous_cookie,
return HS_REND_COOKIE_LEN;
}
-/* Handle an INTRODUCE_ACK cell encoded in payload of length payload_len.
+/** Handle an INTRODUCE_ACK cell encoded in payload of length payload_len.
* Return the status code on success else a negative value if the cell as not
* decodable. */
int
@@ -1035,7 +1035,7 @@ hs_cell_parse_introduce_ack(const uint8_t *payload, size_t payload_len)
return ret;
}
-/* Handle a RENDEZVOUS2 cell encoded in payload of length payload_len. On
+/** Handle a RENDEZVOUS2 cell encoded in payload of length payload_len. On
* success, handshake_info contains the data in the HANDSHAKE_INFO field, and
* 0 is returned. On error, a negative value is returned. */
int
@@ -1067,7 +1067,7 @@ hs_cell_parse_rendezvous2(const uint8_t *payload, size_t payload_len,
return ret;
}
-/* Clear the given INTRODUCE1 data structure data. */
+/** Clear the given INTRODUCE1 data structure data. */
void
hs_cell_introduce1_data_clear(hs_cell_introduce1_data_t *data)
{
diff --git a/src/feature/hs/hs_cell.h b/src/feature/hs/hs_cell.h
index 864b6fda5f..80f37057d2 100644
--- a/src/feature/hs/hs_cell.h
+++ b/src/feature/hs/hs_cell.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,35 +12,35 @@
#include "core/or/or.h"
#include "feature/hs/hs_service.h"
-/* An INTRODUCE1 cell requires at least this amount of bytes (see section
+/** An INTRODUCE1 cell requires at least this amount of bytes (see section
* 3.2.2 of the specification). Below this value, the cell must be padded. */
#define HS_CELL_INTRODUCE1_MIN_SIZE 246
-/* This data structure contains data that we need to build an INTRODUCE1 cell
+/** This data structure contains data that we need to build an INTRODUCE1 cell
* used by the INTRODUCE1 build function. */
typedef struct hs_cell_introduce1_data_t {
- /* Is this a legacy introduction point? */
+ /** Is this a legacy introduction point? */
unsigned int is_legacy : 1;
- /* (Legacy only) The encryption key for a legacy intro point. Only set if
+ /** (Legacy only) The encryption key for a legacy intro point. Only set if
* is_legacy is true. */
const crypto_pk_t *legacy_key;
- /* Introduction point authentication public key. */
+ /** Introduction point authentication public key. */
const ed25519_public_key_t *auth_pk;
- /* Introduction point encryption public key. */
+ /** Introduction point encryption public key. */
const curve25519_public_key_t *enc_pk;
- /* Subcredentials of the service. */
+ /** Subcredentials of the service. */
const uint8_t *subcredential;
- /* Onion public key for the ntor handshake. */
+ /** Onion public key for the ntor handshake. */
const curve25519_public_key_t *onion_pk;
- /* Rendezvous cookie. */
+ /** Rendezvous cookie. */
const uint8_t *rendezvous_cookie;
- /* Public key put before the encrypted data (CLIENT_PK). */
+ /** Public key put before the encrypted data (CLIENT_PK). */
const curve25519_keypair_t *client_kp;
- /* Rendezvous point link specifiers. */
+ /** Rendezvous point link specifiers. */
smartlist_t *link_specifiers;
} hs_cell_introduce1_data_t;
-/* This data structure contains data that we need to parse an INTRODUCE2 cell
+/** This data structure contains data that we need to parse an INTRODUCE2 cell
* which is used by the INTRODUCE2 cell parsing function. On a successful
* parsing, the onion_pk and rendezvous_cookie will be populated with the
* computed key material from the cell data. This structure is only used during
@@ -48,32 +48,32 @@ typedef struct hs_cell_introduce1_data_t {
typedef struct hs_cell_introduce2_data_t {
/*** Immutable Section: Set on structure init. ***/
- /* Introduction point authentication public key. Pointer owned by the
+ /** Introduction point authentication public key. Pointer owned by the
introduction point object through which we received the INTRO2 cell. */
const ed25519_public_key_t *auth_pk;
- /* Introduction point encryption keypair for the ntor handshake. Pointer
+ /** Introduction point encryption keypair for the ntor handshake. Pointer
owned by the introduction point object through which we received the
INTRO2 cell*/
const curve25519_keypair_t *enc_kp;
- /* Subcredentials of the service. Pointer owned by the descriptor that owns
+ /** Subcredentials of the service. Pointer owned by the descriptor that owns
the introduction point through which we received the INTRO2 cell. */
const uint8_t *subcredential;
- /* Payload of the received encoded cell. */
+ /** Payload of the received encoded cell. */
const uint8_t *payload;
- /* Size of the payload of the received encoded cell. */
+ /** Size of the payload of the received encoded cell. */
size_t payload_len;
/*** Mutable Section: Set upon parsing INTRODUCE2 cell. ***/
- /* Onion public key computed using the INTRODUCE2 encrypted section. */
+ /** Onion public key computed using the INTRODUCE2 encrypted section. */
curve25519_public_key_t onion_pk;
- /* Rendezvous cookie taken from the INTRODUCE2 encrypted section. */
+ /** Rendezvous cookie taken from the INTRODUCE2 encrypted section. */
uint8_t rendezvous_cookie[REND_COOKIE_LEN];
- /* Client public key from the INTRODUCE2 encrypted section. */
+ /** Client public key from the INTRODUCE2 encrypted section. */
curve25519_public_key_t client_pk;
- /* Link specifiers of the rendezvous point. Contains link_specifier_t. */
+ /** Link specifiers of the rendezvous point. Contains link_specifier_t. */
smartlist_t *link_specifiers;
- /* Replay cache of the introduction point. */
+ /** Replay cache of the introduction point. */
replaycache_t *replay_cache;
} hs_cell_introduce2_data_t;
@@ -117,4 +117,3 @@ build_establish_intro_extensions(const hs_service_config_t *service_config,
#endif /* defined(TOR_UNIT_TESTS) */
#endif /* !defined(TOR_HS_CELL_H) */
-
diff --git a/src/feature/hs/hs_circuit.c b/src/feature/hs/hs_circuit.c
index 5e213b5aba..90805a98b7 100644
--- a/src/feature/hs/hs_circuit.c
+++ b/src/feature/hs/hs_circuit.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -20,11 +20,13 @@
#include "feature/hs/hs_cell.h"
#include "feature/hs/hs_circuit.h"
#include "feature/hs/hs_circuitmap.h"
+#include "feature/hs/hs_client.h"
#include "feature/hs/hs_ident.h"
#include "feature/hs/hs_service.h"
#include "feature/nodelist/describe.h"
#include "feature/nodelist/nodelist.h"
#include "feature/rend/rendservice.h"
+#include "feature/rend/rendclient.h"
#include "feature/stats/rephist.h"
#include "lib/crypt_ops/crypto_dh.h"
#include "lib/crypt_ops/crypto_rand.h"
@@ -40,7 +42,7 @@
#include "feature/nodelist/node_st.h"
#include "core/or/origin_circuit_st.h"
-/* A circuit is about to become an e2e rendezvous circuit. Check
+/** A circuit is about to become an e2e rendezvous circuit. Check
* <b>circ_purpose</b> and ensure that it's properly set. Return true iff
* circuit purpose is properly set, otherwise return false. */
static int
@@ -67,7 +69,7 @@ circuit_purpose_is_correct_for_rend(unsigned int circ_purpose,
return 1;
}
-/* Create and return a crypt path for the final hop of a v3 prop224 rendezvous
+/** Create and return a crypt path for the final hop of a v3 prop224 rendezvous
* circuit. Initialize the crypt path crypto using the output material from the
* ntor key exchange at <b>ntor_key_seed</b>.
*
@@ -101,7 +103,7 @@ create_rend_cpath(const uint8_t *ntor_key_seed, size_t seed_len,
return cpath;
}
-/* We are a v2 legacy HS client: Create and return a crypt path for the hidden
+/** We are a v2 legacy HS client: Create and return a crypt path for the hidden
* service on the other side of the rendezvous circuit <b>circ</b>. Initialize
* the crypt path crypto using the body of the RENDEZVOUS1 cell at
* <b>rend_cell_body</b> (which must be at least DH1024_KEY_LEN+DIGEST_LEN
@@ -152,7 +154,7 @@ create_rend_cpath_legacy(origin_circuit_t *circ, const uint8_t *rend_cell_body)
return hop;
}
-/* Append the final <b>hop</b> to the cpath of the rend <b>circ</b>, and mark
+/** Append the final <b>hop</b> to the cpath of the rend <b>circ</b>, and mark
* <b>circ</b> ready for use to transfer HS relay cells. */
static void
finalize_rend_circuit(origin_circuit_t *circ, crypt_path_t *hop,
@@ -193,7 +195,7 @@ finalize_rend_circuit(origin_circuit_t *circ, crypt_path_t *hop,
}
}
-/* For a given circuit and a service introduction point object, register the
+/** For a given circuit and a service introduction point object, register the
* intro circuit to the circuitmap. This supports legacy intro point. */
static void
register_intro_circ(const hs_service_intro_point_t *ip,
@@ -211,7 +213,7 @@ register_intro_circ(const hs_service_intro_point_t *ip,
}
}
-/* Return the number of opened introduction circuit for the given circuit that
+/** Return the number of opened introduction circuit for the given circuit that
* is matching its identity key. */
static unsigned int
count_opened_desc_intro_point_circuits(const hs_service_t *service,
@@ -243,7 +245,7 @@ count_opened_desc_intro_point_circuits(const hs_service_t *service,
return count;
}
-/* From a given service, rendezvous cookie and handshake info, create a
+/** From a given service, rendezvous cookie and handshake info, create a
* rendezvous point circuit identifier. This can't fail. */
STATIC hs_ident_circuit_t *
create_rp_circuit_identifier(const hs_service_t *service,
@@ -282,7 +284,7 @@ create_rp_circuit_identifier(const hs_service_t *service,
return ident;
}
-/* From a given service and service intro point, create an introduction point
+/** From a given service and service intro point, create an introduction point
* circuit identifier. This can't fail. */
static hs_ident_circuit_t *
create_intro_circuit_identifier(const hs_service_t *service,
@@ -299,7 +301,7 @@ create_intro_circuit_identifier(const hs_service_t *service,
return ident;
}
-/* For a given introduction point and an introduction circuit, send the
+/** For a given introduction point and an introduction circuit, send the
* ESTABLISH_INTRO cell. The service object is used for logging. This can fail
* and if so, the circuit is closed and the intro point object is flagged
* that the circuit is not established anymore which is important for the
@@ -349,7 +351,7 @@ send_establish_intro(const hs_service_t *service,
memwipe(payload, 0, sizeof(payload));
}
-/* Return a string constant describing the anonymity of service. */
+/** Return a string constant describing the anonymity of service. */
static const char *
get_service_anonymity_string(const hs_service_t *service)
{
@@ -360,7 +362,7 @@ get_service_anonymity_string(const hs_service_t *service)
}
}
-/* For a given service, the ntor onion key and a rendezvous cookie, launch a
+/** For a given service, the ntor onion key and a rendezvous cookie, launch a
* circuit to the rendezvous point specified by the link specifiers. On
* success, a circuit identifier is attached to the circuit with the needed
* data. This function will try to open a circuit for a maximum value of
@@ -469,7 +471,7 @@ launch_rendezvous_point_circuit(const hs_service_t *service,
extend_info_free(info);
}
-/* Return true iff the given service rendezvous circuit circ is allowed for a
+/** Return true iff the given service rendezvous circuit circ is allowed for a
* relaunch to the rendezvous point. */
static int
can_relaunch_service_rendezvous_point(const origin_circuit_t *circ)
@@ -516,7 +518,7 @@ can_relaunch_service_rendezvous_point(const origin_circuit_t *circ)
return 0;
}
-/* Retry the rendezvous point of circ by launching a new circuit to it. */
+/** Retry the rendezvous point of circ by launching a new circuit to it. */
static void
retry_service_rendezvous_point(const origin_circuit_t *circ)
{
@@ -565,7 +567,7 @@ retry_service_rendezvous_point(const origin_circuit_t *circ)
return;
}
-/* Using the given descriptor intro point ip, the node of the
+/** Using the given descriptor intro point ip, the node of the
* rendezvous point rp_node and the service's subcredential, populate the
* already allocated intro1_data object with the needed key material and link
* specifiers.
@@ -618,11 +620,27 @@ setup_introduce1_data(const hs_desc_intro_point_t *ip,
return ret;
}
+/** Helper: cleanup function for client circuit. This is for every HS version.
+ * It is called from hs_circ_cleanup_on_free() entry point. */
+static void
+cleanup_on_free_client_circ(circuit_t *circ)
+{
+ tor_assert(circ);
+
+ if (circuit_is_hs_v2(circ)) {
+ rend_client_circuit_cleanup_on_free(circ);
+ } else if (circuit_is_hs_v3(circ)) {
+ hs_client_circuit_cleanup_on_free(circ);
+ }
+ /* It is possible the circuit has an HS purpose but no identifier (rend_data
+ * or hs_ident). Thus possible that this passess through. */
+}
+
/* ========== */
/* Public API */
/* ========== */
-/* Return an introduction point circuit matching the given intro point object.
+/** Return an introduction point circuit matching the given intro point object.
* NULL is returned is no such circuit can be found. */
origin_circuit_t *
hs_circ_service_get_intro_circ(const hs_service_intro_point_t *ip)
@@ -637,7 +655,29 @@ hs_circ_service_get_intro_circ(const hs_service_intro_point_t *ip)
}
}
-/* Called when we fail building a rendezvous circuit at some point other than
+/** Return an introduction point established circuit matching the given intro
+ * point object. The circuit purpose has to be CIRCUIT_PURPOSE_S_INTRO. NULL
+ * is returned is no such circuit can be found. */
+origin_circuit_t *
+hs_circ_service_get_established_intro_circ(const hs_service_intro_point_t *ip)
+{
+ origin_circuit_t *circ;
+
+ tor_assert(ip);
+
+ if (ip->base.is_only_legacy) {
+ circ = hs_circuitmap_get_intro_circ_v2_service_side(ip->legacy_key_digest);
+ } else {
+ circ = hs_circuitmap_get_intro_circ_v3_service_side(
+ &ip->auth_key_kp.pubkey);
+ }
+
+ /* Only return circuit if it is established. */
+ return (circ && TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_INTRO) ?
+ circ : NULL;
+}
+
+/** Called when we fail building a rendezvous circuit at some point other than
* the last hop: launches a new circuit to the same rendezvous point. This
* supports legacy service.
*
@@ -677,7 +717,7 @@ hs_circ_retry_service_rendezvous_point(origin_circuit_t *circ)
return;
}
-/* For a given service and a service intro point, launch a circuit to the
+/** For a given service and a service intro point, launch a circuit to the
* extend info ei. If the service is a single onion, and direct_conn is true,
* a one-hop circuit will be requested.
*
@@ -738,7 +778,7 @@ hs_circ_launch_intro_point(hs_service_t *service,
return ret;
}
-/* Called when a service introduction point circuit is done building. Given
+/** Called when a service introduction point circuit is done building. Given
* the service and intro point object, this function will send the
* ESTABLISH_INTRO cell on the circuit. Return 0 on success. Return 1 if the
* circuit has been repurposed to General because we already have too many
@@ -807,7 +847,7 @@ hs_circ_service_intro_has_opened(hs_service_t *service,
return ret;
}
-/* Called when a service rendezvous point circuit is done building. Given the
+/** Called when a service rendezvous point circuit is done building. Given the
* service and the circuit, this function will send a RENDEZVOUS1 cell on the
* circuit using the information in the circuit identifier. If the cell can't
* be sent, the circuit is closed. */
@@ -873,7 +913,7 @@ hs_circ_service_rp_has_opened(const hs_service_t *service,
memwipe(payload, 0, sizeof(payload));
}
-/* Circ has been expecting an INTRO_ESTABLISHED cell that just arrived. Handle
+/** Circ has been expecting an INTRO_ESTABLISHED cell that just arrived. Handle
* the INTRO_ESTABLISHED cell payload of length payload_len arriving on the
* given introduction circuit circ. The service is only used for logging
* purposes. Return 0 on success else a negative value. */
@@ -918,7 +958,7 @@ hs_circ_handle_intro_established(const hs_service_t *service,
return ret;
}
-/* We just received an INTRODUCE2 cell on the established introduction circuit
+/** We just received an INTRODUCE2 cell on the established introduction circuit
* circ. Handle the INTRODUCE2 payload of size payload_len for the given
* circuit and service. This cell is associated with the intro point object ip
* and the subcredential. Return 0 on success else a negative value. */
@@ -985,7 +1025,7 @@ hs_circ_handle_introduce2(const hs_service_t *service,
return ret;
}
-/* Circuit <b>circ</b> just finished the rend ntor key exchange. Use the key
+/** Circuit <b>circ</b> just finished the rend ntor key exchange. Use the key
* exchange output material at <b>ntor_key_seed</b> and setup <b>circ</b> to
* serve as a rendezvous end-to-end circuit between the client and the
* service. If <b>is_service_side</b> is set, then we are the hidden service
@@ -1015,7 +1055,7 @@ hs_circuit_setup_e2e_rend_circ(origin_circuit_t *circ,
return 0;
}
-/* We are a v2 legacy HS client and we just received a RENDEZVOUS1 cell
+/** We are a v2 legacy HS client and we just received a RENDEZVOUS1 cell
* <b>rend_cell_body</b> on <b>circ</b>. Finish up the DH key exchange and then
* extend the crypt path of <b>circ</b> so that the hidden service is on the
* other side. */
@@ -1040,7 +1080,7 @@ hs_circuit_setup_e2e_rend_circ_legacy_client(origin_circuit_t *circ,
return 0;
}
-/* Given the introduction circuit intro_circ, the rendezvous circuit
+/** Given the introduction circuit intro_circ, the rendezvous circuit
* rend_circ, a descriptor intro point object ip and the service's
* subcredential, send an INTRODUCE1 cell on intro_circ.
*
@@ -1125,7 +1165,7 @@ hs_circ_send_introduce1(origin_circuit_t *intro_circ,
return ret;
}
-/* Send an ESTABLISH_RENDEZVOUS cell along the rendezvous circuit circ. On
+/** Send an ESTABLISH_RENDEZVOUS cell along the rendezvous circuit circ. On
* success, 0 is returned else -1 and the circuit is marked for close. */
int
hs_circ_send_establish_rendezvous(origin_circuit_t *circ)
@@ -1176,30 +1216,132 @@ hs_circ_send_establish_rendezvous(origin_circuit_t *circ)
return -1;
}
-/* We are about to close or free this <b>circ</b>. Clean it up from any
- * related HS data structures. This function can be called multiple times
- * safely for the same circuit. */
+/** Circuit cleanup strategy:
+ *
+ * What follows is a series of functions that notifies the HS subsystem of 3
+ * different circuit cleanup phase: close, free and repurpose.
+ *
+ * Tor can call any of those in any orders so they have to be safe between
+ * each other. In other words, the free should never depend on close to be
+ * called before.
+ *
+ * The "on_close()" is called from circuit_mark_for_close() which is
+ * considered the tor fast path and thus as little work as possible should
+ * done in that function. Currently, we only remove the circuit from the HS
+ * circuit map and move on.
+ *
+ * The "on_free()" is called from circuit circuit_free_() and it is very
+ * important that at the end of the function, no state or objects related to
+ * this circuit remains alive.
+ *
+ * The "on_repurpose()" is called from circuit_change_purpose() for which we
+ * simply remove it from the HS circuit map. We do not have other cleanup
+ * requirements after that.
+ *
+ * NOTE: The onion service code, specifically the service code, cleans up
+ * lingering objects or state if any of its circuit disappear which is why
+ * our cleanup strategy doesn't involve any service specific actions. As long
+ * as the circuit is removed from the HS circuit map, it won't be used.
+ */
+
+/** We are about to close this <b>circ</b>. Clean it up from any related HS
+ * data structures. This function can be called multiple times safely for the
+ * same circuit. */
+void
+hs_circ_cleanup_on_close(circuit_t *circ)
+{
+ tor_assert(circ);
+
+ /* On close, we simply remove it from the circuit map. It can not be used
+ * anymore. We keep this code path fast and lean. */
+
+ if (circ->hs_token) {
+ hs_circuitmap_remove_circuit(circ);
+ }
+}
+
+/** We are about to free this <b>circ</b>. Clean it up from any related HS
+ * data structures. This function can be called multiple times safely for the
+ * same circuit. */
void
-hs_circ_cleanup(circuit_t *circ)
+hs_circ_cleanup_on_free(circuit_t *circ)
{
tor_assert(circ);
- /* If it's a service-side intro circ, notify the HS subsystem for the intro
- * point circuit closing so it can be dealt with cleanly. */
- if (circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
- circ->purpose == CIRCUIT_PURPOSE_S_INTRO) {
- hs_service_intro_circ_has_closed(TO_ORIGIN_CIRCUIT(circ));
+ /* NOTE: Bulk of the work of cleaning up a circuit is done here. */
+
+ if (circuit_purpose_is_hs_client(circ->purpose)) {
+ cleanup_on_free_client_circ(circ);
}
- /* Clear HS circuitmap token for this circ (if any). Very important to be
- * done after the HS subsystem has been notified of the close else the
- * circuit will not be found.
- *
- * We do this at the close if possible because from that point on, the
- * circuit is good as dead. We can't rely on removing it in the circuit
- * free() function because we open a race window between the close and free
- * where we can't register a new circuit for the same intro point. */
+ /* We have no assurance that the given HS circuit has been closed before and
+ * thus removed from the HS map. This actually happens in unit tests. */
+ if (circ->hs_token) {
+ hs_circuitmap_remove_circuit(circ);
+ }
+}
+
+/** We are about to repurpose this <b>circ</b>. Clean it up from any related
+ * HS data structures. This function can be called multiple times safely for
+ * the same circuit. */
+void
+hs_circ_cleanup_on_repurpose(circuit_t *circ)
+{
+ tor_assert(circ);
+
+ /* On repurpose, we simply remove it from the circuit map but we do not do
+ * the on_free actions since we don't treat a repurpose as something we need
+ * to report in the client cache failure. */
+
if (circ->hs_token) {
hs_circuitmap_remove_circuit(circ);
}
}
+
+/** Return true iff the given established client rendezvous circuit was sent
+ * into the INTRODUCE1 cell. This is called so we can take a decision on
+ * expiring or not the circuit.
+ *
+ * The caller MUST make sure the circuit is an established client rendezvous
+ * circuit (purpose: CIRCUIT_PURPOSE_C_REND_READY).
+ *
+ * This function supports all onion service versions. */
+bool
+hs_circ_is_rend_sent_in_intro1(const origin_circuit_t *circ)
+{
+ tor_assert(circ);
+ /* This can only be called for a rendezvous circuit that is an established
+ * confirmed rendezsvous circuit but without an introduction ACK. */
+ tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_C_REND_READY);
+
+ /* The v2 and v3 circuit are handled differently:
+ *
+ * v2: A circ's pending_final_cpath field is non-NULL iff it is a rend circ
+ * and we have tried to send an INTRODUCE1 cell specifying it. Thus, if the
+ * pending_final_cpath field *is* NULL, then we want to not spare it.
+ *
+ * v3: When the INTRODUCE1 cell is sent, the introduction encryption public
+ * key is copied in the rendezvous circuit hs identifier. If it is a valid
+ * key, we know that this circuit is waiting the ACK on the introduction
+ * circuit. We want to _not_ spare the circuit if the key was never set. */
+
+ if (circ->rend_data) {
+ /* v2. */
+ if (circ->build_state && circ->build_state->pending_final_cpath != NULL) {
+ return true;
+ }
+ } else if (circ->hs_ident) {
+ /* v3. */
+ if (curve25519_public_key_is_ok(&circ->hs_ident->intro_enc_pk)) {
+ return true;
+ }
+ } else {
+ /* A circuit with an HS purpose without an hs_ident or rend_data in theory
+ * can not happen. In case, scream loudly and return false to the caller
+ * that the rendezvous was not sent in the INTRO1 cell. */
+ tor_assert_nonfatal_unreached();
+ }
+
+ /* The rendezvous has not been specified in the INTRODUCE1 cell. */
+ return false;
+}
diff --git a/src/feature/hs/hs_circuit.h b/src/feature/hs/hs_circuit.h
index e168b301f1..92231369c6 100644
--- a/src/feature/hs/hs_circuit.h
+++ b/src/feature/hs/hs_circuit.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,8 +14,10 @@
#include "feature/hs/hs_service.h"
-/* Cleanup function when the circuit is closed or/and freed. */
-void hs_circ_cleanup(circuit_t *circ);
+/* Cleanup function when the circuit is closed or freed. */
+void hs_circ_cleanup_on_close(circuit_t *circ);
+void hs_circ_cleanup_on_free(circuit_t *circ);
+void hs_circ_cleanup_on_repurpose(circuit_t *circ);
/* Circuit API. */
int hs_circ_service_intro_has_opened(hs_service_t *service,
@@ -35,6 +37,8 @@ void hs_circ_retry_service_rendezvous_point(origin_circuit_t *circ);
origin_circuit_t *hs_circ_service_get_intro_circ(
const hs_service_intro_point_t *ip);
+origin_circuit_t *hs_circ_service_get_established_intro_circ(
+ const hs_service_intro_point_t *ip);
/* Cell API. */
int hs_circ_handle_intro_established(const hs_service_t *service,
@@ -62,15 +66,18 @@ int hs_circuit_setup_e2e_rend_circ(origin_circuit_t *circ,
int hs_circuit_setup_e2e_rend_circ_legacy_client(origin_circuit_t *circ,
const uint8_t *rend_cell_body);
+bool hs_circ_is_rend_sent_in_intro1(const origin_circuit_t *circ);
+
#ifdef HS_CIRCUIT_PRIVATE
+struct hs_ntor_rend_cell_keys_t;
+
STATIC hs_ident_circuit_t *
create_rp_circuit_identifier(const hs_service_t *service,
const uint8_t *rendezvous_cookie,
const curve25519_public_key_t *server_pk,
- const hs_ntor_rend_cell_keys_t *keys);
+ const struct hs_ntor_rend_cell_keys_t *keys);
#endif /* defined(HS_CIRCUIT_PRIVATE) */
#endif /* !defined(TOR_HS_CIRCUIT_H) */
-
diff --git a/src/feature/hs/hs_circuitmap.c b/src/feature/hs/hs_circuitmap.c
index e34f564fb4..2343d729dd 100644
--- a/src/feature/hs/hs_circuitmap.c
+++ b/src/feature/hs/hs_circuitmap.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -23,13 +23,13 @@
/************************** HS circuitmap code *******************************/
-/* This is the hidden service circuitmap. It's a hash table that maps
+/** This is the hidden service circuitmap. It's a hash table that maps
introduction and rendezvous tokens to specific circuits such that given a
token it's easy to find the corresponding circuit. */
static struct hs_circuitmap_ht *the_hs_circuitmap = NULL;
-/* This is a helper function used by the hash table code (HT_). It returns 1 if
- * two circuits have the same HS token. */
+/** This is a helper function used by the hash table code (HT_). It returns 1
+ * if two circuits have the same HS token. */
static int
hs_circuits_have_same_token(const circuit_t *first_circuit,
const circuit_t *second_circuit)
@@ -60,8 +60,9 @@ hs_circuits_have_same_token(const circuit_t *first_circuit,
first_token->token_len);
}
-/* This is a helper function for the hash table code (HT_). It hashes a circuit
- * HS token into an unsigned int for use as a key by the hash table routines.*/
+/** This is a helper function for the hash table code (HT_). It hashes a
+ * circuit HS token into an unsigned int for use as a key by the hash table
+ * routines.*/
static inline unsigned int
hs_circuit_hash_token(const circuit_t *circuit)
{
@@ -71,7 +72,7 @@ hs_circuit_hash_token(const circuit_t *circuit)
circuit->hs_token->token_len);
}
-/* Register the circuitmap hash table */
+/** Register the circuitmap hash table */
HT_PROTOTYPE(hs_circuitmap_ht, // The name of the hashtable struct
circuit_t, // The name of the element struct,
hs_circuitmap_node, // The name of HT_ENTRY member
@@ -83,7 +84,7 @@ HT_GENERATE2(hs_circuitmap_ht, circuit_t, hs_circuitmap_node,
#ifdef TOR_UNIT_TESTS
-/* Return the global HS circuitmap. Used by unittests. */
+/** Return the global HS circuitmap. Used by unittests. */
hs_circuitmap_ht *
get_hs_circuitmap(void)
{
@@ -136,7 +137,7 @@ get_circuit_with_token(hs_token_t *search_token)
return HT_FIND(hs_circuitmap_ht, the_hs_circuitmap, &search_circ);
}
-/* Helper function that registers <b>circ</b> with <b>token</b> on the HS
+/** Helper function that registers <b>circ</b> with <b>token</b> on the HS
circuitmap. This function steals reference of <b>token</b>. */
static void
hs_circuitmap_register_impl(circuit_t *circ, hs_token_t *token)
@@ -186,7 +187,7 @@ hs_circuitmap_register_circuit(circuit_t *circ,
hs_circuitmap_register_impl(circ, hs_token);
}
-/* Helper function for hs_circuitmap_get_origin_circuit() and
+/** Helper function for hs_circuitmap_get_origin_circuit() and
* hs_circuitmap_get_or_circuit(). Because only circuit_t are indexed in the
* circuitmap, this function returns object type so the specialized functions
* using this helper can upcast it to the right type.
@@ -220,7 +221,7 @@ hs_circuitmap_get_circuit_impl(hs_token_type_t type,
return found_circ;
}
-/* Helper function: Query circuitmap for origin circuit with <b>token</b> of
+/** Helper function: Query circuitmap for origin circuit with <b>token</b> of
* size <b>token_len</b> and <b>type</b>. Only returns a circuit with purpose
* equal to the <b>wanted_circ_purpose</b> parameter and if it is NOT marked
* for close. Return NULL if no such circuit is found. */
@@ -244,7 +245,7 @@ hs_circuitmap_get_origin_circuit(hs_token_type_t type,
return TO_ORIGIN_CIRCUIT(circ);
}
-/* Helper function: Query circuitmap for OR circuit with <b>token</b> of size
+/** Helper function: Query circuitmap for OR circuit with <b>token</b> of size
* <b>token_len</b> and <b>type</b>. Only returns a circuit with purpose equal
* to the <b>wanted_circ_purpose</b> parameter and if it is NOT marked for
* close. Return NULL if no such circuit is found. */
@@ -272,7 +273,7 @@ hs_circuitmap_get_or_circuit(hs_token_type_t type,
/**** Public relay-side getters: */
-/* Public function: Return v2 and v3 introduction circuit to this relay.
+/** Public function: Return v2 and v3 introduction circuit to this relay.
* Always return a newly allocated list for which it is the caller's
* responsability to free it. */
smartlist_t *
@@ -299,7 +300,7 @@ hs_circuitmap_get_all_intro_circ_relay_side(void)
return circuit_list;
}
-/* Public function: Return a v3 introduction circuit to this relay with
+/** Public function: Return a v3 introduction circuit to this relay with
* <b>auth_key</b>. Return NULL if no such circuit is found in the
* circuitmap. */
or_circuit_t *
@@ -311,7 +312,7 @@ hs_circuitmap_get_intro_circ_v3_relay_side(
CIRCUIT_PURPOSE_INTRO_POINT);
}
-/* Public function: Return v2 introduction circuit to this relay with
+/** Public function: Return v2 introduction circuit to this relay with
* <b>digest</b>. Return NULL if no such circuit is found in the circuitmap. */
or_circuit_t *
hs_circuitmap_get_intro_circ_v2_relay_side(const uint8_t *digest)
@@ -321,7 +322,7 @@ hs_circuitmap_get_intro_circ_v2_relay_side(const uint8_t *digest)
CIRCUIT_PURPOSE_INTRO_POINT);
}
-/* Public function: Return rendezvous circuit to this relay with rendezvous
+/** Public function: Return rendezvous circuit to this relay with rendezvous
* <b>cookie</b>. Return NULL if no such circuit is found in the circuitmap. */
or_circuit_t *
hs_circuitmap_get_rend_circ_relay_side(const uint8_t *cookie)
@@ -333,7 +334,7 @@ hs_circuitmap_get_rend_circ_relay_side(const uint8_t *cookie)
/** Public relay-side setters: */
-/* Public function: Register rendezvous circuit with key <b>cookie</b> to the
+/** Public function: Register rendezvous circuit with key <b>cookie</b> to the
* circuitmap. */
void
hs_circuitmap_register_rend_circ_relay_side(or_circuit_t *circ,
@@ -343,7 +344,7 @@ hs_circuitmap_register_rend_circ_relay_side(or_circuit_t *circ,
HS_TOKEN_REND_RELAY_SIDE,
REND_TOKEN_LEN, cookie);
}
-/* Public function: Register v2 intro circuit with key <b>digest</b> to the
+/** Public function: Register v2 intro circuit with key <b>digest</b> to the
* circuitmap. */
void
hs_circuitmap_register_intro_circ_v2_relay_side(or_circuit_t *circ,
@@ -354,7 +355,7 @@ hs_circuitmap_register_intro_circ_v2_relay_side(or_circuit_t *circ,
REND_TOKEN_LEN, digest);
}
-/* Public function: Register v3 intro circuit with key <b>auth_key</b> to the
+/** Public function: Register v3 intro circuit with key <b>auth_key</b> to the
* circuitmap. */
void
hs_circuitmap_register_intro_circ_v3_relay_side(or_circuit_t *circ,
@@ -367,7 +368,7 @@ hs_circuitmap_register_intro_circ_v3_relay_side(or_circuit_t *circ,
/**** Public servide-side getters: */
-/* Public function: Return v3 introduction circuit with <b>auth_key</b>
+/** Public function: Return v3 introduction circuit with <b>auth_key</b>
* originating from this hidden service. Return NULL if no such circuit is
* found in the circuitmap. */
origin_circuit_t *
@@ -392,9 +393,9 @@ hs_circuitmap_get_intro_circ_v3_service_side(const
return circ;
}
-/* Public function: Return v2 introduction circuit originating from this hidden
- * service with <b>digest</b>. Return NULL if no such circuit is found in the
- * circuitmap. */
+/** Public function: Return v2 introduction circuit originating from this
+ * hidden service with <b>digest</b>. Return NULL if no such circuit is found
+ * in the circuitmap. */
origin_circuit_t *
hs_circuitmap_get_intro_circ_v2_service_side(const uint8_t *digest)
{
@@ -416,7 +417,7 @@ hs_circuitmap_get_intro_circ_v2_service_side(const uint8_t *digest)
return circ;
}
-/* Public function: Return rendezvous circuit originating from this hidden
+/** Public function: Return rendezvous circuit originating from this hidden
* service with rendezvous <b>cookie</b>. Return NULL if no such circuit is
* found in the circuitmap. */
origin_circuit_t *
@@ -439,7 +440,7 @@ hs_circuitmap_get_rend_circ_service_side(const uint8_t *cookie)
return circ;
}
-/* Public function: Return client-side rendezvous circuit with rendezvous
+/** Public function: Return client-side rendezvous circuit with rendezvous
* <b>cookie</b>. It will look for circuits with the following purposes:
* a) CIRCUIT_PURPOSE_C_REND_READY: Established rend circuit (received
@@ -472,7 +473,7 @@ hs_circuitmap_get_rend_circ_client_side(const uint8_t *cookie)
return circ;
}
-/* Public function: Return client-side established rendezvous circuit with
+/** Public function: Return client-side established rendezvous circuit with
* rendezvous <b>cookie</b>. It will look for circuits with the following
* purposes:
*
@@ -514,7 +515,7 @@ hs_circuitmap_get_established_rend_circ_client_side(const uint8_t *cookie)
/**** Public servide-side setters: */
-/* Public function: Register v2 intro circuit with key <b>digest</b> to the
+/** Public function: Register v2 intro circuit with key <b>digest</b> to the
* circuitmap. */
void
hs_circuitmap_register_intro_circ_v2_service_side(origin_circuit_t *circ,
@@ -525,7 +526,7 @@ hs_circuitmap_register_intro_circ_v2_service_side(origin_circuit_t *circ,
REND_TOKEN_LEN, digest);
}
-/* Public function: Register v3 intro circuit with key <b>auth_key</b> to the
+/** Public function: Register v3 intro circuit with key <b>auth_key</b> to the
* circuitmap. */
void
hs_circuitmap_register_intro_circ_v3_service_side(origin_circuit_t *circ,
@@ -536,7 +537,7 @@ hs_circuitmap_register_intro_circ_v3_service_side(origin_circuit_t *circ,
ED25519_PUBKEY_LEN, auth_key->pubkey);
}
-/* Public function: Register rendezvous circuit with key <b>cookie</b> to the
+/** Public function: Register rendezvous circuit with key <b>cookie</b> to the
* circuitmap. */
void
hs_circuitmap_register_rend_circ_service_side(origin_circuit_t *circ,
@@ -547,7 +548,7 @@ hs_circuitmap_register_rend_circ_service_side(origin_circuit_t *circ,
REND_TOKEN_LEN, cookie);
}
-/* Public function: Register rendezvous circuit with key <b>cookie</b> to the
+/** Public function: Register rendezvous circuit with key <b>cookie</b> to the
* client-side circuitmap. */
void
hs_circuitmap_register_rend_circ_client_side(origin_circuit_t *or_circ,
@@ -591,7 +592,7 @@ hs_circuitmap_remove_circuit(circuit_t *circ)
circ->hs_token = NULL;
}
-/* Public function: Initialize the global HS circuitmap. */
+/** Public function: Initialize the global HS circuitmap. */
void
hs_circuitmap_init(void)
{
@@ -601,7 +602,7 @@ hs_circuitmap_init(void)
HT_INIT(hs_circuitmap_ht, the_hs_circuitmap);
}
-/* Public function: Free all memory allocated by the global HS circuitmap. */
+/** Public function: Free all memory allocated by the global HS circuitmap. */
void
hs_circuitmap_free_all(void)
{
diff --git a/src/feature/hs/hs_circuitmap.h b/src/feature/hs/hs_circuitmap.h
index eac8230bbf..df3e7a6e7e 100644
--- a/src/feature/hs/hs_circuitmap.h
+++ b/src/feature/hs/hs_circuitmap.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,6 +14,7 @@ typedef HT_HEAD(hs_circuitmap_ht, circuit_t) hs_circuitmap_ht;
typedef struct hs_token_t hs_token_t;
struct or_circuit_t;
struct origin_circuit_t;
+struct ed25519_public_key_t;
/** Public HS circuitmap API: */
@@ -21,7 +22,7 @@ struct origin_circuit_t;
struct or_circuit_t *
hs_circuitmap_get_intro_circ_v3_relay_side(const
- ed25519_public_key_t *auth_key);
+ struct ed25519_public_key_t *auth_key);
struct or_circuit_t *
hs_circuitmap_get_intro_circ_v2_relay_side(const uint8_t *digest);
struct or_circuit_t *
@@ -32,7 +33,7 @@ void hs_circuitmap_register_rend_circ_relay_side(struct or_circuit_t *circ,
void hs_circuitmap_register_intro_circ_v2_relay_side(struct or_circuit_t *circ,
const uint8_t *digest);
void hs_circuitmap_register_intro_circ_v3_relay_side(struct or_circuit_t *circ,
- const ed25519_public_key_t *auth_key);
+ const struct ed25519_public_key_t *auth_key);
smartlist_t *hs_circuitmap_get_all_intro_circ_relay_side(void);
@@ -40,7 +41,7 @@ smartlist_t *hs_circuitmap_get_all_intro_circ_relay_side(void);
struct origin_circuit_t *
hs_circuitmap_get_intro_circ_v3_service_side(const
- ed25519_public_key_t *auth_key);
+ struct ed25519_public_key_t *auth_key);
struct origin_circuit_t *
hs_circuitmap_get_intro_circ_v2_service_side(const uint8_t *digest);
struct origin_circuit_t *
@@ -54,8 +55,8 @@ void hs_circuitmap_register_intro_circ_v2_service_side(
struct origin_circuit_t *circ,
const uint8_t *digest);
void hs_circuitmap_register_intro_circ_v3_service_side(
- struct origin_circuit_t *circ,
- const ed25519_public_key_t *auth_key);
+ struct origin_circuit_t *circ,
+ const struct ed25519_public_key_t *auth_key);
void hs_circuitmap_register_rend_circ_service_side(
struct origin_circuit_t *circ,
const uint8_t *cookie);
diff --git a/src/feature/hs/hs_client.c b/src/feature/hs/hs_client.c
index 8b63375939..68d6619cea 100644
--- a/src/feature/hs/hs_client.c
+++ b/src/feature/hs/hs_client.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -42,14 +42,15 @@
#include "core/or/entry_connection_st.h"
#include "core/or/extend_info_st.h"
#include "core/or/origin_circuit_st.h"
+#include "core/or/socks_request_st.h"
-/* Client-side authorizations for hidden services; map of service identity
+/** Client-side authorizations for hidden services; map of service identity
* public key to hs_client_service_authorization_t *. */
static digest256map_t *client_auths = NULL;
#include "trunnel/hs/cell_introduce1.h"
-/* Return a human-readable string for the client fetch status code. */
+/** Return a human-readable string for the client fetch status code. */
static const char *
fetch_status_to_string(hs_client_fetch_status_t status)
{
@@ -73,7 +74,7 @@ fetch_status_to_string(hs_client_fetch_status_t status)
}
}
-/* Return true iff tor should close the SOCKS request(s) for the descriptor
+/** Return true iff tor should close the SOCKS request(s) for the descriptor
* fetch that ended up with this given status code. */
static int
fetch_status_should_close_socks(hs_client_fetch_status_t status)
@@ -100,12 +101,51 @@ fetch_status_should_close_socks(hs_client_fetch_status_t status)
return 1;
}
+/* Return a newly allocated list of all the entry connections that matches the
+ * given service identity pk. If service_identity_pk is NULL, all entry
+ * connections with an hs_ident are returned.
+ *
+ * Caller must free the returned list but does NOT have ownership of the
+ * object inside thus they have to remain untouched. */
+static smartlist_t *
+find_entry_conns(const ed25519_public_key_t *service_identity_pk)
+{
+ time_t now = time(NULL);
+ smartlist_t *conns = NULL, *entry_conns = NULL;
+
+ entry_conns = smartlist_new();
+
+ conns = connection_list_by_type_state(CONN_TYPE_AP,
+ AP_CONN_STATE_RENDDESC_WAIT);
+ SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) {
+ entry_connection_t *entry_conn = TO_ENTRY_CONN(base_conn);
+ const edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(entry_conn);
+
+ /* Only consider the entry connections that matches the service for which
+ * we just fetched its descriptor. */
+ if (!edge_conn->hs_ident ||
+ (service_identity_pk &&
+ !ed25519_pubkey_eq(service_identity_pk,
+ &edge_conn->hs_ident->identity_pk))) {
+ continue;
+ }
+ assert_connection_ok(base_conn, now);
+
+ /* Validated! Add the entry connection to the list. */
+ smartlist_add(entry_conns, entry_conn);
+ } SMARTLIST_FOREACH_END(base_conn);
+
+ /* We don't have ownership of the objects in this list. */
+ smartlist_free(conns);
+ return entry_conns;
+}
+
/* Cancel all descriptor fetches currently in progress. */
static void
cancel_descriptor_fetches(void)
{
smartlist_t *conns =
- connection_list_by_type_state(CONN_TYPE_DIR, DIR_PURPOSE_FETCH_HSDESC);
+ connection_list_by_type_purpose(CONN_TYPE_DIR, DIR_PURPOSE_FETCH_HSDESC);
SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
const hs_ident_dir_conn_t *ident = TO_DIR_CONN(conn)->hs_ident;
if (BUG(ident == NULL)) {
@@ -124,7 +164,7 @@ cancel_descriptor_fetches(void)
log_info(LD_REND, "Hidden service client descriptor fetches cancelled.");
}
-/* Get all connections that are waiting on a circuit and flag them back to
+/** Get all connections that are waiting on a circuit and flag them back to
* waiting for a hidden service descriptor for the given service key
* service_identity_pk. */
static void
@@ -151,7 +191,7 @@ flag_all_conn_wait_desc(const ed25519_public_key_t *service_identity_pk)
smartlist_free(conns);
}
-/* Remove tracked HSDir requests from our history for this hidden service
+/** Remove tracked HSDir requests from our history for this hidden service
* identity public key. */
static void
purge_hid_serv_request(const ed25519_public_key_t *identity_pk)
@@ -172,7 +212,7 @@ purge_hid_serv_request(const ed25519_public_key_t *identity_pk)
hs_purge_hid_serv_from_last_hid_serv_requests(base64_blinded_pk);
}
-/* Return true iff there is at least one pending directory descriptor request
+/** Return true iff there is at least one pending directory descriptor request
* for the service identity_pk. */
static int
directory_request_is_pending(const ed25519_public_key_t *identity_pk)
@@ -200,7 +240,7 @@ directory_request_is_pending(const ed25519_public_key_t *identity_pk)
return ret;
}
-/* Helper function that changes the state of an entry connection to waiting
+/** Helper function that changes the state of an entry connection to waiting
* for a circuit. For this to work properly, the connection timestamps are set
* to now and the connection is then marked as pending for a circuit. */
static void
@@ -220,7 +260,7 @@ mark_conn_as_waiting_for_circuit(connection_t *conn, time_t now)
connection_ap_mark_as_pending_circuit(TO_ENTRY_CONN(conn));
}
-/* We failed to fetch a descriptor for the service with <b>identity_pk</b>
+/** We failed to fetch a descriptor for the service with <b>identity_pk</b>
* because of <b>status</b>. Find all pending SOCKS connections for this
* service that are waiting on the descriptor and close them with
* <b>reason</b>. */
@@ -230,26 +270,13 @@ close_all_socks_conns_waiting_for_desc(const ed25519_public_key_t *identity_pk,
int reason)
{
unsigned int count = 0;
- time_t now = approx_time();
- smartlist_t *conns =
- connection_list_by_type_state(CONN_TYPE_AP, AP_CONN_STATE_RENDDESC_WAIT);
+ smartlist_t *entry_conns = find_entry_conns(identity_pk);
- SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) {
- entry_connection_t *entry_conn = TO_ENTRY_CONN(base_conn);
- const edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(entry_conn);
-
- /* Only consider the entry connections that matches the service for which
- * we tried to get the descriptor */
- if (!edge_conn->hs_ident ||
- !ed25519_pubkey_eq(identity_pk,
- &edge_conn->hs_ident->identity_pk)) {
- continue;
- }
- assert_connection_ok(base_conn, now);
+ SMARTLIST_FOREACH_BEGIN(entry_conns, entry_connection_t *, entry_conn) {
/* Unattach the entry connection which will close for the reason. */
connection_mark_unattached_ap(entry_conn, reason);
count++;
- } SMARTLIST_FOREACH_END(base_conn);
+ } SMARTLIST_FOREACH_END(entry_conn);
if (count > 0) {
char onion_address[HS_SERVICE_ADDR_LEN_BASE32 + 1];
@@ -262,26 +289,26 @@ close_all_socks_conns_waiting_for_desc(const ed25519_public_key_t *identity_pk,
}
/* No ownership of the object(s) in this list. */
- smartlist_free(conns);
+ smartlist_free(entry_conns);
}
-/* Find all pending SOCKS connection waiting for a descriptor and retry them
+/** Find all pending SOCKS connection waiting for a descriptor and retry them
* all. This is called when the directory information changed. */
STATIC void
retry_all_socks_conn_waiting_for_desc(void)
{
- smartlist_t *conns =
- connection_list_by_type_state(CONN_TYPE_AP, AP_CONN_STATE_RENDDESC_WAIT);
+ smartlist_t *entry_conns = find_entry_conns(NULL);
- SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) {
+ SMARTLIST_FOREACH_BEGIN(entry_conns, entry_connection_t *, entry_conn) {
hs_client_fetch_status_t status;
- const edge_connection_t *edge_conn =
- ENTRY_TO_EDGE_CONN(TO_ENTRY_CONN(base_conn));
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(entry_conn);
+ connection_t *base_conn = &edge_conn->base_;
/* Ignore non HS or non v3 connection. */
if (edge_conn->hs_ident == NULL) {
continue;
}
+
/* In this loop, we will possibly try to fetch a descriptor for the
* pending connections because we just got more directory information.
* However, the refetch process can cleanup all SOCKS request to the same
@@ -315,13 +342,13 @@ retry_all_socks_conn_waiting_for_desc(void)
* closed or we are still missing directory information. Leave the
* connection in renddesc wait state so when we get more info, we'll be
* able to try it again. */
- } SMARTLIST_FOREACH_END(base_conn);
+ } SMARTLIST_FOREACH_END(entry_conn);
/* We don't have ownership of those objects. */
- smartlist_free(conns);
+ smartlist_free(entry_conns);
}
-/* A v3 HS circuit successfully connected to the hidden service. Update the
+/** A v3 HS circuit successfully connected to the hidden service. Update the
* stream state at <b>hs_conn_ident</b> appropriately. */
static void
note_connection_attempt_succeeded(const hs_ident_edge_conn_t *hs_conn_ident)
@@ -343,7 +370,7 @@ note_connection_attempt_succeeded(const hs_ident_edge_conn_t *hs_conn_ident)
* will be reset and thus possible to be retried. */
}
-/* Given the pubkey of a hidden service in <b>onion_identity_pk</b>, fetch its
+/** Given the pubkey of a hidden service in <b>onion_identity_pk</b>, fetch its
* descriptor by launching a dir connection to <b>hsdir</b>. Return a
* hs_client_fetch_status_t status code depending on how it went. */
static hs_client_fetch_status_t
@@ -451,7 +478,7 @@ fetch_v3_desc, (const ed25519_public_key_t *onion_identity_pk))
return directory_launch_v3_desc_fetch(onion_identity_pk, hsdir_rs);
}
-/* With a given <b>onion_identity_pk</b>, fetch its descriptor. If
+/** With a given <b>onion_identity_pk</b>, fetch its descriptor. If
* <b>hsdirs</b> is specified, use the directory servers specified in the list.
* Else, use a random server. */
void
@@ -469,7 +496,7 @@ hs_client_launch_v3_desc_fetch(const ed25519_public_key_t *onion_identity_pk,
}
}
-/* Make sure that the given v3 origin circuit circ is a valid correct
+/** Make sure that the given v3 origin circuit circ is a valid correct
* introduction circuit. This will BUG() on any problems and hard assert if
* the anonymity of the circuit is not ok. Return 0 on success else -1 where
* the circuit should be mark for closed immediately. */
@@ -498,7 +525,7 @@ intro_circ_is_ok(const origin_circuit_t *circ)
return ret;
}
-/* Find a descriptor intro point object that matches the given ident in the
+/** Find a descriptor intro point object that matches the given ident in the
* given descriptor desc. Return NULL if not found. */
static const hs_desc_intro_point_t *
find_desc_intro_point_by_ident(const hs_ident_circuit_t *ident,
@@ -521,7 +548,7 @@ find_desc_intro_point_by_ident(const hs_ident_circuit_t *ident,
return intro_point;
}
-/* Find a descriptor intro point object from the descriptor object desc that
+/** Find a descriptor intro point object from the descriptor object desc that
* matches the given legacy identity digest in legacy_id. Return NULL if not
* found. */
static hs_desc_intro_point_t *
@@ -559,7 +586,7 @@ find_desc_intro_point_by_legacy_id(const char *legacy_id,
return ret_ip;
}
-/* Send an INTRODUCE1 cell along the intro circuit and populate the rend
+/** Send an INTRODUCE1 cell along the intro circuit and populate the rend
* circuit identifier with the needed key material for the e2e encryption.
* Return 0 on success, -1 if there is a transient error such that an action
* has been taken to recover and -2 if there is a permanent error indicating
@@ -676,7 +703,7 @@ send_introduce1(origin_circuit_t *intro_circ,
return status;
}
-/* Using the introduction circuit circ, setup the authentication key of the
+/** Using the introduction circuit circ, setup the authentication key of the
* intro point this circuit has extended to. */
static void
setup_intro_circ_auth_key(origin_circuit_t *circ)
@@ -715,7 +742,7 @@ setup_intro_circ_auth_key(origin_circuit_t *circ)
return;
}
-/* Called when an introduction circuit has opened. */
+/** Called when an introduction circuit has opened. */
static void
client_intro_circ_has_opened(origin_circuit_t *circ)
{
@@ -732,7 +759,7 @@ client_intro_circ_has_opened(origin_circuit_t *circ)
connection_ap_attach_pending(1);
}
-/* Called when a rendezvous circuit has opened. */
+/** Called when a rendezvous circuit has opened. */
static void
client_rendezvous_circ_has_opened(origin_circuit_t *circ)
{
@@ -766,7 +793,7 @@ client_rendezvous_circ_has_opened(origin_circuit_t *circ)
}
}
-/* This is an helper function that convert a descriptor intro point object ip
+/** This is an helper function that convert a descriptor intro point object ip
* to a newly allocated extend_info_t object fully initialized. Return NULL if
* we can't convert it for which chances are that we are missing or malformed
* link specifiers. */
@@ -784,7 +811,7 @@ desc_intro_point_to_extend_info(const hs_desc_intro_point_t *ip)
return ei;
}
-/* Return true iff the intro point ip for the service service_pk is usable.
+/** Return true iff the intro point ip for the service service_pk is usable.
* This function checks if the intro point is in the client intro state cache
* and checks at the failures. It is considered usable if:
* - No error happened (INTRO_POINT_FAILURE_GENERIC)
@@ -829,7 +856,7 @@ intro_point_is_usable(const ed25519_public_key_t *service_pk,
return 0;
}
-/* Using a descriptor desc, return a newly allocated extend_info_t object of a
+/** Using a descriptor desc, return a newly allocated extend_info_t object of a
* randomly picked introduction point from its list. Return NULL if none are
* usable. */
STATIC extend_info_t *
@@ -934,7 +961,7 @@ client_get_random_intro(const ed25519_public_key_t *service_pk)
return ei;
}
-/* For this introduction circuit, we'll look at if we have any usable
+/** For this introduction circuit, we'll look at if we have any usable
* introduction point left for this service. If so, we'll use the circuit to
* re-extend to a new intro point. Else, we'll close the circuit and its
* corresponding rendezvous circuit. Return 0 if we are re-extending else -1
@@ -991,7 +1018,7 @@ close_or_reextend_intro_circ(origin_circuit_t *intro_circ)
return ret;
}
-/* Called when we get an INTRODUCE_ACK success status code. Do the appropriate
+/** Called when we get an INTRODUCE_ACK success status code. Do the appropriate
* actions for the rendezvous point and finally close intro_circ. */
static void
handle_introduce_ack_success(origin_circuit_t *intro_circ)
@@ -1037,7 +1064,7 @@ handle_introduce_ack_success(origin_circuit_t *intro_circ)
return;
}
-/* Called when we get an INTRODUCE_ACK failure status code. Depending on our
+/** Called when we get an INTRODUCE_ACK failure status code. Depending on our
* failure cache status, either close the circuit or re-extend to a new
* introduction point. */
static void
@@ -1059,7 +1086,7 @@ handle_introduce_ack_bad(origin_circuit_t *circ, int status)
INTRO_POINT_FAILURE_GENERIC);
}
-/* Called when we get an INTRODUCE_ACK on the intro circuit circ. The encoded
+/** Called when we get an INTRODUCE_ACK on the intro circuit circ. The encoded
* cell is in payload of length payload_len. Return 0 on success else a
* negative value. The circuit is either close or reuse to re-extend to a new
* introduction point. */
@@ -1098,7 +1125,7 @@ handle_introduce_ack(origin_circuit_t *circ, const uint8_t *payload,
return ret;
}
-/* Called when we get a RENDEZVOUS2 cell on the rendezvous circuit circ. The
+/** Called when we get a RENDEZVOUS2 cell on the rendezvous circuit circ. The
* encoded cell is in payload of length payload_len. Return 0 on success or a
* negative value on error. On error, the circuit is marked for close. */
STATIC int
@@ -1160,7 +1187,7 @@ handle_rendezvous2(origin_circuit_t *circ, const uint8_t *payload,
return ret;
}
-/* Return true iff the client can fetch a descriptor for this service public
+/** Return true iff the client can fetch a descriptor for this service public
* identity key and status_out if not NULL is untouched. If the client can
* _not_ fetch the descriptor and if status_out is not NULL, it is set with
* the fetch status code. */
@@ -1227,7 +1254,27 @@ can_client_refetch_desc(const ed25519_public_key_t *identity_pk,
return 0;
}
-/* Return the client auth in the map using the service identity public key.
+/** Purge the client authorization cache of all ephemeral entries that is the
+ * entries that are not flagged with CLIENT_AUTH_FLAG_IS_PERMANENT.
+ *
+ * This is called from the hs_client_purge_state() used by a SIGNEWNYM. */
+STATIC void
+purge_ephemeral_client_auth(void)
+{
+ DIGEST256MAP_FOREACH_MODIFY(client_auths, key,
+ hs_client_service_authorization_t *, auth) {
+ /* Cleanup every entry that are _NOT_ permanent that is ephemeral. */
+ if (!(auth->flags & CLIENT_AUTH_FLAG_IS_PERMANENT)) {
+ MAP_DEL_CURRENT(key);
+ client_service_authorization_free(auth);
+ }
+ } DIGESTMAP_FOREACH_END;
+
+ log_info(LD_REND, "Client onion service ephemeral authorization "
+ "cache has been purged.");
+}
+
+/** Return the client auth in the map using the service identity public key.
* Return NULL if it does not exist in the map. */
static hs_client_service_authorization_t *
find_client_auth(const ed25519_public_key_t *service_identity_pk)
@@ -1240,10 +1287,530 @@ find_client_auth(const ed25519_public_key_t *service_identity_pk)
return digest256map_get(client_auths, service_identity_pk->pubkey);
}
+/** This is called when a descriptor has arrived following a fetch request and
+ * has been stored in the client cache. The given entry connections, matching
+ * the service identity key, will get attached to the service circuit. */
+static void
+client_desc_has_arrived(const smartlist_t *entry_conns)
+{
+ time_t now = time(NULL);
+
+ tor_assert(entry_conns);
+
+ SMARTLIST_FOREACH_BEGIN(entry_conns, entry_connection_t *, entry_conn) {
+ const hs_descriptor_t *desc;
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(entry_conn);
+ const ed25519_public_key_t *identity_pk =
+ &edge_conn->hs_ident->identity_pk;
+
+ /* We were just called because we stored the descriptor for this service
+ * so not finding a descriptor means we have a bigger problem. */
+ desc = hs_cache_lookup_as_client(identity_pk);
+ if (BUG(desc == NULL)) {
+ goto end;
+ }
+
+ if (!hs_client_any_intro_points_usable(identity_pk, desc)) {
+ log_info(LD_REND, "Hidden service descriptor is unusable. "
+ "Closing streams.");
+ connection_mark_unattached_ap(entry_conn,
+ END_STREAM_REASON_RESOLVEFAILED);
+ /* We are unable to use the descriptor so remove the directory request
+ * from the cache so the next connection can try again. */
+ note_connection_attempt_succeeded(edge_conn->hs_ident);
+ continue;
+ }
+
+ log_info(LD_REND, "Descriptor has arrived. Launching circuits.");
+
+ /* Mark connection as waiting for a circuit since we do have a usable
+ * descriptor now. */
+ mark_conn_as_waiting_for_circuit(&edge_conn->base_, now);
+ } SMARTLIST_FOREACH_END(entry_conn);
+
+ end:
+ return;
+}
+
+/** This is called when a descriptor fetch was successful but the descriptor
+ * couldn't be decrypted due to missing or bad client authorization. */
+static void
+client_desc_missing_bad_client_auth(const smartlist_t *entry_conns,
+ hs_desc_decode_status_t status)
+{
+ tor_assert(entry_conns);
+
+ SMARTLIST_FOREACH_BEGIN(entry_conns, entry_connection_t *, entry_conn) {
+ socks5_reply_status_t code;
+ if (status == HS_DESC_DECODE_BAD_CLIENT_AUTH) {
+ code = SOCKS5_HS_BAD_CLIENT_AUTH;
+ } else if (status == HS_DESC_DECODE_NEED_CLIENT_AUTH) {
+ code = SOCKS5_HS_MISSING_CLIENT_AUTH;
+ } else {
+ /* We should not be called with another type of status. Recover by
+ * sending a generic error. */
+ tor_assert_nonfatal_unreached();
+ code = SOCKS5_GENERAL_ERROR;
+ }
+ entry_conn->socks_request->socks_extended_error_code = code;
+ connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_MISC);
+ } SMARTLIST_FOREACH_END(entry_conn);
+}
+
+/** Called when we get a 200 directory fetch status code. */
+static void
+client_dir_fetch_200(dir_connection_t *dir_conn,
+ const smartlist_t *entry_conns, const char *body)
+{
+ hs_desc_decode_status_t decode_status;
+
+ tor_assert(dir_conn);
+ tor_assert(entry_conns);
+ tor_assert(body);
+
+ /* We got something: Try storing it in the cache. */
+ decode_status = hs_cache_store_as_client(body,
+ &dir_conn->hs_ident->identity_pk);
+ switch (decode_status) {
+ case HS_DESC_DECODE_OK:
+ case HS_DESC_DECODE_NEED_CLIENT_AUTH:
+ case HS_DESC_DECODE_BAD_CLIENT_AUTH:
+ log_info(LD_REND, "Stored hidden service descriptor successfully.");
+ TO_CONN(dir_conn)->purpose = DIR_PURPOSE_HAS_FETCHED_HSDESC;
+ if (decode_status == HS_DESC_DECODE_OK) {
+ client_desc_has_arrived(entry_conns);
+ } else {
+ /* This handles both client auth decode status. */
+ client_desc_missing_bad_client_auth(entry_conns, decode_status);
+ log_info(LD_REND, "Stored hidden service descriptor requires "
+ "%s client authorization.",
+ decode_status == HS_DESC_DECODE_NEED_CLIENT_AUTH ? "missing"
+ : "new");
+ }
+ /* Fire control port RECEIVED event. */
+ hs_control_desc_event_received(dir_conn->hs_ident,
+ dir_conn->identity_digest);
+ hs_control_desc_event_content(dir_conn->hs_ident,
+ dir_conn->identity_digest, body);
+ break;
+ case HS_DESC_DECODE_ENCRYPTED_ERROR:
+ case HS_DESC_DECODE_SUPERENC_ERROR:
+ case HS_DESC_DECODE_PLAINTEXT_ERROR:
+ case HS_DESC_DECODE_GENERIC_ERROR:
+ default:
+ log_info(LD_REND, "Failed to store hidden service descriptor. "
+ "Descriptor decoding status: %d", decode_status);
+ /* Fire control port FAILED event. */
+ hs_control_desc_event_failed(dir_conn->hs_ident,
+ dir_conn->identity_digest, "BAD_DESC");
+ hs_control_desc_event_content(dir_conn->hs_ident,
+ dir_conn->identity_digest, NULL);
+ break;
+ }
+}
+
+/** Called when we get a 404 directory fetch status code. */
+static void
+client_dir_fetch_404(dir_connection_t *dir_conn,
+ const smartlist_t *entry_conns)
+{
+ tor_assert(entry_conns);
+
+ /* Not there. We'll retry when connection_about_to_close_connection() tries
+ * to clean this conn up. */
+ log_info(LD_REND, "Fetching hidden service v3 descriptor not found: "
+ "Retrying at another directory.");
+ /* Fire control port FAILED event. */
+ hs_control_desc_event_failed(dir_conn->hs_ident, dir_conn->identity_digest,
+ "NOT_FOUND");
+ hs_control_desc_event_content(dir_conn->hs_ident, dir_conn->identity_digest,
+ NULL);
+
+ /* Flag every entry connections that the descriptor was not found. */
+ SMARTLIST_FOREACH_BEGIN(entry_conns, entry_connection_t *, entry_conn) {
+ entry_conn->socks_request->socks_extended_error_code =
+ SOCKS5_HS_NOT_FOUND;
+ } SMARTLIST_FOREACH_END(entry_conn);
+}
+
+/** Called when we get a 400 directory fetch status code. */
+static void
+client_dir_fetch_400(dir_connection_t *dir_conn, const char *reason)
+{
+ tor_assert(dir_conn);
+
+ log_warn(LD_REND, "Fetching v3 hidden service descriptor failed: "
+ "http status 400 (%s). Dirserver didn't like our "
+ "query? Retrying at another directory.",
+ escaped(reason));
+
+ /* Fire control port FAILED event. */
+ hs_control_desc_event_failed(dir_conn->hs_ident, dir_conn->identity_digest,
+ "QUERY_REJECTED");
+ hs_control_desc_event_content(dir_conn->hs_ident, dir_conn->identity_digest,
+ NULL);
+}
+
+/** Called when we get an unexpected directory fetch status code. */
+static void
+client_dir_fetch_unexpected(dir_connection_t *dir_conn, const char *reason,
+ const int status_code)
+{
+ tor_assert(dir_conn);
+
+ log_warn(LD_REND, "Fetching v3 hidden service descriptor failed: "
+ "http status %d (%s) response unexpected from HSDir "
+ "server '%s:%d'. Retrying at another directory.",
+ status_code, escaped(reason), TO_CONN(dir_conn)->address,
+ TO_CONN(dir_conn)->port);
+ /* Fire control port FAILED event. */
+ hs_control_desc_event_failed(dir_conn->hs_ident, dir_conn->identity_digest,
+ "UNEXPECTED");
+ hs_control_desc_event_content(dir_conn->hs_ident, dir_conn->identity_digest,
+ NULL);
+}
+
+/** Get the full filename for storing the client auth credentials for the
+ * service in <b>onion_address</b>. The base directory is <b>dir</b>.
+ * This function never returns NULL. */
+static char *
+get_client_auth_creds_filename(const char *onion_address,
+ const char *dir)
+{
+ char *full_fname = NULL;
+ char *fname;
+
+ tor_asprintf(&fname, "%s.auth_private", onion_address);
+ full_fname = hs_path_from_filename(dir, fname);
+ tor_free(fname);
+
+ return full_fname;
+}
+
+/** Permanently store the credentials in <b>creds</b> to disk.
+ *
+ * Return -1 if there was an error while storing the credentials, otherwise
+ * return 0.
+ */
+static int
+store_permanent_client_auth_credentials(
+ const hs_client_service_authorization_t *creds)
+{
+ const or_options_t *options = get_options();
+ char *full_fname = NULL;
+ char *file_contents = NULL;
+ char priv_key_b32[BASE32_NOPAD_LEN(CURVE25519_PUBKEY_LEN)+1];
+ int retval = -1;
+
+ tor_assert(creds->flags & CLIENT_AUTH_FLAG_IS_PERMANENT);
+
+ /* We need ClientOnionAuthDir to be set, otherwise we can't proceed */
+ if (!options->ClientOnionAuthDir) {
+ log_warn(LD_GENERAL, "Can't register permanent client auth credentials "
+ "for %s without ClientOnionAuthDir option. Discarding.",
+ creds->onion_address);
+ goto err;
+ }
+
+ /* Make sure the directory exists and is private enough. */
+ if (check_private_dir(options->ClientOnionAuthDir, 0, options->User) < 0) {
+ goto err;
+ }
+
+ /* Get filename that we should store the credentials */
+ full_fname = get_client_auth_creds_filename(creds->onion_address,
+ options->ClientOnionAuthDir);
+
+ /* Encode client private key */
+ base32_encode(priv_key_b32, sizeof(priv_key_b32),
+ (char*)creds->enc_seckey.secret_key,
+ sizeof(creds->enc_seckey.secret_key));
+
+ /* Get the full file contents and write it to disk! */
+ tor_asprintf(&file_contents, "%s:descriptor:x25519:%s",
+ creds->onion_address, priv_key_b32);
+ if (write_str_to_file(full_fname, file_contents, 0) < 0) {
+ log_warn(LD_GENERAL, "Failed to write client auth creds file for %s!",
+ creds->onion_address);
+ goto err;
+ }
+
+ retval = 0;
+
+ err:
+ tor_free(file_contents);
+ tor_free(full_fname);
+
+ return retval;
+}
+
+/** Register the credential <b>creds</b> as part of the client auth subsystem.
+ *
+ * Takes ownership of <b>creds</b>.
+ **/
+hs_client_register_auth_status_t
+hs_client_register_auth_credentials(hs_client_service_authorization_t *creds)
+{
+ ed25519_public_key_t service_identity_pk;
+ hs_client_service_authorization_t *old_creds = NULL;
+ hs_client_register_auth_status_t retval = REGISTER_SUCCESS;
+
+ tor_assert(creds);
+
+ if (!client_auths) {
+ client_auths = digest256map_new();
+ }
+
+ if (hs_parse_address(creds->onion_address, &service_identity_pk,
+ NULL, NULL) < 0) {
+ client_service_authorization_free(creds);
+ return REGISTER_FAIL_BAD_ADDRESS;
+ }
+
+ /* If we reach this point, the credentials will be stored one way or another:
+ * Make them permanent if the user asked us to. */
+ if (creds->flags & CLIENT_AUTH_FLAG_IS_PERMANENT) {
+ if (store_permanent_client_auth_credentials(creds) < 0) {
+ client_service_authorization_free(creds);
+ return REGISTER_FAIL_PERMANENT_STORAGE;
+ }
+ }
+
+ old_creds = digest256map_get(client_auths, service_identity_pk.pubkey);
+ if (old_creds) {
+ digest256map_remove(client_auths, service_identity_pk.pubkey);
+ client_service_authorization_free(old_creds);
+ retval = REGISTER_SUCCESS_ALREADY_EXISTS;
+ }
+
+ digest256map_set(client_auths, service_identity_pk.pubkey, creds);
+
+ /** Now that we set the new credentials, also try to decrypt any cached
+ * descriptors. */
+ if (hs_cache_client_new_auth_parse(&service_identity_pk)) {
+ retval = REGISTER_SUCCESS_AND_DECRYPTED;
+ }
+
+ return retval;
+}
+
+/** Load a client authorization file with <b>filename</b> that is stored under
+ * the global client auth directory, and return a newly-allocated credentials
+ * object if it parsed well. Otherwise, return NULL.
+ */
+static hs_client_service_authorization_t *
+get_creds_from_client_auth_filename(const char *filename,
+ const or_options_t *options)
+{
+ hs_client_service_authorization_t *auth = NULL;
+ char *client_key_file_path = NULL;
+ char *client_key_str = NULL;
+
+ log_info(LD_REND, "Loading a client authorization key file %s...",
+ filename);
+
+ if (!auth_key_filename_is_valid(filename)) {
+ log_notice(LD_REND, "Client authorization unrecognized filename %s. "
+ "File must end in .auth_private. Ignoring.",
+ filename);
+ goto err;
+ }
+
+ /* Create a full path for a file. */
+ client_key_file_path = hs_path_from_filename(options->ClientOnionAuthDir,
+ filename);
+
+ client_key_str = read_file_to_str(client_key_file_path, 0, NULL);
+ if (!client_key_str) {
+ log_warn(LD_REND, "The file %s cannot be read.", filename);
+ goto err;
+ }
+
+ auth = parse_auth_file_content(client_key_str);
+ if (!auth) {
+ goto err;
+ }
+
+ err:
+ tor_free(client_key_str);
+ tor_free(client_key_file_path);
+
+ return auth;
+}
+
+/*
+ * Remove the file in <b>filename</b> under the global client auth credential
+ * storage.
+ */
+static void
+remove_client_auth_creds_file(const char *filename)
+{
+ char *creds_file_path = NULL;
+ const or_options_t *options = get_options();
+
+ creds_file_path = hs_path_from_filename(options->ClientOnionAuthDir,
+ filename);
+ if (tor_unlink(creds_file_path) != 0) {
+ log_warn(LD_REND, "Failed to remove client auth file (%s).",
+ creds_file_path);
+ goto end;
+ }
+
+ log_warn(LD_REND, "Successfuly removed client auth file (%s).",
+ creds_file_path);
+
+ end:
+ tor_free(creds_file_path);
+}
+
+/**
+ * Find the filesystem file corresponding to the permanent client auth
+ * credentials in <b>cred</b> and remove it.
+ */
+static void
+find_and_remove_client_auth_creds_file(
+ const hs_client_service_authorization_t *cred)
+{
+ smartlist_t *file_list = NULL;
+ const or_options_t *options = get_options();
+
+ tor_assert(cred->flags & CLIENT_AUTH_FLAG_IS_PERMANENT);
+
+ if (!options->ClientOnionAuthDir) {
+ log_warn(LD_REND, "Found permanent credential but no ClientOnionAuthDir "
+ "configured. There is no file to be removed.");
+ goto end;
+ }
+
+ file_list = tor_listdir(options->ClientOnionAuthDir);
+ if (file_list == NULL) {
+ log_warn(LD_REND, "Client authorization key directory %s can't be listed.",
+ options->ClientOnionAuthDir);
+ goto end;
+ }
+
+ SMARTLIST_FOREACH_BEGIN(file_list, const char *, filename) {
+ hs_client_service_authorization_t *tmp_cred = NULL;
+
+ tmp_cred = get_creds_from_client_auth_filename(filename, options);
+ if (!tmp_cred) {
+ continue;
+ }
+
+ /* Find the right file for this credential */
+ if (!strcmp(tmp_cred->onion_address, cred->onion_address)) {
+ /* Found it! Remove the file! */
+ remove_client_auth_creds_file(filename);
+ /* cleanup and get out of here */
+ client_service_authorization_free(tmp_cred);
+ break;
+ }
+
+ client_service_authorization_free(tmp_cred);
+ } SMARTLIST_FOREACH_END(filename);
+
+ end:
+ if (file_list) {
+ SMARTLIST_FOREACH(file_list, char *, s, tor_free(s));
+ smartlist_free(file_list);
+ }
+}
+
+/** Remove client auth credentials for the service <b>hs_address</b>. */
+hs_client_removal_auth_status_t
+hs_client_remove_auth_credentials(const char *hsaddress)
+{
+ ed25519_public_key_t service_identity_pk;
+
+ if (!client_auths) {
+ return REMOVAL_SUCCESS_NOT_FOUND;
+ }
+
+ if (hs_parse_address(hsaddress, &service_identity_pk, NULL, NULL) < 0) {
+ return REMOVAL_BAD_ADDRESS;
+ }
+
+ hs_client_service_authorization_t *cred = NULL;
+ cred = digest256map_remove(client_auths, service_identity_pk.pubkey);
+
+ /* digestmap_remove() returns the previously stored data if there were any */
+ if (cred) {
+ if (cred->flags & CLIENT_AUTH_FLAG_IS_PERMANENT) {
+ /* These creds are stored on disk: remove the corresponding file. */
+ find_and_remove_client_auth_creds_file(cred);
+ }
+
+ /* Remove associated descriptor if any. */
+ hs_cache_remove_as_client(&service_identity_pk);
+
+ client_service_authorization_free(cred);
+ return REMOVAL_SUCCESS;
+ }
+
+ return REMOVAL_SUCCESS_NOT_FOUND;
+}
+
+/** Get the HS client auth map. */
+digest256map_t *
+get_hs_client_auths_map(void)
+{
+ return client_auths;
+}
+
/* ========== */
/* Public API */
/* ========== */
+/** Called when a circuit was just cleaned up. This is done right before the
+ * circuit is freed. */
+void
+hs_client_circuit_cleanup_on_free(const circuit_t *circ)
+{
+ bool has_timed_out;
+ rend_intro_point_failure_t failure = INTRO_POINT_FAILURE_GENERIC;
+ const origin_circuit_t *orig_circ = NULL;
+
+ tor_assert(circ);
+ tor_assert(CIRCUIT_IS_ORIGIN(circ));
+
+ orig_circ = CONST_TO_ORIGIN_CIRCUIT(circ);
+ tor_assert(orig_circ->hs_ident);
+
+ has_timed_out =
+ (circ->marked_for_close_orig_reason == END_CIRC_REASON_TIMEOUT);
+ if (has_timed_out) {
+ failure = INTRO_POINT_FAILURE_TIMEOUT;
+ }
+
+ switch (circ->purpose) {
+ case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
+ log_info(LD_REND, "Failed v3 intro circ for service %s to intro point %s "
+ "(awaiting ACK). Failure code: %d",
+ safe_str_client(ed25519_fmt(&orig_circ->hs_ident->identity_pk)),
+ safe_str_client(build_state_get_exit_nickname(orig_circ->build_state)),
+ failure);
+ hs_cache_client_intro_state_note(&orig_circ->hs_ident->identity_pk,
+ &orig_circ->hs_ident->intro_auth_pk,
+ failure);
+ break;
+ case CIRCUIT_PURPOSE_C_INTRODUCING:
+ if (has_timed_out || !orig_circ->build_state) {
+ break;
+ }
+ failure = INTRO_POINT_FAILURE_UNREACHABLE;
+ log_info(LD_REND, "Failed v3 intro circ for service %s to intro point %s "
+ "(while building circuit). Marking as unreachable.",
+ safe_str_client(ed25519_fmt(&orig_circ->hs_ident->identity_pk)),
+ safe_str_client(build_state_get_exit_nickname(orig_circ->build_state)));
+ hs_cache_client_intro_state_note(&orig_circ->hs_ident->identity_pk,
+ &orig_circ->hs_ident->intro_auth_pk,
+ failure);
+ break;
+ default:
+ break;
+ }
+}
+
/** A circuit just finished connecting to a hidden service that the stream
* <b>conn</b> has been waiting for. Let the HS subsystem know about this. */
void
@@ -1265,17 +1832,19 @@ hs_client_note_connection_attempt_succeeded(const edge_connection_t *conn)
}
}
-/* With the given encoded descriptor in desc_str and the service key in
+/** With the given encoded descriptor in desc_str and the service key in
* service_identity_pk, decode the descriptor and set the desc pointer with a
* newly allocated descriptor object.
*
- * Return 0 on success else a negative value and desc is set to NULL. */
-int
+ * On success, HS_DESC_DECODE_OK is returned and desc is set to the decoded
+ * descriptor. On error, desc is set to NULL and a decoding error status is
+ * returned depending on what was the issue. */
+hs_desc_decode_status_t
hs_client_decode_descriptor(const char *desc_str,
const ed25519_public_key_t *service_identity_pk,
hs_descriptor_t **desc)
{
- int ret;
+ hs_desc_decode_status_t ret;
uint8_t subcredential[DIGEST256_LEN];
ed25519_public_key_t blinded_pubkey;
hs_client_service_authorization_t *client_auth = NULL;
@@ -1303,7 +1872,7 @@ hs_client_decode_descriptor(const char *desc_str,
ret = hs_desc_decode_descriptor(desc_str, subcredential,
client_auth_sk, desc);
memwipe(subcredential, 0, sizeof(subcredential));
- if (ret < 0) {
+ if (ret != HS_DESC_DECODE_OK) {
goto err;
}
@@ -1316,15 +1885,16 @@ hs_client_decode_descriptor(const char *desc_str,
log_warn(LD_GENERAL, "Descriptor signing key certificate signature "
"doesn't validate with computed blinded key: %s",
tor_cert_describe_signature_status(cert));
+ ret = HS_DESC_DECODE_GENERIC_ERROR;
goto err;
}
- return 0;
+ return HS_DESC_DECODE_OK;
err:
- return -1;
+ return ret;
}
-/* Return true iff there are at least one usable intro point in the service
+/** Return true iff there are at least one usable intro point in the service
* descriptor desc. */
int
hs_client_any_intro_points_usable(const ed25519_public_key_t *service_pk,
@@ -1373,7 +1943,7 @@ hs_client_refetch_hsdesc(const ed25519_public_key_t *identity_pk)
return status;
}
-/* This is called when we are trying to attach an AP connection to these
+/** This is called when we are trying to attach an AP connection to these
* hidden service circuits from connection_ap_handshake_attach_circuit().
* Return 0 on success, -1 for a transient error that is actions were
* triggered to recover or -2 for a permenent error where both circuits will
@@ -1389,7 +1959,7 @@ hs_client_send_introduce1(origin_circuit_t *intro_circ,
rend_circ);
}
-/* Called when the client circuit circ has been established. It can be either
+/** Called when the client circuit circ has been established. It can be either
* an introduction or rendezvous circuit. This function handles all hidden
* service versions. */
void
@@ -1419,7 +1989,7 @@ hs_client_circuit_has_opened(origin_circuit_t *circ)
}
}
-/* Called when we receive a RENDEZVOUS_ESTABLISHED cell. Change the state of
+/** Called when we receive a RENDEZVOUS_ESTABLISHED cell. Change the state of
* the circuit to CIRCUIT_PURPOSE_C_REND_READY. Return 0 on success else a
* negative value and the circuit marked for close. */
int
@@ -1461,16 +2031,14 @@ hs_client_receive_rendezvous_acked(origin_circuit_t *circ,
return -1;
}
-#define client_service_authorization_free(auth) \
- FREE_AND_NULL(hs_client_service_authorization_t, \
- client_service_authorization_free_, (auth))
-
-static void
+void
client_service_authorization_free_(hs_client_service_authorization_t *auth)
{
- if (auth) {
- memwipe(auth, 0, sizeof(*auth));
+ if (!auth) {
+ return;
}
+
+ memwipe(auth, 0, sizeof(*auth));
tor_free(auth);
}
@@ -1490,7 +2058,7 @@ client_service_authorization_free_all(void)
digest256map_free(client_auths, client_service_authorization_free_void);
}
-/* Check if the auth key file name is valid or not. Return 1 if valid,
+/** Check if the auth key file name is valid or not. Return 1 if valid,
* otherwise return 0. */
STATIC int
auth_key_filename_is_valid(const char *filename)
@@ -1512,6 +2080,13 @@ auth_key_filename_is_valid(const char *filename)
return ret;
}
+/** Parse the client auth credentials off a string in <b>client_key_str</b>
+ * based on the file format documented in the "Client side configuration"
+ * section of rend-spec-v3.txt.
+ *
+ * Return NULL if there was an error, otherwise return a newly allocated
+ * hs_client_service_authorization_t structure.
+ */
STATIC hs_client_service_authorization_t *
parse_auth_file_content(const char *client_key_str)
{
@@ -1542,7 +2117,7 @@ parse_auth_file_content(const char *client_key_str)
goto err;
}
- if (strlen(seckey_b32) != BASE32_NOPAD_LEN(CURVE25519_PUBKEY_LEN)) {
+ if (strlen(seckey_b32) != BASE32_NOPAD_LEN(CURVE25519_SECKEY_LEN)) {
log_warn(LD_REND, "Client authorization encoded base32 private key "
"length is invalid: %s", seckey_b32);
goto err;
@@ -1557,8 +2132,18 @@ parse_auth_file_content(const char *client_key_str)
"can't be decoded: %s", seckey_b32);
goto err;
}
+
+ if (fast_mem_is_zero((const char*)auth->enc_seckey.secret_key,
+ sizeof(auth->enc_seckey.secret_key))) {
+ log_warn(LD_REND, "Client authorization private key can't be all-zeroes");
+ goto err;
+ }
+
strncpy(auth->onion_address, onion_address, HS_SERVICE_ADDR_LEN_BASE32);
+ /* We are reading this from the disk, so set the permanent flag anyway. */
+ auth->flags |= CLIENT_AUTH_FLAG_IS_PERMANENT;
+
/* Success. */
goto done;
@@ -1575,7 +2160,7 @@ parse_auth_file_content(const char *client_key_str)
return auth;
}
-/* From a set of <b>options</b>, setup every client authorization detail
+/** From a set of <b>options</b>, setup every client authorization detail
* found. Return 0 on success or -1 on failure. If <b>validate_only</b>
* is set, parse, warn and return as normal, but don't actually change
* the configuration. */
@@ -1585,10 +2170,7 @@ hs_config_client_authorization(const or_options_t *options,
{
int ret = -1;
digest256map_t *auths = digest256map_new();
- char *key_dir = NULL;
smartlist_t *file_list = NULL;
- char *client_key_str = NULL;
- char *client_key_file_path = NULL;
tor_assert(options);
@@ -1599,82 +2181,54 @@ hs_config_client_authorization(const or_options_t *options,
goto end;
}
- key_dir = tor_strdup(options->ClientOnionAuthDir);
-
/* Make sure the directory exists and is private enough. */
- if (check_private_dir(key_dir, 0, options->User) < 0) {
+ if (check_private_dir(options->ClientOnionAuthDir, 0, options->User) < 0) {
goto end;
}
- file_list = tor_listdir(key_dir);
+ file_list = tor_listdir(options->ClientOnionAuthDir);
if (file_list == NULL) {
log_warn(LD_REND, "Client authorization key directory %s can't be listed.",
- key_dir);
+ options->ClientOnionAuthDir);
goto end;
}
- SMARTLIST_FOREACH_BEGIN(file_list, char *, filename) {
-
+ SMARTLIST_FOREACH_BEGIN(file_list, const char *, filename) {
hs_client_service_authorization_t *auth = NULL;
ed25519_public_key_t identity_pk;
- log_info(LD_REND, "Loading a client authorization key file %s...",
- filename);
- if (!auth_key_filename_is_valid(filename)) {
- log_notice(LD_REND, "Client authorization unrecognized filename %s. "
- "File must end in .auth_private. Ignoring.",
- filename);
+ auth = get_creds_from_client_auth_filename(filename, options);
+ if (!auth) {
continue;
}
- /* Create a full path for a file. */
- client_key_file_path = hs_path_from_filename(key_dir, filename);
- client_key_str = read_file_to_str(client_key_file_path, 0, NULL);
- /* Free the file path immediately after using it. */
- tor_free(client_key_file_path);
-
- /* If we cannot read the file, continue with the next file. */
- if (!client_key_str) {
- log_warn(LD_REND, "The file %s cannot be read.", filename);
+ /* Parse the onion address to get an identity public key and use it
+ * as a key of global map in the future. */
+ if (hs_parse_address(auth->onion_address, &identity_pk,
+ NULL, NULL) < 0) {
+ log_warn(LD_REND, "The onion address \"%s\" is invalid in "
+ "file %s", filename, auth->onion_address);
+ client_service_authorization_free(auth);
continue;
}
- auth = parse_auth_file_content(client_key_str);
- /* Free immediately after using it. */
- tor_free(client_key_str);
-
- if (auth) {
- /* Parse the onion address to get an identity public key and use it
- * as a key of global map in the future. */
- if (hs_parse_address(auth->onion_address, &identity_pk,
- NULL, NULL) < 0) {
- log_warn(LD_REND, "The onion address \"%s\" is invalid in "
- "file %s", filename, auth->onion_address);
- client_service_authorization_free(auth);
- continue;
- }
-
- if (digest256map_get(auths, identity_pk.pubkey)) {
+ if (digest256map_get(auths, identity_pk.pubkey)) {
log_warn(LD_REND, "Duplicate authorization for the same hidden "
- "service address %s.",
+ "service address %s.",
safe_str_client_opts(options, auth->onion_address));
client_service_authorization_free(auth);
goto end;
- }
-
- digest256map_set(auths, identity_pk.pubkey, auth);
- log_info(LD_REND, "Loaded a client authorization key file %s.",
- filename);
}
+
+ digest256map_set(auths, identity_pk.pubkey, auth);
+ log_info(LD_REND, "Loaded a client authorization key file %s.",
+ filename);
} SMARTLIST_FOREACH_END(filename);
/* Success. */
ret = 0;
end:
- tor_free(key_dir);
- tor_free(client_key_str);
- tor_free(client_key_file_path);
if (file_list) {
SMARTLIST_FOREACH(file_list, char *, s, tor_free(s));
smartlist_free(file_list);
@@ -1690,65 +2244,48 @@ hs_config_client_authorization(const or_options_t *options,
return ret;
}
-/* This is called when a descriptor has arrived following a fetch request and
- * has been stored in the client cache. Every entry connection that matches
- * the service identity key in the ident will get attached to the hidden
- * service circuit. */
+/** Called when a descriptor directory fetch is done.
+ *
+ * Act accordingly on all entry connections depending on the HTTP status code
+ * we got. In case of an error, the SOCKS error is set (if ExtendedErrors is
+ * set).
+ *
+ * The reason is a human readable string returned by the directory server
+ * which can describe the status of the request. The body is the response
+ * content, on 200 code it is the descriptor itself. Finally, the status_code
+ * is the HTTP code returned by the directory server. */
void
-hs_client_desc_has_arrived(const hs_ident_dir_conn_t *ident)
+hs_client_dir_fetch_done(dir_connection_t *dir_conn, const char *reason,
+ const char *body, const int status_code)
{
- time_t now = time(NULL);
- smartlist_t *conns = NULL;
-
- tor_assert(ident);
-
- conns = connection_list_by_type_state(CONN_TYPE_AP,
- AP_CONN_STATE_RENDDESC_WAIT);
- SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) {
- const hs_descriptor_t *desc;
- entry_connection_t *entry_conn = TO_ENTRY_CONN(base_conn);
- const edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(entry_conn);
+ smartlist_t *entry_conns;
- /* Only consider the entry connections that matches the service for which
- * we just fetched its descriptor. */
- if (!edge_conn->hs_ident ||
- !ed25519_pubkey_eq(&ident->identity_pk,
- &edge_conn->hs_ident->identity_pk)) {
- continue;
- }
- assert_connection_ok(base_conn, now);
+ tor_assert(dir_conn);
+ tor_assert(body);
- /* We were just called because we stored the descriptor for this service
- * so not finding a descriptor means we have a bigger problem. */
- desc = hs_cache_lookup_as_client(&ident->identity_pk);
- if (BUG(desc == NULL)) {
- goto end;
- }
+ /* Get all related entry connections. */
+ entry_conns = find_entry_conns(&dir_conn->hs_ident->identity_pk);
- if (!hs_client_any_intro_points_usable(&ident->identity_pk, desc)) {
- log_info(LD_REND, "Hidden service descriptor is unusable. "
- "Closing streams.");
- connection_mark_unattached_ap(entry_conn,
- END_STREAM_REASON_RESOLVEFAILED);
- /* We are unable to use the descriptor so remove the directory request
- * from the cache so the next connection can try again. */
- note_connection_attempt_succeeded(edge_conn->hs_ident);
- continue;
- }
-
- log_info(LD_REND, "Descriptor has arrived. Launching circuits.");
-
- /* Mark connection as waiting for a circuit since we do have a usable
- * descriptor now. */
- mark_conn_as_waiting_for_circuit(base_conn, now);
- } SMARTLIST_FOREACH_END(base_conn);
+ switch (status_code) {
+ case 200:
+ client_dir_fetch_200(dir_conn, entry_conns, body);
+ break;
+ case 404:
+ client_dir_fetch_404(dir_conn, entry_conns);
+ break;
+ case 400:
+ client_dir_fetch_400(dir_conn, reason);
+ break;
+ default:
+ client_dir_fetch_unexpected(dir_conn, reason, status_code);
+ break;
+ }
- end:
/* We don't have ownership of the objects in this list. */
- smartlist_free(conns);
+ smartlist_free(entry_conns);
}
-/* Return a newly allocated extend_info_t for a randomly chosen introduction
+/** Return a newly allocated extend_info_t for a randomly chosen introduction
* point for the given edge connection identifier ident. Return NULL if we
* can't pick any usable introduction points. */
extend_info_t *
@@ -1761,7 +2298,7 @@ hs_client_get_random_intro_from_edge(const edge_connection_t *edge_conn)
rend_client_get_random_intro(edge_conn->rend_data);
}
-/* Called when get an INTRODUCE_ACK cell on the introduction circuit circ.
+/** Called when get an INTRODUCE_ACK cell on the introduction circuit circ.
* Return 0 on success else a negative value is returned. The circuit will be
* closed or reuse to extend again to another intro point. */
int
@@ -1790,7 +2327,7 @@ hs_client_receive_introduce_ack(origin_circuit_t *circ,
return ret;
}
-/* Called when get a RENDEZVOUS2 cell on the rendezvous circuit circ. Return
+/** Called when get a RENDEZVOUS2 cell on the rendezvous circuit circ. Return
* 0 on success else a negative value is returned. The circuit will be closed
* on error. */
int
@@ -1823,7 +2360,7 @@ hs_client_receive_rendezvous2(origin_circuit_t *circ,
return ret;
}
-/* Extend the introduction circuit circ to another valid introduction point
+/** Extend the introduction circuit circ to another valid introduction point
* for the hidden service it is trying to connect to, or mark it and launch a
* new circuit if we can't extend it. Return 0 on success or possible
* success. Return -1 and mark the introduction circuit for close on permanent
@@ -1873,7 +2410,7 @@ hs_client_reextend_intro_circuit(origin_circuit_t *circ)
return ret;
}
-/* Close all client introduction circuits related to the given descriptor.
+/** Close all client introduction circuits related to the given descriptor.
* This is called with a descriptor that is about to get replaced in the
* client cache.
*
@@ -1905,7 +2442,7 @@ hs_client_close_intro_circuits_from_desc(const hs_descriptor_t *desc)
}
}
-/* Release all the storage held by the client subsystem. */
+/** Release all the storage held by the client subsystem. */
void
hs_client_free_all(void)
{
@@ -1914,7 +2451,7 @@ hs_client_free_all(void)
client_service_authorization_free_all();
}
-/* Purge all potentially remotely-detectable state held in the hidden
+/** Purge all potentially remotely-detectable state held in the hidden
* service client code. Called on SIGNAL NEWNYM. */
void
hs_client_purge_state(void)
@@ -1931,11 +2468,13 @@ hs_client_purge_state(void)
hs_cache_purge_as_client();
/* Purge the last hidden service request cache. */
hs_purge_last_hid_serv_requests();
+ /* Purge ephemeral client authorization. */
+ purge_ephemeral_client_auth();
log_info(LD_REND, "Hidden service client state has been purged.");
}
-/* Called when our directory information has changed. */
+/** Called when our directory information has changed. */
void
hs_client_dir_info_changed(void)
{
@@ -1947,10 +2486,10 @@ hs_client_dir_info_changed(void)
#ifdef TOR_UNIT_TESTS
-STATIC digest256map_t *
-get_hs_client_auths_map(void)
+STATIC void
+set_hs_client_auths_map(digest256map_t *map)
{
- return client_auths;
+ client_auths = map;
}
#endif /* defined(TOR_UNIT_TESTS) */
diff --git a/src/feature/hs/hs_client.h b/src/feature/hs/hs_client.h
index 96a96755fd..d0a3a7015f 100644
--- a/src/feature/hs/hs_client.h
+++ b/src/feature/hs/hs_client.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -10,37 +10,86 @@
#define TOR_HS_CLIENT_H
#include "lib/crypt_ops/crypto_ed25519.h"
+
+#include "feature/hs/hs_circuit.h"
#include "feature/hs/hs_descriptor.h"
#include "feature/hs/hs_ident.h"
-/* Status code of a descriptor fetch request. */
+/** Status code of a descriptor fetch request. */
typedef enum {
- /* Something internally went wrong. */
+ /** Something internally went wrong. */
HS_CLIENT_FETCH_ERROR = -1,
- /* The fetch request has been launched successfully. */
+ /** The fetch request has been launched successfully. */
HS_CLIENT_FETCH_LAUNCHED = 0,
- /* We already have a usable descriptor. No fetch. */
+ /** We already have a usable descriptor. No fetch. */
HS_CLIENT_FETCH_HAVE_DESC = 1,
- /* No more HSDir available to query. */
+ /** No more HSDir available to query. */
HS_CLIENT_FETCH_NO_HSDIRS = 2,
- /* The fetch request is not allowed. */
+ /** The fetch request is not allowed. */
HS_CLIENT_FETCH_NOT_ALLOWED = 3,
- /* We are missing information to be able to launch a request. */
+ /** We are missing information to be able to launch a request. */
HS_CLIENT_FETCH_MISSING_INFO = 4,
- /* There is a pending fetch for the requested service. */
+ /** There is a pending fetch for the requested service. */
HS_CLIENT_FETCH_PENDING = 5,
} hs_client_fetch_status_t;
-/** Client-side configuration of authorization for a service. */
+/* Status code of client auth credential registration */
+typedef enum {
+ /* We successfuly registered these credentials */
+ REGISTER_SUCCESS,
+ /* We successfully registered these credentials, but had to replace some
+ * existing ones. */
+ REGISTER_SUCCESS_ALREADY_EXISTS,
+ /* We successfuly registered these credentials, and also decrypted a cached
+ * descriptor. */
+ REGISTER_SUCCESS_AND_DECRYPTED,
+ /* We failed to register these credentials, because of a bad HS address. */
+ REGISTER_FAIL_BAD_ADDRESS,
+ /* We failed to store these credentials in a persistent file on disk. */
+ REGISTER_FAIL_PERMANENT_STORAGE,
+} hs_client_register_auth_status_t;
+
+/* Status code of client auth credential removal */
+typedef enum {
+ /* We successfuly removed these credentials */
+ REMOVAL_SUCCESS,
+ /* No need to remove those credentials, because they were not there. */
+ REMOVAL_SUCCESS_NOT_FOUND,
+ /* We failed to register these credentials, because of a bad HS address. */
+ REMOVAL_BAD_ADDRESS,
+} hs_client_removal_auth_status_t;
+
+/** Flag to set when a client auth is permanent (saved on disk). */
+#define CLIENT_AUTH_FLAG_IS_PERMANENT (1<<0)
+
+/** Client-side configuration of client authorization */
typedef struct hs_client_service_authorization_t {
- /* An curve25519 secret key used to compute decryption keys that
+ /** An curve25519 secret key used to compute decryption keys that
* allow the client to decrypt the hidden service descriptor. */
curve25519_secret_key_t enc_seckey;
- /* An onion address that is used to connect to the onion service. */
+ /** An onion address that is used to connect to the onion service. */
char onion_address[HS_SERVICE_ADDR_LEN_BASE32+1];
+
+ /* Optional flags for this client. */
+ int flags;
} hs_client_service_authorization_t;
+hs_client_register_auth_status_t
+hs_client_register_auth_credentials(hs_client_service_authorization_t *creds);
+
+hs_client_removal_auth_status_t
+hs_client_remove_auth_credentials(const char *hsaddress);
+
+digest256map_t *get_hs_client_auths_map(void);
+
+#define client_service_authorization_free(auth) \
+ FREE_AND_NULL(hs_client_service_authorization_t, \
+ client_service_authorization_free_, (auth))
+
+void
+client_service_authorization_free_(hs_client_service_authorization_t *auth);
+
void hs_client_note_connection_attempt_succeeded(
const edge_connection_t *conn);
@@ -48,7 +97,7 @@ void hs_client_launch_v3_desc_fetch(
const ed25519_public_key_t *onion_identity_pk,
const smartlist_t *hsdirs);
-int hs_client_decode_descriptor(
+hs_desc_decode_status_t hs_client_decode_descriptor(
const char *desc_str,
const ed25519_public_key_t *service_identity_pk,
hs_descriptor_t **desc);
@@ -61,6 +110,7 @@ int hs_client_send_introduce1(origin_circuit_t *intro_circ,
origin_circuit_t *rend_circ);
void hs_client_circuit_has_opened(origin_circuit_t *circ);
+void hs_client_circuit_cleanup_on_free(const circuit_t *circ);
int hs_client_receive_rendezvous_acked(origin_circuit_t *circ,
const uint8_t *payload,
@@ -72,7 +122,8 @@ int hs_client_receive_rendezvous2(origin_circuit_t *circ,
const uint8_t *payload,
size_t payload_len);
-void hs_client_desc_has_arrived(const hs_ident_dir_conn_t *ident);
+void hs_client_dir_fetch_done(dir_connection_t *dir_conn, const char *reason,
+ const char *body, const int status_code);
extend_info_t *hs_client_get_random_intro_from_edge(
const edge_connection_t *edge_conn);
@@ -111,13 +162,14 @@ MOCK_DECL(STATIC hs_client_fetch_status_t,
STATIC void retry_all_socks_conn_waiting_for_desc(void);
+STATIC void purge_ephemeral_client_auth(void);
+
#ifdef TOR_UNIT_TESTS
-STATIC digest256map_t *get_hs_client_auths_map(void);
+STATIC void set_hs_client_auths_map(digest256map_t *map);
#endif /* defined(TOR_UNIT_TESTS) */
#endif /* defined(HS_CLIENT_PRIVATE) */
#endif /* !defined(TOR_HS_CLIENT_H) */
-
diff --git a/src/feature/hs/hs_common.c b/src/feature/hs/hs_common.c
index 036d23a6b0..f8b031cc26 100644
--- a/src/feature/hs/hs_common.c
+++ b/src/feature/hs/hs_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -44,7 +44,7 @@
/* Trunnel */
#include "trunnel/ed25519_cert.h"
-/* Ed25519 Basepoint value. Taken from section 5 of
+/** Ed25519 Basepoint value. Taken from section 5 of
* https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03 */
static const char *str_ed25519_basepoint =
"(15112221349535400772501151409588531511"
@@ -106,7 +106,7 @@ add_unix_port(smartlist_t *ports, rend_service_port_config_t *p)
#endif /* defined(HAVE_SYS_UN_H) */
-/* Helper function: The key is a digest that we compare to a node_t object
+/** Helper function: The key is a digest that we compare to a node_t object
* current hsdir_index. */
static int
compare_digest_to_fetch_hsdir_index(const void *_key, const void **_member)
@@ -116,7 +116,7 @@ compare_digest_to_fetch_hsdir_index(const void *_key, const void **_member)
return tor_memcmp(key, node->hsdir_index.fetch, DIGEST256_LEN);
}
-/* Helper function: The key is a digest that we compare to a node_t object
+/** Helper function: The key is a digest that we compare to a node_t object
* next hsdir_index. */
static int
compare_digest_to_store_first_hsdir_index(const void *_key,
@@ -127,7 +127,7 @@ compare_digest_to_store_first_hsdir_index(const void *_key,
return tor_memcmp(key, node->hsdir_index.store_first, DIGEST256_LEN);
}
-/* Helper function: The key is a digest that we compare to a node_t object
+/** Helper function: The key is a digest that we compare to a node_t object
* next hsdir_index. */
static int
compare_digest_to_store_second_hsdir_index(const void *_key,
@@ -138,7 +138,7 @@ compare_digest_to_store_second_hsdir_index(const void *_key,
return tor_memcmp(key, node->hsdir_index.store_second, DIGEST256_LEN);
}
-/* Helper function: Compare two node_t objects current hsdir_index. */
+/** Helper function: Compare two node_t objects current hsdir_index. */
static int
compare_node_fetch_hsdir_index(const void **a, const void **b)
{
@@ -149,7 +149,7 @@ compare_node_fetch_hsdir_index(const void **a, const void **b)
DIGEST256_LEN);
}
-/* Helper function: Compare two node_t objects next hsdir_index. */
+/** Helper function: Compare two node_t objects next hsdir_index. */
static int
compare_node_store_first_hsdir_index(const void **a, const void **b)
{
@@ -160,7 +160,7 @@ compare_node_store_first_hsdir_index(const void **a, const void **b)
DIGEST256_LEN);
}
-/* Helper function: Compare two node_t objects next hsdir_index. */
+/** Helper function: Compare two node_t objects next hsdir_index. */
static int
compare_node_store_second_hsdir_index(const void **a, const void **b)
{
@@ -171,7 +171,7 @@ compare_node_store_second_hsdir_index(const void **a, const void **b)
DIGEST256_LEN);
}
-/* Allocate and return a string containing the path to filename in directory.
+/** Allocate and return a string containing the path to filename in directory.
* This function will never return NULL. The caller must free this path. */
char *
hs_path_from_filename(const char *directory, const char *filename)
@@ -185,8 +185,9 @@ hs_path_from_filename(const char *directory, const char *filename)
return file_path;
}
-/* Make sure that the directory for <b>service</b> is private, using the config
- * <b>username</b>.
+/** Make sure that the directory for <b>service</b> is private, using the
+ * config <b>username</b>.
+ *
* If <b>create</b> is true:
* - if the directory exists, change permissions if needed,
* - if the directory does not exist, create it with the correct permissions.
@@ -304,18 +305,18 @@ hs_get_next_time_period_num(time_t now)
return hs_get_time_period_num(now) + 1;
}
-/* Get the number of the _previous_ HS time period, given that the current time
- * is <b>now</b>. If <b>now</b> is not set, we try to get the time from a live
- * consensus. */
+/** Get the number of the _previous_ HS time period, given that the current
+ * time is <b>now</b>. If <b>now</b> is not set, we try to get the time from a
+ * live consensus. */
uint64_t
hs_get_previous_time_period_num(time_t now)
{
return hs_get_time_period_num(now) - 1;
}
-/* Return the start time of the upcoming time period based on <b>now</b>. If
- <b>now</b> is not set, we try to get the time ourselves from a live
- consensus. */
+/** Return the start time of the upcoming time period based on <b>now</b>. If
+ * <b>now</b> is not set, we try to get the time ourselves from a live
+ * consensus. */
time_t
hs_get_start_time_of_next_time_period(time_t now)
{
@@ -330,7 +331,7 @@ hs_get_start_time_of_next_time_period(time_t now)
return (time_t)(start_of_next_tp_in_mins * 60 + time_period_rotation_offset);
}
-/* Create a new rend_data_t for a specific given <b>version</b>.
+/** Create a new rend_data_t for a specific given <b>version</b>.
* Return a pointer to the newly allocated data structure. */
static rend_data_t *
rend_data_alloc(uint32_t version)
@@ -379,7 +380,7 @@ rend_data_free_(rend_data_t *data)
}
}
-/* Allocate and return a deep copy of <b>data</b>. */
+/** Allocate and return a deep copy of <b>data</b>. */
rend_data_t *
rend_data_dup(const rend_data_t *data)
{
@@ -409,7 +410,7 @@ rend_data_dup(const rend_data_t *data)
return data_dup;
}
-/* Compute the descriptor ID for each HS descriptor replica and save them. A
+/** Compute the descriptor ID for each HS descriptor replica and save them. A
* valid onion address must be present in the <b>rend_data</b>.
*
* Return 0 on success else -1. */
@@ -447,7 +448,7 @@ compute_desc_id(rend_data_t *rend_data)
return ret;
}
-/* Allocate and initialize a rend_data_t object for a service using the
+/** Allocate and initialize a rend_data_t object for a service using the
* provided arguments. All arguments are optional (can be NULL), except from
* <b>onion_address</b> which MUST be set. The <b>pk_digest</b> is the hash of
* the service private key. The <b>cookie</b> is the rendezvous cookie and
@@ -479,7 +480,7 @@ rend_data_service_create(const char *onion_address, const char *pk_digest,
return rend_data;
}
-/* Allocate and initialize a rend_data_t object for a client request using the
+/** Allocate and initialize a rend_data_t object for a client request using the
* given arguments. Either an onion address or a descriptor ID is needed. Both
* can be given but in this case only the onion address will be used to make
* the descriptor fetch. The <b>cookie</b> is the rendezvous cookie and
@@ -520,7 +521,7 @@ rend_data_client_create(const char *onion_address, const char *desc_id,
return NULL;
}
-/* Return the onion address from the rend data. Depending on the version,
+/** Return the onion address from the rend data. Depending on the version,
* the size of the address can vary but it's always NUL terminated. */
const char *
rend_data_get_address(const rend_data_t *rend_data)
@@ -536,7 +537,7 @@ rend_data_get_address(const rend_data_t *rend_data)
}
}
-/* Return the descriptor ID for a specific replica number from the rend
+/** Return the descriptor ID for a specific replica number from the rend
* data. The returned data is a binary digest and depending on the version its
* size can vary. The size of the descriptor ID is put in <b>len_out</b> if
* non NULL. */
@@ -559,7 +560,7 @@ rend_data_get_desc_id(const rend_data_t *rend_data, uint8_t replica,
}
}
-/* Return the public key digest using the given <b>rend_data</b>. The size of
+/** Return the public key digest using the given <b>rend_data</b>. The size of
* the digest is put in <b>len_out</b> (if set) which can differ depending on
* the version. */
const uint8_t *
@@ -582,7 +583,7 @@ rend_data_get_pk_digest(const rend_data_t *rend_data, size_t *len_out)
}
}
-/* Using the given time period number, compute the disaster shared random
+/** Using the given time period number, compute the disaster shared random
* value and put it in srv_out. It MUST be at least DIGEST256_LEN bytes. */
static void
compute_disaster_srv(uint64_t time_period_num, uint8_t *srv_out)
@@ -670,7 +671,7 @@ get_second_cached_disaster_srv(void)
#endif /* defined(TOR_UNIT_TESTS) */
-/* When creating a blinded key, we need a parameter which construction is as
+/** When creating a blinded key, we need a parameter which construction is as
* follow: H(pubkey | [secret] | ed25519-basepoint | nonce).
*
* The nonce has a pre-defined format which uses the time period number
@@ -724,7 +725,7 @@ build_blinded_key_param(const ed25519_public_key_t *pubkey,
memwipe(nonce, 0, sizeof(nonce));
}
-/* Using an ed25519 public key and version to build the checksum of an
+/** Using an ed25519 public key and version to build the checksum of an
* address. Put in checksum_out. Format is:
* SHA3-256(".onion checksum" || PUBKEY || VERSION)
*
@@ -751,7 +752,7 @@ build_hs_checksum(const ed25519_public_key_t *key, uint8_t version,
DIGEST_SHA3_256);
}
-/* Using an ed25519 public key, checksum and version to build the binary
+/** Using an ed25519 public key, checksum and version to build the binary
* representation of a service address. Put in addr_out. Format is:
* addr_out = PUBKEY || CHECKSUM || VERSION
*
@@ -774,7 +775,7 @@ build_hs_address(const ed25519_public_key_t *key, const uint8_t *checksum,
tor_assert(offset == HS_SERVICE_ADDR_LEN);
}
-/* Helper for hs_parse_address(): Using a binary representation of a service
+/** Helper for hs_parse_address(): Using a binary representation of a service
* address, parse its content into the key_out, checksum_out and version_out.
* Any out variable can be NULL in case the caller would want only one field.
* checksum_out MUST at least be 2 bytes long. address must be at least
@@ -806,7 +807,7 @@ hs_parse_address_impl(const char *address, ed25519_public_key_t *key_out,
tor_assert(offset == HS_SERVICE_ADDR_LEN);
}
-/* Using the given identity public key and a blinded public key, compute the
+/** Using the given identity public key and a blinded public key, compute the
* subcredential and put it in subcred_out (must be of size DIGEST256_LEN).
* This can't fail. */
void
@@ -846,7 +847,7 @@ hs_get_subcredential(const ed25519_public_key_t *identity_pk,
memwipe(credential, 0, sizeof(credential));
}
-/* From the given list of hidden service ports, find the ones that match the
+/** From the given list of hidden service ports, find the ones that match the
* given edge connection conn, pick one at random and use it to set the
* connection address. Return 0 on success or -1 if none. */
int
@@ -903,7 +904,7 @@ hs_set_conn_addr_port(const smartlist_t *ports, edge_connection_t *conn)
return (chosen_port) ? 0 : -1;
}
-/* Using a base32 representation of a service address, parse its content into
+/** Using a base32 representation of a service address, parse its content into
* the key_out, checksum_out and version_out. Any out variable can be NULL in
* case the caller would want only one field. checksum_out MUST at least be 2
* bytes long.
@@ -943,7 +944,7 @@ hs_parse_address(const char *address, ed25519_public_key_t *key_out,
return -1;
}
-/* Validate a given onion address. The length, the base32 decoding, and
+/** Validate a given onion address. The length, the base32 decoding, and
* checksum are validated. Return 1 if valid else 0. */
int
hs_address_is_valid(const char *address)
@@ -982,7 +983,7 @@ hs_address_is_valid(const char *address)
return 0;
}
-/* Build a service address using an ed25519 public key and a given version.
+/** Build a service address using an ed25519 public key and a given version.
* The returned address is base32 encoded and put in addr_out. The caller MUST
* make sure the addr_out is at least HS_SERVICE_ADDR_LEN_BASE32 + 1 long.
*
@@ -1012,7 +1013,7 @@ hs_build_address(const ed25519_public_key_t *key, uint8_t version,
tor_assert(hs_address_is_valid(addr_out));
}
-/* From a given ed25519 public key pk and an optional secret, compute a
+/** From a given ed25519 public key pk and an optional secret, compute a
* blinded public key and put it in blinded_pk_out. This is only useful to
* the client side because the client only has access to the identity public
* key of the service. */
@@ -1036,7 +1037,7 @@ hs_build_blinded_pubkey(const ed25519_public_key_t *pk,
memwipe(param, 0, sizeof(param));
}
-/* From a given ed25519 keypair kp and an optional secret, compute a blinded
+/** From a given ed25519 keypair kp and an optional secret, compute a blinded
* keypair for the current time period and put it in blinded_kp_out. This is
* only useful by the service side because the client doesn't have access to
* the identity secret key. */
@@ -1062,7 +1063,7 @@ hs_build_blinded_keypair(const ed25519_keypair_t *kp,
memwipe(param, 0, sizeof(param));
}
-/* Return true if we are currently in the time segment between a new time
+/** Return true if we are currently in the time segment between a new time
* period and a new SRV (in the real network that happens between 12:00 and
* 00:00 UTC). Here is a diagram showing exactly when this returns true:
*
@@ -1102,7 +1103,7 @@ hs_in_period_between_tp_and_srv,(const networkstatus_t *consensus, time_t now))
return 1;
}
-/* Return 1 if any virtual port in ports needs a circuit with good uptime.
+/** Return 1 if any virtual port in ports needs a circuit with good uptime.
* Else return 0. */
int
hs_service_requires_uptime_circ(const smartlist_t *ports)
@@ -1118,7 +1119,7 @@ hs_service_requires_uptime_circ(const smartlist_t *ports)
return 0;
}
-/* Build hs_index which is used to find the responsible hsdirs. This index
+/** Build hs_index which is used to find the responsible hsdirs. This index
* value is used to select the responsible HSDir where their hsdir_index is
* closest to this value.
* SHA3-256("store-at-idx" | blinded_public_key |
@@ -1160,7 +1161,7 @@ hs_build_hs_index(uint64_t replica, const ed25519_public_key_t *blinded_pk,
crypto_digest_free(digest);
}
-/* Build hsdir_index which is used to find the responsible hsdirs. This is the
+/** Build hsdir_index which is used to find the responsible hsdirs. This is the
* index value that is compare to the hs_index when selecting an HSDir.
* SHA3-256("node-idx" | node_identity |
* shared_random_value | INT_8(period_length) | INT_8(period_num) )
@@ -1201,7 +1202,7 @@ hs_build_hsdir_index(const ed25519_public_key_t *identity_pk,
crypto_digest_free(digest);
}
-/* Return a newly allocated buffer containing the current shared random value
+/** Return a newly allocated buffer containing the current shared random value
* or if not present, a disaster value is computed using the given time period
* number. If a consensus is provided in <b>ns</b>, use it to get the SRV
* value. This function can't fail. */
@@ -1220,7 +1221,7 @@ hs_get_current_srv(uint64_t time_period_num, const networkstatus_t *ns)
return sr_value;
}
-/* Return a newly allocated buffer containing the previous shared random
+/** Return a newly allocated buffer containing the previous shared random
* value or if not present, a disaster value is computed using the given time
* period number. This function can't fail. */
uint8_t *
@@ -1238,7 +1239,7 @@ hs_get_previous_srv(uint64_t time_period_num, const networkstatus_t *ns)
return sr_value;
}
-/* Return the number of replicas defined by a consensus parameter or the
+/** Return the number of replicas defined by a consensus parameter or the
* default value. */
int32_t
hs_get_hsdir_n_replicas(void)
@@ -1248,7 +1249,7 @@ hs_get_hsdir_n_replicas(void)
HS_DEFAULT_HSDIR_N_REPLICAS, 1, 16);
}
-/* Return the spread fetch value defined by a consensus parameter or the
+/** Return the spread fetch value defined by a consensus parameter or the
* default value. */
int32_t
hs_get_hsdir_spread_fetch(void)
@@ -1258,7 +1259,7 @@ hs_get_hsdir_spread_fetch(void)
HS_DEFAULT_HSDIR_SPREAD_FETCH, 1, 128);
}
-/* Return the spread store value defined by a consensus parameter or the
+/** Return the spread store value defined by a consensus parameter or the
* default value. */
int32_t
hs_get_hsdir_spread_store(void)
@@ -1301,7 +1302,7 @@ node_has_hsdir_index(const node_t *node)
return 1;
}
-/* For a given blinded key and time period number, get the responsible HSDir
+/** For a given blinded key and time period number, get the responsible HSDir
* and put their routerstatus_t object in the responsible_dirs list. If
* 'use_second_hsdir_index' is true, use the second hsdir_index of the node_t
* is used. If 'for_fetching' is true, the spread fetch consensus parameter is
@@ -1674,7 +1675,7 @@ hs_pick_hsdir(smartlist_t *responsible_dirs, const char *req_key_str,
return hs_dir;
}
-/* Given a list of link specifiers lspecs, a curve 25519 onion_key, and
+/** Given a list of link specifiers lspecs, a curve 25519 onion_key, and
* a direct connection boolean direct_conn (true for single onion services),
* return a newly allocated extend_info_t object.
*
@@ -1787,7 +1788,7 @@ hs_get_extend_info_from_lspecs(const smartlist_t *lspecs,
/***********************************************************************/
-/* Initialize the entire HS subsytem. This is called in tor_init() before any
+/** Initialize the entire HS subsytem. This is called in tor_init() before any
* torrc options are loaded. Only for >= v3. */
void
hs_init(void)
@@ -1797,7 +1798,7 @@ hs_init(void)
hs_cache_init();
}
-/* Release and cleanup all memory of the HS subsystem (all version). This is
+/** Release and cleanup all memory of the HS subsystem (all version). This is
* called by tor_free_all(). */
void
hs_free_all(void)
@@ -1808,7 +1809,7 @@ hs_free_all(void)
hs_client_free_all();
}
-/* For the given origin circuit circ, decrement the number of rendezvous
+/** For the given origin circuit circ, decrement the number of rendezvous
* stream counter. This handles every hidden service version. */
void
hs_dec_rdv_stream_counter(origin_circuit_t *circ)
@@ -1825,7 +1826,7 @@ hs_dec_rdv_stream_counter(origin_circuit_t *circ)
}
}
-/* For the given origin circuit circ, increment the number of rendezvous
+/** For the given origin circuit circ, increment the number of rendezvous
* stream counter. This handles every hidden service version. */
void
hs_inc_rdv_stream_counter(origin_circuit_t *circ)
@@ -1842,7 +1843,7 @@ hs_inc_rdv_stream_counter(origin_circuit_t *circ)
}
}
-/* Return a newly allocated link specifier object that is a copy of dst. */
+/** Return a newly allocated link specifier object that is a copy of dst. */
link_specifier_t *
link_specifier_dup(const link_specifier_t *src)
{
diff --git a/src/feature/hs/hs_common.h b/src/feature/hs/hs_common.h
index 3009780d90..8f743d4d37 100644
--- a/src/feature/hs/hs_common.h
+++ b/src/feature/hs/hs_common.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -19,13 +19,14 @@ struct ed25519_keypair_t;
/* Trunnel */
#include "trunnel/ed25519_cert.h"
-/* Protocol version 2. Use this instead of hardcoding "2" in the code base,
+/** Protocol version 2. Use this instead of hardcoding "2" in the code base,
* this adds a clearer semantic to the value when used. */
#define HS_VERSION_TWO 2
-/* Version 3 of the protocol (prop224). */
+/** Version 3 of the protocol (prop224). */
#define HS_VERSION_THREE 3
-/* Earliest and latest version we support. */
+/** Earliest version we support. */
#define HS_VERSION_MIN HS_VERSION_TWO
+/** Latest version we support. */
#define HS_VERSION_MAX HS_VERSION_THREE
/** Try to maintain this many intro points per service by default. */
@@ -48,94 +49,95 @@ struct ed25519_keypair_t;
* rendezvous point before giving up? */
#define MAX_REND_TIMEOUT 30
-/* String prefix for the signature of ESTABLISH_INTRO */
+/** String prefix for the signature of ESTABLISH_INTRO */
#define ESTABLISH_INTRO_SIG_PREFIX "Tor establish-intro cell v1"
-/* The default HS time period length */
+/** The default HS time period length */
#define HS_TIME_PERIOD_LENGTH_DEFAULT 1440 /* 1440 minutes == one day */
-/* The minimum time period length as seen in prop224 section [TIME-PERIODS] */
+/** The minimum time period length as seen in prop224 section [TIME-PERIODS] */
#define HS_TIME_PERIOD_LENGTH_MIN 30 /* minutes */
-/* The minimum time period length as seen in prop224 section [TIME-PERIODS] */
+/** The minimum time period length as seen in prop224 section [TIME-PERIODS] */
#define HS_TIME_PERIOD_LENGTH_MAX (60 * 24 * 10) /* 10 days or 14400 minutes */
-/* Prefix of the onion address checksum. */
+/** Prefix of the onion address checksum. */
#define HS_SERVICE_ADDR_CHECKSUM_PREFIX ".onion checksum"
-/* Length of the checksum prefix minus the NUL terminated byte. */
+/** Length of the checksum prefix minus the NUL terminated byte. */
#define HS_SERVICE_ADDR_CHECKSUM_PREFIX_LEN \
(sizeof(HS_SERVICE_ADDR_CHECKSUM_PREFIX) - 1)
-/* Length of the resulting checksum of the address. The construction of this
+/** Length of the resulting checksum of the address. The construction of this
* checksum looks like:
* CHECKSUM = ".onion checksum" || PUBKEY || VERSION
* where VERSION is 1 byte. This is pre-hashing. */
#define HS_SERVICE_ADDR_CHECKSUM_INPUT_LEN \
(HS_SERVICE_ADDR_CHECKSUM_PREFIX_LEN + ED25519_PUBKEY_LEN + sizeof(uint8_t))
-/* The amount of bytes we use from the address checksum. */
+/** The amount of bytes we use from the address checksum. */
#define HS_SERVICE_ADDR_CHECKSUM_LEN_USED 2
-/* Length of the binary encoded service address which is of course before the
+/** Length of the binary encoded service address which is of course before the
* base32 encoding. Construction is:
* PUBKEY || CHECKSUM || VERSION
* with 1 byte VERSION and 2 bytes CHECKSUM. The following is 35 bytes. */
#define HS_SERVICE_ADDR_LEN \
(ED25519_PUBKEY_LEN + HS_SERVICE_ADDR_CHECKSUM_LEN_USED + sizeof(uint8_t))
-/* Length of 'y' portion of 'y.onion' URL. This is base32 encoded and the
+/** Length of 'y' portion of 'y.onion' URL. This is base32 encoded and the
* length ends up to 56 bytes (not counting the terminated NUL byte.) */
#define HS_SERVICE_ADDR_LEN_BASE32 \
(CEIL_DIV(HS_SERVICE_ADDR_LEN * 8, 5))
-/* The default HS time period length */
+/** The default HS time period length */
#define HS_TIME_PERIOD_LENGTH_DEFAULT 1440 /* 1440 minutes == one day */
-/* The minimum time period length as seen in prop224 section [TIME-PERIODS] */
+/** The minimum time period length as seen in prop224 section [TIME-PERIODS] */
#define HS_TIME_PERIOD_LENGTH_MIN 30 /* minutes */
-/* The minimum time period length as seen in prop224 section [TIME-PERIODS] */
+/** The minimum time period length as seen in prop224 section [TIME-PERIODS] */
#define HS_TIME_PERIOD_LENGTH_MAX (60 * 24 * 10) /* 10 days or 14400 minutes */
-/* The time period rotation offset as seen in prop224 section [TIME-PERIODS] */
+/** The time period rotation offset as seen in prop224 section
+ * [TIME-PERIODS] */
#define HS_TIME_PERIOD_ROTATION_OFFSET (12 * 60) /* minutes */
-/* Keyblinding parameter construction is as follow:
+/** Keyblinding parameter construction is as follow:
* "key-blind" || INT_8(period_num) || INT_8(start_period_sec) */
#define HS_KEYBLIND_NONCE_PREFIX "key-blind"
#define HS_KEYBLIND_NONCE_PREFIX_LEN (sizeof(HS_KEYBLIND_NONCE_PREFIX) - 1)
#define HS_KEYBLIND_NONCE_LEN \
(HS_KEYBLIND_NONCE_PREFIX_LEN + sizeof(uint64_t) + sizeof(uint64_t))
-/* Credential and subcredential prefix value. */
+/** Credential and subcredential prefix value. */
#define HS_CREDENTIAL_PREFIX "credential"
#define HS_CREDENTIAL_PREFIX_LEN (sizeof(HS_CREDENTIAL_PREFIX) - 1)
#define HS_SUBCREDENTIAL_PREFIX "subcredential"
#define HS_SUBCREDENTIAL_PREFIX_LEN (sizeof(HS_SUBCREDENTIAL_PREFIX) - 1)
-/* Node hidden service stored at index prefix value. */
+/** Node hidden service stored at index prefix value. */
#define HS_INDEX_PREFIX "store-at-idx"
#define HS_INDEX_PREFIX_LEN (sizeof(HS_INDEX_PREFIX) - 1)
-/* Node hidden service directory index prefix value. */
+/** Node hidden service directory index prefix value. */
#define HSDIR_INDEX_PREFIX "node-idx"
#define HSDIR_INDEX_PREFIX_LEN (sizeof(HSDIR_INDEX_PREFIX) - 1)
-/* Prefix of the shared random value disaster mode. */
+/** Prefix of the shared random value disaster mode. */
#define HS_SRV_DISASTER_PREFIX "shared-random-disaster"
#define HS_SRV_DISASTER_PREFIX_LEN (sizeof(HS_SRV_DISASTER_PREFIX) - 1)
-/* Default value of number of hsdir replicas (hsdir_n_replicas). */
+/** Default value of number of hsdir replicas (hsdir_n_replicas). */
#define HS_DEFAULT_HSDIR_N_REPLICAS 2
-/* Default value of hsdir spread store (hsdir_spread_store). */
+/** Default value of hsdir spread store (hsdir_spread_store). */
#define HS_DEFAULT_HSDIR_SPREAD_STORE 4
-/* Default value of hsdir spread fetch (hsdir_spread_fetch). */
+/** Default value of hsdir spread fetch (hsdir_spread_fetch). */
#define HS_DEFAULT_HSDIR_SPREAD_FETCH 3
-/* The size of a legacy RENDEZVOUS1 cell which adds up to 168 bytes. It is
+/** The size of a legacy RENDEZVOUS1 cell which adds up to 168 bytes. It is
* bigger than the 84 bytes needed for version 3 so we need to pad up to that
* length so it is indistinguishable between versions. */
#define HS_LEGACY_RENDEZVOUS_CELL_SIZE \
(REND_COOKIE_LEN + DH1024_KEY_LEN + DIGEST_LEN)
-/* Type of authentication key used by an introduction point. */
+/** Type of authentication key used by an introduction point. */
typedef enum {
HS_AUTH_KEY_TYPE_LEGACY = 1,
HS_AUTH_KEY_TYPE_ED25519 = 2,
} hs_auth_key_type_t;
-/* Return value when adding an ephemeral service through the ADD_ONION
+/** Return value when adding an ephemeral service through the ADD_ONION
* control port command. Both v2 and v3 share these. */
typedef enum {
RSAE_BADAUTH = -5, /**< Invalid auth_type/auth_clients */
@@ -146,18 +148,18 @@ typedef enum {
RSAE_OKAY = 0 /**< Service added as expected */
} hs_service_add_ephemeral_status_t;
-/* Represents the mapping from a virtual port of a rendezvous service to a
+/** Represents the mapping from a virtual port of a rendezvous service to a
* real port on some IP. */
typedef struct rend_service_port_config_t {
- /* The incoming HS virtual port we're mapping */
+ /** The incoming HS virtual port we're mapping */
uint16_t virtual_port;
- /* Is this an AF_UNIX port? */
+ /** Is this an AF_UNIX port? */
unsigned int is_unix_addr:1;
- /* The outgoing TCP port to use, if !is_unix_addr */
+ /** The outgoing TCP port to use, if !is_unix_addr */
uint16_t real_port;
- /* The outgoing IPv4 or IPv6 address to use, if !is_unix_addr */
+ /** The outgoing IPv4 or IPv6 address to use, if !is_unix_addr */
tor_addr_t real_addr;
- /* The socket path to connect to, if is_unix_addr */
+ /** The socket path to connect to, if is_unix_addr */
char unix_addr[FLEXIBLE_ARRAY_MEMBER];
} rend_service_port_config_t;
diff --git a/src/feature/hs/hs_config.c b/src/feature/hs/hs_config.c
index 3b6caaec6a..64656b1935 100644
--- a/src/feature/hs/hs_config.c
+++ b/src/feature/hs/hs_config.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -23,8 +23,6 @@
* every option that is common to all version (config_generic_service).
**/
-#define HS_CONFIG_PRIVATE
-
#include "feature/hs/hs_common.h"
#include "feature/hs/hs_config.h"
#include "feature/hs/hs_client.h"
@@ -34,7 +32,7 @@
#include "lib/encoding/confline.h"
#include "app/config/or_options_st.h"
-/* Using the given list of services, stage them into our global state. Every
+/** Using the given list of services, stage them into our global state. Every
* service version are handled. This function can remove entries in the given
* service_list.
*
@@ -70,7 +68,7 @@ stage_services(smartlist_t *service_list)
hs_service_stage_services(service_list);
}
-/* Validate the given service against all service in the given list. If the
+/** Validate the given service against all service in the given list. If the
* service is ephemeral, this function ignores it. Services with the same
* directory path aren't allowed and will return an error. If a duplicate is
* found, 1 is returned else 0 if none found. */
@@ -118,7 +116,7 @@ service_is_duplicate_in_list(const smartlist_t *service_list,
return ret;
}
-/* Helper function: Given an configuration option name, its value, a minimum
+/** Helper function: Given an configuration option name, its value, a minimum
* min and a maxium max, parse the value as a uint64_t. On success, ok is set
* to 1 and ret is the parsed value. On error, ok is set to 0 and ret must be
* ignored. This function logs both on error and success. */
@@ -173,7 +171,7 @@ helper_parse_circuit_id_protocol(const char *key, const char *value, int *ok)
return ret;
}
-/* Return the service version by trying to learn it from the key on disk if
+/** Return the service version by trying to learn it from the key on disk if
* any. If nothing is found, the current service configured version is
* returned. */
static int
@@ -191,7 +189,7 @@ config_learn_service_version(hs_service_t *service)
return version;
}
-/* Return true iff the given options starting at line_ for a hidden service
+/** Return true iff the given options starting at line_ for a hidden service
* contains at least one invalid option. Each hidden service option don't
* apply to all versions so this function can find out. The line_ MUST start
* right after the HiddenServiceDir line of this service.
@@ -273,7 +271,7 @@ config_has_invalid_options(const config_line_t *line_,
return ret;
}
-/* Validate service configuration. This is used when loading the configuration
+/** Validate service configuration. This is used when loading the configuration
* and once we've setup a service object, it's config object is passed to this
* function for further validation. This does not validate service key
* material. Return 0 if valid else -1 if invalid. */
@@ -304,7 +302,7 @@ config_validate_service(const hs_service_config_t *config)
return -1;
}
-/* Configuration funcion for a version 3 service. The line_ must be pointing
+/** Configuration funcion for a version 3 service. The line_ must be pointing
* to the directive directly after a HiddenServiceDir. That way, when hitting
* the next HiddenServiceDir line or reaching the end of the list of lines, we
* know that we have to stop looking for more options. The given service
@@ -423,7 +421,7 @@ config_service_v3(const config_line_t *line_,
return -1;
}
-/* Configure a service using the given options in line_ and options. This is
+/** Configure a service using the given options in line_ and options. This is
* called for any service regardless of its version which means that all
* directives in this function are generic to any service version. This
* function will also check the validity of the service directory path.
@@ -577,7 +575,7 @@ config_generic_service(const config_line_t *line_,
return -1;
}
-/* Configure a service using the given line and options. This function will
+/** Configure a service using the given line and options. This function will
* call the corresponding configuration function for a specific service
* version and validate the service against the other ones. On success, add
* the service to the given list and return 0. On error, nothing is added to
@@ -663,7 +661,7 @@ config_service(const config_line_t *line, const or_options_t *options,
return -1;
}
-/* From a set of <b>options</b>, setup every hidden service found. Return 0 on
+/** From a set of <b>options</b>, setup every hidden service found. Return 0 on
* success or -1 on failure. If <b>validate_only</b> is set, parse, warn and
* return as normal, but don't actually change the configured services. */
int
@@ -731,7 +729,7 @@ hs_config_service_all(const or_options_t *options, int validate_only)
return ret;
}
-/* From a set of <b>options</b>, setup every client authorization found.
+/** From a set of <b>options</b>, setup every client authorization found.
* Return 0 on success or -1 on failure. If <b>validate_only</b> is set,
* parse, warn and return as normal, but don't actually change the
* configured state. */
diff --git a/src/feature/hs/hs_config.h b/src/feature/hs/hs_config.h
index beefc7a613..5694cf1e9b 100644
--- a/src/feature/hs/hs_config.h
+++ b/src/feature/hs/hs_config.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/hs/hs_control.c b/src/feature/hs/hs_control.c
index abb421345c..78b0735c29 100644
--- a/src/feature/hs/hs_control.c
+++ b/src/feature/hs/hs_control.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -20,7 +20,7 @@
#include "feature/nodelist/node_st.h"
#include "feature/nodelist/routerstatus_st.h"
-/* Send on the control port the "HS_DESC REQUESTED [...]" event.
+/** Send on the control port the "HS_DESC REQUESTED [...]" event.
*
* The onion_pk is the onion service public key, base64_blinded_pk is the
* base64 encoded blinded key for the service and hsdir_rs is the routerstatus
@@ -57,7 +57,7 @@ hs_control_desc_event_requested(const ed25519_public_key_t *onion_pk,
memwipe(onion_address, 0, sizeof(onion_address));
}
-/* Send on the control port the "HS_DESC FAILED [...]" event.
+/** Send on the control port the "HS_DESC FAILED [...]" event.
*
* Using a directory connection identifier, the HSDir identity digest and a
* reason for the failure. None can be NULL. */
@@ -81,7 +81,7 @@ hs_control_desc_event_failed(const hs_ident_dir_conn_t *ident,
hsdir_id_digest, reason);
}
-/* Send on the control port the "HS_DESC RECEIVED [...]" event.
+/** Send on the control port the "HS_DESC RECEIVED [...]" event.
*
* Using a directory connection identifier and the HSDir identity digest.
* None can be NULL. */
@@ -103,7 +103,7 @@ hs_control_desc_event_received(const hs_ident_dir_conn_t *ident,
hsdir_id_digest);
}
-/* Send on the control port the "HS_DESC CREATED [...]" event.
+/** Send on the control port the "HS_DESC CREATED [...]" event.
*
* Using the onion address of the descriptor's service and the blinded public
* key of the descriptor as a descriptor ID. None can be NULL. */
@@ -124,7 +124,7 @@ hs_control_desc_event_created(const char *onion_address,
control_event_hs_descriptor_created(onion_address, base64_blinded_pk, -1);
}
-/* Send on the control port the "HS_DESC UPLOAD [...]" event.
+/** Send on the control port the "HS_DESC UPLOAD [...]" event.
*
* Using the onion address of the descriptor's service, the HSDir identity
* digest, the blinded public key of the descriptor as a descriptor ID and the
@@ -151,7 +151,7 @@ hs_control_desc_event_upload(const char *onion_address,
DIGEST256_LEN));
}
-/* Send on the control port the "HS_DESC UPLOADED [...]" event.
+/** Send on the control port the "HS_DESC UPLOADED [...]" event.
*
* Using the directory connection identifier and the HSDir identity digest.
* None can be NULL. */
@@ -169,7 +169,7 @@ hs_control_desc_event_uploaded(const hs_ident_dir_conn_t *ident,
control_event_hs_descriptor_uploaded(hsdir_id_digest, onion_address);
}
-/* Send on the control port the "HS_DESC_CONTENT [...]" event.
+/** Send on the control port the "HS_DESC_CONTENT [...]" event.
*
* Using the directory connection identifier, the HSDir identity digest and
* the body of the descriptor (as it was received from the directory). None
@@ -193,7 +193,7 @@ hs_control_desc_event_content(const hs_ident_dir_conn_t *ident,
hsdir_id_digest, body);
}
-/* Handle the "HSPOST [...]" command. The body is an encoded descriptor for
+/** Handle the "HSPOST [...]" command. The body is an encoded descriptor for
* the given onion_address. The descriptor will be uploaded to each directory
* in hsdirs_rs. If NULL, the responsible directories for the current time
* period will be selected.
@@ -248,7 +248,7 @@ hs_control_hspost_command(const char *body, const char *onion_address,
return ret;
}
-/* With a given <b>onion_identity_pk</b>, fetch its descriptor, optionally
+/** With a given <b>onion_identity_pk</b>, fetch its descriptor, optionally
* using the list of directory servers given in <b>hsdirs</b>, or a random
* server if it is NULL. This function calls hs_client_launch_v3_desc_fetch().
*/
diff --git a/src/feature/hs/hs_control.h b/src/feature/hs/hs_control.h
index b55e4c53c9..947b0ebf1c 100644
--- a/src/feature/hs/hs_control.h
+++ b/src/feature/hs/hs_control.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/hs/hs_descriptor.c b/src/feature/hs/hs_descriptor.c
index 924ab3115e..d1c81bbff8 100644
--- a/src/feature/hs/hs_descriptor.c
+++ b/src/feature/hs/hs_descriptor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -56,6 +56,7 @@
#define HS_DESCRIPTOR_PRIVATE
#include "core/or/or.h"
+#include "app/config/config.h"
#include "trunnel/ed25519_cert.h" /* Trunnel interface. */
#include "feature/hs/hs_descriptor.h"
#include "core/or/circuitbuild.h"
@@ -102,7 +103,7 @@
#define str_desc_auth_client "auth-client"
#define str_encrypted "encrypted"
-/* Authentication supported types. */
+/** Authentication supported types. */
static const struct {
hs_desc_auth_type_t type;
const char *identifier;
@@ -112,7 +113,7 @@ static const struct {
{ 0, NULL }
};
-/* Descriptor ruleset. */
+/** Descriptor ruleset. */
static token_rule_t hs_desc_v3_token_table[] = {
T1_START(str_hs_desc, R_HS_DESCRIPTOR, EQ(1), NO_OBJ),
T1(str_lifetime, R3_DESC_LIFETIME, EQ(1), NO_OBJ),
@@ -123,7 +124,7 @@ static token_rule_t hs_desc_v3_token_table[] = {
END_OF_TABLE
};
-/* Descriptor ruleset for the superencrypted section. */
+/** Descriptor ruleset for the superencrypted section. */
static token_rule_t hs_desc_superencrypted_v3_token_table[] = {
T1_START(str_desc_auth_type, R3_DESC_AUTH_TYPE, GE(1), NO_OBJ),
T1(str_desc_auth_key, R3_DESC_AUTH_KEY, GE(1), NO_OBJ),
@@ -132,7 +133,7 @@ static token_rule_t hs_desc_superencrypted_v3_token_table[] = {
END_OF_TABLE
};
-/* Descriptor ruleset for the encrypted section. */
+/** Descriptor ruleset for the encrypted section. */
static token_rule_t hs_desc_encrypted_v3_token_table[] = {
T1_START(str_create2_formats, R3_CREATE2_FORMATS, CONCAT_ARGS, NO_OBJ),
T01(str_intro_auth_required, R3_INTRO_AUTH_REQUIRED, ARGS, NO_OBJ),
@@ -140,7 +141,7 @@ static token_rule_t hs_desc_encrypted_v3_token_table[] = {
END_OF_TABLE
};
-/* Descriptor ruleset for the introduction points section. */
+/** Descriptor ruleset for the introduction points section. */
static token_rule_t hs_desc_intro_point_v3_token_table[] = {
T1_START(str_intro_point, R3_INTRODUCTION_POINT, EQ(1), NO_OBJ),
T1N(str_ip_onion_key, R3_INTRO_ONION_KEY, GE(2), OBJ_OK),
@@ -152,7 +153,7 @@ static token_rule_t hs_desc_intro_point_v3_token_table[] = {
END_OF_TABLE
};
-/* Using a key, salt and encrypted payload, build a MAC and put it in mac_out.
+/** Using a key, salt and encrypted payload, build a MAC and put it in mac_out.
* We use SHA3-256 for the MAC computation.
* This function can't fail. */
static void
@@ -184,7 +185,7 @@ build_mac(const uint8_t *mac_key, size_t mac_key_len,
crypto_digest_free(digest);
}
-/* Using a secret data and a given decriptor object, build the secret
+/** Using a secret data and a given decriptor object, build the secret
* input needed for the KDF.
*
* secret_input = SECRET_DATA | subcredential | INT_8(revision_counter)
@@ -224,7 +225,7 @@ build_secret_input(const hs_descriptor_t *desc,
return secret_input_len;
}
-/* Do the KDF construction and put the resulting data in key_out which is of
+/** Do the KDF construction and put the resulting data in key_out which is of
* key_out_len length. It uses SHAKE-256 as specified in the spec. */
static void
build_kdf_key(const hs_descriptor_t *desc,
@@ -269,7 +270,7 @@ build_kdf_key(const hs_descriptor_t *desc,
tor_free(secret_input);
}
-/* Using the given descriptor, secret data, and salt, run it through our
+/** Using the given descriptor, secret data, and salt, run it through our
* KDF function and then extract a secret key in key_out, the IV in iv_out
* and MAC in mac_out. This function can't fail. */
static void
@@ -308,7 +309,7 @@ build_secret_key_iv_mac(const hs_descriptor_t *desc,
/* === ENCODING === */
-/* Encode the given link specifier objects into a newly allocated string.
+/** Encode the given link specifier objects into a newly allocated string.
* This can't fail so caller can always assume a valid string being
* returned. */
STATIC char *
@@ -355,7 +356,7 @@ encode_link_specifiers(const smartlist_t *specs)
return encoded_b64;
}
-/* Encode an introduction point legacy key and certificate. Return a newly
+/** Encode an introduction point legacy key and certificate. Return a newly
* allocated string with it. On failure, return NULL. */
static char *
encode_legacy_key(const hs_desc_intro_point_t *ip)
@@ -392,7 +393,7 @@ encode_legacy_key(const hs_desc_intro_point_t *ip)
return encoded;
}
-/* Encode an introduction point encryption key and certificate. Return a newly
+/** Encode an introduction point encryption key and certificate. Return a newly
* allocated string with it. On failure, return NULL. */
static char *
encode_enc_key(const hs_desc_intro_point_t *ip)
@@ -418,7 +419,7 @@ encode_enc_key(const hs_desc_intro_point_t *ip)
return encoded;
}
-/* Encode an introduction point onion key. Return a newly allocated string
+/** Encode an introduction point onion key. Return a newly allocated string
* with it. Can not fail. */
static char *
encode_onion_key(const hs_desc_intro_point_t *ip)
@@ -435,7 +436,7 @@ encode_onion_key(const hs_desc_intro_point_t *ip)
return encoded;
}
-/* Encode an introduction point object and return a newly allocated string
+/** Encode an introduction point object and return a newly allocated string
* with it. On failure, return NULL. */
static char *
encode_intro_point(const ed25519_public_key_t *sig_key,
@@ -505,7 +506,7 @@ encode_intro_point(const ed25519_public_key_t *sig_key,
return encoded_ip;
}
-/* Given a source length, return the new size including padding for the
+/** Given a source length, return the new size including padding for the
* plaintext encryption. */
static size_t
compute_padded_plaintext_length(size_t plaintext_len)
@@ -525,7 +526,7 @@ compute_padded_plaintext_length(size_t plaintext_len)
return plaintext_padded_len;
}
-/* Given a buffer, pad it up to the encrypted section padding requirement. Set
+/** Given a buffer, pad it up to the encrypted section padding requirement. Set
* the newly allocated string in padded_out and return the length of the
* padded buffer. */
STATIC size_t
@@ -548,7 +549,7 @@ build_plaintext_padding(const char *plaintext, size_t plaintext_len,
return padded_len;
}
-/* Using a key, IV and plaintext data of length plaintext_len, create the
+/** Using a key, IV and plaintext data of length plaintext_len, create the
* encrypted section by encrypting it and setting encrypted_out with the
* data. Return size of the encrypted data buffer. */
static size_t
@@ -593,7 +594,7 @@ build_encrypted(const uint8_t *key, const uint8_t *iv, const char *plaintext,
return encrypted_len;
}
-/* Encrypt the given <b>plaintext</b> buffer using <b>desc</b> and
+/** Encrypt the given <b>plaintext</b> buffer using <b>desc</b> and
* <b>secret_data</b> to get the keys. Set encrypted_out with the encrypted
* data and return the length of it. <b>is_superencrypted_layer</b> is set
* if this is the outer encrypted layer of the descriptor. */
@@ -663,7 +664,7 @@ encrypt_descriptor_data(const hs_descriptor_t *desc,
return final_blob_len;
}
-/* Create and return a string containing a client-auth entry. It's the
+/** Create and return a string containing a client-auth entry. It's the
* responsibility of the caller to free the returned string. This function
* will never fail. */
static char *
@@ -733,7 +734,7 @@ get_all_auth_client_lines(const hs_descriptor_t *desc)
return auth_client_lines_str;
}
-/* Create the inner layer of the descriptor (which includes the intro points,
+/** Create the inner layer of the descriptor (which includes the intro points,
* etc.). Return a newly-allocated string with the layer plaintext, or NULL if
* an error occurred. It's the responsibility of the caller to free the
* returned string. */
@@ -789,7 +790,7 @@ get_inner_encrypted_layer_plaintext(const hs_descriptor_t *desc)
return encoded_str;
}
-/* Create the middle layer of the descriptor, which includes the client auth
+/** Create the middle layer of the descriptor, which includes the client auth
* data and the encrypted inner layer (provided as a base64 string at
* <b>layer2_b64_ciphertext</b>). Return a newly-allocated string with the
* layer plaintext. It's the responsibility of the caller to free the returned
@@ -845,7 +846,7 @@ get_outer_encrypted_layer_plaintext(const hs_descriptor_t *desc,
return layer1_str;
}
-/* Encrypt <b>encoded_str</b> into an encrypted blob and then base64 it before
+/** Encrypt <b>encoded_str</b> into an encrypted blob and then base64 it before
* returning it. <b>desc</b> is provided to derive the encryption
* keys. <b>secret_data</b> is also proved to derive the encryption keys.
* <b>is_superencrypted_layer</b> is set if <b>encoded_str</b> is the
@@ -878,7 +879,7 @@ encrypt_desc_data_and_base64(const hs_descriptor_t *desc,
return enc_b64;
}
-/* Generate the secret data which is used to encrypt/decrypt the descriptor.
+/** Generate the secret data which is used to encrypt/decrypt the descriptor.
*
* SECRET_DATA = blinded-public-key
* SECRET_DATA = blinded-public-key | descriptor_cookie
@@ -925,7 +926,7 @@ build_secret_data(const ed25519_public_key_t *blinded_pubkey,
return secret_data_len;
}
-/* Generate and encode the superencrypted portion of <b>desc</b>. This also
+/** Generate and encode the superencrypted portion of <b>desc</b>. This also
* involves generating the encrypted portion of the descriptor, and performing
* the superencryption. A newly allocated NUL-terminated string pointer
* containing the encrypted encoded blob is put in encrypted_blob_out. Return 0
@@ -999,7 +1000,7 @@ encode_superencrypted_data(const hs_descriptor_t *desc,
return ret;
}
-/* Encode a v3 HS descriptor. Return 0 on success and set encoded_out to the
+/** Encode a v3 HS descriptor. Return 0 on success and set encoded_out to the
* newly allocated string of the encoded descriptor. On error, -1 is returned
* and encoded_out is untouched. */
static int
@@ -1111,7 +1112,7 @@ desc_encode_v3(const hs_descriptor_t *desc,
/* === DECODING === */
-/* Given the token tok for an auth client, decode it as
+/** Given the token tok for an auth client, decode it as
* hs_desc_authorized_client_t. tok->args MUST contain at least 3 elements
* Return 0 on success else -1 on failure. */
static int
@@ -1147,7 +1148,7 @@ decode_auth_client(const directory_token_t *tok,
return ret;
}
-/* Given an encoded string of the link specifiers, return a newly allocated
+/** Given an encoded string of the link specifiers, return a newly allocated
* list of decoded link specifiers. Return NULL on error. */
STATIC smartlist_t *
decode_link_specifiers(const char *encoded)
@@ -1201,7 +1202,7 @@ decode_link_specifiers(const char *encoded)
return results;
}
-/* Given a list of authentication types, decode it and put it in the encrypted
+/** Given a list of authentication types, decode it and put it in the encrypted
* data section. Return 1 if we at least know one of the type or 0 if we know
* none of them. */
static int
@@ -1229,7 +1230,7 @@ decode_auth_type(hs_desc_encrypted_data_t *desc, const char *list)
return match;
}
-/* Parse a space-delimited list of integers representing CREATE2 formats into
+/** Parse a space-delimited list of integers representing CREATE2 formats into
* the bitfield in hs_desc_encrypted_data_t. Ignore unrecognized values. */
static void
decode_create2_list(hs_desc_encrypted_data_t *desc, const char *list)
@@ -1263,7 +1264,7 @@ decode_create2_list(hs_desc_encrypted_data_t *desc, const char *list)
smartlist_free(tokens);
}
-/* Given a certificate, validate the certificate for certain conditions which
+/** Given a certificate, validate the certificate for certain conditions which
* are if the given type matches the cert's one, if the signing key is
* included and if the that key was actually used to sign the certificate.
*
@@ -1287,11 +1288,20 @@ cert_is_valid(tor_cert_t *cert, uint8_t type, const char *log_obj_type)
log_warn(LD_REND, "Signing key is NOT included for %s.", log_obj_type);
goto err;
}
+
/* The following will not only check if the signature matches but also the
* expiration date and overall validity. */
if (tor_cert_checksig(cert, &cert->signing_key, approx_time()) < 0) {
- log_warn(LD_REND, "Invalid signature for %s: %s", log_obj_type,
- tor_cert_describe_signature_status(cert));
+ if (cert->cert_expired) {
+ char expiration_str[ISO_TIME_LEN+1];
+ format_iso_time(expiration_str, cert->valid_until);
+ log_fn(LOG_PROTOCOL_WARN, LD_REND, "Invalid signature for %s: %s (%s)",
+ log_obj_type, tor_cert_describe_signature_status(cert),
+ expiration_str);
+ } else {
+ log_warn(LD_REND, "Invalid signature for %s: %s",
+ log_obj_type, tor_cert_describe_signature_status(cert));
+ }
goto err;
}
@@ -1300,7 +1310,7 @@ cert_is_valid(tor_cert_t *cert, uint8_t type, const char *log_obj_type)
return 0;
}
-/* Given some binary data, try to parse it to get a certificate object. If we
+/** Given some binary data, try to parse it to get a certificate object. If we
* have a valid cert, validate it using the given wanted type. On error, print
* a log using the err_msg has the certificate identifier adding semantic to
* the log and cert_out is set to NULL. On success, 0 is returned and cert_out
@@ -1337,7 +1347,7 @@ cert_parse_and_validate(tor_cert_t **cert_out, const char *data,
return -1;
}
-/* Return true iff the given length of the encrypted data of a descriptor
+/** Return true iff the given length of the encrypted data of a descriptor
* passes validation. */
STATIC int
encrypted_data_length_is_valid(size_t len)
@@ -1356,7 +1366,7 @@ encrypted_data_length_is_valid(size_t len)
return 0;
}
-/* Build the KEYS component for the authorized client computation. The format
+/** Build the KEYS component for the authorized client computation. The format
* of the construction is:
*
* SECRET_SEED = x25519(sk, pk)
@@ -1400,7 +1410,7 @@ build_descriptor_cookie_keys(const uint8_t *subcredential,
return keystream_len;
}
-/* Decrypt the descriptor cookie given the descriptor, the auth client,
+/** Decrypt the descriptor cookie given the descriptor, the auth client,
* and the client secret key. On sucess, return 0 and a newly allocated
* descriptor cookie descriptor_cookie_out. On error or if the client id
* is invalid, return -1 and descriptor_cookie_out is set to
@@ -1424,10 +1434,14 @@ decrypt_descriptor_cookie(const hs_descriptor_t *desc,
tor_assert(!fast_mem_is_zero(
(char *) &desc->superencrypted_data.auth_ephemeral_pubkey,
sizeof(desc->superencrypted_data.auth_ephemeral_pubkey)));
- tor_assert(!fast_mem_is_zero((char *) client_auth_sk,
- sizeof(*client_auth_sk)));
tor_assert(!fast_mem_is_zero((char *) desc->subcredential, DIGEST256_LEN));
+ /* Catch potential code-flow cases of an unitialized private key sneaking
+ * into this function. */
+ if (BUG(fast_mem_is_zero((char *)client_auth_sk, sizeof(*client_auth_sk)))) {
+ goto done;
+ }
+
/* Get the KEYS component to derive the CLIENT-ID and COOKIE-KEY. */
keystream_length =
build_descriptor_cookie_keys(desc->subcredential, DIGEST256_LEN,
@@ -1592,7 +1606,7 @@ decrypt_desc_layer,(const hs_descriptor_t *desc,
return result_len;
}
-/* Decrypt the superencrypted section of the descriptor using the given
+/** Decrypt the superencrypted section of the descriptor using the given
* descriptor object <b>desc</b>. A newly allocated NUL terminated string is
* put in decrypted_out which contains the superencrypted layer of the
* descriptor. Return the length of decrypted_out on success else 0 is
@@ -1624,7 +1638,7 @@ desc_decrypt_superencrypted(const hs_descriptor_t *desc, char **decrypted_out)
return superencrypted_len;
}
-/* Decrypt the encrypted section of the descriptor using the given descriptor
+/** Decrypt the encrypted section of the descriptor using the given descriptor
* object <b>desc</b>. A newly allocated NUL terminated string is put in
* decrypted_out which contains the encrypted layer of the descriptor.
* Return the length of decrypted_out on success else 0 is returned and
@@ -1677,7 +1691,7 @@ desc_decrypt_encrypted(const hs_descriptor_t *desc,
return encrypted_len;
}
-/* Given the token tok for an intro point legacy key, the list of tokens, the
+/** Given the token tok for an intro point legacy key, the list of tokens, the
* introduction point ip being decoded and the descriptor desc from which it
* comes from, decode the legacy key and set the intro point object. Return 0
* on success else -1 on failure. */
@@ -1735,7 +1749,7 @@ decode_intro_legacy_key(const directory_token_t *tok,
return -1;
}
-/* Dig into the descriptor <b>tokens</b> to find the onion key we should use
+/** Dig into the descriptor <b>tokens</b> to find the onion key we should use
* for this intro point, and set it into <b>onion_key_out</b>. Return 0 if it
* was found and well-formed, otherwise return -1 in case of errors. */
static int
@@ -1779,7 +1793,7 @@ set_intro_point_onion_key(curve25519_public_key_t *onion_key_out,
return retval;
}
-/* Given the start of a section and the end of it, decode a single
+/** Given the start of a section and the end of it, decode a single
* introduction point from that section. Return a newly allocated introduction
* point object containing the decoded data. Return NULL if the section can't
* be decoded. */
@@ -1908,7 +1922,7 @@ decode_introduction_point(const hs_descriptor_t *desc, const char *start)
return ip;
}
-/* Given a descriptor string at <b>data</b>, decode all possible introduction
+/** Given a descriptor string at <b>data</b>, decode all possible introduction
* points that we can find. Add the introduction point object to desc_enc as we
* find them. This function can't fail and it is possible that zero
* introduction points can be decoded. */
@@ -1972,7 +1986,7 @@ decode_intro_points(const hs_descriptor_t *desc,
smartlist_free(intro_points);
}
-/* Return 1 iff the given base64 encoded signature in b64_sig from the encoded
+/** Return 1 iff the given base64 encoded signature in b64_sig from the encoded
* descriptor in encoded_desc validates the descriptor content. */
STATIC int
desc_sig_is_valid(const char *b64_sig,
@@ -2031,14 +2045,14 @@ desc_sig_is_valid(const char *b64_sig,
return ret;
}
-/* Decode descriptor plaintext data for version 3. Given a list of tokens, an
+/** Decode descriptor plaintext data for version 3. Given a list of tokens, an
* allocated plaintext object that will be populated and the encoded
* descriptor with its length. The last one is needed for signature
* verification. Unknown tokens are simply ignored so this won't error on
* unknowns but requires that all v3 token be present and valid.
*
* Return 0 on success else a negative value. */
-static int
+static hs_desc_decode_status_t
desc_decode_plaintext_v3(smartlist_t *tokens,
hs_desc_plaintext_data_t *desc,
const char *encoded_desc, size_t encoded_len)
@@ -2128,21 +2142,19 @@ desc_decode_plaintext_v3(smartlist_t *tokens,
goto err;
}
- return 0;
-
+ return HS_DESC_DECODE_OK;
err:
- return -1;
+ return HS_DESC_DECODE_PLAINTEXT_ERROR;
}
-/* Decode the version 3 superencrypted section of the given descriptor desc.
- * The desc_superencrypted_out will be populated with the decoded data.
- * Return 0 on success else -1. */
-static int
+/** Decode the version 3 superencrypted section of the given descriptor desc.
+ * The desc_superencrypted_out will be populated with the decoded data. */
+static hs_desc_decode_status_t
desc_decode_superencrypted_v3(const hs_descriptor_t *desc,
hs_desc_superencrypted_data_t *
desc_superencrypted_out)
{
- int ret = -1;
+ int ret = HS_DESC_DECODE_SUPERENC_ERROR;
char *message = NULL;
size_t message_len;
memarea_t *area = NULL;
@@ -2228,11 +2240,11 @@ desc_decode_superencrypted_v3(const hs_descriptor_t *desc,
tok->object_size);
superencrypted->encrypted_blob_size = tok->object_size;
- ret = 0;
+ ret = HS_DESC_DECODE_OK;
goto done;
err:
- tor_assert(ret < 0);
+ tor_assert(ret < HS_DESC_DECODE_OK);
hs_desc_superencrypted_data_free_contents(desc_superencrypted_out);
done:
@@ -2249,15 +2261,14 @@ desc_decode_superencrypted_v3(const hs_descriptor_t *desc,
return ret;
}
-/* Decode the version 3 encrypted section of the given descriptor desc. The
- * desc_encrypted_out will be populated with the decoded data. Return 0 on
- * success else -1. */
-static int
+/** Decode the version 3 encrypted section of the given descriptor desc. The
+ * desc_encrypted_out will be populated with the decoded data. */
+static hs_desc_decode_status_t
desc_decode_encrypted_v3(const hs_descriptor_t *desc,
const curve25519_secret_key_t *client_auth_sk,
hs_desc_encrypted_data_t *desc_encrypted_out)
{
- int ret = -1;
+ int ret = HS_DESC_DECODE_ENCRYPTED_ERROR;
char *message = NULL;
size_t message_len;
memarea_t *area = NULL;
@@ -2280,12 +2291,14 @@ desc_decode_encrypted_v3(const hs_descriptor_t *desc,
* authorization is failing. */
log_warn(LD_REND, "Client authorization for requested onion address "
"is invalid. Can't decrypt the descriptor.");
+ ret = HS_DESC_DECODE_BAD_CLIENT_AUTH;
} else {
/* Inform at notice level that the onion address requested can't be
* reached without client authorization most likely. */
log_notice(LD_REND, "Fail to decrypt descriptor for requested onion "
"address. It is likely requiring client "
"authorization.");
+ ret = HS_DESC_DECODE_NEED_CLIENT_AUTH;
}
goto err;
}
@@ -2343,11 +2356,11 @@ desc_decode_encrypted_v3(const hs_descriptor_t *desc,
/* NOTE: Unknown fields are allowed because this function could be used to
* decode other descriptor version. */
- ret = 0;
+ ret = HS_DESC_DECODE_OK;
goto done;
err:
- tor_assert(ret < 0);
+ tor_assert(ret < HS_DESC_DECODE_OK);
hs_desc_encrypted_data_free_contents(desc_encrypted_out);
done:
@@ -2364,9 +2377,9 @@ desc_decode_encrypted_v3(const hs_descriptor_t *desc,
return ret;
}
-/* Table of encrypted decode function version specific. The function are
+/** Table of encrypted decode function version specific. The function are
* indexed by the version number so v3 callback is at index 3 in the array. */
-static int
+static hs_desc_decode_status_t
(*decode_encrypted_handlers[])(
const hs_descriptor_t *desc,
const curve25519_secret_key_t *client_auth_sk,
@@ -2376,15 +2389,15 @@ static int
desc_decode_encrypted_v3,
};
-/* Decode the encrypted data section of the given descriptor and store the
+/** Decode the encrypted data section of the given descriptor and store the
* data in the given encrypted data object. Return 0 on success else a
* negative value on error. */
-int
+hs_desc_decode_status_t
hs_desc_decode_encrypted(const hs_descriptor_t *desc,
const curve25519_secret_key_t *client_auth_sk,
hs_desc_encrypted_data_t *desc_encrypted)
{
- int ret;
+ int ret = HS_DESC_DECODE_ENCRYPTED_ERROR;
uint32_t version;
tor_assert(desc);
@@ -2398,7 +2411,6 @@ hs_desc_decode_encrypted(const hs_descriptor_t *desc,
/* Let's make sure we have a supported version as well. By correctly parsing
* the plaintext, this should not fail. */
if (BUG(!hs_desc_is_supported_version(version))) {
- ret = -1;
goto err;
}
/* Extra precaution. Having no handler for the supported version should
@@ -2417,9 +2429,9 @@ hs_desc_decode_encrypted(const hs_descriptor_t *desc,
return ret;
}
-/* Table of superencrypted decode function version specific. The function are
+/** Table of superencrypted decode function version specific. The function are
* indexed by the version number so v3 callback is at index 3 in the array. */
-static int
+static hs_desc_decode_status_t
(*decode_superencrypted_handlers[])(
const hs_descriptor_t *desc,
hs_desc_superencrypted_data_t *desc_superencrypted) =
@@ -2428,15 +2440,14 @@ static int
desc_decode_superencrypted_v3,
};
-/* Decode the superencrypted data section of the given descriptor and store the
- * data in the given superencrypted data object. Return 0 on success else a
- * negative value on error. */
-int
+/** Decode the superencrypted data section of the given descriptor and store
+ * the data in the given superencrypted data object. */
+hs_desc_decode_status_t
hs_desc_decode_superencrypted(const hs_descriptor_t *desc,
hs_desc_superencrypted_data_t *
desc_superencrypted)
{
- int ret;
+ int ret = HS_DESC_DECODE_SUPERENC_ERROR;
uint32_t version;
tor_assert(desc);
@@ -2450,7 +2461,6 @@ hs_desc_decode_superencrypted(const hs_descriptor_t *desc,
/* Let's make sure we have a supported version as well. By correctly parsing
* the plaintext, this should not fail. */
if (BUG(!hs_desc_is_supported_version(version))) {
- ret = -1;
goto err;
}
/* Extra precaution. Having no handler for the supported version should
@@ -2468,9 +2478,9 @@ hs_desc_decode_superencrypted(const hs_descriptor_t *desc,
return ret;
}
-/* Table of plaintext decode function version specific. The function are
+/** Table of plaintext decode function version specific. The function are
* indexed by the version number so v3 callback is at index 3 in the array. */
-static int
+static hs_desc_decode_status_t
(*decode_plaintext_handlers[])(
smartlist_t *tokens,
hs_desc_plaintext_data_t *desc,
@@ -2481,13 +2491,13 @@ static int
desc_decode_plaintext_v3,
};
-/* Fully decode the given descriptor plaintext and store the data in the
- * plaintext data object. Returns 0 on success else a negative value. */
-int
+/** Fully decode the given descriptor plaintext and store the data in the
+ * plaintext data object. */
+hs_desc_decode_status_t
hs_desc_decode_plaintext(const char *encoded,
hs_desc_plaintext_data_t *plaintext)
{
- int ok = 0, ret = -1;
+ int ok = 0, ret = HS_DESC_DECODE_PLAINTEXT_ERROR;
memarea_t *area = NULL;
smartlist_t *tokens = NULL;
size_t encoded_len;
@@ -2537,11 +2547,11 @@ hs_desc_decode_plaintext(const char *encoded,
/* Run the version specific plaintext decoder. */
ret = decode_plaintext_handlers[plaintext->version](tokens, plaintext,
encoded, encoded_len);
- if (ret < 0) {
+ if (ret != HS_DESC_DECODE_OK) {
goto err;
}
/* Success. Descriptor has been populated with the data. */
- ret = 0;
+ ret = HS_DESC_DECODE_OK;
err:
if (tokens) {
@@ -2554,19 +2564,19 @@ hs_desc_decode_plaintext(const char *encoded,
return ret;
}
-/* Fully decode an encoded descriptor and set a newly allocated descriptor
+/** Fully decode an encoded descriptor and set a newly allocated descriptor
* object in desc_out. Client secret key is used to decrypt the "encrypted"
* section if not NULL else it's ignored.
*
* Return 0 on success. A negative value is returned on error and desc_out is
* set to NULL. */
-int
+hs_desc_decode_status_t
hs_desc_decode_descriptor(const char *encoded,
const uint8_t *subcredential,
const curve25519_secret_key_t *client_auth_sk,
hs_descriptor_t **desc_out)
{
- int ret = -1;
+ hs_desc_decode_status_t ret = HS_DESC_DECODE_GENERIC_ERROR;
hs_descriptor_t *desc;
tor_assert(encoded);
@@ -2583,17 +2593,17 @@ hs_desc_decode_descriptor(const char *encoded,
memcpy(desc->subcredential, subcredential, sizeof(desc->subcredential));
ret = hs_desc_decode_plaintext(encoded, &desc->plaintext_data);
- if (ret < 0) {
+ if (ret != HS_DESC_DECODE_OK) {
goto err;
}
ret = hs_desc_decode_superencrypted(desc, &desc->superencrypted_data);
- if (ret < 0) {
+ if (ret != HS_DESC_DECODE_OK) {
goto err;
}
ret = hs_desc_decode_encrypted(desc, client_auth_sk, &desc->encrypted_data);
- if (ret < 0) {
+ if (ret != HS_DESC_DECODE_OK) {
goto err;
}
@@ -2614,7 +2624,7 @@ hs_desc_decode_descriptor(const char *encoded,
return ret;
}
-/* Table of encode function version specific. The functions are indexed by the
+/** Table of encode function version specific. The functions are indexed by the
* version number so v3 callback is at index 3 in the array. */
static int
(*encode_handlers[])(
@@ -2627,7 +2637,7 @@ static int
desc_encode_v3,
};
-/* Encode the given descriptor desc including signing with the given key pair
+/** Encode the given descriptor desc including signing with the given key pair
* signing_kp and encrypting with the given descriptor cookie.
*
* If the client authorization is enabled, descriptor_cookie must be the same
@@ -2672,7 +2682,8 @@ hs_desc_encode_descriptor,(const hs_descriptor_t *desc,
if (!descriptor_cookie) {
ret = hs_desc_decode_descriptor(*encoded_out, desc->subcredential,
NULL, NULL);
- if (BUG(ret < 0)) {
+ if (BUG(ret != HS_DESC_DECODE_OK)) {
+ ret = -1;
goto err;
}
}
@@ -2684,7 +2695,7 @@ hs_desc_encode_descriptor,(const hs_descriptor_t *desc,
return ret;
}
-/* Free the content of the plaintext section of a descriptor. */
+/** Free the content of the plaintext section of a descriptor. */
void
hs_desc_plaintext_data_free_contents(hs_desc_plaintext_data_t *desc)
{
@@ -2700,7 +2711,7 @@ hs_desc_plaintext_data_free_contents(hs_desc_plaintext_data_t *desc)
memwipe(desc, 0, sizeof(*desc));
}
-/* Free the content of the superencrypted section of a descriptor. */
+/** Free the content of the superencrypted section of a descriptor. */
void
hs_desc_superencrypted_data_free_contents(hs_desc_superencrypted_data_t *desc)
{
@@ -2720,7 +2731,7 @@ hs_desc_superencrypted_data_free_contents(hs_desc_superencrypted_data_t *desc)
memwipe(desc, 0, sizeof(*desc));
}
-/* Free the content of the encrypted section of a descriptor. */
+/** Free the content of the encrypted section of a descriptor. */
void
hs_desc_encrypted_data_free_contents(hs_desc_encrypted_data_t *desc)
{
@@ -2740,7 +2751,7 @@ hs_desc_encrypted_data_free_contents(hs_desc_encrypted_data_t *desc)
memwipe(desc, 0, sizeof(*desc));
}
-/* Free the descriptor plaintext data object. */
+/** Free the descriptor plaintext data object. */
void
hs_desc_plaintext_data_free_(hs_desc_plaintext_data_t *desc)
{
@@ -2748,7 +2759,7 @@ hs_desc_plaintext_data_free_(hs_desc_plaintext_data_t *desc)
tor_free(desc);
}
-/* Free the descriptor plaintext data object. */
+/** Free the descriptor plaintext data object. */
void
hs_desc_superencrypted_data_free_(hs_desc_superencrypted_data_t *desc)
{
@@ -2756,7 +2767,7 @@ hs_desc_superencrypted_data_free_(hs_desc_superencrypted_data_t *desc)
tor_free(desc);
}
-/* Free the descriptor encrypted data object. */
+/** Free the descriptor encrypted data object. */
void
hs_desc_encrypted_data_free_(hs_desc_encrypted_data_t *desc)
{
@@ -2764,7 +2775,7 @@ hs_desc_encrypted_data_free_(hs_desc_encrypted_data_t *desc)
tor_free(desc);
}
-/* Free the given descriptor object. */
+/** Free the given descriptor object. */
void
hs_descriptor_free_(hs_descriptor_t *desc)
{
@@ -2778,7 +2789,7 @@ hs_descriptor_free_(hs_descriptor_t *desc)
tor_free(desc);
}
-/* Return the size in bytes of the given plaintext data object. A sizeof() is
+/** Return the size in bytes of the given plaintext data object. A sizeof() is
* not enough because the object contains pointers and the encrypted blob.
* This is particularly useful for our OOM subsystem that tracks the HSDir
* cache size for instance. */
@@ -2790,7 +2801,7 @@ hs_desc_plaintext_obj_size(const hs_desc_plaintext_data_t *data)
data->superencrypted_blob_size);
}
-/* Return the size in bytes of the given encrypted data object. Used by OOM
+/** Return the size in bytes of the given encrypted data object. Used by OOM
* subsystem. */
static size_t
hs_desc_encrypted_obj_size(const hs_desc_encrypted_data_t *data)
@@ -2810,18 +2821,20 @@ hs_desc_encrypted_obj_size(const hs_desc_encrypted_data_t *data)
return sizeof(*data) + intro_size;
}
-/* Return the size in bytes of the given descriptor object. Used by OOM
+/** Return the size in bytes of the given descriptor object. Used by OOM
* subsystem. */
size_t
hs_desc_obj_size(const hs_descriptor_t *data)
{
- tor_assert(data);
+ if (data == NULL) {
+ return 0;
+ }
return (hs_desc_plaintext_obj_size(&data->plaintext_data) +
hs_desc_encrypted_obj_size(&data->encrypted_data) +
sizeof(data->subcredential));
}
-/* Return a newly allocated descriptor intro point. */
+/** Return a newly allocated descriptor intro point. */
hs_desc_intro_point_t *
hs_desc_intro_point_new(void)
{
@@ -2830,7 +2843,7 @@ hs_desc_intro_point_new(void)
return ip;
}
-/* Free a descriptor intro point object. */
+/** Free a descriptor intro point object. */
void
hs_desc_intro_point_free_(hs_desc_intro_point_t *ip)
{
@@ -2849,7 +2862,7 @@ hs_desc_intro_point_free_(hs_desc_intro_point_t *ip)
tor_free(ip);
}
-/* Allocate and build a new fake client info for the descriptor. Return a
+/** Allocate and build a new fake client info for the descriptor. Return a
* newly allocated object. This can't fail. */
hs_desc_authorized_client_t *
hs_desc_build_fake_authorized_client(void)
@@ -2867,7 +2880,7 @@ hs_desc_build_fake_authorized_client(void)
return client_auth;
}
-/* Using the service's subcredential, client public key, auth ephemeral secret
+/** Using the service's subcredential, client public key, auth ephemeral secret
* key, and descriptor cookie, build the auth client so we can then encode the
* descriptor for publication. client_out must be already allocated. */
void
@@ -2925,14 +2938,14 @@ hs_desc_build_authorized_client(const uint8_t *subcredential,
crypto_cipher_free(cipher);
}
-/* Free an authoriezd client object. */
+/** Free an authoriezd client object. */
void
hs_desc_authorized_client_free_(hs_desc_authorized_client_t *client)
{
tor_free(client);
}
-/* From the given descriptor, remove and free every introduction point. */
+/** From the given descriptor, remove and free every introduction point. */
void
hs_descriptor_clear_intro_points(hs_descriptor_t *desc)
{
diff --git a/src/feature/hs/hs_descriptor.h b/src/feature/hs/hs_descriptor.h
index 0a843f4f3c..639dd31c8f 100644
--- a/src/feature/hs/hs_descriptor.h
+++ b/src/feature/hs/hs_descriptor.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -18,88 +18,113 @@
/* Trunnel */
struct link_specifier_t;
-/* The earliest descriptor format version we support. */
+/** The earliest descriptor format version we support. */
#define HS_DESC_SUPPORTED_FORMAT_VERSION_MIN 3
-/* The latest descriptor format version we support. */
+/** The latest descriptor format version we support. */
#define HS_DESC_SUPPORTED_FORMAT_VERSION_MAX 3
-/* Default lifetime of a descriptor in seconds. The valus is set at 3 hours
+/** Default lifetime of a descriptor in seconds. The valus is set at 3 hours
* which is 180 minutes or 10800 seconds. */
#define HS_DESC_DEFAULT_LIFETIME (3 * 60 * 60)
-/* Maximum lifetime of a descriptor in seconds. The value is set at 12 hours
+/** Maximum lifetime of a descriptor in seconds. The value is set at 12 hours
* which is 720 minutes or 43200 seconds. */
#define HS_DESC_MAX_LIFETIME (12 * 60 * 60)
-/* Lifetime of certificate in the descriptor. This defines the lifetime of the
+/** Lifetime of certificate in the descriptor. This defines the lifetime of the
* descriptor signing key and the cross certification cert of that key. It is
* set to 54 hours because a descriptor can be around for 48 hours and because
* consensuses are used after the hour, add an extra 6 hours to give some time
* for the service to stop using it. */
#define HS_DESC_CERT_LIFETIME (54 * 60 * 60)
-/* Length of the salt needed for the encrypted section of a descriptor. */
+/** Length of the salt needed for the encrypted section of a descriptor. */
#define HS_DESC_ENCRYPTED_SALT_LEN 16
-/* Length of the KDF output value which is the length of the secret key,
+/** Length of the KDF output value which is the length of the secret key,
* the secret IV and MAC key length which is the length of H() output. */
#define HS_DESC_ENCRYPTED_KDF_OUTPUT_LEN \
CIPHER256_KEY_LEN + CIPHER_IV_LEN + DIGEST256_LEN
-/* Pad plaintext of superencrypted data section before encryption so that its
+/** Pad plaintext of superencrypted data section before encryption so that its
* length is a multiple of this value. */
#define HS_DESC_SUPERENC_PLAINTEXT_PAD_MULTIPLE 10000
-/* Maximum length in bytes of a full hidden service descriptor. */
+/** Maximum length in bytes of a full hidden service descriptor. */
#define HS_DESC_MAX_LEN 50000 /* 50kb max size */
-/* Key length for the descriptor symmetric encryption. As specified in the
+/** Key length for the descriptor symmetric encryption. As specified in the
* protocol, we use AES-256 for the encrypted section of the descriptor. The
* following is the length in bytes and the bit size. */
#define HS_DESC_ENCRYPTED_KEY_LEN CIPHER256_KEY_LEN
#define HS_DESC_ENCRYPTED_BIT_SIZE (HS_DESC_ENCRYPTED_KEY_LEN * 8)
-/* Length of each components in the auth client section in the descriptor. */
+/** Length of each components in the auth client section in the descriptor. */
#define HS_DESC_CLIENT_ID_LEN 8
#define HS_DESC_DESCRIPTOR_COOKIE_LEN 16
#define HS_DESC_COOKIE_KEY_LEN 32
#define HS_DESC_COOKIE_KEY_BIT_SIZE (HS_DESC_COOKIE_KEY_LEN * 8)
#define HS_DESC_ENCRYPED_COOKIE_LEN HS_DESC_DESCRIPTOR_COOKIE_LEN
-/* The number of auth client entries in the descriptor must be the multiple
+/** The number of auth client entries in the descriptor must be the multiple
* of this constant. */
#define HS_DESC_AUTH_CLIENT_MULTIPLE 16
-/* Type of authentication in the descriptor. */
+/** Type of authentication in the descriptor. */
typedef enum {
HS_DESC_AUTH_ED25519 = 1
} hs_desc_auth_type_t;
-/* Introduction point information located in a descriptor. */
+/** Error code when decoding a descriptor. */
+typedef enum {
+ /* The configured client authorization for the requested .onion address
+ * failed to decode the descriptor. */
+ HS_DESC_DECODE_BAD_CLIENT_AUTH = -6,
+
+ /* The requested .onion address requires a client authorization. */
+ HS_DESC_DECODE_NEED_CLIENT_AUTH = -5,
+
+ /* Error during decryption of the encrypted layer. */
+ HS_DESC_DECODE_ENCRYPTED_ERROR = -4,
+
+ /* Error during decryption of the super encrypted layer. */
+ HS_DESC_DECODE_SUPERENC_ERROR = -3,
+
+ /* Error while decoding the plaintext section. */
+ HS_DESC_DECODE_PLAINTEXT_ERROR = -2,
+
+ /* Generic error. */
+ HS_DESC_DECODE_GENERIC_ERROR = -1,
+
+ /* Decoding a descriptor was successful. */
+ HS_DESC_DECODE_OK = 0,
+} hs_desc_decode_status_t;
+
+/** Introduction point information located in a descriptor. */
typedef struct hs_desc_intro_point_t {
- /* Link specifier(s) which details how to extend to the relay. This list
+ /** Link specifier(s) which details how to extend to the relay. This list
* contains link_specifier_t objects. It MUST have at least one. */
smartlist_t *link_specifiers;
- /* Onion key of the introduction point used to extend to it for the ntor
+ /** Onion key of the introduction point used to extend to it for the ntor
* handshake. */
curve25519_public_key_t onion_key;
- /* Authentication key used to establish the introduction point circuit and
+ /** Authentication key used to establish the introduction point circuit and
* cross-certifies the blinded public key for the replica thus signed by
* the blinded key and in turn signs it. */
tor_cert_t *auth_key_cert;
- /* Encryption key for the "ntor" type. */
+ /** Encryption key for the "ntor" type. */
curve25519_public_key_t enc_key;
- /* Certificate cross certifying the descriptor signing key by the encryption
+ /** Certificate cross certifying the descriptor signing key by the encryption
* curve25519 key. This certificate contains the signing key and is of type
* CERT_TYPE_CROSS_HS_IP_KEYS [0B]. */
tor_cert_t *enc_key_cert;
- /* (Optional): If this introduction point is a legacy one that is version <=
+ /** (Optional): If this introduction point is a legacy one that is version <=
* 0.2.9.x (HSIntro=3), we use this extra key for the intro point to be able
* to relay the cells to the service correctly. */
struct {
- /* RSA public key. */
+ /** RSA public key. */
crypto_pk_t *key;
- /* Cross certified cert with the descriptor signing key (RSA->Ed). Because
+ /** Cross certified cert with the descriptor signing key (RSA->Ed). Because
* of the cross certification API, we need to keep the certificate binary
* blob and its length in order to properly encode it after. */
struct {
@@ -108,115 +133,115 @@ typedef struct hs_desc_intro_point_t {
} cert;
} legacy;
- /* True iff the introduction point has passed the cross certification. Upon
+ /** True iff the introduction point has passed the cross certification. Upon
* decoding an intro point, this must be true. */
unsigned int cross_certified : 1;
} hs_desc_intro_point_t;
-/* Authorized client information located in a descriptor. */
+/** Authorized client information located in a descriptor. */
typedef struct hs_desc_authorized_client_t {
- /* An identifier that the client will use to identify which auth client
+ /** An identifier that the client will use to identify which auth client
* entry it needs to use. */
uint8_t client_id[HS_DESC_CLIENT_ID_LEN];
- /* An IV that is used to decrypt the encrypted descriptor cookie. */
+ /** An IV that is used to decrypt the encrypted descriptor cookie. */
uint8_t iv[CIPHER_IV_LEN];
- /* An encrypted descriptor cookie that the client needs to decrypt to use
+ /** An encrypted descriptor cookie that the client needs to decrypt to use
* it to decrypt the descriptor. */
uint8_t encrypted_cookie[HS_DESC_ENCRYPED_COOKIE_LEN];
} hs_desc_authorized_client_t;
-/* The encrypted data section of a descriptor. Obviously the data in this is
+/** The encrypted data section of a descriptor. Obviously the data in this is
* in plaintext but encrypted once encoded. */
typedef struct hs_desc_encrypted_data_t {
- /* Bitfield of CREATE2 cell supported formats. The only currently supported
+ /** Bitfield of CREATE2 cell supported formats. The only currently supported
* format is ntor. */
unsigned int create2_ntor : 1;
- /* A list of authentication types that a client must at least support one
+ /** A list of authentication types that a client must at least support one
* in order to contact the service. Contains NULL terminated strings. */
smartlist_t *intro_auth_types;
- /* Is this descriptor a single onion service? */
+ /** Is this descriptor a single onion service? */
unsigned int single_onion_service : 1;
- /* A list of intro points. Contains hs_desc_intro_point_t objects. */
+ /** A list of intro points. Contains hs_desc_intro_point_t objects. */
smartlist_t *intro_points;
} hs_desc_encrypted_data_t;
-/* The superencrypted data section of a descriptor. Obviously the data in
+/** The superencrypted data section of a descriptor. Obviously the data in
* this is in plaintext but encrypted once encoded. */
typedef struct hs_desc_superencrypted_data_t {
- /* This field contains ephemeral x25519 public key which is used by
+ /** This field contains ephemeral x25519 public key which is used by
* the encryption scheme in the client authorization. */
curve25519_public_key_t auth_ephemeral_pubkey;
- /* A list of authorized clients. Contains hs_desc_authorized_client_t
+ /** A list of authorized clients. Contains hs_desc_authorized_client_t
* objects. */
smartlist_t *clients;
- /* Decoding only: The b64-decoded encrypted blob from the descriptor */
+ /** Decoding only: The b64-decoded encrypted blob from the descriptor */
uint8_t *encrypted_blob;
- /* Decoding only: Size of the encrypted_blob */
+ /** Decoding only: Size of the encrypted_blob */
size_t encrypted_blob_size;
} hs_desc_superencrypted_data_t;
-/* Plaintext data that is unencrypted information of the descriptor. */
+/** Plaintext data that is unencrypted information of the descriptor. */
typedef struct hs_desc_plaintext_data_t {
- /* Version of the descriptor format. Spec specifies this field as a
+ /** Version of the descriptor format. Spec specifies this field as a
* positive integer. */
uint32_t version;
- /* The lifetime of the descriptor in seconds. */
+ /** The lifetime of the descriptor in seconds. */
uint32_t lifetime_sec;
- /* Certificate with the short-term ed22519 descriptor signing key for the
+ /** Certificate with the short-term ed22519 descriptor signing key for the
* replica which is signed by the blinded public key for that replica. */
tor_cert_t *signing_key_cert;
- /* Signing public key which is used to sign the descriptor. Same public key
+ /** Signing public key which is used to sign the descriptor. Same public key
* as in the signing key certificate. */
ed25519_public_key_t signing_pubkey;
- /* Blinded public key used for this descriptor derived from the master
+ /** Blinded public key used for this descriptor derived from the master
* identity key and generated for a specific replica number. */
ed25519_public_key_t blinded_pubkey;
- /* Revision counter is incremented at each upload, regardless of whether
+ /** Revision counter is incremented at each upload, regardless of whether
* the descriptor has changed. This avoids leaking whether the descriptor
* has changed. Spec specifies this as a 8 bytes positive integer. */
uint64_t revision_counter;
- /* Decoding only: The b64-decoded superencrypted blob from the descriptor */
+ /** Decoding only: The b64-decoded superencrypted blob from the descriptor */
uint8_t *superencrypted_blob;
- /* Decoding only: Size of the superencrypted_blob */
+ /** Decoding only: Size of the superencrypted_blob */
size_t superencrypted_blob_size;
} hs_desc_plaintext_data_t;
-/* Service descriptor in its decoded form. */
+/** Service descriptor in its decoded form. */
typedef struct hs_descriptor_t {
- /* Contains the plaintext part of the descriptor. */
+ /** Contains the plaintext part of the descriptor. */
hs_desc_plaintext_data_t plaintext_data;
- /* The following contains what's in the superencrypted part of the
+ /** The following contains what's in the superencrypted part of the
* descriptor. It's only encrypted in the encoded version of the descriptor
* thus the data contained in that object is in plaintext. */
hs_desc_superencrypted_data_t superencrypted_data;
- /* The following contains what's in the encrypted part of the descriptor.
+ /** The following contains what's in the encrypted part of the descriptor.
* It's only encrypted in the encoded version of the descriptor thus the
* data contained in that object is in plaintext. */
hs_desc_encrypted_data_t encrypted_data;
- /* Subcredentials of a service, used by the client and service to decrypt
+ /** Subcredentials of a service, used by the client and service to decrypt
* the encrypted data. */
uint8_t subcredential[DIGEST256_LEN];
} hs_descriptor_t;
-/* Return true iff the given descriptor format version is supported. */
+/** Return true iff the given descriptor format version is supported. */
static inline int
hs_desc_is_supported_version(uint32_t version)
{
diff --git a/src/feature/hs/hs_dos.c b/src/feature/hs/hs_dos.c
index 19794e09d3..1f7415a280 100644
--- a/src/feature/hs/hs_dos.c
+++ b/src/feature/hs/hs_dos.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2019, The Tor Project, Inc. */
+/* Copyright (c) 2019-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -31,20 +31,23 @@
#include "feature/hs/hs_dos.h"
-/* Default value of the allowed INTRODUCE2 cell rate per second. Above that
+/** Default value of the allowed INTRODUCE2 cell rate per second. Above that
* value per second, the introduction is denied. */
#define HS_DOS_INTRODUCE_DEFAULT_CELL_RATE_PER_SEC 25
-/* Default value of the allowed INTRODUCE2 cell burst per second. This is the
+/** Default value of the allowed INTRODUCE2 cell burst per second. This is the
* maximum value a token bucket has per second. We thus allow up to this value
* of INTRODUCE2 cell per second but the bucket is refilled by the rate value
* but never goes above that burst value. */
#define HS_DOS_INTRODUCE_DEFAULT_CELL_BURST_PER_SEC 200
-/* Default value of the consensus parameter enabling or disabling the
+/** Default value of the consensus parameter enabling or disabling the
* introduction DoS defense. Disabled by default. */
#define HS_DOS_INTRODUCE_ENABLED_DEFAULT 0
+/** INTRODUCE2 rejected request counter. */
+static uint64_t intro2_rejected_count = 0;
+
/* Consensus parameters. The ESTABLISH_INTRO DoS cell extension have higher
* priority than these values. If no extension is sent, these are used only by
* the introduction point. */
@@ -62,7 +65,7 @@ get_intro2_enable_consensus_param(const networkstatus_t *ns)
HS_DOS_INTRODUCE_ENABLED_DEFAULT, 0, 1);
}
-/* Return the parameter for the introduction rate per sec. */
+/** Return the parameter for the introduction rate per sec. */
STATIC uint32_t
get_intro2_rate_consensus_param(const networkstatus_t *ns)
{
@@ -71,7 +74,7 @@ get_intro2_rate_consensus_param(const networkstatus_t *ns)
0, INT32_MAX);
}
-/* Return the parameter for the introduction burst per sec. */
+/** Return the parameter for the introduction burst per sec. */
STATIC uint32_t
get_intro2_burst_consensus_param(const networkstatus_t *ns)
{
@@ -80,7 +83,7 @@ get_intro2_burst_consensus_param(const networkstatus_t *ns)
0, INT32_MAX);
}
-/* Go over all introduction circuit relay side and adjust their rate/burst
+/** Go over all introduction circuit relay side and adjust their rate/burst
* values using the global parameters. This is called right after the
* consensus parameters might have changed. */
static void
@@ -102,7 +105,7 @@ update_intro_circuits(void)
smartlist_free(intro_circs);
}
-/* Set consensus parameters. */
+/** Set consensus parameters. */
static void
set_consensus_parameters(const networkstatus_t *ns)
{
@@ -122,7 +125,7 @@ set_consensus_parameters(const networkstatus_t *ns)
* Public API.
*/
-/* Initialize the INTRODUCE2 token bucket for the DoS defenses using the
+/** Initialize the INTRODUCE2 token bucket for the DoS defenses using the
* consensus/default values. We might get a cell extension that changes those
* later but if we don't, the default or consensus parameters are used. */
void
@@ -138,7 +141,7 @@ hs_dos_setup_default_intro2_defenses(or_circuit_t *circ)
(uint32_t) approx_time());
}
-/* Called when the consensus has changed. We might have new consensus
+/** Called when the consensus has changed. We might have new consensus
* parameters to look at. */
void
hs_dos_consensus_has_changed(const networkstatus_t *ns)
@@ -152,7 +155,7 @@ hs_dos_consensus_has_changed(const networkstatus_t *ns)
set_consensus_parameters(ns);
}
-/* Return true iff an INTRODUCE2 cell can be sent on the given service
+/** Return true iff an INTRODUCE2 cell can be sent on the given service
* introduction circuit. */
bool
hs_dos_can_send_intro2(or_circuit_t *s_intro_circ)
@@ -163,12 +166,12 @@ hs_dos_can_send_intro2(or_circuit_t *s_intro_circ)
* This can be set by the consensus, the ESTABLISH_INTRO cell extension or
* the hardcoded values in tor code. */
if (!s_intro_circ->introduce2_dos_defense_enabled) {
- return true;
+ goto allow;
}
/* Should not happen but if so, scream loudly. */
if (BUG(TO_CIRCUIT(s_intro_circ)->purpose != CIRCUIT_PURPOSE_INTRO_POINT)) {
- return false;
+ goto disallow;
}
/* This is called just after we got a valid and parsed INTRODUCE1 cell. The
@@ -189,10 +192,30 @@ hs_dos_can_send_intro2(or_circuit_t *s_intro_circ)
}
/* Finally, we can send a new INTRODUCE2 if there are still tokens. */
- return token_bucket_ctr_get(&s_intro_circ->introduce2_bucket) > 0;
+ if (token_bucket_ctr_get(&s_intro_circ->introduce2_bucket) > 0) {
+ goto allow;
+ }
+
+ /* If we reach this point, then it means the bucket has reached zero, and
+ we're going to disallow. */
+
+ disallow:
+ /* Increment stats counter, we are rejecting the INTRO2 cell. */
+ intro2_rejected_count++;
+ return false;
+
+ allow:
+ return true;
+}
+
+/** Return rolling count of rejected INTRO2. */
+uint64_t
+hs_dos_get_intro2_rejected_count(void)
+{
+ return intro2_rejected_count;
}
-/* Initialize the onion service Denial of Service subsystem. */
+/** Initialize the onion service Denial of Service subsystem. */
void
hs_dos_init(void)
{
diff --git a/src/feature/hs/hs_dos.h b/src/feature/hs/hs_dos.h
index ccf4e27179..8e36ece204 100644
--- a/src/feature/hs/hs_dos.h
+++ b/src/feature/hs/hs_dos.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2019, The Tor Project, Inc. */
+/* Copyright (c) 2019-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -24,6 +24,9 @@ void hs_dos_consensus_has_changed(const networkstatus_t *ns);
bool hs_dos_can_send_intro2(or_circuit_t *s_intro_circ);
void hs_dos_setup_default_intro2_defenses(or_circuit_t *circ);
+/* Statistics. */
+uint64_t hs_dos_get_intro2_rejected_count(void);
+
#ifdef HS_DOS_PRIVATE
#ifdef TOR_UNIT_TESTS
diff --git a/src/feature/hs/hs_ident.c b/src/feature/hs/hs_ident.c
index a00e55ec23..1d93ff9610 100644
--- a/src/feature/hs/hs_ident.c
+++ b/src/feature/hs/hs_ident.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -10,7 +10,7 @@
#include "lib/crypt_ops/crypto_util.h"
#include "feature/hs/hs_ident.h"
-/* Return a newly allocated circuit identifier. The given public key is copied
+/** Return a newly allocated circuit identifier. The given public key is copied
* identity_pk into the identifier. */
hs_ident_circuit_t *
hs_ident_circuit_new(const ed25519_public_key_t *identity_pk)
@@ -20,7 +20,7 @@ hs_ident_circuit_new(const ed25519_public_key_t *identity_pk)
return ident;
}
-/* Free the given circuit identifier. */
+/** Free the given circuit identifier. */
void
hs_ident_circuit_free_(hs_ident_circuit_t *ident)
{
@@ -31,7 +31,7 @@ hs_ident_circuit_free_(hs_ident_circuit_t *ident)
tor_free(ident);
}
-/* For a given circuit identifier src, return a newly allocated copy of it.
+/** For a given circuit identifier src, return a newly allocated copy of it.
* This can't fail. */
hs_ident_circuit_t *
hs_ident_circuit_dup(const hs_ident_circuit_t *src)
@@ -41,7 +41,7 @@ hs_ident_circuit_dup(const hs_ident_circuit_t *src)
return ident;
}
-/* For a given directory connection identifier src, return a newly allocated
+/** For a given directory connection identifier src, return a newly allocated
* copy of it. This can't fail. */
hs_ident_dir_conn_t *
hs_ident_dir_conn_dup(const hs_ident_dir_conn_t *src)
@@ -51,7 +51,7 @@ hs_ident_dir_conn_dup(const hs_ident_dir_conn_t *src)
return ident;
}
-/* Free the given directory connection identifier. */
+/** Free the given directory connection identifier. */
void
hs_ident_dir_conn_free_(hs_ident_dir_conn_t *ident)
{
@@ -62,7 +62,7 @@ hs_ident_dir_conn_free_(hs_ident_dir_conn_t *ident)
tor_free(ident);
}
-/* Initialized the allocated ident object with identity_pk and blinded_pk.
+/** Initialized the allocated ident object with identity_pk and blinded_pk.
* None of them can be NULL since a valid directory connection identifier must
* have all fields set. */
void
@@ -78,7 +78,7 @@ hs_ident_dir_conn_init(const ed25519_public_key_t *identity_pk,
ed25519_pubkey_copy(&ident->blinded_pk, blinded_pk);
}
-/* Return a newly allocated edge connection identifier. The given public key
+/** Return a newly allocated edge connection identifier. The given public key
* identity_pk is copied into the identifier. */
hs_ident_edge_conn_t *
hs_ident_edge_conn_new(const ed25519_public_key_t *identity_pk)
@@ -88,7 +88,7 @@ hs_ident_edge_conn_new(const ed25519_public_key_t *identity_pk)
return ident;
}
-/* Free the given edge connection identifier. */
+/** Free the given edge connection identifier. */
void
hs_ident_edge_conn_free_(hs_ident_edge_conn_t *ident)
{
@@ -99,7 +99,7 @@ hs_ident_edge_conn_free_(hs_ident_edge_conn_t *ident)
tor_free(ident);
}
-/* Return true if the given ident is valid for an introduction circuit. */
+/** Return true if the given ident is valid for an introduction circuit. */
int
hs_ident_intro_circ_is_valid(const hs_ident_circuit_t *ident)
{
@@ -120,4 +120,3 @@ hs_ident_intro_circ_is_valid(const hs_ident_circuit_t *ident)
invalid:
return 0;
}
-
diff --git a/src/feature/hs/hs_ident.h b/src/feature/hs/hs_ident.h
index 82ca50f6b5..f4b9b2432d 100644
--- a/src/feature/hs/hs_ident.h
+++ b/src/feature/hs/hs_ident.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -25,70 +25,71 @@
#include "feature/hs/hs_common.h"
-/* Length of the rendezvous cookie that is used to connect circuits at the
+/** Length of the rendezvous cookie that is used to connect circuits at the
* rendezvous point. */
#define HS_REND_COOKIE_LEN DIGEST_LEN
-/* Type of circuit an hs_ident_t object is associated with. */
+/** Type of circuit an hs_ident_t object is associated with. */
typedef enum {
HS_IDENT_CIRCUIT_INTRO = 1,
HS_IDENT_CIRCUIT_RENDEZVOUS = 2,
} hs_ident_circuit_type_t;
-/* Client and service side circuit identifier that is used for hidden service
+/** Client and service side circuit identifier that is used for hidden service
* circuit establishment. Not all fields contain data, it depends on the
* circuit purpose. This is attached to an origin_circuit_t. All fields are
* used by both client and service. */
typedef struct hs_ident_circuit_t {
- /* (All circuit) The public key used to uniquely identify the service. It is
+ /** (All circuit) The public key used to uniquely identify the service. It is
* the one found in the onion address. */
ed25519_public_key_t identity_pk;
- /* (All circuit) Introduction point authentication key. It's also needed on
+ /** (All circuit) Introduction point authentication key. It's also needed on
* the rendezvous circuit for the ntor handshake. It's used as the unique key
* of the introduction point so it should not be shared between multiple
* intro points. */
ed25519_public_key_t intro_auth_pk;
- /* (Only client rendezvous circuit) Introduction point encryption public
+ /** (Only client rendezvous circuit) Introduction point encryption public
* key. We keep it in the rendezvous identifier for the ntor handshake. */
curve25519_public_key_t intro_enc_pk;
- /* (Only rendezvous circuit) Rendezvous cookie sent from the client to the
+ /** (Only rendezvous circuit) Rendezvous cookie sent from the client to the
* service with an INTRODUCE1 cell and used by the service in an
* RENDEZVOUS1 cell. */
uint8_t rendezvous_cookie[HS_REND_COOKIE_LEN];
- /* (Only service rendezvous circuit) The HANDSHAKE_INFO needed in the
+ /** (Only service rendezvous circuit) The HANDSHAKE_INFO needed in the
* RENDEZVOUS1 cell of the service. The construction is as follows:
- * SERVER_PK [32 bytes]
- * AUTH_MAC [32 bytes]
+ *
+ * SERVER_PK [32 bytes]
+ * AUTH_MAC [32 bytes]
*/
uint8_t rendezvous_handshake_info[CURVE25519_PUBKEY_LEN + DIGEST256_LEN];
- /* (Only client rendezvous circuit) Client ephemeral keypair needed for the
+ /** (Only client rendezvous circuit) Client ephemeral keypair needed for the
* e2e encryption with the service. */
curve25519_keypair_t rendezvous_client_kp;
- /* (Only rendezvous circuit) The NTOR_KEY_SEED needed for key derivation for
+ /** (Only rendezvous circuit) The NTOR_KEY_SEED needed for key derivation for
* the e2e encryption with the client on the circuit. */
uint8_t rendezvous_ntor_key_seed[DIGEST256_LEN];
- /* (Only rendezvous circuit) Number of streams associated with this
+ /** (Only rendezvous circuit) Number of streams associated with this
* rendezvous circuit. We track this because there is a check on a maximum
* value. */
uint64_t num_rdv_streams;
} hs_ident_circuit_t;
-/* Client and service side directory connection identifier used for a
+/** Client and service side directory connection identifier used for a
* directory connection to identify which service is being queried. This is
* attached to a dir_connection_t. */
typedef struct hs_ident_dir_conn_t {
- /* The public key used to uniquely identify the service. It is the one found
+ /** The public key used to uniquely identify the service. It is the one found
* in the onion address. */
ed25519_public_key_t identity_pk;
- /* The blinded public key used to uniquely identify the descriptor that this
+ /** The blinded public key used to uniquely identify the descriptor that this
* directory connection identifier is for. Only used by the service-side code
* to fine control descriptor uploads. */
ed25519_public_key_t blinded_pk;
@@ -96,15 +97,15 @@ typedef struct hs_ident_dir_conn_t {
/* XXX: Client authorization. */
} hs_ident_dir_conn_t;
-/* Client and service side edge connection identifier used for an edge
+/** Client and service side edge connection identifier used for an edge
* connection to identify which service is being queried. This is attached to
* a edge_connection_t. */
typedef struct hs_ident_edge_conn_t {
- /* The public key used to uniquely identify the service. It is the one found
+ /** The public key used to uniquely identify the service. It is the one found
* in the onion address. */
ed25519_public_key_t identity_pk;
- /* The original virtual port that was used by the client to access the onion
+ /** The original virtual port that was used by the client to access the onion
* service, regardless of the internal port forwarding that might have
* happened on the service-side. */
uint16_t orig_virtual_port;
@@ -139,4 +140,3 @@ void hs_ident_edge_conn_free_(hs_ident_edge_conn_t *ident);
int hs_ident_intro_circ_is_valid(const hs_ident_circuit_t *ident);
#endif /* !defined(TOR_HS_IDENT_H) */
-
diff --git a/src/feature/hs/hs_intropoint.c b/src/feature/hs/hs_intropoint.c
index fe8486b1a6..e282d1f1bd 100644
--- a/src/feature/hs/hs_intropoint.c
+++ b/src/feature/hs/hs_intropoint.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -147,7 +147,7 @@ verify_establish_intro_cell(const trn_cell_establish_intro_t *cell,
return 0;
}
-/* Send an INTRO_ESTABLISHED cell to <b>circ</b>. */
+/** Send an INTRO_ESTABLISHED cell to <b>circ</b>. */
MOCK_IMPL(int,
hs_intro_send_intro_established_cell,(or_circuit_t *circ))
{
@@ -182,7 +182,7 @@ hs_intro_send_intro_established_cell,(or_circuit_t *circ))
return ret;
}
-/* Validate the cell DoS extension parameters. Return true iff they've been
+/** Validate the cell DoS extension parameters. Return true iff they've been
* bound check and can be used. Else return false. See proposal 305 for
* details and reasons about this validation. */
STATIC bool
@@ -244,7 +244,7 @@ cell_dos_extension_parameters_are_valid(uint64_t intro2_rate_per_sec,
return ret;
}
-/* Parse the cell DoS extension and apply defenses on the given circuit if
+/** Parse the cell DoS extension and apply defenses on the given circuit if
* validation passes. If the cell extension is malformed or contains unusable
* values, the DoS defenses is disabled on the circuit. */
static void
@@ -321,7 +321,7 @@ handle_establish_intro_cell_dos_extension(
return;
}
-/* Parse every cell extension in the given ESTABLISH_INTRO cell. */
+/** Parse every cell extension in the given ESTABLISH_INTRO cell. */
static void
handle_establish_intro_cell_extensions(
const trn_cell_establish_intro_t *parsed_cell,
@@ -457,7 +457,7 @@ handle_establish_intro(or_circuit_t *circ, const uint8_t *request,
return retval;
}
-/* Return True if circuit is suitable for being an intro circuit. */
+/** Return True if circuit is suitable for being an intro circuit. */
static int
circuit_is_suitable_intro_point(const or_circuit_t *circ,
const char *log_cell_type_str)
@@ -482,14 +482,14 @@ circuit_is_suitable_intro_point(const or_circuit_t *circ,
return 1;
}
-/* Return True if circuit is suitable for being service-side intro circuit. */
+/** Return True if circuit is suitable for being service-side intro circuit. */
int
hs_intro_circuit_is_suitable_for_establish_intro(const or_circuit_t *circ)
{
return circuit_is_suitable_intro_point(circ, "ESTABLISH_INTRO");
}
-/* We just received an ESTABLISH_INTRO cell in <b>circ</b>. Figure out of it's
+/** We just received an ESTABLISH_INTRO cell in <b>circ</b>. Figure out of it's
* a legacy or a next gen cell, and pass it to the appropriate handler. */
int
hs_intro_received_establish_intro(or_circuit_t *circ, const uint8_t *request,
@@ -523,7 +523,7 @@ hs_intro_received_establish_intro(or_circuit_t *circ, const uint8_t *request,
return -1;
}
-/* Send an INTRODUCE_ACK cell onto the circuit <b>circ</b> with the status
+/** Send an INTRODUCE_ACK cell onto the circuit <b>circ</b> with the status
* value in <b>status</b>. Depending on the status, it can be ACK or a NACK.
* Return 0 on success else a negative value on error which will close the
* circuit. */
@@ -567,7 +567,7 @@ send_introduce_ack_cell(or_circuit_t *circ, uint16_t status)
return ret;
}
-/* Validate a parsed INTRODUCE1 <b>cell</b>. Return 0 if valid or else a
+/** Validate a parsed INTRODUCE1 <b>cell</b>. Return 0 if valid or else a
* negative value for an invalid cell that should be NACKed. */
STATIC int
validate_introduce1_parsed_cell(const trn_cell_introduce1_t *cell)
@@ -613,7 +613,7 @@ validate_introduce1_parsed_cell(const trn_cell_introduce1_t *cell)
return -1;
}
-/* We just received a non legacy INTRODUCE1 cell on <b>client_circ</b> with
+/** We just received a non legacy INTRODUCE1 cell on <b>client_circ</b> with
* the payload in <b>request</b> of size <b>request_len</b>. Return 0 if
* everything went well, or -1 if an error occurred. This function is in charge
* of sending back an INTRODUCE_ACK cell and will close client_circ on error.
@@ -712,7 +712,7 @@ handle_introduce1(or_circuit_t *client_circ, const uint8_t *request,
return ret;
}
-/* Identify if the encoded cell we just received is a legacy one or not. The
+/** Identify if the encoded cell we just received is a legacy one or not. The
* <b>request</b> should be at least DIGEST_LEN bytes long. */
STATIC int
introduce1_cell_is_legacy(const uint8_t *request)
@@ -729,7 +729,7 @@ introduce1_cell_is_legacy(const uint8_t *request)
return 0;
}
-/* Return true iff the circuit <b>circ</b> is suitable for receiving an
+/** Return true iff the circuit <b>circ</b> is suitable for receiving an
* INTRODUCE1 cell. */
STATIC int
circuit_is_suitable_for_introduce1(const or_circuit_t *circ)
@@ -760,7 +760,7 @@ circuit_is_suitable_for_introduce1(const or_circuit_t *circ)
return 1;
}
-/* We just received an INTRODUCE1 cell on <b>circ</b>. Figure out which type
+/** We just received an INTRODUCE1 cell on <b>circ</b>. Figure out which type
* it is and pass it to the appropriate handler. Return 0 on success else a
* negative value and the circuit is closed. */
int
@@ -804,8 +804,8 @@ hs_intro_received_introduce1(or_circuit_t *circ, const uint8_t *request,
return -1;
}
-/* Clear memory allocated by the given intropoint object ip (but don't free the
- * object itself). */
+/** Clear memory allocated by the given intropoint object ip (but don't free
+ * the object itself). */
void
hs_intropoint_clear(hs_intropoint_t *ip)
{
diff --git a/src/feature/hs/hs_intropoint.h b/src/feature/hs/hs_intropoint.h
index 94ebf021e4..8b2b9892b3 100644
--- a/src/feature/hs/hs_intropoint.h
+++ b/src/feature/hs/hs_intropoint.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,15 +12,15 @@
#include "lib/crypt_ops/crypto_curve25519.h"
#include "feature/nodelist/torcert.h"
-/* Object containing introduction point common data between the service and
+/** Object containing introduction point common data between the service and
* the client side. */
typedef struct hs_intropoint_t {
- /* Does this intro point only supports legacy ID ?. */
+ /** Does this intro point only supports legacy ID ?. */
unsigned int is_only_legacy : 1;
- /* Authentication key certificate from the descriptor. */
+ /** Authentication key certificate from the descriptor. */
tor_cert_t *auth_key_cert;
- /* A list of link specifier. */
+ /** A list of link specifier. */
smartlist_t *link_specifiers;
} hs_intropoint_t;
@@ -64,4 +64,3 @@ STATIC bool cell_dos_extension_parameters_are_valid(
#endif /* defined(HS_INTROPOINT_PRIVATE) */
#endif /* !defined(TOR_HS_INTRO_H) */
-
diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c
index 17ac4fa4a9..b366ce83d9 100644
--- a/src/feature/hs/hs_service.c
+++ b/src/feature/hs/hs_service.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -30,7 +30,6 @@
#include "feature/rend/rendservice.h"
#include "lib/crypt_ops/crypto_ope.h"
#include "lib/crypt_ops/crypto_rand.h"
-#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_util.h"
#include "feature/hs/hs_circuit.h"
@@ -67,7 +66,8 @@
#include <unistd.h>
#endif
-/* Helper macro. Iterate over every service in the global map. The var is the
+#ifndef COCCI
+/** Helper macro. Iterate over every service in the global map. The var is the
* name of the service pointer. */
#define FOR_EACH_SERVICE_BEGIN(var) \
STMT_BEGIN \
@@ -76,7 +76,7 @@
var = *var##_iter;
#define FOR_EACH_SERVICE_END } STMT_END ;
-/* Helper macro. Iterate over both current and previous descriptor of a
+/** Helper macro. Iterate over both current and previous descriptor of a
* service. The var is the name of the descriptor pointer. This macro skips
* any descriptor object of the service that is NULL. */
#define FOR_EACH_DESCRIPTOR_BEGIN(service, var) \
@@ -88,6 +88,7 @@
(var = service->desc_next); \
if (var == NULL) continue;
#define FOR_EACH_DESCRIPTOR_END } STMT_END ;
+#endif /* !defined(COCCI) */
/* Onion service directory file names. */
static const char fname_keyfile_prefix[] = "hs_ed25519";
@@ -95,7 +96,7 @@ static const char dname_client_pubkeys[] = "authorized_clients";
static const char fname_hostname[] = "hostname";
static const char address_tld[] = "onion";
-/* Staging list of service object. When configuring service, we add them to
+/** Staging list of service object. When configuring service, we add them to
* this list considered a staging area and they will get added to our global
* map once the keys have been loaded. These two steps are separated because
* loading keys requires that we are an actual running tor process. */
@@ -118,7 +119,7 @@ static int service_encode_descriptor(const hs_service_t *service,
const ed25519_keypair_t *signing_kp,
char **encoded_out);
-/* Helper: Function to compare two objects in the service map. Return 1 if the
+/** Helper: Function to compare two objects in the service map. Return 1 if the
* two service have the same master public identity key. */
static inline int
hs_service_ht_eq(const hs_service_t *first, const hs_service_t *second)
@@ -130,7 +131,7 @@ hs_service_ht_eq(const hs_service_t *first, const hs_service_t *second)
&second->keys.identity_pk);
}
-/* Helper: Function for the service hash table code below. The key used is the
+/** Helper: Function for the service hash table code below. The key used is the
* master public identity key which is ultimately the onion address. */
static inline unsigned int
hs_service_ht_hash(const hs_service_t *service)
@@ -140,7 +141,7 @@ hs_service_ht_hash(const hs_service_t *service)
sizeof(service->keys.identity_pk.pubkey));
}
-/* This is _the_ global hash map of hidden services which indexed the service
+/** This is _the_ global hash map of hidden services which indexed the service
* contained in it by master public identity key which is roughly the onion
* address of the service. */
static struct hs_service_ht *hs_service_map;
@@ -156,7 +157,7 @@ HT_GENERATE2(hs_service_ht, hs_service_t, hs_service_node,
hs_service_ht_hash, hs_service_ht_eq,
0.6, tor_reallocarray, tor_free_)
-/* Query the given service map with a public key and return a service object
+/** Query the given service map with a public key and return a service object
* if found else NULL. It is also possible to set a directory path in the
* search query. If pk is NULL, then it will be set to zero indicating the
* hash table to compare the directory path instead. */
@@ -171,7 +172,7 @@ find_service(hs_service_ht *map, const ed25519_public_key_t *pk)
return HT_FIND(hs_service_ht, map, &dummy_service);
}
-/* Register the given service in the given map. If the service already exists
+/** Register the given service in the given map. If the service already exists
* in the map, -1 is returned. On success, 0 is returned and the service
* ownership has been transferred to the global map. */
STATIC int
@@ -196,7 +197,7 @@ register_service(hs_service_ht *map, hs_service_t *service)
return 0;
}
-/* Remove a given service from the given map. If service is NULL or the
+/** Remove a given service from the given map. If service is NULL or the
* service key is unset, return gracefully. */
STATIC void
remove_service(hs_service_ht *map, hs_service_t *service)
@@ -226,7 +227,7 @@ remove_service(hs_service_ht *map, hs_service_t *service)
}
}
-/* Set the default values for a service configuration object <b>c</b>. */
+/** Set the default values for a service configuration object <b>c</b>. */
static void
set_service_default_config(hs_service_config_t *c,
const or_options_t *options)
@@ -247,7 +248,7 @@ set_service_default_config(hs_service_config_t *c,
c->intro_dos_burst_per_sec = HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_DEFAULT;
}
-/* From a service configuration object config, clear everything from it
+/** From a service configuration object config, clear everything from it
* meaning free allocated pointers and reset the values. */
STATIC void
service_clear_config(hs_service_config_t *config)
@@ -269,7 +270,7 @@ service_clear_config(hs_service_config_t *config)
memset(config, 0, sizeof(*config));
}
-/* Helper function to return a human readable description of the given intro
+/** Helper function to return a human readable description of the given intro
* point object.
*
* This function is not thread-safe. Each call to this invalidates the
@@ -301,7 +302,7 @@ describe_intro_point(const hs_service_intro_point_t *ip)
return buf;
}
-/* Return the lower bound of maximum INTRODUCE2 cells per circuit before we
+/** Return the lower bound of maximum INTRODUCE2 cells per circuit before we
* rotate intro point (defined by a consensus parameter or the default
* value). */
static int32_t
@@ -314,7 +315,7 @@ get_intro_point_min_introduce2(void)
0, INT32_MAX);
}
-/* Return the upper bound of maximum INTRODUCE2 cells per circuit before we
+/** Return the upper bound of maximum INTRODUCE2 cells per circuit before we
* rotate intro point (defined by a consensus parameter or the default
* value). */
static int32_t
@@ -327,8 +328,8 @@ get_intro_point_max_introduce2(void)
0, INT32_MAX);
}
-/* Return the minimum lifetime in seconds of an introduction point defined by a
- * consensus parameter or the default value. */
+/** Return the minimum lifetime in seconds of an introduction point defined by
+ * a consensus parameter or the default value. */
static int32_t
get_intro_point_min_lifetime(void)
{
@@ -344,8 +345,8 @@ get_intro_point_min_lifetime(void)
0, INT32_MAX);
}
-/* Return the maximum lifetime in seconds of an introduction point defined by a
- * consensus parameter or the default value. */
+/** Return the maximum lifetime in seconds of an introduction point defined by
+ * a consensus parameter or the default value. */
static int32_t
get_intro_point_max_lifetime(void)
{
@@ -361,7 +362,7 @@ get_intro_point_max_lifetime(void)
0, INT32_MAX);
}
-/* Return the number of extra introduction point defined by a consensus
+/** Return the number of extra introduction point defined by a consensus
* parameter or the default value. */
static int32_t
get_intro_point_num_extra(void)
@@ -372,7 +373,7 @@ get_intro_point_num_extra(void)
NUM_INTRO_POINTS_EXTRA, 0, 128);
}
-/* Helper: Function that needs to return 1 for the HT for each loop which
+/** Helper: Function that needs to return 1 for the HT for each loop which
* frees every service in an hash map. */
static int
ht_free_service_(struct hs_service_t *service, void *data)
@@ -384,7 +385,7 @@ ht_free_service_(struct hs_service_t *service, void *data)
return 1;
}
-/* Free every service that can be found in the global map. Once done, clear
+/** Free every service that can be found in the global map. Once done, clear
* and free the global map. */
static void
service_free_all(void)
@@ -406,7 +407,7 @@ service_free_all(void)
}
}
-/* Free a given service intro point object. */
+/** Free a given service intro point object. */
STATIC void
service_intro_point_free_(hs_service_intro_point_t *ip)
{
@@ -421,7 +422,7 @@ service_intro_point_free_(hs_service_intro_point_t *ip)
tor_free(ip);
}
-/* Helper: free an hs_service_intro_point_t object. This function is used by
+/** Helper: free an hs_service_intro_point_t object. This function is used by
* digest256map_free() which requires a void * pointer. */
static void
service_intro_point_free_void(void *obj)
@@ -429,7 +430,7 @@ service_intro_point_free_void(void *obj)
service_intro_point_free_(obj);
}
-/* Return a newly allocated service intro point and fully initialized from the
+/** Return a newly allocated service intro point and fully initialized from the
* given node_t node, if non NULL.
*
* If node is NULL, returns a hs_service_intro_point_t with an empty link
@@ -507,7 +508,7 @@ service_intro_point_new(const node_t *node)
return NULL;
}
-/* Add the given intro point object to the given intro point map. The intro
+/** Add the given intro point object to the given intro point map. The intro
* point MUST have its RSA encryption key set if this is a legacy type or the
* authentication key set otherwise. */
STATIC void
@@ -523,7 +524,7 @@ service_intro_point_add(digest256map_t *map, hs_service_intro_point_t *ip)
tor_assert_nonfatal(!old_ip_entry);
}
-/* For a given service, remove the intro point from that service's descriptors
+/** For a given service, remove the intro point from that service's descriptors
* (check both current and next descriptor) */
STATIC void
service_intro_point_remove(const hs_service_t *service,
@@ -541,7 +542,7 @@ service_intro_point_remove(const hs_service_t *service,
} FOR_EACH_DESCRIPTOR_END;
}
-/* For a given service and authentication key, return the intro point or NULL
+/** For a given service and authentication key, return the intro point or NULL
* if not found. This will check both descriptors in the service. */
STATIC hs_service_intro_point_t *
service_intro_point_find(const hs_service_t *service,
@@ -572,7 +573,7 @@ service_intro_point_find(const hs_service_t *service,
return ip;
}
-/* For a given service and intro point, return the descriptor for which the
+/** For a given service and intro point, return the descriptor for which the
* intro point is assigned to. NULL is returned if not found. */
STATIC hs_service_descriptor_t *
service_desc_find_by_intro(const hs_service_t *service,
@@ -594,7 +595,7 @@ service_desc_find_by_intro(const hs_service_t *service,
return descp;
}
-/* From a circuit identifier, get all the possible objects associated with the
+/** From a circuit identifier, get all the possible objects associated with the
* ident. If not NULL, service, ip or desc are set if the object can be found.
* They are untouched if they can't be found.
*
@@ -627,7 +628,7 @@ get_objects_from_ident(const hs_ident_circuit_t *ident,
}
}
-/* From a given intro point, return the first link specifier of type
+/** From a given intro point, return the first link specifier of type
* encountered in the link specifier list. Return NULL if it can't be found.
*
* The caller does NOT have ownership of the object, the intro point does. */
@@ -650,7 +651,7 @@ get_link_spec_by_type(const hs_service_intro_point_t *ip, uint8_t type)
return lnk_spec;
}
-/* Given a service intro point, return the node_t associated to it. This can
+/** Given a service intro point, return the node_t associated to it. This can
* return NULL if the given intro point has no legacy ID or if the node can't
* be found in the consensus. */
STATIC const node_t *
@@ -669,7 +670,7 @@ get_node_from_intro_point(const hs_service_intro_point_t *ip)
(const char *) link_specifier_getconstarray_un_legacy_id(ls));
}
-/* Given a service intro point, return the extend_info_t for it. This can
+/** Given a service intro point, return the extend_info_t for it. This can
* return NULL if the node can't be found for the intro point or the extend
* info can't be created for the found node. If direct_conn is set, the extend
* info is validated on if we can connect directly. */
@@ -698,7 +699,7 @@ get_extend_info_from_intro_point(const hs_service_intro_point_t *ip,
return info;
}
-/* Return the number of introduction points that are established for the
+/** Return the number of introduction points that are established for the
* given descriptor. */
static unsigned int
count_desc_circuit_established(const hs_service_descriptor_t *desc)
@@ -709,13 +710,13 @@ count_desc_circuit_established(const hs_service_descriptor_t *desc)
DIGEST256MAP_FOREACH(desc->intro_points.map, key,
const hs_service_intro_point_t *, ip) {
- count += ip->circuit_established;
+ count += !!hs_circ_service_get_established_intro_circ(ip);
} DIGEST256MAP_FOREACH_END;
return count;
}
-/* For a given service and descriptor of that service, close all active
+/** For a given service and descriptor of that service, close all active
* directory connections. */
static void
close_directory_connections(const hs_service_t *service,
@@ -750,7 +751,7 @@ close_directory_connections(const hs_service_t *service,
smartlist_free(dir_conns);
}
-/* Close all rendezvous circuits for the given service. */
+/** Close all rendezvous circuits for the given service. */
static void
close_service_rp_circuits(hs_service_t *service)
{
@@ -780,7 +781,7 @@ close_service_rp_circuits(hs_service_t *service)
}
}
-/* Close the circuit(s) for the given map of introduction points. */
+/** Close the circuit(s) for the given map of introduction points. */
static void
close_intro_circuits(hs_service_intropoints_t *intro_points)
{
@@ -798,7 +799,7 @@ close_intro_circuits(hs_service_intropoints_t *intro_points)
} DIGEST256MAP_FOREACH_END;
}
-/* Close all introduction circuits for the given service. */
+/** Close all introduction circuits for the given service. */
static void
close_service_intro_circuits(hs_service_t *service)
{
@@ -809,7 +810,7 @@ close_service_intro_circuits(hs_service_t *service)
} FOR_EACH_DESCRIPTOR_END;
}
-/* Close any circuits related to the given service. */
+/** Close any circuits related to the given service. */
static void
close_service_circuits(hs_service_t *service)
{
@@ -825,7 +826,7 @@ close_service_circuits(hs_service_t *service)
close_service_rp_circuits(service);
}
-/* Move every ephemeral services from the src service map to the dst service
+/** Move every ephemeral services from the src service map to the dst service
* map. It is possible that a service can't be register to the dst map which
* won't stop the process of moving them all but will trigger a log warn. */
static void
@@ -855,7 +856,7 @@ move_ephemeral_services(hs_service_ht *src, hs_service_ht *dst)
}
}
-/* Return a const string of the directory path escaped. If this is an
+/** Return a const string of the directory path escaped. If this is an
* ephemeral service, it returns "[EPHEMERAL]". This can only be called from
* the main thread because escaped() uses a static variable. */
static const char *
@@ -889,7 +890,7 @@ move_hs_state(hs_service_t *src_service, hs_service_t *dst_service)
src->replay_cache_rend_cookie = NULL; /* steal pointer reference */
}
-/* Register services that are in the staging list. Once this function returns,
+/** Register services that are in the staging list. Once this function returns,
* the global service map will be set with the right content and all non
* surviving services will be cleaned up. */
static void
@@ -957,7 +958,7 @@ register_all_services(void)
hs_service_map_has_changed();
}
-/* Write the onion address of a given service to the given filename fname_ in
+/** Write the onion address of a given service to the given filename fname_ in
* the service directory. Return 0 on success else -1 on error. */
STATIC int
write_address_to_file(const hs_service_t *service, const char *fname_)
@@ -998,7 +999,7 @@ write_address_to_file(const hs_service_t *service, const char *fname_)
return ret;
}
-/* Load and/or generate private keys for the given service. On success, the
+/** Load and/or generate private keys for the given service. On success, the
* hostname file will be written to disk along with the master private key iff
* the service is not configured for offline keys. Return 0 on success else -1
* on failure. */
@@ -1074,7 +1075,7 @@ load_service_keys(hs_service_t *service)
return ret;
}
-/* Check if the client file name is valid or not. Return 1 if valid,
+/** Check if the client file name is valid or not. Return 1 if valid,
* otherwise return 0. */
STATIC int
client_filename_is_valid(const char *filename)
@@ -1096,7 +1097,7 @@ client_filename_is_valid(const char *filename)
return ret;
}
-/* Parse an authorized client from a string. The format of a client string
+/** Parse an authorized client from a string. The format of a client string
* looks like (see rend-spec-v3.txt):
*
* <auth-type>:<key-type>:<base32-encoded-public-key>
@@ -1178,7 +1179,7 @@ parse_authorized_client(const char *client_key_str)
return client;
}
-/* Load all the client public keys for the given service. Return 0 on
+/** Load all the client public keys for the given service. Return 0 on
* success else -1 on failure. */
static int
load_client_keys(hs_service_t *service)
@@ -1281,6 +1282,7 @@ load_client_keys(hs_service_t *service)
return ret;
}
+/** Release all storage held in <b>client</b>. */
STATIC void
service_authorized_client_free_(hs_service_authorized_client_t *client)
{
@@ -1291,7 +1293,7 @@ service_authorized_client_free_(hs_service_authorized_client_t *client)
tor_free(client);
}
-/* Free a given service descriptor object and all key material is wiped. */
+/** Free a given service descriptor object and all key material is wiped. */
STATIC void
service_descriptor_free_(hs_service_descriptor_t *desc)
{
@@ -1312,7 +1314,7 @@ service_descriptor_free_(hs_service_descriptor_t *desc)
tor_free(desc);
}
-/* Return a newly allocated service descriptor object. */
+/** Return a newly allocated service descriptor object. */
STATIC hs_service_descriptor_t *
service_descriptor_new(void)
{
@@ -1325,7 +1327,7 @@ service_descriptor_new(void)
return sdesc;
}
-/* Allocate and return a deep copy of client. */
+/** Allocate and return a deep copy of client. */
static hs_service_authorized_client_t *
service_authorized_client_dup(const hs_service_authorized_client_t *client)
{
@@ -1343,7 +1345,7 @@ service_authorized_client_dup(const hs_service_authorized_client_t *client)
return client_dup;
}
-/* If two authorized clients are equal, return 0. If the first one should come
+/** If two authorized clients are equal, return 0. If the first one should come
* before the second, return less than zero. If the first should come after
* the second, return greater than zero. */
static int
@@ -1360,7 +1362,7 @@ service_authorized_client_cmp(const hs_service_authorized_client_t *client1,
CURVE25519_PUBKEY_LEN);
}
-/* Helper for sorting authorized clients. */
+/** Helper for sorting authorized clients. */
static int
compare_service_authorzized_client_(const void **_a, const void **_b)
{
@@ -1368,7 +1370,7 @@ compare_service_authorzized_client_(const void **_a, const void **_b)
return service_authorized_client_cmp(a, b);
}
-/* If the list of hs_service_authorized_client_t's is different between
+/** If the list of hs_service_authorized_client_t's is different between
* src and dst, return 1. Otherwise, return 0. */
STATIC int
service_authorized_client_config_equal(const hs_service_config_t *config1,
@@ -1429,7 +1431,7 @@ service_authorized_client_config_equal(const hs_service_config_t *config1,
return ret;
}
-/* Move descriptor(s) from the src service to the dst service and modify their
+/** Move descriptor(s) from the src service to the dst service and modify their
* content if necessary. We do this during SIGHUP when we re-create our
* hidden services. */
static void
@@ -1488,7 +1490,7 @@ move_descriptors(hs_service_t *src, hs_service_t *dst)
service_descriptor_free(dst->desc_next);
}
-/* From the given service, remove all expired failing intro points for each
+/** From the given service, remove all expired failing intro points for each
* descriptor. */
static void
remove_expired_failing_intro(hs_service_t *service, time_t now)
@@ -1507,7 +1509,7 @@ remove_expired_failing_intro(hs_service_t *service, time_t now)
} FOR_EACH_DESCRIPTOR_END;
}
-/* For the given descriptor desc, put all node_t object found from its failing
+/** For the given descriptor desc, put all node_t object found from its failing
* intro point list and put them in the given node_list. */
static void
setup_intro_point_exclude_list(const hs_service_descriptor_t *desc,
@@ -1525,7 +1527,7 @@ setup_intro_point_exclude_list(const hs_service_descriptor_t *desc,
} DIGESTMAP_FOREACH_END;
}
-/* For the given failing intro point ip, we add its time of failure to the
+/** For the given failing intro point ip, we add its time of failure to the
* failed map and index it by identity digest (legacy ID) in the descriptor
* desc failed id map. */
static void
@@ -1549,7 +1551,7 @@ remember_failing_intro_point(const hs_service_intro_point_t *ip,
tor_free(prev_ptr);
}
-/* Using a given descriptor signing keypair signing_kp, a service intro point
+/** Using a given descriptor signing keypair signing_kp, a service intro point
* object ip and the time now, setup the content of an already allocated
* descriptor intro desc_ip.
*
@@ -1638,7 +1640,7 @@ setup_desc_intro_point(const ed25519_keypair_t *signing_kp,
return ret;
}
-/* Using the given descriptor from the given service, build the descriptor
+/** Using the given descriptor from the given service, build the descriptor
* intro point list so we can then encode the descriptor for publication. This
* function does not pick intro points, they have to be in the descriptor
* current map. Cryptographic material (keys) must be initialized in the
@@ -1659,7 +1661,7 @@ build_desc_intro_points(const hs_service_t *service,
DIGEST256MAP_FOREACH(desc->intro_points.map, key,
const hs_service_intro_point_t *, ip) {
- if (!ip->circuit_established) {
+ if (!hs_circ_service_get_established_intro_circ(ip)) {
/* Ignore un-established intro points. They can linger in that list
* because their circuit has not opened and they haven't been removed
* yet even though we have enough intro circuits.
@@ -1678,7 +1680,7 @@ build_desc_intro_points(const hs_service_t *service,
} DIGEST256MAP_FOREACH_END;
}
-/* Build the descriptor signing key certificate. */
+/** Build the descriptor signing key certificate. */
static void
build_desc_signing_key_cert(hs_service_descriptor_t *desc, time_t now)
{
@@ -1704,7 +1706,7 @@ build_desc_signing_key_cert(hs_service_descriptor_t *desc, time_t now)
tor_assert_nonfatal(plaintext->signing_key_cert);
}
-/* Populate the descriptor encrypted section from the given service object.
+/** Populate the descriptor encrypted section from the given service object.
* This will generate a valid list of introduction points that can be used
* after for circuit creation. Return 0 on success else -1 on error. */
static int
@@ -1734,7 +1736,7 @@ build_service_desc_encrypted(const hs_service_t *service,
return 0;
}
-/* Populate the descriptor superencrypted section from the given service
+/** Populate the descriptor superencrypted section from the given service
* object. This will generate a valid list of hs_desc_authorized_client_t
* of clients that are authorized to use the service. Return 0 on success
* else -1 on error. */
@@ -1817,7 +1819,7 @@ build_service_desc_superencrypted(const hs_service_t *service,
return 0;
}
-/* Populate the descriptor plaintext section from the given service object.
+/** Populate the descriptor plaintext section from the given service object.
* The caller must make sure that the keys in the descriptors are valid that
* is are non-zero. This can't fail. */
static void
@@ -1868,7 +1870,7 @@ generate_ope_cipher_for_desc(const hs_service_descriptor_t *hs_desc)
return crypto_ope_new(key);
}
-/* For the given service and descriptor object, create the key material which
+/** For the given service and descriptor object, create the key material which
* is the blinded keypair, the descriptor signing keypair, the ephemeral
* keypair, and the descriptor cookie. Return 0 on success else -1 on error
* where the generated keys MUST be ignored. */
@@ -1930,7 +1932,7 @@ build_service_desc_keys(const hs_service_t *service,
return ret;
}
-/* Given a service and the current time, build a descriptor for the service.
+/** Given a service and the current time, build a descriptor for the service.
* This function does not pick introduction point, this needs to be done by
* the update function. On success, desc_out will point to the newly allocated
* descriptor object.
@@ -1987,7 +1989,7 @@ build_service_descriptor(hs_service_t *service, uint64_t time_period_num,
service_descriptor_free(desc);
}
-/* Build both descriptors for the given service that has just booted up.
+/** Build both descriptors for the given service that has just booted up.
* Because it's a special case, it deserves its special function ;). */
static void
build_descriptors_for_new_service(hs_service_t *service, time_t now)
@@ -2037,7 +2039,7 @@ build_descriptors_for_new_service(hs_service_t *service, time_t now)
safe_str_client(service->onion_address));
}
-/* Build descriptors for each service if needed. There are conditions to build
+/** Build descriptors for each service if needed. There are conditions to build
* a descriptor which are details in the function. */
STATIC void
build_all_descriptors(time_t now)
@@ -2070,7 +2072,7 @@ build_all_descriptors(time_t now)
} FOR_EACH_DESCRIPTOR_END;
}
-/* Randomly pick a node to become an introduction point but not present in the
+/** Randomly pick a node to become an introduction point but not present in the
* given exclude_nodes list. The chosen node is put in the exclude list
* regardless of success or not because in case of failure, the node is simply
* unsusable from that point on.
@@ -2131,7 +2133,7 @@ pick_intro_point(unsigned int direct_conn, smartlist_t *exclude_nodes)
return NULL;
}
-/* For a given descriptor from the given service, pick any needed intro points
+/** For a given descriptor from the given service, pick any needed intro points
* and update the current map with those newly picked intro points. Return the
* number node that might have been added to the descriptor current map. */
static unsigned int
@@ -2255,7 +2257,7 @@ service_desc_schedule_upload(hs_service_descriptor_t *desc,
}
}
-/* Pick missing intro points for this descriptor if needed. */
+/** Pick missing intro points for this descriptor if needed. */
static void
update_service_descriptor_intro_points(hs_service_t *service,
hs_service_descriptor_t *desc, time_t now)
@@ -2296,7 +2298,7 @@ update_service_descriptor_intro_points(hs_service_t *service,
}
}
-/* Update descriptor intro points for each service if needed. We do this as
+/** Update descriptor intro points for each service if needed. We do this as
* part of the periodic event because we need to establish intro point circuits
* before we publish descriptors. */
STATIC void
@@ -2311,7 +2313,7 @@ update_all_descriptors_intro_points(time_t now)
} FOR_EACH_SERVICE_END;
}
-/* Return true iff the given intro point has expired that is it has been used
+/** Return true iff the given intro point has expired that is it has been used
* for too long or we've reached our max seen INTRODUCE2 cell. */
STATIC int
intro_point_should_expire(const hs_service_intro_point_t *ip,
@@ -2333,7 +2335,7 @@ intro_point_should_expire(const hs_service_intro_point_t *ip,
return 1;
}
-/* Return true iff we should remove the intro point ip from its service.
+/** Return true iff we should remove the intro point ip from its service.
*
* We remove an intro point from the service descriptor list if one of
* these criteria is met:
@@ -2369,10 +2371,6 @@ should_remove_intro_point(hs_service_intro_point_t *ip, time_t now)
* remove it because it might simply be valid and opened at the previous
* scheduled event for the last retry. */
- /* Did we established already? */
- if (ip->circuit_established) {
- goto end;
- }
/* Do we simply have an existing circuit regardless of its state? */
if (hs_circ_service_get_intro_circ(ip)) {
goto end;
@@ -2395,7 +2393,7 @@ should_remove_intro_point(hs_service_intro_point_t *ip, time_t now)
return ret;
}
-/* Go over the given set of intro points for each service and remove any
+/** Go over the given set of intro points for each service and remove any
* invalid ones.
*
* If an intro point is removed, the circuit (if any) is immediately close.
@@ -2405,12 +2403,10 @@ static void
cleanup_intro_points(hs_service_t *service, time_t now)
{
/* List of intro points to close. We can't mark the intro circuits for close
- * in the modify loop because doing so calls
- * hs_service_intro_circ_has_closed() which does a digest256map_get() on the
- * intro points map (that we are iterating over). This can't be done in a
- * single iteration after a MAP_DEL_CURRENT, the object will still be
- * returned leading to a use-after-free. So, we close the circuits and free
- * the intro points after the loop if any. */
+ * in the modify loop because doing so calls back into the HS subsystem and
+ * we need to keep that code path outside of the service/desc loop so those
+ * maps don't get modified during the close making us in a possible
+ * use-after-free situation. */
smartlist_t *ips_to_free = smartlist_new();
tor_assert(service);
@@ -2458,7 +2454,7 @@ cleanup_intro_points(hs_service_t *service, time_t now)
smartlist_free(ips_to_free);
}
-/* Set the next rotation time of the descriptors for the given service for the
+/** Set the next rotation time of the descriptors for the given service for the
* time now. */
static void
set_rotation_time(hs_service_t *service)
@@ -2477,7 +2473,7 @@ set_rotation_time(hs_service_t *service)
}
}
-/* Return true iff the service should rotate its descriptor. The time now is
+/** Return true iff the service should rotate its descriptor. The time now is
* only used to fetch the live consensus and if none can be found, this
* returns false. */
static unsigned int
@@ -2529,7 +2525,7 @@ should_rotate_descriptors(hs_service_t *service, time_t now)
return 1;
}
-/* Rotate the service descriptors of the given service. The current descriptor
+/** Rotate the service descriptors of the given service. The current descriptor
* will be freed, the next one put in as the current and finally the next
* descriptor pointer is NULLified. */
static void
@@ -2551,7 +2547,7 @@ rotate_service_descriptors(hs_service_t *service)
set_rotation_time(service);
}
-/* Rotate descriptors for each service if needed. A non existing current
+/** Rotate descriptors for each service if needed. A non existing current
* descriptor will trigger a descriptor build for the next time period. */
STATIC void
rotate_all_descriptors(time_t now)
@@ -2580,7 +2576,7 @@ rotate_all_descriptors(time_t now)
} FOR_EACH_SERVICE_END;
}
-/* Scheduled event run from the main loop. Make sure all our services are up
+/** Scheduled event run from the main loop. Make sure all our services are up
* to date and ready for the other scheduled events. This includes looking at
* the introduction points status and descriptor rotation time. */
STATIC void
@@ -2615,7 +2611,7 @@ run_housekeeping_event(time_t now)
} FOR_EACH_SERVICE_END;
}
-/* Scheduled event run from the main loop. Make sure all descriptors are up to
+/** Scheduled event run from the main loop. Make sure all descriptors are up to
* date. Once this returns, each service descriptor needs to be considered for
* new introduction circuits and then for upload. */
static void
@@ -2638,7 +2634,7 @@ run_build_descriptor_event(time_t now)
update_all_descriptors_intro_points(now);
}
-/* For the given service, launch any intro point circuits that could be
+/** For the given service, launch any intro point circuits that could be
* needed. This considers every descriptor of the service. */
static void
launch_intro_point_circuits(hs_service_t *service)
@@ -2692,7 +2688,7 @@ launch_intro_point_circuits(hs_service_t *service)
} FOR_EACH_DESCRIPTOR_END;
}
-/* Don't try to build more than this many circuits before giving up for a
+/** Don't try to build more than this many circuits before giving up for a
* while. Dynamically calculated based on the configured number of intro
* points for the given service and how many descriptor exists. The default
* use case of 3 introduction points and two descriptors will allow 28
@@ -2708,7 +2704,7 @@ get_max_intro_circ_per_period(const hs_service_t *service)
tor_assert(service->config.num_intro_points <=
HS_CONFIG_V3_MAX_INTRO_POINTS);
-/* For a testing network, allow to do it for the maximum amount so circuit
+/** For a testing network, allow to do it for the maximum amount so circuit
* creation and rotation and so on can actually be tested without limit. */
#define MAX_INTRO_POINT_CIRCUIT_RETRIES_TESTING -1
if (get_options()->TestingTorNetwork) {
@@ -2737,7 +2733,7 @@ get_max_intro_circ_per_period(const hs_service_t *service)
return (count * multiplier);
}
-/* For the given service, return 1 if the service is allowed to launch more
+/** For the given service, return 1 if the service is allowed to launch more
* introduction circuits else 0 if the maximum has been reached for the retry
* period of INTRO_CIRC_RETRY_PERIOD. */
STATIC int
@@ -2783,7 +2779,7 @@ can_service_launch_intro_circuit(hs_service_t *service, time_t now)
return 1;
}
-/* Scheduled event run from the main loop. Make sure we have all the circuits
+/** Scheduled event run from the main loop. Make sure we have all the circuits
* we need for each service. */
static void
run_build_circuit_event(time_t now)
@@ -2813,7 +2809,7 @@ run_build_circuit_event(time_t now)
} FOR_EACH_SERVICE_END;
}
-/* Encode and sign the service descriptor desc and upload it to the given
+/** Encode and sign the service descriptor desc and upload it to the given
* hidden service directory. This does nothing if PublishHidServDescriptors
* is false. */
static void
@@ -2949,7 +2945,7 @@ set_descriptor_revision_counter(hs_service_descriptor_t *hs_desc, time_t now,
hs_desc->desc->plaintext_data.revision_counter = rev_counter;
}
-/* Encode and sign the service descriptor desc and upload it to the
+/** Encode and sign the service descriptor desc and upload it to the
* responsible hidden service directories. If for_next_period is true, the set
* of directories are selected using the next hsdir_index. This does nothing
* if PublishHidServDescriptors is false. */
@@ -3046,7 +3042,7 @@ service_desc_hsdirs_changed(const hs_service_t *service,
return should_reupload;
}
-/* Return 1 if the given descriptor from the given service can be uploaded
+/** Return 1 if the given descriptor from the given service can be uploaded
* else return 0 if it can not. */
static int
should_service_upload_descriptor(const hs_service_t *service,
@@ -3103,7 +3099,7 @@ should_service_upload_descriptor(const hs_service_t *service,
return 0;
}
-/* Refresh the given service descriptor meaning this will update every mutable
+/** Refresh the given service descriptor meaning this will update every mutable
* field that needs to be updated before we upload.
*
* This should ONLY be called before uploading a descriptor. It assumes that
@@ -3134,7 +3130,7 @@ refresh_service_descriptor(const hs_service_t *service,
set_descriptor_revision_counter(desc, now, service->desc_current == desc);
}
-/* Scheduled event run from the main loop. Try to upload the descriptor for
+/** Scheduled event run from the main loop. Try to upload the descriptor for
* each service. */
STATIC void
run_upload_descriptor_event(time_t now)
@@ -3183,7 +3179,7 @@ run_upload_descriptor_event(time_t now)
consider_republishing_hs_descriptors = 0;
}
-/* Called when the introduction point circuit is done building and ready to be
+/** Called when the introduction point circuit is done building and ready to be
* used. */
static void
service_intro_circ_has_opened(origin_circuit_t *circ)
@@ -3241,7 +3237,7 @@ service_intro_circ_has_opened(origin_circuit_t *circ)
return;
}
-/* Called when a rendezvous circuit is done building and ready to be used. */
+/** Called when a rendezvous circuit is done building and ready to be used. */
static void
service_rendezvous_circ_has_opened(origin_circuit_t *circ)
{
@@ -3282,7 +3278,7 @@ service_rendezvous_circ_has_opened(origin_circuit_t *circ)
return;
}
-/* We've been expecting an INTRO_ESTABLISHED cell on this circuit and it just
+/** We've been expecting an INTRO_ESTABLISHED cell on this circuit and it just
* arrived. Handle the INTRO_ESTABLISHED cell arriving on the given
* introduction circuit. Return 0 on success else a negative value. */
static int
@@ -3325,11 +3321,6 @@ service_handle_intro_established(origin_circuit_t *circ,
goto err;
}
- /* Flag that we have an established circuit for this intro point. This value
- * is what indicates the upload scheduled event if we are ready to build the
- * intro point into the descriptor and upload. */
- ip->circuit_established = 1;
-
log_info(LD_REND, "Successfully received an INTRO_ESTABLISHED cell "
"on circuit %u for service %s",
TO_CIRCUIT(circ)->n_circ_id,
@@ -3340,7 +3331,7 @@ service_handle_intro_established(origin_circuit_t *circ,
return -1;
}
-/* We just received an INTRODUCE2 cell on the established introduction circuit
+/** We just received an INTRODUCE2 cell on the established introduction circuit
* circ. Handle the cell and return 0 on success else a negative value. */
static int
service_handle_introduce2(origin_circuit_t *circ, const uint8_t *payload,
@@ -3388,7 +3379,7 @@ service_handle_introduce2(origin_circuit_t *circ, const uint8_t *payload,
return -1;
}
-/* Add to list every filename used by service. This is used by the sandbox
+/** Add to list every filename used by service. This is used by the sandbox
* subsystem. */
static void
service_add_fnames_to_list(const hs_service_t *service, smartlist_t *list)
@@ -3410,7 +3401,7 @@ service_add_fnames_to_list(const hs_service_t *service, smartlist_t *list)
smartlist_add(list, hs_path_from_filename(s_dir, fname));
}
-/* Return true iff the given service identity key is present on disk. */
+/** Return true iff the given service identity key is present on disk. */
static int
service_key_on_disk(const char *directory_path)
{
@@ -3434,7 +3425,7 @@ service_key_on_disk(const char *directory_path)
return ret;
}
-/* This is a proxy function before actually calling hs_desc_encode_descriptor
+/** This is a proxy function before actually calling hs_desc_encode_descriptor
* because we need some preprocessing here */
static int
service_encode_descriptor(const hs_service_t *service,
@@ -3465,7 +3456,7 @@ service_encode_descriptor(const hs_service_t *service,
/* Public API */
/* ========== */
-/* This is called everytime the service map (v2 or v3) changes that is if an
+/** This is called everytime the service map (v2 or v3) changes that is if an
* element is added or removed. */
void
hs_service_map_has_changed(void)
@@ -3476,7 +3467,7 @@ hs_service_map_has_changed(void)
rescan_periodic_events(get_options());
}
-/* Upload an encoded descriptor in encoded_desc of the given version. This
+/** Upload an encoded descriptor in encoded_desc of the given version. This
* descriptor is for the service identity_pk and blinded_pk used to setup the
* directory connection identifier. It is uploaded to the directory hsdir_rs
* routerstatus_t object.
@@ -3524,7 +3515,7 @@ hs_service_upload_desc_to_dir(const char *encoded_desc,
directory_request_free(dir_req);
}
-/* Add the ephemeral service using the secret key sk and ports. Both max
+/** Add the ephemeral service using the secret key sk and ports. Both max
* streams parameter will be set in the newly created service.
*
* Ownership of sk and ports is passed to this routine. Regardless of
@@ -3610,7 +3601,7 @@ hs_service_add_ephemeral(ed25519_secret_key_t *sk, smartlist_t *ports,
return ret;
}
-/* For the given onion address, delete the ephemeral service. Return 0 on
+/** For the given onion address, delete the ephemeral service. Return 0 on
* success else -1 on error. */
int
hs_service_del_ephemeral(const char *address)
@@ -3660,7 +3651,7 @@ hs_service_del_ephemeral(const char *address)
return -1;
}
-/* Using the ed25519 public key pk, find a service for that key and return the
+/** Using the ed25519 public key pk, find a service for that key and return the
* current encoded descriptor as a newly allocated string or NULL if not
* found. This is used by the control port subsystem. */
char *
@@ -3686,7 +3677,7 @@ hs_service_lookup_current_desc(const ed25519_public_key_t *pk)
return NULL;
}
-/* Return the number of service we have configured and usable. */
+/** Return the number of service we have configured and usable. */
MOCK_IMPL(unsigned int,
hs_service_get_num_services,(void))
{
@@ -3696,49 +3687,7 @@ hs_service_get_num_services,(void))
return HT_SIZE(hs_service_map);
}
-/* Called once an introduction circuit is closed. If the circuit doesn't have
- * a v3 identifier, it is ignored. */
-void
-hs_service_intro_circ_has_closed(origin_circuit_t *circ)
-{
- hs_service_t *service = NULL;
- hs_service_intro_point_t *ip = NULL;
- hs_service_descriptor_t *desc = NULL;
-
- tor_assert(circ);
-
- if (circ->hs_ident == NULL) {
- /* This is not a v3 circuit, ignore. */
- goto end;
- }
-
- get_objects_from_ident(circ->hs_ident, &service, &ip, &desc);
- if (service == NULL) {
- /* This is possible if the circuits are closed and the service is
- * immediately deleted. */
- log_info(LD_REND, "Unable to find any hidden service associated "
- "identity key %s on intro circuit %u.",
- ed25519_fmt(&circ->hs_ident->identity_pk),
- TO_CIRCUIT(circ)->n_circ_id);
- goto end;
- }
- if (ip == NULL) {
- /* The introduction point object has already been removed probably by our
- * cleanup process so ignore. */
- goto end;
- }
- /* Can't have an intro point object without a descriptor. */
- tor_assert(desc);
-
- /* Circuit disappeared so make sure the intro point is updated. By
- * keeping the object in the descriptor, we'll be able to retry. */
- ip->circuit_established = 0;
-
- end:
- return;
-}
-
-/* Given conn, a rendezvous edge connection acting as an exit stream, look up
+/** Given conn, a rendezvous edge connection acting as an exit stream, look up
* the hidden service for the circuit circ, and look up the port and address
* based on the connection port. Assign the actual connection address.
*
@@ -3836,7 +3785,7 @@ hs_service_exports_circuit_id(const ed25519_public_key_t *pk)
return service->config.circuit_id_protocol;
}
-/* Add to file_list every filename used by a configured hidden service, and to
+/** Add to file_list every filename used by a configured hidden service, and to
* dir_list every directory path used by a configured hidden service. This is
* used by the sandbox subsystem to whitelist those. */
void
@@ -3861,7 +3810,7 @@ hs_service_lists_fnames_for_sandbox(smartlist_t *file_list,
} FOR_EACH_DESCRIPTOR_END;
}
-/* Called when our internal view of the directory has changed. We might have
+/** Called when our internal view of the directory has changed. We might have
* received a new batch of descriptors which might affect the shape of the
* HSDir hash ring. Signal that we should reexamine the hash ring and
* re-upload our HS descriptors if needed. */
@@ -3878,7 +3827,7 @@ hs_service_dir_info_changed(void)
}
}
-/* Called when we get an INTRODUCE2 cell on the circ. Respond to the cell and
+/** Called when we get an INTRODUCE2 cell on the circ. Respond to the cell and
* launch a circuit to the rendezvous point. */
int
hs_service_receive_introduce2(origin_circuit_t *circ, const uint8_t *payload,
@@ -3909,7 +3858,7 @@ hs_service_receive_introduce2(origin_circuit_t *circ, const uint8_t *payload,
return ret;
}
-/* Called when we get an INTRO_ESTABLISHED cell. Mark the circuit as an
+/** Called when we get an INTRO_ESTABLISHED cell. Mark the circuit as an
* established introduction point. Return 0 on success else a negative value
* and the circuit is closed. */
int
@@ -3946,7 +3895,7 @@ hs_service_receive_intro_established(origin_circuit_t *circ,
return -1;
}
-/* Called when any kind of hidden service circuit is done building thus
+/** Called when any kind of hidden service circuit is done building thus
* opened. This is the entry point from the circuit subsystem. */
void
hs_service_circuit_has_opened(origin_circuit_t *circ)
@@ -3975,7 +3924,7 @@ hs_service_circuit_has_opened(origin_circuit_t *circ)
}
}
-/* Return the service version by looking at the key in the service directory.
+/** Return the service version by looking at the key in the service directory.
* If the key is not found or unrecognized, -1 is returned. Else, the service
* version is returned. */
int
@@ -4005,7 +3954,7 @@ hs_service_get_version_from_key(const hs_service_t *service)
return version;
}
-/* Load and/or generate keys for all onion services including the client
+/** Load and/or generate keys for all onion services including the client
* authorization if any. Return 0 on success, -1 on failure. */
int
hs_service_load_all_keys(void)
@@ -4041,7 +3990,7 @@ hs_service_load_all_keys(void)
return -1;
}
-/* Put all service object in the given service list. After this, the caller
+/** Put all service object in the given service list. After this, the caller
* looses ownership of every elements in the list and responsible to free the
* list pointer. */
void
@@ -4058,7 +4007,7 @@ hs_service_stage_services(const smartlist_t *service_list)
smartlist_add_all(hs_service_staging_list, service_list);
}
-/* Allocate and initilize a service object. The service configuration will
+/** Allocate and initilize a service object. The service configuration will
* contain the default values. Return the newly allocated object pointer. This
* function can't fail. */
hs_service_t *
@@ -4076,7 +4025,7 @@ hs_service_new(const or_options_t *options)
return service;
}
-/* Free the given <b>service</b> object and all its content. This function
+/** Free the given <b>service</b> object and all its content. This function
* also takes care of wiping service keys from memory. It is safe to pass a
* NULL pointer. */
void
@@ -4105,7 +4054,7 @@ hs_service_free_(hs_service_t *service)
tor_free(service);
}
-/* Periodic callback. Entry point from the main loop to the HS service
+/** Periodic callback. Entry point from the main loop to the HS service
* subsystem. This is call every second. This is skipped if tor can't build a
* circuit or the network is disabled. */
void
@@ -4128,7 +4077,7 @@ hs_service_run_scheduled_events(time_t now)
run_upload_descriptor_event(now);
}
-/* Initialize the service HS subsystem. */
+/** Initialize the service HS subsystem. */
void
hs_service_init(void)
{
@@ -4145,7 +4094,7 @@ hs_service_init(void)
hs_service_staging_list = smartlist_new();
}
-/* Release all global storage of the hidden service subsystem. */
+/** Release all global storage of the hidden service subsystem. */
void
hs_service_free_all(void)
{
@@ -4155,14 +4104,14 @@ hs_service_free_all(void)
#ifdef TOR_UNIT_TESTS
-/* Return the global service map size. Only used by unit test. */
+/** Return the global service map size. Only used by unit test. */
STATIC unsigned int
get_hs_service_map_size(void)
{
return HT_SIZE(hs_service_map);
}
-/* Return the staging list size. Only used by unit test. */
+/** Return the staging list size. Only used by unit test. */
STATIC int
get_hs_service_staging_list_size(void)
{
diff --git a/src/feature/hs/hs_service.h b/src/feature/hs/hs_service.h
index c4bbb293bb..8809411e01 100644
--- a/src/feature/hs/hs_service.h
+++ b/src/feature/hs/hs_service.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -21,92 +21,92 @@
/* Trunnel */
#include "trunnel/hs/cell_establish_intro.h"
-/* When loading and configuring a service, this is the default version it will
+#include "ext/ht.h"
+
+/** When loading and configuring a service, this is the default version it will
* be configured for as it is possible that no HiddenServiceVersion is
* present. */
#define HS_SERVICE_DEFAULT_VERSION HS_VERSION_THREE
-/* As described in the specification, service publishes their next descriptor
+/** As described in the specification, service publishes their next descriptor
* at a random time between those two values (in seconds). */
#define HS_SERVICE_NEXT_UPLOAD_TIME_MIN (60 * 60)
+/** Maximum interval for uploading next descriptor (in seconds). */
#define HS_SERVICE_NEXT_UPLOAD_TIME_MAX (120 * 60)
-/* Service side introduction point. */
+/** Service side introduction point. */
typedef struct hs_service_intro_point_t {
- /* Top level intropoint "shared" data between client/service. */
+ /** Top level intropoint "shared" data between client/service. */
hs_intropoint_t base;
- /* Onion key of the introduction point used to extend to it for the ntor
+ /** Onion key of the introduction point used to extend to it for the ntor
* handshake. */
curve25519_public_key_t onion_key;
- /* Authentication keypair used to create the authentication certificate
+ /** Authentication keypair used to create the authentication certificate
* which is published in the descriptor. */
ed25519_keypair_t auth_key_kp;
- /* Encryption keypair for the "ntor" type. */
+ /** Encryption keypair for the "ntor" type. */
curve25519_keypair_t enc_key_kp;
- /* Legacy key if that intro point doesn't support v3. This should be used if
+ /** Legacy key if that intro point doesn't support v3. This should be used if
* the base object legacy flag is set. */
crypto_pk_t *legacy_key;
- /* Legacy key SHA1 public key digest. This should be used only if the base
+ /** Legacy key SHA1 public key digest. This should be used only if the base
* object legacy flag is set. */
uint8_t legacy_key_digest[DIGEST_LEN];
- /* Amount of INTRODUCE2 cell accepted from this intro point. */
+ /** Amount of INTRODUCE2 cell accepted from this intro point. */
uint64_t introduce2_count;
- /* Maximum number of INTRODUCE2 cell this intro point should accept. */
+ /** Maximum number of INTRODUCE2 cell this intro point should accept. */
uint64_t introduce2_max;
- /* The time at which this intro point should expire and stop being used. */
+ /** The time at which this intro point should expire and stop being used. */
time_t time_to_expire;
- /* The amount of circuit creation we've made to this intro point. This is
+ /** The amount of circuit creation we've made to this intro point. This is
* incremented every time we do a circuit relaunch on this intro point which
* is triggered when the circuit dies but the node is still in the
* consensus. After MAX_INTRO_POINT_CIRCUIT_RETRIES, we give up on it. */
uint32_t circuit_retries;
- /* Set if this intro point has an established circuit. */
- unsigned int circuit_established : 1;
-
- /* Replay cache recording the encrypted part of an INTRODUCE2 cell that the
+ /** Replay cache recording the encrypted part of an INTRODUCE2 cell that the
* circuit associated with this intro point has received. This is used to
* prevent replay attacks. */
replaycache_t *replay_cache;
- /* Support the INTRO2 DoS defense. If set, the DoS extension described by
+ /** Support the INTRO2 DoS defense. If set, the DoS extension described by
* proposal 305 is sent. */
unsigned int support_intro2_dos_defense : 1;
} hs_service_intro_point_t;
-/* Object handling introduction points of a service. */
+/** Object handling introduction points of a service. */
typedef struct hs_service_intropoints_t {
- /* The time at which we've started our retry period to build circuits. We
+ /** The time at which we've started our retry period to build circuits. We
* don't want to stress circuit creation so we can only retry for a certain
* time and then after we stop and wait. */
time_t retry_period_started;
- /* Number of circuit we've launched during a single retry period. */
+ /** Number of circuit we've launched during a single retry period. */
unsigned int num_circuits_launched;
- /* Contains the current hs_service_intro_point_t objects indexed by
+ /** Contains the current hs_service_intro_point_t objects indexed by
* authentication public key. */
digest256map_t *map;
- /* Contains node's identity key digest that were introduction point for this
+ /** Contains node's identity key digest that were introduction point for this
* descriptor but were retried to many times. We keep those so we avoid
* re-picking them over and over for a circuit retry period.
* XXX: Once we have #22173, change this to only use ed25519 identity. */
digestmap_t *failed_id;
} hs_service_intropoints_t;
-/* Representation of a service descriptor.
+/** Representation of a service descriptor.
*
* Some elements of the descriptor are mutable whereas others are immutable:
-
+ *
* Immutable elements are initialized once when the descriptor is built (when
* service descriptors gets rotated). This means that these elements are
* initialized once and then they don't change for the lifetime of the
@@ -121,40 +121,42 @@ typedef struct hs_service_intropoints_t {
* update_service_descriptor_intro_points().
*/
typedef struct hs_service_descriptor_t {
- /* Immutable: Client authorization ephemeral keypair. */
+ /** Immutable: Client authorization ephemeral keypair. */
curve25519_keypair_t auth_ephemeral_kp;
- /* Immutable: Descriptor cookie used to encrypt the descriptor, when the
+ /** Immutable: Descriptor cookie used to encrypt the descriptor, when the
* client authorization is enabled */
uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN];
- /* Immutable: Descriptor signing keypair. */
+ /** Immutable: Descriptor signing keypair. */
ed25519_keypair_t signing_kp;
- /* Immutable: Blinded keypair derived from the master identity public key. */
+ /** Immutable: Blinded keypair derived from the master identity public
+ * key. */
ed25519_keypair_t blinded_kp;
- /* Immutable: The time period number this descriptor has been created for. */
+ /** Immutable: The time period number this descriptor has been created
+ * for. */
uint64_t time_period_num;
/** Immutable: The OPE cipher for encrypting revision counters for this
* descriptor. Tied to the descriptor blinded key. */
struct crypto_ope_t *ope_cipher;
- /* Mutable: Decoded descriptor. This object is used for encoding when the
+ /** Mutable: Decoded descriptor. This object is used for encoding when the
* service publishes the descriptor. */
hs_descriptor_t *desc;
- /* Mutable: When is the next time when we should upload the descriptor. */
+ /** Mutable: When is the next time when we should upload the descriptor. */
time_t next_upload_time;
- /* Mutable: Introduction points assign to this descriptor which contains
+ /** Mutable: Introduction points assign to this descriptor which contains
* hs_service_intropoints_t object indexed by authentication key (the RSA key
* if the node is legacy). */
hs_service_intropoints_t intro_points;
- /* Mutable: True iff we have missing intro points for this descriptor because
- * we couldn't pick any nodes. */
+ /** Mutable: True iff we have missing intro points for this descriptor
+ * because we couldn't pick any nodes. */
unsigned int missing_intro_points : 1;
/** Mutable: List of the responsible HSDirs (their b64ed identity digest)
@@ -164,20 +166,20 @@ typedef struct hs_service_descriptor_t {
smartlist_t *previous_hsdirs;
} hs_service_descriptor_t;
-/* Service key material. */
+/** Service key material. */
typedef struct hs_service_keys_t {
- /* Master identify public key. */
+ /** Master identify public key. */
ed25519_public_key_t identity_pk;
- /* Master identity private key. */
+ /** Master identity private key. */
ed25519_secret_key_t identity_sk;
- /* True iff the key is kept offline which means the identity_sk MUST not be
+ /** True iff the key is kept offline which means the identity_sk MUST not be
* used in that case. */
unsigned int is_identify_key_offline : 1;
} hs_service_keys_t;
/** Service side configuration of client authorization. */
typedef struct hs_service_authorized_client_t {
- /* The client auth public key used to encrypt the descriptor cookie. */
+ /** The client auth public key used to encrypt the descriptor cookie. */
curve25519_public_key_t client_pk;
} hs_service_authorized_client_t;
@@ -190,60 +192,60 @@ typedef enum {
HS_CIRCUIT_ID_PROTOCOL_HAPROXY
} hs_circuit_id_protocol_t;
-/* Service configuration. The following are set from the torrc options either
+/** Service configuration. The following are set from the torrc options either
* set by the configuration file or by the control port. Nothing else should
* change those values. */
typedef struct hs_service_config_t {
- /* Protocol version of the service. Specified by HiddenServiceVersion
+ /** Protocol version of the service. Specified by HiddenServiceVersion
* option. */
uint32_t version;
- /* Have we explicitly set HiddenServiceVersion? */
+ /** Have we explicitly set HiddenServiceVersion? */
unsigned int hs_version_explicitly_set : 1;
- /* List of rend_service_port_config_t */
+ /** List of rend_service_port_config_t */
smartlist_t *ports;
- /* Path on the filesystem where the service persistent data is stored. NULL
+ /** Path on the filesystem where the service persistent data is stored. NULL
* if the service is ephemeral. Specified by HiddenServiceDir option. */
char *directory_path;
- /* The maximum number of simultaneous streams per rendezvous circuit that
+ /** The maximum number of simultaneous streams per rendezvous circuit that
* are allowed to be created. No limit if 0. Specified by
* HiddenServiceMaxStreams option. */
uint64_t max_streams_per_rdv_circuit;
- /* If true, we close circuits that exceed the max_streams_per_rdv_circuit
+ /** If true, we close circuits that exceed the max_streams_per_rdv_circuit
* limit. Specified by HiddenServiceMaxStreamsCloseCircuit option. */
unsigned int max_streams_close_circuit : 1;
- /* How many introduction points this service has. Specified by
+ /** How many introduction points this service has. Specified by
* HiddenServiceNumIntroductionPoints option. */
unsigned int num_intro_points;
- /* True iff the client auth is enabled. */
+ /** True iff the client auth is enabled. */
unsigned int is_client_auth_enabled : 1;
- /* List of hs_service_authorized_client_t's of clients that may access this
+ /** List of hs_service_authorized_client_t's of clients that may access this
* service. Specified by HiddenServiceAuthorizeClient option. */
smartlist_t *clients;
- /* True iff we allow request made on unknown ports. Specified by
+ /** True iff we allow request made on unknown ports. Specified by
* HiddenServiceAllowUnknownPorts option. */
unsigned int allow_unknown_ports : 1;
- /* If true, this service is a Single Onion Service. Specified by
+ /** If true, this service is a Single Onion Service. Specified by
* HiddenServiceSingleHopMode and HiddenServiceNonAnonymousMode options. */
unsigned int is_single_onion : 1;
- /* If true, allow group read permissions on the directory_path. Specified by
+ /** If true, allow group read permissions on the directory_path. Specified by
* HiddenServiceDirGroupReadable option. */
unsigned int dir_group_readable : 1;
- /* Is this service ephemeral? */
+ /** Is this service ephemeral? */
unsigned int is_ephemeral : 1;
- /* Does this service export the circuit ID of its clients? */
+ /** Does this service export the circuit ID of its clients? */
hs_circuit_id_protocol_t circuit_id_protocol;
/* DoS defenses. For the ESTABLISH_INTRO cell extension. */
@@ -252,58 +254,58 @@ typedef struct hs_service_config_t {
uint32_t intro_dos_burst_per_sec;
} hs_service_config_t;
-/* Service state. */
+/** Service state. */
typedef struct hs_service_state_t {
- /* The time at which we've started our retry period to build circuits. We
+ /** The time at which we've started our retry period to build circuits. We
* don't want to stress circuit creation so we can only retry for a certain
* time and then after we stop and wait. */
time_t intro_circ_retry_started_time;
- /* Number of circuit we've launched during a single retry period. This
+ /** Number of circuit we've launched during a single retry period. This
* should never go over MAX_INTRO_CIRCS_PER_PERIOD. */
unsigned int num_intro_circ_launched;
- /* Replay cache tracking the REND_COOKIE found in INTRODUCE2 cell to detect
+ /** Replay cache tracking the REND_COOKIE found in INTRODUCE2 cell to detect
* repeats. Clients may send INTRODUCE1 cells for the same rendezvous point
* through two or more different introduction points; when they do, this
* keeps us from launching multiple simultaneous attempts to connect to the
* same rend point. */
replaycache_t *replay_cache_rend_cookie;
- /* When is the next time we should rotate our descriptors. This is has to be
+ /** When is the next time we should rotate our descriptors. This is has to be
* done at the start time of the next SRV protocol run. */
time_t next_rotation_time;
} hs_service_state_t;
-/* Representation of a service running on this tor instance. */
+/** Representation of a service running on this tor instance. */
typedef struct hs_service_t {
- /* Onion address base32 encoded and NUL terminated. We keep it for logging
+ /** Onion address base32 encoded and NUL terminated. We keep it for logging
* purposes so we don't have to build it everytime. */
char onion_address[HS_SERVICE_ADDR_LEN_BASE32 + 1];
- /* Hashtable node: use to look up the service by its master public identity
+ /** Hashtable node: use to look up the service by its master public identity
* key in the service global map. */
HT_ENTRY(hs_service_t) hs_service_node;
- /* Service state which contains various flags and counters. */
+ /** Service state which contains various flags and counters. */
hs_service_state_t state;
- /* Key material of the service. */
+ /** Key material of the service. */
hs_service_keys_t keys;
- /* Configuration of the service. */
+ /** Configuration of the service. */
hs_service_config_t config;
- /* Current descriptor. */
+ /** Current descriptor. */
hs_service_descriptor_t *desc_current;
- /* Next descriptor. */
+ /** Next descriptor. */
hs_service_descriptor_t *desc_next;
/* XXX: Credential (client auth.) #20700. */
} hs_service_t;
-/* For the service global hash map, we define a specific type for it which
+/** For the service global hash map, we define a specific type for it which
* will make it safe to use and specific to some controlled parameters such as
* the hashing function and how to compare services. */
typedef HT_HEAD(hs_service_ht, hs_service_t) hs_service_ht;
@@ -317,6 +319,11 @@ void hs_service_free_all(void);
/* Service new/free functions. */
hs_service_t *hs_service_new(const or_options_t *options);
void hs_service_free_(hs_service_t *service);
+/**
+ * @copydoc hs_service_free_
+ *
+ * Additionally, set the pointer <b>s</b> to NULL.
+ **/
#define hs_service_free(s) FREE_AND_NULL(hs_service_t, hs_service_free_, (s))
MOCK_DECL(unsigned int, hs_service_get_num_services,(void));
@@ -339,8 +346,6 @@ int hs_service_receive_introduce2(origin_circuit_t *circ,
const uint8_t *payload,
size_t payload_len);
-void hs_service_intro_circ_has_closed(origin_circuit_t *circ);
-
char *hs_service_lookup_current_desc(const ed25519_public_key_t *pk);
hs_service_add_ephemeral_status_t
diff --git a/src/feature/hs/hs_stats.c b/src/feature/hs/hs_stats.c
index f24b731328..f9d458d630 100644
--- a/src/feature/hs/hs_stats.c
+++ b/src/feature/hs/hs_stats.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/hs/hs_stats.h b/src/feature/hs/hs_stats.h
index 6700eca15b..aea2ccf5c2 100644
--- a/src/feature/hs/hs_stats.h
+++ b/src/feature/hs/hs_stats.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/hs/hsdir_index_st.h b/src/feature/hs/hsdir_index_st.h
index 6c86c02f47..6ce0bf5c69 100644
--- a/src/feature/hs/hsdir_index_st.h
+++ b/src/feature/hs/hsdir_index_st.h
@@ -1,24 +1,29 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file hsdir_index_st.h
+ * @brief HS directory index structure
+ **/
+
#ifndef HSDIR_INDEX_ST_H
#define HSDIR_INDEX_ST_H
-/* Hidden service directory index used in a node_t which is set once we set
+/** Hidden service directory index used in a node_t which is set once we set
* the consensus. */
struct hsdir_index_t {
- /* HSDir index to use when fetching a descriptor. */
+ /** HSDir index to use when fetching a descriptor. */
uint8_t fetch[DIGEST256_LEN];
- /* HSDir index used by services to store their first and second
+ /** HSDir index used by services to store their first and second
* descriptor. The first descriptor is chronologically older than the second
* one and uses older TP and SRV values. */
uint8_t store_first[DIGEST256_LEN];
+ /** Newer index, for second descriptor. */
uint8_t store_second[DIGEST256_LEN];
};
#endif /* !defined(HSDIR_INDEX_ST_H) */
-
diff --git a/src/feature/hs/include.am b/src/feature/hs/include.am
new file mode 100644
index 0000000000..5e69607e59
--- /dev/null
+++ b/src/feature/hs/include.am
@@ -0,0 +1,35 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/hs/hs_cache.c \
+ src/feature/hs/hs_cell.c \
+ src/feature/hs/hs_circuit.c \
+ src/feature/hs/hs_circuitmap.c \
+ src/feature/hs/hs_client.c \
+ src/feature/hs/hs_common.c \
+ src/feature/hs/hs_config.c \
+ src/feature/hs/hs_control.c \
+ src/feature/hs/hs_descriptor.c \
+ src/feature/hs/hs_dos.c \
+ src/feature/hs/hs_ident.c \
+ src/feature/hs/hs_intropoint.c \
+ src/feature/hs/hs_service.c \
+ src/feature/hs/hs_stats.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/hs/hs_cache.h \
+ src/feature/hs/hs_cell.h \
+ src/feature/hs/hs_circuit.h \
+ src/feature/hs/hs_circuitmap.h \
+ src/feature/hs/hs_client.h \
+ src/feature/hs/hs_common.h \
+ src/feature/hs/hs_config.h \
+ src/feature/hs/hs_control.h \
+ src/feature/hs/hs_descriptor.h \
+ src/feature/hs/hs_dos.h \
+ src/feature/hs/hs_ident.h \
+ src/feature/hs/hs_intropoint.h \
+ src/feature/hs/hs_service.h \
+ src/feature/hs/hs_stats.h \
+ src/feature/hs/hsdir_index_st.h
diff --git a/src/feature/hs_common/.may_include b/src/feature/hs_common/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/hs_common/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/hs_common/feature_hs_common.md b/src/feature/hs_common/feature_hs_common.md
new file mode 100644
index 0000000000..3a5e351a0a
--- /dev/null
+++ b/src/feature/hs_common/feature_hs_common.md
@@ -0,0 +1,3 @@
+@dir /feature/hs_common
+@brief feature/hs_common: Common to v2 (old) and v3 (current) onion services
+
diff --git a/src/feature/hs_common/include.am b/src/feature/hs_common/include.am
new file mode 100644
index 0000000000..3bb9225c12
--- /dev/null
+++ b/src/feature/hs_common/include.am
@@ -0,0 +1,10 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/hs_common/replaycache.c \
+ src/feature/hs_common/shared_random_client.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/hs_common/replaycache.h \
+ src/feature/hs_common/shared_random_client.h
diff --git a/src/feature/hs_common/replaycache.c b/src/feature/hs_common/replaycache.c
index 9e8c13b1c5..ab058ce759 100644
--- a/src/feature/hs_common/replaycache.c
+++ b/src/feature/hs_common/replaycache.c
@@ -1,4 +1,4 @@
- /* Copyright (c) 2012-2019, The Tor Project, Inc. */
+ /* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/hs_common/replaycache.h b/src/feature/hs_common/replaycache.h
index 01f5e600c2..3a3eed29c0 100644
--- a/src/feature/hs_common/replaycache.h
+++ b/src/feature/hs_common/replaycache.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,16 +14,16 @@ typedef struct replaycache_t replaycache_t;
#ifdef REPLAYCACHE_PRIVATE
struct replaycache_t {
- /* Scrub interval */
+ /** Scrub interval */
time_t scrub_interval;
- /* Last scrubbed */
+ /** Last scrubbed */
time_t scrubbed;
- /*
+ /**
* Horizon
* (don't return true on digests in the cache but older than this)
*/
time_t horizon;
- /*
+ /**
* Digest map: keys are digests, values are times the digest was last seen
*/
digest256map_t *digests_seen;
@@ -34,6 +34,11 @@ struct replaycache_t {
/* replaycache_t free/new */
void replaycache_free_(replaycache_t *r);
+/**
+ * @copydoc replaycache_free_
+ *
+ * Additionally, set the pointer <b>r</b> to NULL.
+ **/
#define replaycache_free(r) \
FREE_AND_NULL(replaycache_t, replaycache_free_, (r))
replaycache_t * replaycache_new(time_t horizon, time_t interval);
diff --git a/src/feature/hs_common/shared_random_client.c b/src/feature/hs_common/shared_random_client.c
index 5772034c6d..a46666ab50 100644
--- a/src/feature/hs_common/shared_random_client.c
+++ b/src/feature/hs_common/shared_random_client.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -8,7 +8,6 @@
* as part of the dirauth module.
**/
-#define SHARED_RANDOM_CLIENT_PRIVATE
#include "feature/hs_common/shared_random_client.h"
#include "app/config/config.h"
@@ -18,7 +17,7 @@
#include "feature/nodelist/networkstatus_st.h"
-/* Convert a given srv object to a string for the control port. This doesn't
+/** Convert a given srv object to a string for the control port. This doesn't
* fail and the srv object MUST be valid. */
static char *
srv_to_control_string(const sr_srv_t *srv)
@@ -32,7 +31,7 @@ srv_to_control_string(const sr_srv_t *srv)
return srv_str;
}
-/* Return the voting interval of the tor vote subsystem. */
+/** Return the voting interval of the tor vote subsystem. */
int
get_voting_interval(void)
{
@@ -51,7 +50,7 @@ get_voting_interval(void)
return interval;
}
-/* Given the current consensus, return the start time of the current round of
+/** Given the current consensus, return the start time of the current round of
* the SR protocol. For example, if it's 23:47:08, the current round thus
* started at 23:47:00 for a voting interval of 10 seconds.
*
@@ -78,7 +77,7 @@ get_start_time_of_current_round(void)
* Public API
*/
-/* Encode the given shared random value and put it in dst. Destination
+/** Encode the given shared random value and put it in dst. Destination
* buffer must be at least SR_SRV_VALUE_BASE64_LEN plus the NULL byte. */
void
sr_srv_encode(char *dst, size_t dst_len, const sr_srv_t *srv)
@@ -99,7 +98,7 @@ sr_srv_encode(char *dst, size_t dst_len, const sr_srv_t *srv)
strlcpy(dst, buf, dst_len);
}
-/* Return the current SRV string representation for the control port. Return a
+/** Return the current SRV string representation for the control port. Return a
* newly allocated string on success containing the value else "" if not found
* or if we don't have a valid consensus yet. */
char *
@@ -115,7 +114,7 @@ sr_get_current_for_control(void)
return srv_str;
}
-/* Return the previous SRV string representation for the control port. Return
+/** Return the previous SRV string representation for the control port. Return
* a newly allocated string on success containing the value else "" if not
* found or if we don't have a valid consensus yet. */
char *
@@ -131,7 +130,7 @@ sr_get_previous_for_control(void)
return srv_str;
}
-/* Return current shared random value from the latest consensus. Caller can
+/** Return current shared random value from the latest consensus. Caller can
* NOT keep a reference to the returned pointer. Return NULL if none. */
const sr_srv_t *
sr_get_current(const networkstatus_t *ns)
@@ -154,7 +153,7 @@ sr_get_current(const networkstatus_t *ns)
return NULL;
}
-/* Return previous shared random value from the latest consensus. Caller can
+/** Return previous shared random value from the latest consensus. Caller can
* NOT keep a reference to the returned pointer. Return NULL if none. */
const sr_srv_t *
sr_get_previous(const networkstatus_t *ns)
@@ -177,7 +176,7 @@ sr_get_previous(const networkstatus_t *ns)
return NULL;
}
-/* Parse a list of arguments from a SRV value either from a vote, consensus
+/** Parse a list of arguments from a SRV value either from a vote, consensus
* or from our disk state and return a newly allocated srv object. NULL is
* returned on error.
*
@@ -290,4 +289,3 @@ sr_state_get_protocol_run_duration(void)
int total_protocol_rounds = SHARED_RANDOM_N_ROUNDS * SHARED_RANDOM_N_PHASES;
return total_protocol_rounds * get_voting_interval();
}
-
diff --git a/src/feature/hs_common/shared_random_client.h b/src/feature/hs_common/shared_random_client.h
index c90c52cfea..3031a2bb9a 100644
--- a/src/feature/hs_common/shared_random_client.h
+++ b/src/feature/hs_common/shared_random_client.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/keymgt/.may_include b/src/feature/keymgt/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/keymgt/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/keymgt/feature_keymgt.md b/src/feature/keymgt/feature_keymgt.md
new file mode 100644
index 0000000000..1eac7cca50
--- /dev/null
+++ b/src/feature/keymgt/feature_keymgt.md
@@ -0,0 +1,3 @@
+@dir /feature/keymgt
+@brief feature/keymgt: Store keys for relays, authorities, etc.
+
diff --git a/src/feature/keymgt/include.am b/src/feature/keymgt/include.am
new file mode 100644
index 0000000000..bc9beaa523
--- /dev/null
+++ b/src/feature/keymgt/include.am
@@ -0,0 +1,8 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/keymgt/loadkey.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/keymgt/loadkey.h
diff --git a/src/feature/keymgt/loadkey.c b/src/feature/keymgt/loadkey.c
index a8cbf0e582..7958bd964f 100644
--- a/src/feature/keymgt/loadkey.c
+++ b/src/feature/keymgt/loadkey.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -33,7 +33,7 @@
/** Try to read an RSA key from <b>fname</b>. If <b>fname</b> doesn't exist
* and <b>generate</b> is true, create a new RSA key and save it in
* <b>fname</b>. Return the read/created key, or NULL on error. Log all
- * errors at level <b>severity</b>. If <b>created_out/b> is non-NULL and a
+ * errors at level <b>severity</b>. If <b>created_out</b> is non-NULL and a
* new key was created, set *<b>created_out</b> to true.
*/
crypto_pk_t *
diff --git a/src/feature/keymgt/loadkey.h b/src/feature/keymgt/loadkey.h
index 0a5af0b804..5a8ca32dea 100644
--- a/src/feature/keymgt/loadkey.h
+++ b/src/feature/keymgt/loadkey.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/.may_include b/src/feature/nodelist/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/nodelist/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/nodelist/authcert.c b/src/feature/nodelist/authcert.c
index 9fc3b62525..7bdfabaeab 100644
--- a/src/feature/nodelist/authcert.c
+++ b/src/feature/nodelist/authcert.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/authcert.h b/src/feature/nodelist/authcert.h
index 071293f9ee..33065589ba 100644
--- a/src/feature/nodelist/authcert.h
+++ b/src/feature/nodelist/authcert.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/authority_cert_st.h b/src/feature/nodelist/authority_cert_st.h
index bf9b690c24..9145b12bbf 100644
--- a/src/feature/nodelist/authority_cert_st.h
+++ b/src/feature/nodelist/authority_cert_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file authority_cert_st.h
+ * @brief Authority certificate structure.
+ **/
+
#ifndef AUTHORITY_CERT_ST_H
#define AUTHORITY_CERT_ST_H
@@ -29,4 +34,3 @@ struct authority_cert_t {
};
#endif /* !defined(AUTHORITY_CERT_ST_H) */
-
diff --git a/src/feature/nodelist/desc_store_st.h b/src/feature/nodelist/desc_store_st.h
index 4d1378cdfa..5f35a490a5 100644
--- a/src/feature/nodelist/desc_store_st.h
+++ b/src/feature/nodelist/desc_store_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file desc_store_st.h
+ * @brief Routerinfo/extrainfo storage structure.
+ **/
+
#ifndef DESC_STORE_ST_H
#define DESC_STORE_ST_H
diff --git a/src/feature/nodelist/describe.c b/src/feature/nodelist/describe.c
index 1e46837685..00896d5a44 100644
--- a/src/feature/nodelist/describe.c
+++ b/src/feature/nodelist/describe.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/describe.h b/src/feature/nodelist/describe.h
index 6c0d6dc48d..d0fa1af263 100644
--- a/src/feature/nodelist/describe.h
+++ b/src/feature/nodelist/describe.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/dirlist.c b/src/feature/nodelist/dirlist.c
index ccbb378513..ad3af0a143 100644
--- a/src/feature/nodelist/dirlist.c
+++ b/src/feature/nodelist/dirlist.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/dirlist.h b/src/feature/nodelist/dirlist.h
index c49162f1e9..9201e76a9c 100644
--- a/src/feature/nodelist/dirlist.h
+++ b/src/feature/nodelist/dirlist.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/document_signature_st.h b/src/feature/nodelist/document_signature_st.h
index ac2a803252..4bde9d89ec 100644
--- a/src/feature/nodelist/document_signature_st.h
+++ b/src/feature/nodelist/document_signature_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file document_signature_st.h
+ * @brief Authority signature structure
+ **/
+
#ifndef DOCUMENT_SIGNATURE_ST_H
#define DOCUMENT_SIGNATURE_ST_H
@@ -26,4 +31,3 @@ struct document_signature_t {
};
#endif /* !defined(DOCUMENT_SIGNATURE_ST_H) */
-
diff --git a/src/feature/nodelist/extrainfo_st.h b/src/feature/nodelist/extrainfo_st.h
index 22c708f018..6bd6232cd8 100644
--- a/src/feature/nodelist/extrainfo_st.h
+++ b/src/feature/nodelist/extrainfo_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file extrainfo_st.h
+ * @brief A relay's extra-info structure.
+ **/
+
#ifndef EXTRAINFO_ST_H
#define EXTRAINFO_ST_H
@@ -27,4 +32,3 @@ struct extrainfo_t {
};
#endif /* !defined(EXTRAINFO_ST_H) */
-
diff --git a/src/feature/nodelist/feature_nodelist.md b/src/feature/nodelist/feature_nodelist.md
new file mode 100644
index 0000000000..9d715308c2
--- /dev/null
+++ b/src/feature/nodelist/feature_nodelist.md
@@ -0,0 +1,2 @@
+@dir /feature/nodelist
+@brief feature/nodelist: Download and manage a list of relays
diff --git a/src/feature/nodelist/fmt_routerstatus.c b/src/feature/nodelist/fmt_routerstatus.c
index fea7cf4c65..0cf4a6eeab 100644
--- a/src/feature/nodelist/fmt_routerstatus.c
+++ b/src/feature/nodelist/fmt_routerstatus.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -27,10 +27,6 @@
* allocated character buffer. Use the same format as in network-status
* documents. If <b>version</b> is non-NULL, add a "v" line for the platform.
*
- * consensus_method is the current consensus method when format is
- * NS_V3_CONSENSUS or NS_V3_CONSENSUS_MICRODESC. It is ignored for other
- * formats: pass ROUTERSTATUS_FORMAT_NO_CONSENSUS_METHOD.
- *
* Return 0 on success, -1 on failure.
*
* The format argument has one of the following values:
@@ -47,7 +43,6 @@ char *
routerstatus_format_entry(const routerstatus_t *rs, const char *version,
const char *protocols,
routerstatus_format_type_t format,
- int consensus_method,
const vote_routerstatus_t *vrs)
{
char *summary;
@@ -78,12 +73,6 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version,
* networkstatus_type_t values, with an additional control port value
* added -MP */
- /* V3 microdesc consensuses only have "a" lines in later consensus methods
- */
- if (format == NS_V3_CONSENSUS_MICRODESC &&
- consensus_method < MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS)
- goto done;
-
/* Possible "a" line. At most one for now. */
if (!tor_addr_is_null(&rs->ipv6_addr)) {
smartlist_add_asprintf(chunks, "a %s\n",
@@ -124,6 +113,8 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version,
if (format != NS_CONTROL_PORT) {
/* Blow up more or less nicely if we didn't get anything or not the
* thing we expected.
+ * This should be kept in sync with the function
+ * routerstatus_has_visibly_changed and the struct routerstatus_t
*/
if (!desc) {
char id[HEX_DIGEST_LEN+1];
diff --git a/src/feature/nodelist/fmt_routerstatus.h b/src/feature/nodelist/fmt_routerstatus.h
index ddd7a7cf37..a007989af3 100644
--- a/src/feature/nodelist/fmt_routerstatus.h
+++ b/src/feature/nodelist/fmt_routerstatus.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -35,7 +35,6 @@ char *routerstatus_format_entry(
const char *version,
const char *protocols,
routerstatus_format_type_t format,
- int consensus_method,
const vote_routerstatus_t *vrs);
#endif /* !defined(TOR_FMT_ROUTERSTATUS_H) */
diff --git a/src/feature/nodelist/include.am b/src/feature/nodelist/include.am
new file mode 100644
index 0000000000..2f5d58ec1c
--- /dev/null
+++ b/src/feature/nodelist/include.am
@@ -0,0 +1,49 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/nodelist/authcert.c \
+ src/feature/nodelist/describe.c \
+ src/feature/nodelist/dirlist.c \
+ src/feature/nodelist/microdesc.c \
+ src/feature/nodelist/networkstatus.c \
+ src/feature/nodelist/nickname.c \
+ src/feature/nodelist/nodefamily.c \
+ src/feature/nodelist/nodelist.c \
+ src/feature/nodelist/node_select.c \
+ src/feature/nodelist/routerinfo.c \
+ src/feature/nodelist/routerlist.c \
+ src/feature/nodelist/routerset.c \
+ src/feature/nodelist/fmt_routerstatus.c \
+ src/feature/nodelist/torcert.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/nodelist/authcert.h \
+ src/feature/nodelist/authority_cert_st.h \
+ src/feature/nodelist/describe.h \
+ src/feature/nodelist/desc_store_st.h \
+ src/feature/nodelist/dirlist.h \
+ src/feature/nodelist/document_signature_st.h \
+ src/feature/nodelist/extrainfo_st.h \
+ src/feature/nodelist/microdesc.h \
+ src/feature/nodelist/microdesc_st.h \
+ src/feature/nodelist/networkstatus.h \
+ src/feature/nodelist/networkstatus_sr_info_st.h \
+ src/feature/nodelist/networkstatus_st.h \
+ src/feature/nodelist/networkstatus_voter_info_st.h \
+ src/feature/nodelist/nickname.h \
+ src/feature/nodelist/node_st.h \
+ src/feature/nodelist/nodefamily.h \
+ src/feature/nodelist/nodefamily_st.h \
+ src/feature/nodelist/nodelist.h \
+ src/feature/nodelist/node_select.h \
+ src/feature/nodelist/routerinfo.h \
+ src/feature/nodelist/routerinfo_st.h \
+ src/feature/nodelist/routerlist.h \
+ src/feature/nodelist/routerlist_st.h \
+ src/feature/nodelist/routerset.h \
+ src/feature/nodelist/fmt_routerstatus.h \
+ src/feature/nodelist/routerstatus_st.h \
+ src/feature/nodelist/signed_descriptor_st.h \
+ src/feature/nodelist/torcert.h \
+ src/feature/nodelist/vote_routerstatus_st.h
diff --git a/src/feature/nodelist/microdesc.c b/src/feature/nodelist/microdesc.c
index 89ac0a2f83..d32a4ea61e 100644
--- a/src/feature/nodelist/microdesc.c
+++ b/src/feature/nodelist/microdesc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2019, The Tor Project, Inc. */
+/* Copyright (c) 2009-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -18,6 +18,7 @@
#include "feature/client/entrynodes.h"
#include "feature/dircache/dirserv.h"
#include "feature/dirclient/dlstatus.h"
+#include "feature/dirclient/dirclient_modes.h"
#include "feature/dircommon/directory.h"
#include "feature/dirparse/microdesc_parse.h"
#include "feature/nodelist/dirlist.h"
@@ -997,7 +998,7 @@ update_microdesc_downloads(time_t now)
if (should_delay_dir_fetches(options, NULL))
return;
- if (directory_too_idle_to_fetch_descriptors(options, now))
+ if (dirclient_too_idle_to_fetch_descriptors(options, now))
return;
/* Give up if we don't have a reasonably live consensus. */
diff --git a/src/feature/nodelist/microdesc.h b/src/feature/nodelist/microdesc.h
index c18099d540..b352f58e34 100644
--- a/src/feature/nodelist/microdesc.h
+++ b/src/feature/nodelist/microdesc.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/microdesc_st.h b/src/feature/nodelist/microdesc_st.h
index e017c46c79..410403e965 100644
--- a/src/feature/nodelist/microdesc_st.h
+++ b/src/feature/nodelist/microdesc_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file microdesc_st.h
+ * @brief Microdescriptor structure
+ **/
+
#ifndef MICRODESC_ST_H
#define MICRODESC_ST_H
@@ -12,6 +17,8 @@ struct ed25519_public_key_t;
struct nodefamily_t;
struct short_policy_t;
+#include "ext/ht.h"
+
/** A microdescriptor is the smallest amount of information needed to build a
* circuit through a router. They are generated by the directory authorities,
* using information from the uploaded routerinfo documents. They are not
diff --git a/src/feature/nodelist/networkstatus.c b/src/feature/nodelist/networkstatus.c
index 496bafb865..cc4b8e1c34 100644
--- a/src/feature/nodelist/networkstatus.c
+++ b/src/feature/nodelist/networkstatus.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -63,6 +63,7 @@
#include "feature/dircache/consdiffmgr.h"
#include "feature/dircache/dirserv.h"
#include "feature/dirclient/dirclient.h"
+#include "feature/dirclient/dirclient_modes.h"
#include "feature/dirclient/dlstatus.h"
#include "feature/dircommon/directory.h"
#include "feature/dircommon/voting_schedule.h"
@@ -101,6 +102,7 @@
#include "feature/nodelist/routerlist_st.h"
#include "feature/dirauth/vote_microdesc_hash_st.h"
#include "feature/nodelist/vote_routerstatus_st.h"
+#include "feature/nodelist/routerstatus_st.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -216,10 +218,10 @@ networkstatus_reset_download_failures(void)
}
/** Return the filename used to cache the consensus of a given flavor */
-static char *
-networkstatus_get_cache_fname(int flav,
- const char *flavorname,
- int unverified_consensus)
+MOCK_IMPL(char *,
+networkstatus_get_cache_fname,(int flav,
+ const char *flavorname,
+ int unverified_consensus))
{
char buf[128];
const char *prefix;
@@ -1162,7 +1164,7 @@ update_consensus_networkstatus_fetch_time_impl(time_t now, int flav)
}
}
- if (directory_fetches_dir_info_early(options)) {
+ if (dirclient_fetches_dir_info_early(options)) {
/* We want to cache the next one at some point after this one
* is no longer fresh... */
start = (time_t)(c->fresh_until + min_sec_before_caching);
@@ -1184,7 +1186,7 @@ update_consensus_networkstatus_fetch_time_impl(time_t now, int flav)
/* If we're a bridge user, make use of the numbers we just computed
* to choose the rest of the interval *after* them. */
- if (directory_fetches_dir_info_later(options)) {
+ if (dirclient_fetches_dir_info_later(options)) {
/* Give all the *clients* enough time to download the consensus. */
start = (time_t)(start + dl_interval + min_sec_before_caching);
/* But try to get it before ours actually expires. */
@@ -1537,7 +1539,7 @@ networkstatus_consensus_can_use_extra_fallbacks,(const or_options_t *options))
>= smartlist_len(router_get_trusted_dir_servers()));
/* If we don't fetch from the authorities, and we have additional mirrors,
* we can use them. */
- return (!directory_fetches_from_authorities(options)
+ return (!dirclient_fetches_from_authorities(options)
&& (smartlist_len(router_get_fallback_dir_servers())
> smartlist_len(router_get_trusted_dir_servers())));
}
@@ -1577,36 +1579,16 @@ networkstatus_consensus_is_already_downloading(const char *resource)
return answer;
}
-/* Does the current, reasonably live consensus have IPv6 addresses?
- * Returns 1 if there is a reasonably live consensus and its consensus method
- * includes IPv6 addresses in the consensus.
- * Otherwise, if there is no consensus, or the method does not include IPv6
- * addresses, returns 0. */
-int
-networkstatus_consensus_has_ipv6(const or_options_t* options)
-{
- const networkstatus_t *cons = networkstatus_get_reasonably_live_consensus(
- approx_time(),
- usable_consensus_flavor());
-
- /* If we have no consensus, we have no IPv6 in it */
- if (!cons) {
- return 0;
- }
-
- /* Different flavours of consensus gained IPv6 at different times */
- if (we_use_microdescriptors_for_circuits(options)) {
- return
- cons->consensus_method >= MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS;
- } else {
- return 1;
- }
-}
-
-/** Given two router status entries for the same router identity, return 1 if
- * if the contents have changed between them. Otherwise, return 0. */
-static int
-routerstatus_has_changed(const routerstatus_t *a, const routerstatus_t *b)
+/** Given two router status entries for the same router identity, return 1
+ * if the contents have changed between them. Otherwise, return 0.
+ * It only checks for fields that are output by control port.
+ * This should be kept in sync with the struct routerstatus_t
+ * and the printing function routerstatus_format_entry in
+ * NS_CONTROL_PORT mode.
+ **/
+STATIC int
+routerstatus_has_visibly_changed(const routerstatus_t *a,
+ const routerstatus_t *b)
{
tor_assert(tor_memeq(a->identity_digest, b->identity_digest, DIGEST_LEN));
@@ -1625,9 +1607,14 @@ routerstatus_has_changed(const routerstatus_t *a, const routerstatus_t *b)
a->is_valid != b->is_valid ||
a->is_possible_guard != b->is_possible_guard ||
a->is_bad_exit != b->is_bad_exit ||
- a->is_hs_dir != b->is_hs_dir;
- // XXXX this function needs a huge refactoring; it has gotten out
- // XXXX of sync with routerstatus_t, and it will do so again.
+ a->is_hs_dir != b->is_hs_dir ||
+ a->is_staledesc != b->is_staledesc ||
+ a->has_bandwidth != b->has_bandwidth ||
+ a->published_on != b->published_on ||
+ a->ipv6_orport != b->ipv6_orport ||
+ a->is_v2_dir != b->is_v2_dir ||
+ a->bandwidth_kb != b->bandwidth_kb ||
+ tor_addr_compare(&a->ipv6_addr, &b->ipv6_addr, CMP_EXACT);
}
/** Notify controllers of any router status entries that changed between
@@ -1659,7 +1646,7 @@ notify_control_networkstatus_changed(const networkstatus_t *old_c,
tor_memcmp(rs_old->identity_digest,
rs_new->identity_digest, DIGEST_LEN),
smartlist_add(changed, (void*) rs_new)) {
- if (routerstatus_has_changed(rs_old, rs_new))
+ if (routerstatus_has_visibly_changed(rs_old, rs_new))
smartlist_add(changed, (void*)rs_new);
} SMARTLIST_FOREACH_JOIN_END(rs_old, rs_new);
@@ -2364,7 +2351,6 @@ char *
networkstatus_getinfo_helper_single(const routerstatus_t *rs)
{
return routerstatus_format_entry(rs, NULL, NULL, NS_CONTROL_PORT,
- ROUTERSTATUS_FORMAT_NO_CONSENSUS_METHOD,
NULL);
}
diff --git a/src/feature/nodelist/networkstatus.h b/src/feature/nodelist/networkstatus.h
index 600fd7fbd5..5e8c8a9e57 100644
--- a/src/feature/nodelist/networkstatus.h
+++ b/src/feature/nodelist/networkstatus.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -16,6 +16,9 @@
void networkstatus_reset_warnings(void);
void networkstatus_reset_download_failures(void);
+MOCK_DECL(char *,networkstatus_get_cache_fname,(int flav,
+ const char *flavorname,
+ int unverified_consensus));
tor_mmap_t *networkstatus_map_cached_consensus(const char *flavorname);
int router_reload_consensus_networkstatus(void);
void routerstatus_free_(routerstatus_t *rs);
@@ -101,7 +104,6 @@ int networkstatus_consensus_can_use_multiple_directories(
MOCK_DECL(int, networkstatus_consensus_can_use_extra_fallbacks,(
const or_options_t *options));
int networkstatus_consensus_is_already_downloading(const char *resource);
-int networkstatus_consensus_has_ipv6(const or_options_t* options);
#define NSSET_FROM_CACHE 1
#define NSSET_WAS_WAITING_FOR_CERTS 2
@@ -161,6 +163,8 @@ STATIC void warn_early_consensus(const networkstatus_t *c, const char *flavor,
extern networkstatus_t *current_ns_consensus;
extern networkstatus_t *current_md_consensus;
#endif /* defined(TOR_UNIT_TESTS) */
+STATIC int routerstatus_has_visibly_changed(const routerstatus_t *a,
+ const routerstatus_t *b);
#endif /* defined(NETWORKSTATUS_PRIVATE) */
#endif /* !defined(TOR_NETWORKSTATUS_H) */
diff --git a/src/feature/nodelist/networkstatus_sr_info_st.h b/src/feature/nodelist/networkstatus_sr_info_st.h
index 420c3d61e4..04d0dfe8f6 100644
--- a/src/feature/nodelist/networkstatus_sr_info_st.h
+++ b/src/feature/nodelist/networkstatus_sr_info_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file networkstatus_sr_info_st.h
+ * @brief Shared-randomness structure.
+ **/
+
#ifndef NETWORKSTATUS_SR_INFO_ST_H
#define NETWORKSTATUS_SR_INFO_ST_H
@@ -20,4 +25,3 @@ struct networkstatus_sr_info_t {
};
#endif /* !defined(NETWORKSTATUS_SR_INFO_ST_H) */
-
diff --git a/src/feature/nodelist/networkstatus_st.h b/src/feature/nodelist/networkstatus_st.h
index 6e84c170d6..021168d3ca 100644
--- a/src/feature/nodelist/networkstatus_st.h
+++ b/src/feature/nodelist/networkstatus_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file networkstatus_st.h
+ * @brief Networkstatus consensus/vote structure.
+ **/
+
#ifndef NETWORKSTATUS_ST_H
#define NETWORKSTATUS_ST_H
diff --git a/src/feature/nodelist/networkstatus_voter_info_st.h b/src/feature/nodelist/networkstatus_voter_info_st.h
index 66af82a8e3..b4d0b1dd17 100644
--- a/src/feature/nodelist/networkstatus_voter_info_st.h
+++ b/src/feature/nodelist/networkstatus_voter_info_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file networkstatus_voter_info_st.h
+ * @brief Single consensus voter structure.
+ **/
+
#ifndef NETWORKSTATUS_VOTER_INFO_ST_H
#define NETWORKSTATUS_VOTER_INFO_ST_H
diff --git a/src/feature/nodelist/nickname.c b/src/feature/nodelist/nickname.c
index 5378b749ca..c022dd6bc4 100644
--- a/src/feature/nodelist/nickname.c
+++ b/src/feature/nodelist/nickname.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/nickname.h b/src/feature/nodelist/nickname.h
index 78db2a5f91..11c6416f3a 100644
--- a/src/feature/nodelist/nickname.h
+++ b/src/feature/nodelist/nickname.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/node_select.c b/src/feature/nodelist/node_select.c
index 719b4b1b27..e831248413 100644
--- a/src/feature/nodelist/node_select.c
+++ b/src/feature/nodelist/node_select.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -19,6 +19,7 @@
#include "core/or/reasons.h"
#include "feature/client/entrynodes.h"
#include "feature/dirclient/dirclient.h"
+#include "feature/dirclient/dirclient_modes.h"
#include "feature/dircommon/directory.h"
#include "feature/nodelist/describe.h"
#include "feature/nodelist/dirlist.h"
@@ -147,7 +148,7 @@ router_pick_dirserver_generic(smartlist_t *sourcelist,
try_ip_pref = 0; \
goto retry_label; \
} \
- STMT_END \
+ STMT_END
/* Common retry code for router_pick_directory_server_impl and
* router_pick_trusteddirserver_impl. Retry without excluding nodes, but with
@@ -322,7 +323,7 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags,
const int skip_or_fw = router_skip_or_reachability(options, try_ip_pref);
const int skip_dir_fw = router_skip_dir_reachability(options, try_ip_pref);
- const int must_have_or = directory_must_use_begindir(options);
+ const int must_have_or = dirclient_must_use_begindir(options);
/* Find all the running dirservers we know about. */
SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) {
@@ -541,6 +542,51 @@ bridge_get_advertised_bandwidth_bounded(routerinfo_t *router)
return result;
}
+/**
+ * We have found an instance of bug 32868: log our best guess about where the
+ * routerstatus was found.
+ **/
+static void
+log_buggy_rs_source(const routerstatus_t *rs)
+{
+ static ratelim_t buggy_rs_ratelim = RATELIM_INIT(1200);
+ char *m;
+ if ((m = rate_limit_log(&buggy_rs_ratelim, approx_time()))) {
+ log_warn(LD_BUG,
+ "Found a routerstatus %p with has_guardfraction=%u "
+ " and guardfraction_percentage=%u, but is_possible_guard=%u.%s",
+ rs,
+ rs->has_guardfraction,
+ rs->guardfraction_percentage,
+ rs->is_possible_guard,
+ m);
+ tor_free(m);
+ networkstatus_t *ns;
+ int in_ns_count = 0;
+ if ((ns = networkstatus_get_latest_consensus_by_flavor(FLAV_NS))) {
+ int pos = smartlist_pos(ns->routerstatus_list, rs);
+ if (pos >= 0) {
+ ++in_ns_count;
+ log_warn(LD_BUG, "Found the routerstatus at position %d of the "
+ "NS consensus.", pos);
+ }
+ }
+ if ((ns = networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC))) {
+ int pos = smartlist_pos(ns->routerstatus_list, rs);
+ if (pos >= 0) {
+ ++in_ns_count;
+ log_warn(LD_BUG, "Found the routerstatus at position %d of the "
+ "MD consensus.", pos);
+ }
+ }
+ if (in_ns_count == 0) {
+ log_warn(LD_BUG, "Could not find the routerstatus in any "
+ "latest consensus.");
+ }
+ tor_assert_nonfatal_unreached();
+ }
+}
+
/** Given a list of routers and a weighting rule as in
* smartlist_choose_node_by_bandwidth_weights, compute weighted bandwidth
* values for each node and store them in a freshly allocated
@@ -717,10 +763,11 @@ compute_weighted_bandwidths(const smartlist_t *sl,
* choose N proportionally to F*Wpf*B + (1-F)*Wpn*B.
*/
if (node->rs && node->rs->has_guardfraction && rule != WEIGHT_FOR_GUARD) {
- /* XXX The assert should actually check for is_guard. However,
- * that crashes dirauths because of #13297. This should be
- * equivalent: */
- tor_assert(node->rs->is_possible_guard);
+ /* We should only have guardfraction set if the node has the Guard
+ flag. */
+ if (! node->rs->is_possible_guard) {
+ log_buggy_rs_source(node->rs);
+ }
guard_get_guardfraction_bandwidth(&guardfraction_bw,
this_bw,
@@ -1075,7 +1122,7 @@ router_pick_trusteddirserver_impl(const smartlist_t *sourcelist,
const int skip_or_fw = router_skip_or_reachability(options, try_ip_pref);
const int skip_dir_fw = router_skip_dir_reachability(options, try_ip_pref);
- const int must_have_or = directory_must_use_begindir(options);
+ const int must_have_or = dirclient_must_use_begindir(options);
SMARTLIST_FOREACH_BEGIN(sourcelist, const dir_server_t *, d)
{
diff --git a/src/feature/nodelist/node_select.h b/src/feature/nodelist/node_select.h
index d8b4aca5c1..2e67f990f6 100644
--- a/src/feature/nodelist/node_select.h
+++ b/src/feature/nodelist/node_select.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/node_st.h b/src/feature/nodelist/node_st.h
index c63a535a19..b1ec4db202 100644
--- a/src/feature/nodelist/node_st.h
+++ b/src/feature/nodelist/node_st.h
@@ -1,14 +1,20 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file node_st.h
+ * @brief Node information structure.
+ **/
+
#ifndef NODE_ST_H
#define NODE_ST_H
#include "feature/hs/hsdir_index_st.h"
#include "lib/crypt_ops/crypto_ed25519.h"
+#include "ext/ht.h"
/** A node_t represents a Tor router.
*
diff --git a/src/feature/nodelist/nodefamily.c b/src/feature/nodelist/nodefamily.c
index 2ec9d5fa40..7ae8620749 100644
--- a/src/feature/nodelist/nodefamily.c
+++ b/src/feature/nodelist/nodefamily.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/nodefamily.h b/src/feature/nodelist/nodefamily.h
index 31b71e77a0..16e161ba82 100644
--- a/src/feature/nodelist/nodefamily.h
+++ b/src/feature/nodelist/nodefamily.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/nodefamily_st.h b/src/feature/nodelist/nodefamily_st.h
index 20390c9308..c581c917a9 100644
--- a/src/feature/nodelist/nodefamily_st.h
+++ b/src/feature/nodelist/nodefamily_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file nodefamily_st.h
+ * @brief Compact node-family structure
+ **/
+
#ifndef TOR_NODEFAMILY_ST_H
#define TOR_NODEFAMILY_ST_H
diff --git a/src/feature/nodelist/nodelist.c b/src/feature/nodelist/nodelist.c
index 9191173c3b..b7c7552561 100644
--- a/src/feature/nodelist/nodelist.c
+++ b/src/feature/nodelist/nodelist.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -51,7 +51,7 @@
#include "feature/client/entrynodes.h"
#include "feature/control/control_events.h"
#include "feature/dirauth/process_descs.h"
-#include "feature/dircache/dirserv.h"
+#include "feature/dirclient/dirclient_modes.h"
#include "feature/hs/hs_client.h"
#include "feature/hs/hs_common.h"
#include "feature/nodelist/describe.h"
@@ -2779,7 +2779,7 @@ update_router_have_minimum_dir_info(void)
/* If paths have just become unavailable in this update. */
if (!res && have_min_dir_info) {
- int quiet = directory_too_idle_to_fetch_descriptors(options, now);
+ int quiet = dirclient_too_idle_to_fetch_descriptors(options, now);
tor_log(quiet ? LOG_INFO : LOG_NOTICE, LD_DIR,
"Our directory information is no longer up-to-date "
"enough to build circuits: %s", dir_info_status);
diff --git a/src/feature/nodelist/nodelist.h b/src/feature/nodelist/nodelist.h
index 87cfa48e25..87020b81eb 100644
--- a/src/feature/nodelist/nodelist.h
+++ b/src/feature/nodelist/nodelist.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/routerinfo.c b/src/feature/nodelist/routerinfo.c
index 975b503615..0bf2a977f5 100644
--- a/src/feature/nodelist/routerinfo.c
+++ b/src/feature/nodelist/routerinfo.c
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file routerinfo.c
+ * @brief Manipulate full router descriptors.
+ **/
+
#include "core/or/or.h"
#include "feature/nodelist/nodelist.h"
diff --git a/src/feature/nodelist/routerinfo.h b/src/feature/nodelist/routerinfo.h
index 8465060f93..604e478999 100644
--- a/src/feature/nodelist/routerinfo.h
+++ b/src/feature/nodelist/routerinfo.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/routerinfo_st.h b/src/feature/nodelist/routerinfo_st.h
index 59fd56d0a0..e54a444ec4 100644
--- a/src/feature/nodelist/routerinfo_st.h
+++ b/src/feature/nodelist/routerinfo_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file routerinfo_st.h
+ * @brief Router descriptor structure.
+ **/
+
#ifndef ROUTERINFO_ST_H
#define ROUTERINFO_ST_H
diff --git a/src/feature/nodelist/routerlist.c b/src/feature/nodelist/routerlist.c
index b3cf3e2394..a0c9db8438 100644
--- a/src/feature/nodelist/routerlist.c
+++ b/src/feature/nodelist/routerlist.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -73,6 +73,7 @@
#include "feature/dirauth/reachability.h"
#include "feature/dircache/dirserv.h"
#include "feature/dirclient/dirclient.h"
+#include "feature/dirclient/dirclient_modes.h"
#include "feature/dirclient/dlstatus.h"
#include "feature/dircommon/directory.h"
#include "feature/nodelist/authcert.h"
@@ -1940,9 +1941,7 @@ routerlist_descriptors_added(smartlist_t *sl, int from_cache)
learned_bridge_descriptor(ri, from_cache);
if (ri->needs_retest_if_added) {
ri->needs_retest_if_added = 0;
-#ifdef HAVE_MODULE_DIRAUTH
dirserv_single_reachability_test(approx_time(), ri);
-#endif
}
} SMARTLIST_FOREACH_END(ri);
}
@@ -2410,7 +2409,7 @@ max_dl_per_request(const or_options_t *options, int purpose)
}
/* If we're going to tunnel our connections, we can ask for a lot more
* in a request. */
- if (directory_must_use_begindir(options)) {
+ if (dirclient_must_use_begindir(options)) {
max = 500;
}
return max;
@@ -2453,7 +2452,7 @@ launch_descriptor_downloads(int purpose,
if (!n_downloadable)
return;
- if (!directory_fetches_dir_info_early(options)) {
+ if (!dirclient_fetches_dir_info_early(options)) {
if (n_downloadable >= MAX_DL_TO_DELAY) {
log_debug(LD_DIR,
"There are enough downloadable %ss to launch requests.",
@@ -2544,7 +2543,7 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
int n_delayed=0, n_have=0, n_would_reject=0, n_wouldnt_use=0,
n_inprogress=0, n_in_oldrouters=0;
- if (directory_too_idle_to_fetch_descriptors(options, now))
+ if (dirclient_too_idle_to_fetch_descriptors(options, now))
goto done;
if (!consensus)
goto done;
@@ -2564,8 +2563,15 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
map = digestmap_new();
list_pending_descriptor_downloads(map, 0);
SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, void *, rsp) {
- routerstatus_t *rs =
- is_vote ? &(((vote_routerstatus_t *)rsp)->status) : rsp;
+ routerstatus_t *rs;
+ vote_routerstatus_t *vrs;
+ if (is_vote) {
+ rs = &(((vote_routerstatus_t *)rsp)->status);
+ vrs = rsp;
+ } else {
+ rs = rsp;
+ vrs = NULL;
+ }
signed_descriptor_t *sd;
if ((sd = router_get_by_descriptor_digest(rs->descriptor_digest))) {
const routerinfo_t *ri;
@@ -2590,7 +2596,7 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
++n_delayed; /* Not ready for retry. */
continue;
}
- if (authdir && dirserv_would_reject_router(rs)) {
+ if (authdir && is_vote && dirserv_would_reject_router(rs, vrs)) {
++n_would_reject;
continue; /* We would throw it out immediately. */
}
diff --git a/src/feature/nodelist/routerlist.h b/src/feature/nodelist/routerlist.h
index dc9203e015..81a2343540 100644
--- a/src/feature/nodelist/routerlist.h
+++ b/src/feature/nodelist/routerlist.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/routerlist_st.h b/src/feature/nodelist/routerlist_st.h
index 10b919a1bf..ec8933c7cb 100644
--- a/src/feature/nodelist/routerlist_st.h
+++ b/src/feature/nodelist/routerlist_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file routerlist_st.h
+ * @brief Router descriptor list structure.
+ **/
+
#ifndef ROUTERLIST_ST_H
#define ROUTERLIST_ST_H
@@ -37,4 +42,3 @@ struct routerlist_t {
};
#endif /* !defined(ROUTERLIST_ST_H) */
-
diff --git a/src/feature/nodelist/routerset.c b/src/feature/nodelist/routerset.c
index 9a205d39b7..2e06ecbf04 100644
--- a/src/feature/nodelist/routerset.c
+++ b/src/feature/nodelist/routerset.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -17,7 +17,7 @@
*
* Routersets are typically used for user-specified restrictions, and
* are created by invoking routerset_new and routerset_parse from
- * config.c and confparse.c. To use a routerset, invoke one of
+ * config.c and confmgt.c. To use a routerset, invoke one of
* routerset_contains_...() functions , or use
* routerstatus_get_all_nodes() / routerstatus_subtract_nodes() to
* manipulate a smartlist of node_t pointers.
diff --git a/src/feature/nodelist/routerset.h b/src/feature/nodelist/routerset.h
index f3bf4a1f7c..0e4fedf64e 100644
--- a/src/feature/nodelist/routerset.h
+++ b/src/feature/nodelist/routerset.h
@@ -1,10 +1,10 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file routerlist.h
+ * \file routerset.h
* \brief Header file for routerset.c
**/
@@ -46,6 +46,7 @@ int routerset_len(const routerset_t *set);
struct var_type_def_t;
extern const struct var_type_def_t ROUTERSET_type_defn;
+typedef routerset_t *config_decl_ROUTERSET;
#ifdef ROUTERSET_PRIVATE
#include "lib/container/bitarray.h"
diff --git a/src/feature/nodelist/routerstatus_st.h b/src/feature/nodelist/routerstatus_st.h
index 46337c9e52..735c754b31 100644
--- a/src/feature/nodelist/routerstatus_st.h
+++ b/src/feature/nodelist/routerstatus_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file routerstatus_st.h
+ * @brief Routerstatus (consensus entry) structure
+ **/
+
#ifndef ROUTERSTATUS_ST_H
#define ROUTERSTATUS_ST_H
@@ -12,6 +17,10 @@
/** Contents of a single router entry in a network status object.
*/
struct routerstatus_t {
+ /* This should be kept in sync with the function
+ * routerstatus_has_visibly_changed and the printing function
+ * routerstatus_format_entry in NS_CONTROL_PORT mode.
+ */
time_t published_on; /**< When was this router published? */
char nickname[MAX_NICKNAME_LEN+1]; /**< The nickname this router says it
* has. */
@@ -79,4 +88,3 @@ struct routerstatus_t {
};
#endif /* !defined(ROUTERSTATUS_ST_H) */
-
diff --git a/src/feature/nodelist/signed_descriptor_st.h b/src/feature/nodelist/signed_descriptor_st.h
index 64c28f7440..068f2a733c 100644
--- a/src/feature/nodelist/signed_descriptor_st.h
+++ b/src/feature/nodelist/signed_descriptor_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file signed_descriptor_st.h
+ * @brief Descriptor/extrainfo signature structure
+ **/
+
#ifndef SIGNED_DESCRIPTOR_ST_H
#define SIGNED_DESCRIPTOR_ST_H
@@ -58,4 +63,3 @@ struct signed_descriptor_t {
};
#endif /* !defined(SIGNED_DESCRIPTOR_ST_H) */
-
diff --git a/src/feature/nodelist/torcert.c b/src/feature/nodelist/torcert.c
index 270c14eb1c..89cc9c88fb 100644
--- a/src/feature/nodelist/torcert.c
+++ b/src/feature/nodelist/torcert.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/torcert.h b/src/feature/nodelist/torcert.h
index 03d5bdca93..f8fba2b794 100644
--- a/src/feature/nodelist/torcert.h
+++ b/src/feature/nodelist/torcert.h
@@ -1,6 +1,11 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file torcert.h
+ * @brief Header for torcert.c
+ **/
+
#ifndef TORCERT_H_INCLUDED
#define TORCERT_H_INCLUDED
diff --git a/src/feature/nodelist/vote_routerstatus_st.h b/src/feature/nodelist/vote_routerstatus_st.h
index 0d909da260..ad0ee3f23b 100644
--- a/src/feature/nodelist/vote_routerstatus_st.h
+++ b/src/feature/nodelist/vote_routerstatus_st.h
@@ -1,9 +1,13 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file vote_routerstatus_st.h
+ * @brief Routerstatus (vote entry) structure
+ **/
#ifndef VOTE_ROUTERSTATUS_ST_H
#define VOTE_ROUTERSTATUS_ST_H
diff --git a/src/feature/relay/.may_include b/src/feature/relay/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/relay/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/relay/dns.c b/src/feature/relay/dns.c
index d62598d46f..7ab4ca0f45 100644
--- a/src/feature/relay/dns.c
+++ b/src/feature/relay/dns.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/relay/dns.h b/src/feature/relay/dns.h
index 7b2a31a311..2b1da8d126 100644
--- a/src/feature/relay/dns.h
+++ b/src/feature/relay/dns.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/relay/dns_structs.h b/src/feature/relay/dns_structs.h
index e128746f81..27a791b9b3 100644
--- a/src/feature/relay/dns_structs.h
+++ b/src/feature/relay/dns_structs.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,6 +13,8 @@
#ifndef TOR_DNS_STRUCTS_H
#define TOR_DNS_STRUCTS_H
+#include "ext/ht.h"
+
/** Longest hostname we're willing to resolve. */
#define MAX_ADDRESSLEN 256
@@ -99,4 +101,3 @@ typedef struct cached_resolve_t {
} cached_resolve_t;
#endif /* !defined(TOR_DNS_STRUCTS_H) */
-
diff --git a/src/feature/relay/ext_orport.c b/src/feature/relay/ext_orport.c
index c343d19b8d..ce4e043dd7 100644
--- a/src/feature/relay/ext_orport.c
+++ b/src/feature/relay/ext_orport.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/relay/ext_orport.h b/src/feature/relay/ext_orport.h
index 7313ebd03d..dbe89fce18 100644
--- a/src/feature/relay/ext_orport.h
+++ b/src/feature/relay/ext_orport.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file ext_orport.h
+ * @brief Header for ext_orport.c
+ **/
+
#ifndef EXT_ORPORT_H
#define EXT_ORPORT_H
diff --git a/src/feature/relay/feature_relay.md b/src/feature/relay/feature_relay.md
new file mode 100644
index 0000000000..a7f0c2153a
--- /dev/null
+++ b/src/feature/relay/feature_relay.md
@@ -0,0 +1,4 @@
+@dir /feature/relay
+@brief feature/relay: Relay-specific code
+
+(There is also a bunch of relay-specific code in other modules.)
diff --git a/src/feature/relay/include.am b/src/feature/relay/include.am
new file mode 100644
index 0000000000..a4c025ae12
--- /dev/null
+++ b/src/feature/relay/include.am
@@ -0,0 +1,40 @@
+
+# Legacy shared relay code: migrate to the relay module over time
+LIBTOR_APP_A_SOURCES += \
+ src/feature/relay/dns.c \
+ src/feature/relay/ext_orport.c \
+ src/feature/relay/onion_queue.c \
+ src/feature/relay/router.c \
+ src/feature/relay/routerkeys.c \
+ src/feature/relay/selftest.c
+
+# The Relay module.
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+MODULE_RELAY_SOURCES = \
+ src/feature/relay/routermode.c \
+ src/feature/relay/relay_config.c \
+ src/feature/relay/relay_periodic.c \
+ src/feature/relay/relay_sys.c \
+ src/feature/relay/transport_config.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/relay/dns.h \
+ src/feature/relay/dns_structs.h \
+ src/feature/relay/ext_orport.h \
+ src/feature/relay/onion_queue.h \
+ src/feature/relay/relay_config.h \
+ src/feature/relay/relay_periodic.h \
+ src/feature/relay/relay_sys.h \
+ src/feature/relay/router.h \
+ src/feature/relay/routerkeys.h \
+ src/feature/relay/routermode.h \
+ src/feature/relay/selftest.h \
+ src/feature/relay/transport_config.h
+
+if BUILD_MODULE_RELAY
+LIBTOR_APP_A_SOURCES += $(MODULE_RELAY_SOURCES)
+else
+LIBTOR_APP_A_STUB_SOURCES += src/feature/relay/relay_stub.c
+endif
diff --git a/src/feature/relay/onion_queue.c b/src/feature/relay/onion_queue.c
index c37745cf33..ce2d41b7e1 100644
--- a/src/feature/relay/onion_queue.c
+++ b/src/feature/relay/onion_queue.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/relay/onion_queue.h b/src/feature/relay/onion_queue.h
index cf478bc1a0..08379b2c00 100644
--- a/src/feature/relay/onion_queue.h
+++ b/src/feature/relay/onion_queue.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/relay/relay_config.c b/src/feature/relay/relay_config.c
new file mode 100644
index 0000000000..3e9961f47e
--- /dev/null
+++ b/src/feature/relay/relay_config.c
@@ -0,0 +1,1444 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file relay_config.c
+ * @brief Code to interpret the user's configuration of Tor's relay module.
+ **/
+
+#include "orconfig.h"
+#define RELAY_CONFIG_PRIVATE
+#include "feature/relay/relay_config.h"
+
+#include "lib/encoding/confline.h"
+#include "lib/confmgt/confmgt.h"
+
+#include "lib/container/smartlist.h"
+#include "lib/geoip/geoip.h"
+#include "lib/meminfo/meminfo.h"
+#include "lib/osinfo/uname.h"
+#include "lib/process/setuid.h"
+
+/* Required for dirinfo_type_t in or_options_t */
+#include "core/or/or.h"
+#include "app/config/config.h"
+
+#include "core/mainloop/connection.h"
+#include "core/mainloop/cpuworker.h"
+#include "core/mainloop/mainloop.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/connection_or.h"
+#include "core/or/port_cfg_st.h"
+
+#include "feature/hibernate/hibernate.h"
+#include "feature/nodelist/nickname.h"
+#include "feature/stats/geoip_stats.h"
+#include "feature/stats/predict_ports.h"
+#include "feature/stats/rephist.h"
+
+#include "feature/dirauth/authmode.h"
+
+#include "feature/dircache/consdiffmgr.h"
+#include "feature/relay/dns.h"
+#include "feature/relay/routermode.h"
+
+/** Contents of most recently read DirPortFrontPage file. */
+static char *global_dirfrontpagecontents = NULL;
+
+/* Copied from config.c, we will refactor later in 29211. */
+#define REJECT(arg) \
+ STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
+#if defined(__GNUC__) && __GNUC__ <= 3
+#define COMPLAIN(args...) \
+ STMT_BEGIN log_warn(LD_CONFIG, args); STMT_END
+#else
+#define COMPLAIN(args, ...) \
+ STMT_BEGIN log_warn(LD_CONFIG, args, ##__VA_ARGS__); STMT_END
+#endif /* defined(__GNUC__) && __GNUC__ <= 3 */
+
+/* Used in the various options_transition_affects* functions. */
+#define YES_IF_CHANGED_BOOL(opt) \
+ if (!CFG_EQ_BOOL(old_options, new_options, opt)) return 1;
+#define YES_IF_CHANGED_INT(opt) \
+ if (!CFG_EQ_INT(old_options, new_options, opt)) return 1;
+#define YES_IF_CHANGED_STRING(opt) \
+ if (!CFG_EQ_STRING(old_options, new_options, opt)) return 1;
+#define YES_IF_CHANGED_LINELIST(opt) \
+ if (!CFG_EQ_LINELIST(old_options, new_options, opt)) return 1;
+
+/** Return the contents of our frontpage string, or NULL if not configured. */
+MOCK_IMPL(const char*,
+relay_get_dirportfrontpage, (void))
+{
+ return global_dirfrontpagecontents;
+}
+
+/** Release all memory and resources held by global relay configuration
+ * structures.
+ */
+void
+relay_config_free_all(void)
+{
+ tor_free(global_dirfrontpagecontents);
+}
+
+/** Return the bandwidthrate that we are going to report to the authorities
+ * based on the config options. */
+uint32_t
+relay_get_effective_bwrate(const or_options_t *options)
+{
+ uint64_t bw = options->BandwidthRate;
+ if (bw > options->MaxAdvertisedBandwidth)
+ bw = options->MaxAdvertisedBandwidth;
+ if (options->RelayBandwidthRate > 0 && bw > options->RelayBandwidthRate)
+ bw = options->RelayBandwidthRate;
+ /* config_ensure_bandwidth_cap() makes sure that this cast can't overflow. */
+ return (uint32_t)bw;
+}
+
+/** Return the bandwidthburst that we are going to report to the authorities
+ * based on the config options. */
+uint32_t
+relay_get_effective_bwburst(const or_options_t *options)
+{
+ uint64_t bw = options->BandwidthBurst;
+ if (options->RelayBandwidthBurst > 0 && bw > options->RelayBandwidthBurst)
+ bw = options->RelayBandwidthBurst;
+ /* config_ensure_bandwidth_cap() makes sure that this cast can't overflow. */
+ return (uint32_t)bw;
+}
+
+/** Warn for every Extended ORPort port in <b>ports</b> that is on a
+ * publicly routable address. */
+void
+port_warn_nonlocal_ext_orports(const smartlist_t *ports, const char *portname)
+{
+ SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) {
+ if (port->type != CONN_TYPE_EXT_OR_LISTENER)
+ continue;
+ if (port->is_unix_addr)
+ continue;
+ /* XXX maybe warn even if address is RFC1918? */
+ if (!tor_addr_is_internal(&port->addr, 1)) {
+ log_warn(LD_CONFIG, "You specified a public address '%s' for %sPort. "
+ "This is not advised; this address is supposed to only be "
+ "exposed on localhost so that your pluggable transport "
+ "proxies can connect to it.",
+ fmt_addrport(&port->addr, port->port), portname);
+ }
+ } SMARTLIST_FOREACH_END(port);
+}
+
+/** Given a list of <b>port_cfg_t</b> in <b>ports</b>, check them for internal
+ * consistency and warn as appropriate. On Unix-based OSes, set
+ * *<b>n_low_ports_out</b> to the number of sub-1024 ports we will be
+ * binding, and warn if we may be unable to re-bind after hibernation. */
+static int
+check_server_ports(const smartlist_t *ports,
+ const or_options_t *options,
+ int *n_low_ports_out)
+{
+ if (BUG(!ports))
+ return -1;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!n_low_ports_out))
+ return -1;
+
+ int n_orport_advertised = 0;
+ int n_orport_advertised_ipv4 = 0;
+ int n_orport_listeners = 0;
+ int n_dirport_advertised = 0;
+ int n_dirport_listeners = 0;
+ int n_low_port = 0;
+ int r = 0;
+
+ SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) {
+ if (port->type == CONN_TYPE_DIR_LISTENER) {
+ if (! port->server_cfg.no_advertise)
+ ++n_dirport_advertised;
+ if (! port->server_cfg.no_listen)
+ ++n_dirport_listeners;
+ } else if (port->type == CONN_TYPE_OR_LISTENER) {
+ if (! port->server_cfg.no_advertise) {
+ ++n_orport_advertised;
+ if (port_binds_ipv4(port))
+ ++n_orport_advertised_ipv4;
+ }
+ if (! port->server_cfg.no_listen)
+ ++n_orport_listeners;
+ } else {
+ continue;
+ }
+#ifndef _WIN32
+ if (!port->server_cfg.no_listen && port->port < 1024)
+ ++n_low_port;
+#endif
+ } SMARTLIST_FOREACH_END(port);
+
+ if (n_orport_advertised && !n_orport_listeners) {
+ log_warn(LD_CONFIG, "We are advertising an ORPort, but not actually "
+ "listening on one.");
+ r = -1;
+ }
+ if (n_orport_listeners && !n_orport_advertised) {
+ log_warn(LD_CONFIG, "We are listening on an ORPort, but not advertising "
+ "any ORPorts. This will keep us from building a %s "
+ "descriptor, and make us impossible to use.",
+ options->BridgeRelay ? "bridge" : "router");
+ r = -1;
+ }
+ if (n_dirport_advertised && !n_dirport_listeners) {
+ log_warn(LD_CONFIG, "We are advertising a DirPort, but not actually "
+ "listening on one.");
+ r = -1;
+ }
+ if (n_dirport_advertised > 1) {
+ log_warn(LD_CONFIG, "Can't advertise more than one DirPort.");
+ r = -1;
+ }
+ if (n_orport_advertised && !n_orport_advertised_ipv4 &&
+ !options->BridgeRelay) {
+ log_warn(LD_CONFIG, "Configured public relay to listen only on an IPv6 "
+ "address. Tor needs to listen on an IPv4 address too.");
+ r = -1;
+ }
+
+ if (n_low_port && options->AccountingMax &&
+ (!have_capability_support() || options->KeepBindCapabilities == 0)) {
+ const char *extra = "";
+ if (options->KeepBindCapabilities == 0 && have_capability_support())
+ extra = ", and you have disabled KeepBindCapabilities.";
+ log_warn(LD_CONFIG,
+ "You have set AccountingMax to use hibernation. You have also "
+ "chosen a low DirPort or OrPort%s."
+ "This combination can make Tor stop "
+ "working when it tries to re-attach the port after a period of "
+ "hibernation. Please choose a different port or turn off "
+ "hibernation unless you know this combination will work on your "
+ "platform.", extra);
+ }
+
+ if (n_low_ports_out)
+ *n_low_ports_out = n_low_port;
+
+ return r;
+}
+
+/** Parse all relay ports from <b>options</b>. On success, add parsed ports to
+ * <b>ports</b>, and return 0. On failure, set *<b>msg</b> to a newly
+ * allocated string describing the problem, and return -1.
+ **/
+int
+port_parse_ports_relay(or_options_t *options,
+ char **msg,
+ smartlist_t *ports_out,
+ int *have_low_ports_out)
+{
+ int retval = -1;
+ smartlist_t *ports = smartlist_new();
+ int n_low_ports = 0;
+
+ if (BUG(!options))
+ goto err;
+
+ if (BUG(!msg))
+ goto err;
+
+ if (BUG(!ports_out))
+ goto err;
+
+ if (BUG(!have_low_ports_out))
+ goto err;
+
+ if (options->ClientOnly) {
+ retval = 0;
+ goto err;
+ }
+
+ if (port_parse_config(ports,
+ options->ORPort_lines,
+ "OR", CONN_TYPE_OR_LISTENER,
+ "0.0.0.0", 0,
+ CL_PORT_SERVER_OPTIONS) < 0) {
+ *msg = tor_strdup("Invalid ORPort configuration");
+ goto err;
+ }
+ if (port_parse_config(ports,
+ options->ExtORPort_lines,
+ "ExtOR", CONN_TYPE_EXT_OR_LISTENER,
+ "127.0.0.1", 0,
+ CL_PORT_SERVER_OPTIONS|CL_PORT_WARN_NONLOCAL) < 0) {
+ *msg = tor_strdup("Invalid ExtORPort configuration");
+ goto err;
+ }
+ if (port_parse_config(ports,
+ options->DirPort_lines,
+ "Dir", CONN_TYPE_DIR_LISTENER,
+ "0.0.0.0", 0,
+ CL_PORT_SERVER_OPTIONS) < 0) {
+ *msg = tor_strdup("Invalid DirPort configuration");
+ goto err;
+ }
+
+ if (check_server_ports(ports, options, &n_low_ports) < 0) {
+ *msg = tor_strdup("Misconfigured server ports");
+ goto err;
+ }
+
+ smartlist_add_all(ports_out, ports);
+ smartlist_free(ports);
+ ports = NULL;
+ retval = 0;
+
+ err:
+ if (*have_low_ports_out < 0)
+ *have_low_ports_out = (n_low_ports > 0);
+ if (ports) {
+ SMARTLIST_FOREACH(ports, port_cfg_t *, p, port_cfg_free(p));
+ smartlist_free(ports);
+ }
+ return retval;
+}
+
+/** Update the relay *Port_set values in <b>options</b> from <b>ports</b>. */
+void
+port_update_port_set_relay(or_options_t *options,
+ const smartlist_t *ports)
+{
+ if (BUG(!options))
+ return;
+
+ if (BUG(!ports))
+ return;
+
+ if (options->ClientOnly)
+ return;
+
+ /* Update the relay *Port_set options. The !! here is to force a boolean
+ * out of an integer. */
+ options->ORPort_set =
+ !! port_count_real_listeners(ports, CONN_TYPE_OR_LISTENER, 0);
+ options->DirPort_set =
+ !! port_count_real_listeners(ports, CONN_TYPE_DIR_LISTENER, 0);
+ options->ExtORPort_set =
+ !! port_count_real_listeners(ports, CONN_TYPE_EXT_OR_LISTENER, 0);
+}
+
+/**
+ * Legacy validation function, which checks that the current OS is usable in
+ * relay mode, if options is set to a relay mode.
+ *
+ * Warns about OSes with potential issues. Does not set *<b>msg</b>.
+ * Always returns 0.
+ */
+int
+options_validate_relay_os(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ if (!server_mode(options))
+ return 0;
+
+ const char *uname = get_uname();
+
+ if (!strcmpstart(uname, "Windows 95") ||
+ !strcmpstart(uname, "Windows 98") ||
+ !strcmpstart(uname, "Windows Me")) {
+ log_warn(LD_CONFIG, "Tor is running as a server, but you are "
+ "running %s; this probably won't work. See "
+ "https://www.torproject.org/docs/faq.html#BestOSForRelay "
+ "for details.", uname);
+ }
+
+ return 0;
+}
+
+/**
+ * Legacy validation/normalization function for the relay info options.
+ * Uses old_options as the previous options.
+ *
+ * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
+ * on error.
+ */
+int
+options_validate_relay_info(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ if (options->Nickname == NULL) {
+ if (server_mode(options)) {
+ options->Nickname = tor_strdup(UNNAMED_ROUTER_NICKNAME);
+ }
+ } else {
+ if (!is_legal_nickname(options->Nickname)) {
+ tor_asprintf(msg,
+ "Nickname '%s', nicknames must be between 1 and 19 characters "
+ "inclusive, and must contain only the characters [a-zA-Z0-9].",
+ options->Nickname);
+ return -1;
+ }
+ }
+
+ if (server_mode(options) && !options->ContactInfo) {
+ log_warn(LD_CONFIG,
+ "Your ContactInfo config option is not set. Please strongly "
+ "consider setting it, so we can contact you if your relay is "
+ "misconfigured, end-of-life, or something else goes wrong. "
+ "It is also possible that your relay might get rejected from "
+ "the network due to a missing valid contact address.");
+ }
+
+ const char *ContactInfo = options->ContactInfo;
+ if (ContactInfo && !string_is_utf8(ContactInfo, strlen(ContactInfo)))
+ REJECT("ContactInfo config option must be UTF-8.");
+
+ return 0;
+}
+
+/** Parse an authority type from <b>options</b>-\>PublishServerDescriptor
+ * and write it to <b>options</b>-\>PublishServerDescriptor_. Treat "1"
+ * as "v3" unless BridgeRelay is 1, in which case treat it as "bridge".
+ * Treat "0" as "".
+ * Return 0 on success or -1 if not a recognized authority type (in which
+ * case the value of PublishServerDescriptor_ is undefined). */
+static int
+compute_publishserverdescriptor(or_options_t *options)
+{
+ smartlist_t *list = options->PublishServerDescriptor;
+ dirinfo_type_t *auth = &options->PublishServerDescriptor_;
+ *auth = NO_DIRINFO;
+ if (!list) /* empty list, answer is none */
+ return 0;
+ SMARTLIST_FOREACH_BEGIN(list, const char *, string) {
+ if (!strcasecmp(string, "v1"))
+ log_warn(LD_CONFIG, "PublishServerDescriptor v1 has no effect, because "
+ "there are no v1 directory authorities anymore.");
+ else if (!strcmp(string, "1"))
+ if (options->BridgeRelay)
+ *auth |= BRIDGE_DIRINFO;
+ else
+ *auth |= V3_DIRINFO;
+ else if (!strcasecmp(string, "v2"))
+ log_warn(LD_CONFIG, "PublishServerDescriptor v2 has no effect, because "
+ "there are no v2 directory authorities anymore.");
+ else if (!strcasecmp(string, "v3"))
+ *auth |= V3_DIRINFO;
+ else if (!strcasecmp(string, "bridge"))
+ *auth |= BRIDGE_DIRINFO;
+ else if (!strcasecmp(string, "hidserv"))
+ log_warn(LD_CONFIG,
+ "PublishServerDescriptor hidserv is invalid. See "
+ "PublishHidServDescriptors.");
+ else if (!strcasecmp(string, "") || !strcmp(string, "0"))
+ /* no authority */;
+ else
+ return -1;
+ } SMARTLIST_FOREACH_END(string);
+ return 0;
+}
+
+/**
+ * Validate the configured bridge distribution method from a BridgeDistribution
+ * config line.
+ *
+ * The input <b>bd</b>, is a string taken from the BridgeDistribution config
+ * line (if present). If the option wasn't set, return 0 immediately. The
+ * BridgeDistribution option is then validated. Currently valid, recognised
+ * options are:
+ *
+ * - "none"
+ * - "any"
+ * - "https"
+ * - "email"
+ * - "moat"
+ *
+ * If the option string is unrecognised, a warning will be logged and 0 is
+ * returned. If the option string contains an invalid character, -1 is
+ * returned.
+ **/
+STATIC int
+check_bridge_distribution_setting(const char *bd)
+{
+ if (bd == NULL)
+ return 0;
+
+ const char *RECOGNIZED[] = {
+ "none", "any", "https", "email", "moat"
+ };
+ unsigned i;
+ for (i = 0; i < ARRAY_LENGTH(RECOGNIZED); ++i) {
+ if (!strcasecmp(bd, RECOGNIZED[i]))
+ return 0;
+ }
+
+ const char *cp = bd;
+ // Method = (KeywordChar | "_") +
+ while (TOR_ISALNUM(*cp) || *cp == '-' || *cp == '_')
+ ++cp;
+
+ if (*cp == 0) {
+ log_warn(LD_CONFIG, "Unrecognized BridgeDistribution value %s. I'll "
+ "assume you know what you are doing...", escaped(bd));
+ return 0; // we reached the end of the string; all is well
+ } else {
+ return -1; // we found a bad character in the string.
+ }
+}
+
+/**
+ * Legacy validation/normalization function for the bridge relay options.
+ * Uses old_options as the previous options.
+ *
+ * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
+ * on error.
+ */
+int
+options_validate_publish_server(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ if (compute_publishserverdescriptor(options) < 0) {
+ tor_asprintf(msg, "Unrecognized value in PublishServerDescriptor");
+ return -1;
+ }
+
+ if ((options->BridgeRelay
+ || options->PublishServerDescriptor_ & BRIDGE_DIRINFO)
+ && (options->PublishServerDescriptor_ & V3_DIRINFO)) {
+ REJECT("Bridges are not supposed to publish router descriptors to the "
+ "directory authorities. Please correct your "
+ "PublishServerDescriptor line.");
+ }
+
+ if (options->BridgeDistribution) {
+ if (!options->BridgeRelay) {
+ REJECT("You set BridgeDistribution, but you didn't set BridgeRelay!");
+ }
+ if (check_bridge_distribution_setting(options->BridgeDistribution) < 0) {
+ REJECT("Invalid BridgeDistribution value.");
+ }
+ }
+
+ if (options->PublishServerDescriptor)
+ SMARTLIST_FOREACH(options->PublishServerDescriptor, const char *, pubdes, {
+ if (!strcmp(pubdes, "1") || !strcmp(pubdes, "0"))
+ if (smartlist_len(options->PublishServerDescriptor) > 1) {
+ COMPLAIN("You have passed a list of multiple arguments to the "
+ "PublishServerDescriptor option that includes 0 or 1. "
+ "0 or 1 should only be used as the sole argument. "
+ "This configuration will be rejected in a future release.");
+ break;
+ }
+ });
+
+ return 0;
+}
+
+/**
+ * Legacy validation/normalization function for the relay padding options.
+ * Uses old_options as the previous options.
+ *
+ * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
+ * on error.
+ */
+int
+options_validate_relay_padding(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ if (!server_mode(options))
+ return 0;
+
+ if (options->ConnectionPadding != -1) {
+ REJECT("Relays must use 'auto' for the ConnectionPadding setting.");
+ }
+
+ if (options->ReducedConnectionPadding != 0) {
+ REJECT("Relays cannot set ReducedConnectionPadding. ");
+ }
+
+ if (options->CircuitPadding == 0) {
+ REJECT("Relays cannot set CircuitPadding to 0. ");
+ }
+
+ if (options->ReducedCircuitPadding == 1) {
+ REJECT("Relays cannot set ReducedCircuitPadding. ");
+ }
+
+ return 0;
+}
+
+/**
+ * Legacy validation/normalization function for the relay bandwidth options.
+ * Uses old_options as the previous options.
+ *
+ * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
+ * on error.
+ */
+int
+options_validate_relay_bandwidth(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ /* 31851: the tests expect us to validate bandwidths, even when we are not
+ * in relay mode. */
+ if (config_ensure_bandwidth_cap(&options->MaxAdvertisedBandwidth,
+ "MaxAdvertisedBandwidth", msg) < 0)
+ return -1;
+ if (config_ensure_bandwidth_cap(&options->RelayBandwidthRate,
+ "RelayBandwidthRate", msg) < 0)
+ return -1;
+ if (config_ensure_bandwidth_cap(&options->RelayBandwidthBurst,
+ "RelayBandwidthBurst", msg) < 0)
+ return -1;
+ if (config_ensure_bandwidth_cap(&options->PerConnBWRate,
+ "PerConnBWRate", msg) < 0)
+ return -1;
+ if (config_ensure_bandwidth_cap(&options->PerConnBWBurst,
+ "PerConnBWBurst", msg) < 0)
+ return -1;
+
+ if (options->RelayBandwidthRate && !options->RelayBandwidthBurst)
+ options->RelayBandwidthBurst = options->RelayBandwidthRate;
+ if (options->RelayBandwidthBurst && !options->RelayBandwidthRate)
+ options->RelayBandwidthRate = options->RelayBandwidthBurst;
+
+ if (server_mode(options)) {
+ const unsigned required_min_bw =
+ public_server_mode(options) ?
+ RELAY_REQUIRED_MIN_BANDWIDTH : BRIDGE_REQUIRED_MIN_BANDWIDTH;
+ const char * const optbridge =
+ public_server_mode(options) ? "" : "bridge ";
+ if (options->BandwidthRate < required_min_bw) {
+ tor_asprintf(msg,
+ "BandwidthRate is set to %d bytes/second. "
+ "For %sservers, it must be at least %u.",
+ (int)options->BandwidthRate, optbridge,
+ required_min_bw);
+ return -1;
+ } else if (options->MaxAdvertisedBandwidth <
+ required_min_bw/2) {
+ tor_asprintf(msg,
+ "MaxAdvertisedBandwidth is set to %d bytes/second. "
+ "For %sservers, it must be at least %u.",
+ (int)options->MaxAdvertisedBandwidth, optbridge,
+ required_min_bw/2);
+ return -1;
+ }
+ if (options->RelayBandwidthRate &&
+ options->RelayBandwidthRate < required_min_bw) {
+ tor_asprintf(msg,
+ "RelayBandwidthRate is set to %d bytes/second. "
+ "For %sservers, it must be at least %u.",
+ (int)options->RelayBandwidthRate, optbridge,
+ required_min_bw);
+ return -1;
+ }
+ }
+
+ /* 31851: the tests expect us to validate bandwidths, even when we are not
+ * in relay mode. */
+ if (options->RelayBandwidthRate > options->RelayBandwidthBurst)
+ REJECT("RelayBandwidthBurst must be at least equal "
+ "to RelayBandwidthRate.");
+
+ /* if they set relaybandwidth* really high but left bandwidth*
+ * at the default, raise the defaults. */
+ if (options->RelayBandwidthRate > options->BandwidthRate)
+ options->BandwidthRate = options->RelayBandwidthRate;
+ if (options->RelayBandwidthBurst > options->BandwidthBurst)
+ options->BandwidthBurst = options->RelayBandwidthBurst;
+
+ return 0;
+}
+
+/**
+ * Legacy validation/normalization function for the relay bandwidth accounting
+ * options. Uses old_options as the previous options.
+ *
+ * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
+ * on error.
+ */
+int
+options_validate_relay_accounting(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ /* 31851: the tests expect us to validate accounting, even when we are not
+ * in relay mode. */
+ if (accounting_parse_options(options, 1)<0)
+ REJECT("Failed to parse accounting options. See logs for details.");
+
+ if (options->AccountingMax) {
+ if (options->RendConfigLines && server_mode(options)) {
+ log_warn(LD_CONFIG, "Using accounting with a hidden service and an "
+ "ORPort is risky: your hidden service(s) and your public "
+ "address will all turn off at the same time, which may alert "
+ "observers that they are being run by the same party.");
+ } else if (config_count_key(options->RendConfigLines,
+ "HiddenServiceDir") > 1) {
+ log_warn(LD_CONFIG, "Using accounting with multiple hidden services is "
+ "risky: they will all turn off at the same time, which may "
+ "alert observers that they are being run by the same party.");
+ }
+ }
+
+ options->AccountingRule = ACCT_MAX;
+ if (options->AccountingRule_option) {
+ if (!strcmp(options->AccountingRule_option, "sum"))
+ options->AccountingRule = ACCT_SUM;
+ else if (!strcmp(options->AccountingRule_option, "max"))
+ options->AccountingRule = ACCT_MAX;
+ else if (!strcmp(options->AccountingRule_option, "in"))
+ options->AccountingRule = ACCT_IN;
+ else if (!strcmp(options->AccountingRule_option, "out"))
+ options->AccountingRule = ACCT_OUT;
+ else
+ REJECT("AccountingRule must be 'sum', 'max', 'in', or 'out'");
+ }
+
+ return 0;
+}
+
+/** Verify whether lst is a list of strings containing valid-looking
+ * comma-separated nicknames, or NULL. Will normalise <b>lst</b> to prefix '$'
+ * to any nickname or fingerprint that needs it. Also splits comma-separated
+ * list elements into multiple elements. Return 0 on success.
+ * Warn and return -1 on failure.
+ */
+static int
+normalize_nickname_list(config_line_t **normalized_out,
+ const config_line_t *lst, const char *name,
+ char **msg)
+{
+ if (!lst)
+ return 0;
+
+ config_line_t *new_nicknames = NULL;
+ config_line_t **new_nicknames_next = &new_nicknames;
+
+ const config_line_t *cl;
+ for (cl = lst; cl; cl = cl->next) {
+ const char *line = cl->value;
+ if (!line)
+ continue;
+
+ int valid_line = 1;
+ smartlist_t *sl = smartlist_new();
+ smartlist_split_string(sl, line, ",",
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK|SPLIT_STRIP_SPACE, 0);
+ SMARTLIST_FOREACH_BEGIN(sl, char *, s)
+ {
+ char *normalized = NULL;
+ if (!is_legal_nickname_or_hexdigest(s)) {
+ // check if first char is dollar
+ if (s[0] != '$') {
+ // Try again but with a dollar symbol prepended
+ char *prepended;
+ tor_asprintf(&prepended, "$%s", s);
+
+ if (is_legal_nickname_or_hexdigest(prepended)) {
+ // The nickname is valid when it's prepended, set it as the
+ // normalized version
+ normalized = prepended;
+ } else {
+ // Still not valid, free and fallback to error message
+ tor_free(prepended);
+ }
+ }
+
+ if (!normalized) {
+ tor_asprintf(msg, "Invalid nickname '%s' in %s line", s, name);
+ valid_line = 0;
+ break;
+ }
+ } else {
+ normalized = tor_strdup(s);
+ }
+
+ config_line_t *next = tor_malloc_zero(sizeof(*next));
+ next->key = tor_strdup(cl->key);
+ next->value = normalized;
+ next->next = NULL;
+
+ *new_nicknames_next = next;
+ new_nicknames_next = &next->next;
+ } SMARTLIST_FOREACH_END(s);
+
+ SMARTLIST_FOREACH(sl, char *, s, tor_free(s));
+ smartlist_free(sl);
+
+ if (!valid_line) {
+ config_free_lines(new_nicknames);
+ return -1;
+ }
+ }
+
+ *normalized_out = new_nicknames;
+
+ return 0;
+}
+
+#define ONE_MEGABYTE (UINT64_C(1) << 20)
+
+/* If we have less than 300 MB suggest disabling dircache */
+#define DIRCACHE_MIN_MEM_MB 300
+#define DIRCACHE_MIN_MEM_BYTES (DIRCACHE_MIN_MEM_MB*ONE_MEGABYTE)
+#define STRINGIFY(val) #val
+
+/** Create a warning message for emitting if we are a dircache but may not have
+ * enough system memory, or if we are not a dircache but probably should be.
+ * Return -1 when a message is returned in *msg*, else return 0. */
+STATIC int
+have_enough_mem_for_dircache(const or_options_t *options, size_t total_mem,
+ char **msg)
+{
+ *msg = NULL;
+ /* XXX We should possibly be looking at MaxMemInQueues here
+ * unconditionally. Or we should believe total_mem unconditionally. */
+ if (total_mem == 0) {
+ if (get_total_system_memory(&total_mem) < 0) {
+ total_mem = options->MaxMemInQueues >= SIZE_MAX ?
+ SIZE_MAX : (size_t)options->MaxMemInQueues;
+ }
+ }
+ if (options->DirCache) {
+ if (total_mem < DIRCACHE_MIN_MEM_BYTES) {
+ if (options->BridgeRelay) {
+ tor_asprintf(msg, "Running a Bridge with less than %d MB of memory "
+ "is not recommended.", DIRCACHE_MIN_MEM_MB);
+ } else {
+ tor_asprintf(msg, "Being a directory cache (default) with less than "
+ "%d MB of memory is not recommended and may consume "
+ "most of the available resources. Consider disabling "
+ "this functionality by setting the DirCache option "
+ "to 0.", DIRCACHE_MIN_MEM_MB);
+ }
+ }
+ } else {
+ if (total_mem >= DIRCACHE_MIN_MEM_BYTES) {
+ *msg = tor_strdup("DirCache is disabled and we are configured as a "
+ "relay. We will not become a Guard.");
+ }
+ }
+ return *msg == NULL ? 0 : -1;
+}
+#undef STRINGIFY
+
+/**
+ * Legacy validation/normalization function for the relay mode options.
+ * Uses old_options as the previous options.
+ *
+ * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
+ * on error.
+ */
+int
+options_validate_relay_mode(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ if (server_mode(options) && options->RendConfigLines)
+ log_warn(LD_CONFIG,
+ "Tor is currently configured as a relay and a hidden service. "
+ "That's not very secure: you should probably run your hidden service "
+ "in a separate Tor process, at least -- see "
+ "https://trac.torproject.org/8742");
+
+ if (options->BridgeRelay && options->DirPort_set) {
+ log_warn(LD_CONFIG, "Can't set a DirPort on a bridge relay; disabling "
+ "DirPort");
+ config_free_lines(options->DirPort_lines);
+ options->DirPort_lines = NULL;
+ options->DirPort_set = 0;
+ }
+
+ if (options->DirPort_set && !options->DirCache) {
+ REJECT("DirPort configured but DirCache disabled. DirPort requires "
+ "DirCache.");
+ }
+
+ if (options->BridgeRelay && !options->DirCache) {
+ REJECT("We're a bridge but DirCache is disabled. BridgeRelay requires "
+ "DirCache.");
+ }
+
+ if (options->BridgeRelay == 1 && ! options->ORPort_set)
+ REJECT("BridgeRelay is 1, ORPort is not set. This is an invalid "
+ "combination.");
+
+ if (server_mode(options)) {
+ char *dircache_msg = NULL;
+ if (have_enough_mem_for_dircache(options, 0, &dircache_msg)) {
+ log_warn(LD_CONFIG, "%s", dircache_msg);
+ tor_free(dircache_msg);
+ }
+ }
+
+ if (options->MyFamily_lines && options->BridgeRelay) {
+ log_warn(LD_CONFIG, "Listing a family for a bridge relay is not "
+ "supported: it can reveal bridge fingerprints to censors. "
+ "You should also make sure you aren't listing this bridge's "
+ "fingerprint in any other MyFamily.");
+ }
+ if (options->MyFamily_lines && !options->ContactInfo) {
+ log_warn(LD_CONFIG, "MyFamily is set but ContactInfo is not configured. "
+ "ContactInfo should always be set when MyFamily option is too.");
+ }
+ if (normalize_nickname_list(&options->MyFamily,
+ options->MyFamily_lines, "MyFamily", msg))
+ return -1;
+
+ if (options->ConstrainedSockets) {
+ if (options->DirPort_set) {
+ /* Providing cached directory entries while system TCP buffers are scarce
+ * will exacerbate the socket errors. Suggest that this be disabled. */
+ COMPLAIN("You have requested constrained socket buffers while also "
+ "serving directory entries via DirPort. It is strongly "
+ "suggested that you disable serving directory requests when "
+ "system TCP buffer resources are scarce.");
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Legacy validation/normalization function for the relay testing options
+ * in options. Uses old_options as the previous options.
+ *
+ * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
+ * on error.
+ */
+int
+options_validate_relay_testing(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ if (options->SigningKeyLifetime < options->TestingSigningKeySlop*2)
+ REJECT("SigningKeyLifetime is too short.");
+ if (options->TestingLinkCertLifetime < options->TestingAuthKeySlop*2)
+ REJECT("LinkCertLifetime is too short.");
+ if (options->TestingAuthKeyLifetime < options->TestingLinkKeySlop*2)
+ REJECT("TestingAuthKeyLifetime is too short.");
+
+ return 0;
+}
+
+/** Return 1 if any change from <b>old_options</b> to <b>new_options</b>
+ * will require us to rotate the CPU and DNS workers; else return 0. */
+static int
+options_transition_affects_workers(const or_options_t *old_options,
+ const or_options_t *new_options)
+{
+ YES_IF_CHANGED_STRING(DataDirectory);
+ YES_IF_CHANGED_INT(NumCPUs);
+ YES_IF_CHANGED_LINELIST(ORPort_lines);
+ YES_IF_CHANGED_BOOL(ServerDNSSearchDomains);
+ YES_IF_CHANGED_BOOL(SafeLogging_);
+ YES_IF_CHANGED_BOOL(ClientOnly);
+ YES_IF_CHANGED_BOOL(LogMessageDomains);
+ YES_IF_CHANGED_LINELIST(Logs);
+
+ if (server_mode(old_options) != server_mode(new_options) ||
+ public_server_mode(old_options) != public_server_mode(new_options) ||
+ dir_server_mode(old_options) != dir_server_mode(new_options))
+ return 1;
+
+ /* Nothing that changed matters. */
+ return 0;
+}
+
+/** Return 1 if any change from <b>old_options</b> to <b>new_options</b>
+ * will require us to generate a new descriptor; else return 0. */
+static int
+options_transition_affects_descriptor(const or_options_t *old_options,
+ const or_options_t *new_options)
+{
+ /* XXX We can be smarter here. If your DirPort isn't being
+ * published and you just turned it off, no need to republish. Etc. */
+
+ YES_IF_CHANGED_STRING(DataDirectory);
+ YES_IF_CHANGED_STRING(Nickname);
+ YES_IF_CHANGED_STRING(Address);
+ YES_IF_CHANGED_LINELIST(ExitPolicy);
+ YES_IF_CHANGED_BOOL(ExitRelay);
+ YES_IF_CHANGED_BOOL(ExitPolicyRejectPrivate);
+ YES_IF_CHANGED_BOOL(ExitPolicyRejectLocalInterfaces);
+ YES_IF_CHANGED_BOOL(IPv6Exit);
+ YES_IF_CHANGED_LINELIST(ORPort_lines);
+ YES_IF_CHANGED_LINELIST(DirPort_lines);
+ YES_IF_CHANGED_LINELIST(DirPort_lines);
+ YES_IF_CHANGED_BOOL(ClientOnly);
+ YES_IF_CHANGED_BOOL(DisableNetwork);
+ YES_IF_CHANGED_BOOL(PublishServerDescriptor_);
+ YES_IF_CHANGED_STRING(ContactInfo);
+ YES_IF_CHANGED_STRING(BridgeDistribution);
+ YES_IF_CHANGED_LINELIST(MyFamily);
+ YES_IF_CHANGED_STRING(AccountingStart);
+ YES_IF_CHANGED_INT(AccountingMax);
+ YES_IF_CHANGED_INT(AccountingRule);
+ YES_IF_CHANGED_BOOL(DirCache);
+ YES_IF_CHANGED_BOOL(AssumeReachable);
+
+ if (relay_get_effective_bwrate(old_options) !=
+ relay_get_effective_bwrate(new_options) ||
+ relay_get_effective_bwburst(old_options) !=
+ relay_get_effective_bwburst(new_options) ||
+ public_server_mode(old_options) != public_server_mode(new_options))
+ return 1;
+
+ return 0;
+}
+
+/** Fetch the active option list, and take relay actions based on it. All of
+ * the things we do should survive being done repeatedly. If present,
+ * <b>old_options</b> contains the previous value of the options.
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_relay(const or_options_t *old_options)
+{
+ const or_options_t *options = get_options();
+
+ const int transition_affects_workers =
+ old_options && options_transition_affects_workers(old_options, options);
+
+ /* We want to reinit keys as needed before we do much of anything else:
+ keys are important, and other things can depend on them. */
+ if (transition_affects_workers ||
+ (authdir_mode_v3(options) && (!old_options ||
+ !authdir_mode_v3(old_options)))) {
+ if (init_keys() < 0) {
+ log_warn(LD_BUG,"Error initializing keys; exiting");
+ return -1;
+ }
+ }
+
+ if (server_mode(options)) {
+ static int cdm_initialized = 0;
+ if (cdm_initialized == 0) {
+ cdm_initialized = 1;
+ consdiffmgr_configure(NULL);
+ consdiffmgr_validate();
+ }
+ }
+
+ /* Check for transitions that need action. */
+ if (old_options) {
+ if (transition_affects_workers) {
+ log_info(LD_GENERAL,
+ "Worker-related options changed. Rotating workers.");
+ const int server_mode_turned_on =
+ server_mode(options) && !server_mode(old_options);
+ const int dir_server_mode_turned_on =
+ dir_server_mode(options) && !dir_server_mode(old_options);
+
+ if (server_mode_turned_on || dir_server_mode_turned_on) {
+ cpu_init();
+ }
+
+ if (server_mode_turned_on) {
+ ip_address_changed(0);
+ if (have_completed_a_circuit() || !any_predicted_circuits(time(NULL)))
+ inform_testing_reachability();
+ }
+ cpuworkers_rotate_keyinfo();
+ }
+ }
+
+ return 0;
+}
+
+/** Fetch the active option list, and take relay accounting actions based on
+ * it. All of the things we do should survive being done repeatedly. If
+ * present, <b>old_options</b> contains the previous value of the options.
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_relay_accounting(const or_options_t *old_options)
+{
+ (void)old_options;
+
+ const or_options_t *options = get_options();
+
+ /* Set up accounting */
+ if (accounting_parse_options(options, 0)<0) {
+ // LCOV_EXCL_START
+ log_warn(LD_BUG,"Error in previously validated accounting options");
+ return -1;
+ // LCOV_EXCL_STOP
+ }
+ if (accounting_is_enabled(options))
+ configure_accounting(time(NULL));
+
+ return 0;
+}
+
+/** Fetch the active option list, and take relay bandwidth actions based on
+ * it. All of the things we do should survive being done repeatedly. If
+ * present, <b>old_options</b> contains the previous value of the options.
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_relay_bandwidth(const or_options_t *old_options)
+{
+ const or_options_t *options = get_options();
+
+ /* Check for transitions that need action. */
+ if (old_options) {
+ if (options->PerConnBWRate != old_options->PerConnBWRate ||
+ options->PerConnBWBurst != old_options->PerConnBWBurst)
+ connection_or_update_token_buckets(get_connection_array(), options);
+
+ if (options->RelayBandwidthRate != old_options->RelayBandwidthRate ||
+ options->RelayBandwidthBurst != old_options->RelayBandwidthBurst)
+ connection_bucket_adjust(options);
+ }
+
+ return 0;
+}
+
+/** Fetch the active option list, and take bridge statistics actions based on
+ * it. All of the things we do should survive being done repeatedly. If
+ * present, <b>old_options</b> contains the previous value of the options.
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_bridge_stats(const or_options_t *old_options)
+{
+ const or_options_t *options = get_options();
+
+/* How long should we delay counting bridge stats after becoming a bridge?
+ * We use this so we don't count clients who used our bridge thinking it is
+ * a relay. If you change this, don't forget to change the log message
+ * below. It's 4 hours (the time it takes to stop being used by clients)
+ * plus some extra time for clock skew. */
+#define RELAY_BRIDGE_STATS_DELAY (6 * 60 * 60)
+
+ /* Check for transitions that need action. */
+ if (old_options) {
+ if (! bool_eq(options->BridgeRelay, old_options->BridgeRelay)) {
+ int was_relay = 0;
+ if (options->BridgeRelay) {
+ time_t int_start = time(NULL);
+ if (config_lines_eq(old_options->ORPort_lines,options->ORPort_lines)) {
+ int_start += RELAY_BRIDGE_STATS_DELAY;
+ was_relay = 1;
+ }
+ geoip_bridge_stats_init(int_start);
+ log_info(LD_CONFIG, "We are acting as a bridge now. Starting new "
+ "GeoIP stats interval%s.", was_relay ? " in 6 "
+ "hours from now" : "");
+ } else {
+ geoip_bridge_stats_term();
+ log_info(LD_GENERAL, "We are no longer acting as a bridge. "
+ "Forgetting GeoIP stats.");
+ }
+ }
+ }
+
+ return 0;
+}
+
+/** Fetch the active option list, and take relay statistics actions based on
+ * it. All of the things we do should survive being done repeatedly. If
+ * present, <b>old_options</b> contains the previous value of the options.
+ *
+ * Sets <b>*print_notice_out</b> if we enabled stats, and need to print
+ * a stats log using options_act_relay_stats_msg().
+ *
+ * If loading the GeoIP file failed, sets DirReqStatistics and
+ * EntryStatistics to 0. This breaks the normalization/act ordering
+ * introduced in 29211.
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_relay_stats(const or_options_t *old_options,
+ bool *print_notice_out)
+{
+ if (BUG(!print_notice_out))
+ return -1;
+
+ or_options_t *options = get_options_mutable();
+
+ if (options->CellStatistics || options->DirReqStatistics ||
+ options->EntryStatistics || options->ExitPortStatistics ||
+ options->ConnDirectionStatistics ||
+ options->HiddenServiceStatistics) {
+ time_t now = time(NULL);
+ int print_notice = 0;
+
+ if ((!old_options || !old_options->CellStatistics) &&
+ options->CellStatistics) {
+ rep_hist_buffer_stats_init(now);
+ print_notice = 1;
+ }
+ if ((!old_options || !old_options->DirReqStatistics) &&
+ options->DirReqStatistics) {
+ if (geoip_is_loaded(AF_INET)) {
+ geoip_dirreq_stats_init(now);
+ print_notice = 1;
+ } else {
+ /* disable statistics collection since we have no geoip file */
+ /* 29211: refactor to avoid the normalisation/act inversion */
+ options->DirReqStatistics = 0;
+ if (options->ORPort_set)
+ log_notice(LD_CONFIG, "Configured to measure directory request "
+ "statistics, but no GeoIP database found. "
+ "Please specify a GeoIP database using the "
+ "GeoIPFile option.");
+ }
+ }
+ if ((!old_options || !old_options->EntryStatistics) &&
+ options->EntryStatistics && !should_record_bridge_info(options)) {
+ /* If we get here, we've started recording bridge info when we didn't
+ * do so before. Note that "should_record_bridge_info()" will
+ * always be false at this point, because of the earlier block
+ * that cleared EntryStatistics when public_server_mode() was false.
+ * We're leaving it in as defensive programming. */
+ if (geoip_is_loaded(AF_INET) || geoip_is_loaded(AF_INET6)) {
+ geoip_entry_stats_init(now);
+ print_notice = 1;
+ } else {
+ options->EntryStatistics = 0;
+ log_notice(LD_CONFIG, "Configured to measure entry node "
+ "statistics, but no GeoIP database found. "
+ "Please specify a GeoIP database using the "
+ "GeoIPFile option.");
+ }
+ }
+ if ((!old_options || !old_options->ExitPortStatistics) &&
+ options->ExitPortStatistics) {
+ rep_hist_exit_stats_init(now);
+ print_notice = 1;
+ }
+ if ((!old_options || !old_options->ConnDirectionStatistics) &&
+ options->ConnDirectionStatistics) {
+ rep_hist_conn_stats_init(now);
+ }
+ if ((!old_options || !old_options->HiddenServiceStatistics) &&
+ options->HiddenServiceStatistics) {
+ log_info(LD_CONFIG, "Configured to measure hidden service statistics.");
+ rep_hist_hs_stats_init(now);
+ }
+ if (print_notice)
+ *print_notice_out = 1;
+ }
+
+ /* If we used to have statistics enabled but we just disabled them,
+ stop gathering them. */
+ if (old_options && old_options->CellStatistics &&
+ !options->CellStatistics)
+ rep_hist_buffer_stats_term();
+ if (old_options && old_options->DirReqStatistics &&
+ !options->DirReqStatistics)
+ geoip_dirreq_stats_term();
+ if (old_options && old_options->EntryStatistics &&
+ !options->EntryStatistics)
+ geoip_entry_stats_term();
+ if (old_options && old_options->HiddenServiceStatistics &&
+ !options->HiddenServiceStatistics)
+ rep_hist_hs_stats_term();
+ if (old_options && old_options->ExitPortStatistics &&
+ !options->ExitPortStatistics)
+ rep_hist_exit_stats_term();
+ if (old_options && old_options->ConnDirectionStatistics &&
+ !options->ConnDirectionStatistics)
+ rep_hist_conn_stats_term();
+
+ return 0;
+}
+
+/** Print a notice about relay/dirauth stats being enabled. */
+void
+options_act_relay_stats_msg(void)
+{
+ log_notice(LD_CONFIG, "Configured to measure statistics. Look for "
+ "the *-stats files that will first be written to the "
+ "data directory in 24 hours from now.");
+}
+
+/** Fetch the active option list, and take relay descriptor actions based on
+ * it. All of the things we do should survive being done repeatedly. If
+ * present, <b>old_options</b> contains the previous value of the options.
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_relay_desc(const or_options_t *old_options)
+{
+ const or_options_t *options = get_options();
+
+ /* Since our options changed, we might need to regenerate and upload our
+ * server descriptor.
+ */
+ if (!old_options ||
+ options_transition_affects_descriptor(old_options, options))
+ mark_my_descriptor_dirty("config change");
+
+ return 0;
+}
+
+/** Fetch the active option list, and take relay DoS actions based on
+ * it. All of the things we do should survive being done repeatedly. If
+ * present, <b>old_options</b> contains the previous value of the options.
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_relay_dos(const or_options_t *old_options)
+{
+ const or_options_t *options = get_options();
+
+ /* DoS mitigation subsystem only applies to public relay. */
+ if (public_server_mode(options)) {
+ /* If we are configured as a relay, initialize the subsystem. Even on HUP,
+ * this is safe to call as it will load data from the current options
+ * or/and the consensus. */
+ dos_init();
+ } else if (old_options && public_server_mode(old_options)) {
+ /* Going from relay to non relay, clean it up. */
+ dos_free_all();
+ }
+
+ return 0;
+}
+
+/** Fetch the active option list, and take dirport actions based on
+ * it. All of the things we do should survive being done repeatedly. If
+ * present, <b>old_options</b> contains the previous value of the options.
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_relay_dir(const or_options_t *old_options)
+{
+ (void)old_options;
+
+ const or_options_t *options = get_options();
+
+ if (!public_server_mode(options))
+ return 0;
+
+ /* Load the webpage we're going to serve every time someone asks for '/' on
+ our DirPort. */
+ tor_free(global_dirfrontpagecontents);
+ if (options->DirPortFrontPage) {
+ global_dirfrontpagecontents =
+ read_file_to_str(options->DirPortFrontPage, 0, NULL);
+ if (!global_dirfrontpagecontents) {
+ log_warn(LD_CONFIG,
+ "DirPortFrontPage file '%s' not found. Continuing anyway.",
+ options->DirPortFrontPage);
+ }
+ }
+
+ return 0;
+}
diff --git a/src/feature/relay/relay_config.h b/src/feature/relay/relay_config.h
new file mode 100644
index 0000000000..c70c322d88
--- /dev/null
+++ b/src/feature/relay/relay_config.h
@@ -0,0 +1,196 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file relay_config.h
+ * @brief Header for feature/relay/relay_config.c
+ **/
+
+#ifndef TOR_FEATURE_RELAY_RELAY_CONFIG_H
+#define TOR_FEATURE_RELAY_RELAY_CONFIG_H
+
+struct or_options_t;
+
+#ifdef HAVE_MODULE_RELAY
+
+#include "lib/cc/torint.h"
+#include "lib/testsupport/testsupport.h"
+
+struct smartlist_t;
+
+int options_validate_relay_mode(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+MOCK_DECL(const char*, relay_get_dirportfrontpage, (void));
+void relay_config_free_all(void);
+
+uint32_t relay_get_effective_bwrate(const struct or_options_t *options);
+uint32_t relay_get_effective_bwburst(const struct or_options_t *options);
+
+void port_warn_nonlocal_ext_orports(const struct smartlist_t *ports,
+ const char *portname);
+
+int port_parse_ports_relay(struct or_options_t *options,
+ char **msg,
+ struct smartlist_t *ports_out,
+ int *have_low_ports_out);
+void port_update_port_set_relay(struct or_options_t *options,
+ const struct smartlist_t *ports);
+
+int options_validate_relay_os(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+int options_validate_relay_info(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+int options_validate_publish_server(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+int options_validate_relay_padding(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+int options_validate_relay_bandwidth(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+int options_validate_relay_accounting(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+int options_validate_relay_testing(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+int options_act_relay(const struct or_options_t *old_options);
+int options_act_relay_accounting(const struct or_options_t *old_options);
+int options_act_relay_bandwidth(const struct or_options_t *old_options);
+int options_act_bridge_stats(const struct or_options_t *old_options);
+
+int options_act_relay_stats(const struct or_options_t *old_options,
+ bool *print_notice_out);
+void options_act_relay_stats_msg(void);
+
+int options_act_relay_desc(const struct or_options_t *old_options);
+int options_act_relay_dos(const struct or_options_t *old_options);
+int options_act_relay_dir(const struct or_options_t *old_options);
+
+#ifdef RELAY_CONFIG_PRIVATE
+
+STATIC int check_bridge_distribution_setting(const char *bd);
+STATIC int have_enough_mem_for_dircache(const struct or_options_t *options,
+ size_t total_mem, char **msg);
+
+#endif /* defined(RELAY_CONFIG_PRIVATE) */
+
+#else /* !defined(HAVE_MODULE_RELAY) */
+
+#include "lib/cc/compat_compiler.h"
+
+/** When tor is compiled with the relay module disabled, it can't be
+ * configured as a relay or bridge.
+ *
+ * Always sets ClientOnly to 1.
+ *
+ * Returns -1 and sets msg to a newly allocated string, if ORPort, DirPort,
+ * DirCache, or BridgeRelay are set in options. Otherwise returns 0. */
+static inline int
+options_validate_relay_mode(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ /* Only check the primary options for now, #29211 will disable more
+ * options. These ORPort and DirPort checks are too strict, and will
+ * reject valid configs that disable ports, like "ORPort 0". */
+ if (options->DirCache ||
+ options->BridgeRelay ||
+ options->ORPort_lines ||
+ options->DirPort_lines) {
+ /* REJECT() this configuration */
+ *msg = tor_strdup("This tor was built with relay mode disabled. "
+ "It can not be configured with an ORPort, a DirPort, "
+ "DirCache 1, or BridgeRelay 1.");
+ return -1;
+ }
+
+ return 0;
+}
+
+static inline int
+port_parse_ports_relay(or_options_t *options,
+ char **msg,
+ smartlist_t *ports_out,
+ int *have_low_ports_out)
+{
+ (void)options;
+ (void)msg;
+ (void)ports_out;
+ if (*have_low_ports_out < 0)
+ *have_low_ports_out = 0;
+ return 0;
+}
+
+#define relay_get_dirportfrontpage() \
+ (NULL)
+#define relay_config_free_all() \
+ STMT_BEGIN STMT_END
+
+#define relay_get_effective_bwrate(options) \
+ (((void)(options)),0)
+#define relay_get_effective_bwburst(options) \
+ (((void)(options)),0)
+
+#define port_warn_nonlocal_ext_orports(ports, portname) \
+ (((void)(ports)),((void)(portname)))
+
+#define port_update_port_set_relay(options, ports) \
+ (((void)(options)),((void)(ports)))
+
+#define options_validate_relay_os(old_options, options, msg) \
+ (((void)(old_options)),((void)(options)),((void)(msg)),0)
+#define options_validate_relay_info(old_options, options, msg) \
+ (((void)(old_options)),((void)(options)),((void)(msg)),0)
+#define options_validate_publish_server(old_options, options, msg) \
+ (((void)(old_options)),((void)(options)),((void)(msg)),0)
+#define options_validate_relay_padding(old_options, options, msg) \
+ (((void)(old_options)),((void)(options)),((void)(msg)),0)
+#define options_validate_relay_bandwidth(old_options, options, msg) \
+ (((void)(old_options)),((void)(options)),((void)(msg)),0)
+#define options_validate_relay_accounting(old_options, options, msg) \
+ (((void)(old_options)),((void)(options)),((void)(msg)),0)
+#define options_validate_relay_testing(old_options, options, msg) \
+ (((void)(old_options)),((void)(options)),((void)(msg)),0)
+
+#define options_act_relay(old_options) \
+ (((void)(old_options)),0)
+#define options_act_relay_accounting(old_options) \
+ (((void)(old_options)),0)
+#define options_act_relay_bandwidth(old_options) \
+ (((void)(old_options)),0)
+#define options_act_bridge_stats(old_options) \
+ (((void)(old_options)),0)
+
+#define options_act_relay_stats(old_options, print_notice_out) \
+ (((void)(old_options)),((void)(print_notice_out)),0)
+#define options_act_relay_stats_msg() \
+ STMT_BEGIN STMT_END
+
+#define options_act_relay_desc(old_options) \
+ (((void)(old_options)),0)
+#define options_act_relay_dos(old_options) \
+ (((void)(old_options)),0)
+#define options_act_relay_dir(old_options) \
+ (((void)(old_options)),0)
+
+#endif /* defined(HAVE_MODULE_RELAY) */
+
+#endif /* !defined(TOR_FEATURE_RELAY_RELAY_CONFIG_H) */
diff --git a/src/feature/relay/relay_periodic.c b/src/feature/relay/relay_periodic.c
index b48b495895..b751323e0d 100644
--- a/src/feature/relay/relay_periodic.c
+++ b/src/feature/relay/relay_periodic.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -31,11 +31,13 @@
#include "feature/nodelist/routerinfo_st.h"
#include "feature/control/control_events.h"
+#ifndef COCCI
#define DECLARE_EVENT(name, roles, flags) \
static periodic_event_item_t name ## _event = \
PERIODIC_EVENT(name, \
PERIODIC_EVENT_ROLE_##roles, \
flags)
+#endif /* !defined(COCCI) */
#define FL(name) (PERIODIC_EVENT_FLAG_##name)
diff --git a/src/feature/relay/relay_periodic.h b/src/feature/relay/relay_periodic.h
index b6ea83c749..ccda9a440b 100644
--- a/src/feature/relay/relay_periodic.h
+++ b/src/feature/relay/relay_periodic.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,7 +12,20 @@
#ifndef TOR_FEATURE_RELAY_RELAY_PERIODIC_H
#define TOR_FEATURE_RELAY_RELAY_PERIODIC_H
+#ifdef HAVE_MODULE_RELAY
+
void relay_register_periodic_events(void);
void reschedule_descriptor_update_check(void);
+#else /* !defined(HAVE_MODULE_RELAY) */
+
+#include "lib/cc/compat_compiler.h"
+
+#define relay_register_periodic_events() \
+ STMT_NIL
+#define reschedule_descriptor_update_check() \
+ STMT_NIL
+
+#endif /* defined(HAVE_MODULE_RELAY) */
+
#endif /* !defined(TOR_FEATURE_RELAY_RELAY_PERIODIC_H) */
diff --git a/src/feature/relay/relay_stub.c b/src/feature/relay/relay_stub.c
new file mode 100644
index 0000000000..42e08fcb6c
--- /dev/null
+++ b/src/feature/relay/relay_stub.c
@@ -0,0 +1,20 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file relay_stub.c
+ * @brief Stub declarations for use when relay module is disabled.
+ **/
+
+#include "orconfig.h"
+#include "feature/relay/relay_sys.h"
+#include "lib/subsys/subsys.h"
+
+const struct subsys_fns_t sys_relay = {
+ .name = "relay",
+ .supported = false,
+ .level = RELAY_SUBSYS_LEVEL,
+};
diff --git a/src/feature/relay/relay_sys.c b/src/feature/relay/relay_sys.c
index 106e88b2a5..34489cf5aa 100644
--- a/src/feature/relay/relay_sys.c
+++ b/src/feature/relay/relay_sys.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -42,7 +42,7 @@ subsys_relay_shutdown(void)
const struct subsys_fns_t sys_relay = {
.name = "relay",
.supported = true,
- .level = 50,
+ .level = RELAY_SUBSYS_LEVEL,
.initialize = subsys_relay_initialize,
.shutdown = subsys_relay_shutdown,
};
diff --git a/src/feature/relay/relay_sys.h b/src/feature/relay/relay_sys.h
index 32e21d90d8..9bad93a6c9 100644
--- a/src/feature/relay/relay_sys.h
+++ b/src/feature/relay/relay_sys.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,4 +14,12 @@
extern const struct subsys_fns_t sys_relay;
+/**
+ * Subsystem level for the relay system.
+ *
+ * Defined here so that it can be shared between the real and stub
+ * definitions.
+ **/
+#define RELAY_SUBSYS_LEVEL 50
+
#endif /* !defined(TOR_FEATURE_RELAY_RELAY_SYS_H) */
diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c
index a46b522bd6..3e92f202e6 100644
--- a/src/feature/relay/router.c
+++ b/src/feature/relay/router.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ROUTER_PRIVATE
@@ -35,6 +35,7 @@
#include "feature/nodelist/routerlist.h"
#include "feature/nodelist/torcert.h"
#include "feature/relay/dns.h"
+#include "feature/relay/relay_config.h"
#include "feature/relay/router.h"
#include "feature/relay/routerkeys.h"
#include "feature/relay/routermode.h"
@@ -372,6 +373,8 @@ assert_identity_keys_ok(void)
}
}
+#ifdef HAVE_MODULE_RELAY
+
/** Returns the current server identity key; requires that the key has
* been set, and that we are running as a Tor server.
*/
@@ -384,6 +387,8 @@ get_server_identity_key,(void))
return server_identitykey;
}
+#endif /* defined(HAVE_MODULE_RELAY) */
+
/** Return true iff we are a server and the server identity key
* has been set. */
int
@@ -882,15 +887,6 @@ init_keys_common(void)
if (!key_lock)
key_lock = tor_mutex_new();
- /* There are a couple of paths that put us here before we've asked
- * openssl to initialize itself. */
- if (crypto_global_init(get_options()->HardwareAccel,
- get_options()->AccelName,
- get_options()->AccelDir)) {
- log_err(LD_BUG, "Unable to initialize OpenSSL. Exiting.");
- return -1;
- }
-
return 0;
}
@@ -1078,8 +1074,10 @@ init_keys(void)
if (authdir_mode_v3(options)) {
const char *m = NULL;
routerinfo_t *ri;
- /* We need to add our own fingerprint so it gets recognized. */
- if (dirserv_add_own_fingerprint(get_server_identity_key())) {
+ /* We need to add our own fingerprint and ed25519 key so it gets
+ * recognized. */
+ if (dirserv_add_own_fingerprint(get_server_identity_key(),
+ get_master_identity_key())) {
log_err(LD_GENERAL,"Error adding own fingerprint to set of relays");
return -1;
}
@@ -1218,7 +1216,7 @@ router_should_be_dirserver(const or_options_t *options, int dir_port)
* much larger effect on output than input so there is no reason to turn it
* off if using AccountingRule in. */
int interval_length = accounting_get_interval_length();
- uint32_t effective_bw = get_effective_bwrate(options);
+ uint32_t effective_bw = relay_get_effective_bwrate(options);
uint64_t acc_bytes;
if (!interval_length) {
log_warn(LD_BUG, "An accounting interval is not allowed to be zero "
@@ -1400,7 +1398,7 @@ consider_publishable_server(int force)
}
/** Return the port of the first active listener of type
- * <b>listener_type</b>. */
+ * <b>listener_type</b>. Returns 0 if no port is found. */
/** XXX not a very good interface. it's not reliable when there are
multiple listeners. */
uint16_t
@@ -1422,8 +1420,7 @@ router_get_active_listener_port_by_type_af(int listener_type,
/** Return the port that we should advertise as our ORPort; this is either
* the one configured in the ORPort option, or the one we actually bound to
- * if ORPort is "auto".
- */
+ * if ORPort is "auto". Returns 0 if no port is found. */
uint16_t
router_get_advertised_or_port(const or_options_t *options)
{
@@ -1449,6 +1446,50 @@ router_get_advertised_or_port_by_af(const or_options_t *options,
return port;
}
+/** As router_get_advertised_or_port(), but returns the IPv6 address and
+ * port in ipv6_ap_out, which must not be NULL. Returns a null address and
+ * zero port, if no ORPort is found. */
+void
+router_get_advertised_ipv6_or_ap(const or_options_t *options,
+ tor_addr_port_t *ipv6_ap_out)
+{
+ /* Bug in calling function, we can't return a sensible result, and it
+ * shouldn't use the NULL pointer once we return. */
+ tor_assert(ipv6_ap_out);
+
+ /* If there is no valid IPv6 ORPort, return a null address and port. */
+ tor_addr_make_null(&ipv6_ap_out->addr, AF_INET6);
+ ipv6_ap_out->port = 0;
+
+ const tor_addr_t *addr = get_first_advertised_addr_by_type_af(
+ CONN_TYPE_OR_LISTENER,
+ AF_INET6);
+ const uint16_t port = router_get_advertised_or_port_by_af(
+ options,
+ AF_INET6);
+
+ if (!addr || port == 0) {
+ log_info(LD_CONFIG, "There is no advertised IPv6 ORPort.");
+ return;
+ }
+
+ /* If the relay is configured using the default authorities, disallow
+ * internal IPs. Otherwise, allow them. For IPv4 ORPorts and DirPorts,
+ * this check is done in resolve_my_address(). See #33681. */
+ const int default_auth = using_default_dir_authorities(options);
+ if (tor_addr_is_internal(addr, 0) && default_auth) {
+ log_warn(LD_CONFIG,
+ "Unable to use configured IPv6 ORPort \"%s\" in a "
+ "descriptor. Skipping it. "
+ "Try specifying a globally reachable address explicitly.",
+ fmt_addrport(addr, port));
+ return;
+ }
+
+ tor_addr_copy(&ipv6_ap_out->addr, addr);
+ ipv6_ap_out->port = port;
+}
+
/** Return the port that we should advertise as our DirPort;
* this is one of three possibilities:
* The one that is passed as <b>dirport</b> if the DirPort option is 0, or
@@ -1993,34 +2034,11 @@ router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out))
sizeof(curve25519_public_key_t));
/* For now, at most one IPv6 or-address is being advertised. */
- {
- const port_cfg_t *ipv6_orport = NULL;
- SMARTLIST_FOREACH_BEGIN(get_configured_ports(), const port_cfg_t *, p) {
- if (p->type == CONN_TYPE_OR_LISTENER &&
- ! p->server_cfg.no_advertise &&
- ! p->server_cfg.bind_ipv4_only &&
- tor_addr_family(&p->addr) == AF_INET6) {
- /* Like IPv4, if the relay is configured using the default
- * authorities, disallow internal IPs. Otherwise, allow them. */
- const int default_auth = using_default_dir_authorities(options);
- if (! tor_addr_is_internal(&p->addr, 0) || ! default_auth) {
- ipv6_orport = p;
- break;
- } else {
- char addrbuf[TOR_ADDR_BUF_LEN];
- log_warn(LD_CONFIG,
- "Unable to use configured IPv6 address \"%s\" in a "
- "descriptor. Skipping it. "
- "Try specifying a globally reachable address explicitly.",
- tor_addr_to_str(addrbuf, &p->addr, sizeof(addrbuf), 1));
- }
- }
- } SMARTLIST_FOREACH_END(p);
- if (ipv6_orport) {
- tor_addr_copy(&ri->ipv6_addr, &ipv6_orport->addr);
- ri->ipv6_orport = ipv6_orport->port;
- }
- }
+ tor_addr_port_t ipv6_orport;
+ router_get_advertised_ipv6_or_ap(options, &ipv6_orport);
+ /* If there is no valud IPv6 ORPort, the address and port are null. */
+ tor_addr_copy(&ri->ipv6_addr, &ipv6_orport.addr);
+ ri->ipv6_orport = ipv6_orport.port;
ri->identity_pkey = crypto_pk_dup_key(get_server_identity_key());
if (BUG(crypto_pk_get_digest(ri->identity_pkey,
@@ -2037,10 +2055,10 @@ router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out))
ri->protocol_list = tor_strdup(protover_get_supported_protocols());
/* compute ri->bandwidthrate as the min of various options */
- ri->bandwidthrate = get_effective_bwrate(options);
+ ri->bandwidthrate = relay_get_effective_bwrate(options);
/* and compute ri->bandwidthburst similarly */
- ri->bandwidthburst = get_effective_bwburst(options);
+ ri->bandwidthburst = relay_get_effective_bwburst(options);
/* Report bandwidth, unless we're hibernating or shutting down */
ri->bandwidthcapacity = hibernating ? 0 : rep_hist_bandwidth_assess();
diff --git a/src/feature/relay/router.h b/src/feature/relay/router.h
index 55b9ef9e68..061daa0628 100644
--- a/src/feature/relay/router.h
+++ b/src/feature/relay/router.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -28,7 +28,13 @@ struct ed25519_keypair_t;
MOCK_DECL(crypto_pk_t *,get_onion_key,(void));
time_t get_onion_key_set_at(void);
void set_server_identity_key(crypto_pk_t *k);
+/* Some compilers are clever enough to know that when relay mode is disabled,
+ * this function never returns. */
+#ifdef HAVE_MODULE_RELAY
MOCK_DECL(crypto_pk_t *,get_server_identity_key,(void));
+#else
+#define get_server_identity_key() (tor_abort_(),NULL)
+#endif
int server_identity_key_is_set(void);
void set_client_identity_key(crypto_pk_t *k);
crypto_pk_t *get_tlsclient_identity_key(void);
@@ -60,6 +66,8 @@ int init_keys_client(void);
uint16_t router_get_active_listener_port_by_type_af(int listener_type,
sa_family_t family);
uint16_t router_get_advertised_or_port(const or_options_t *options);
+void router_get_advertised_ipv6_or_ap(const or_options_t *options,
+ tor_addr_port_t *ipv6_ap_out);
uint16_t router_get_advertised_or_port_by_af(const or_options_t *options,
sa_family_t family);
uint16_t router_get_advertised_dir_port(const or_options_t *options,
diff --git a/src/feature/relay/routerkeys.c b/src/feature/relay/routerkeys.c
index a9190b2e13..d3de83cb86 100644
--- a/src/feature/relay/routerkeys.c
+++ b/src/feature/relay/routerkeys.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/relay/routerkeys.h b/src/feature/relay/routerkeys.h
index cde07b52c3..c2475f195f 100644
--- a/src/feature/relay/routerkeys.h
+++ b/src/feature/relay/routerkeys.h
@@ -1,6 +1,11 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file routerkeys.h
+ * @brief Header for routerkeys.c
+ **/
+
#ifndef TOR_ROUTERKEYS_H
#define TOR_ROUTERKEYS_H
diff --git a/src/feature/relay/routermode.c b/src/feature/relay/routermode.c
index 2a9ddeac4d..c4d8792b5b 100644
--- a/src/feature/relay/routermode.c
+++ b/src/feature/relay/routermode.c
@@ -1,14 +1,17 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file routermode.c
+ * @brief Check if we're running as a relay/cache.
+ **/
+
#include "core/or/or.h"
#include "app/config/config.h"
-#include "core/mainloop/connection.h"
-#include "core/or/port_cfg_st.h"
#include "feature/relay/router.h"
#include "feature/relay/routermode.h"
@@ -25,21 +28,6 @@ dir_server_mode(const or_options_t *options)
(server_mode(options) && router_has_bandwidth_to_be_dirserver(options));
}
-/** Return true iff we are trying to proxy client connections. */
-int
-proxy_mode(const or_options_t *options)
-{
- (void)options;
- SMARTLIST_FOREACH_BEGIN(get_configured_ports(), const port_cfg_t *, p) {
- if (p->type == CONN_TYPE_AP_LISTENER ||
- p->type == CONN_TYPE_AP_TRANS_LISTENER ||
- p->type == CONN_TYPE_AP_DNS_LISTENER ||
- p->type == CONN_TYPE_AP_NATD_LISTENER)
- return 1;
- } SMARTLIST_FOREACH_END(p);
- return 0;
-}
-
/** Return true iff we are trying to be a server.
*/
MOCK_IMPL(int,
diff --git a/src/feature/relay/routermode.h b/src/feature/relay/routermode.h
index be535af478..6d7404968d 100644
--- a/src/feature/relay/routermode.h
+++ b/src/feature/relay/routermode.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,13 +12,31 @@
#ifndef TOR_ROUTERMODE_H
#define TOR_ROUTERMODE_H
+#ifdef HAVE_MODULE_RELAY
+
int dir_server_mode(const or_options_t *options);
MOCK_DECL(int, server_mode, (const or_options_t *options));
MOCK_DECL(int, public_server_mode, (const or_options_t *options));
MOCK_DECL(int, advertised_server_mode, (void));
-int proxy_mode(const or_options_t *options);
void set_server_advertised(int s);
+/** Is the relay module enabled? */
+#define have_module_relay() (1)
+
+#else /* !defined(HAVE_MODULE_RELAY) */
+
+#define dir_server_mode(options) (((void)(options)),0)
+#define server_mode(options) (((void)(options)),0)
+#define public_server_mode(options) (((void)(options)),0)
+#define advertised_server_mode() (0)
+
+/* We shouldn't be publishing descriptors when relay mode is disabled. */
+#define set_server_advertised(s) tor_assert_nonfatal(!(s))
+
+#define have_module_relay() (0)
+
+#endif /* defined(HAVE_MODULE_RELAY) */
+
#endif /* !defined(TOR_ROUTERMODE_H) */
diff --git a/src/feature/relay/selftest.c b/src/feature/relay/selftest.c
index f8b54ff45d..29febdee82 100644
--- a/src/feature/relay/selftest.c
+++ b/src/feature/relay/selftest.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,8 +12,6 @@
* their own bandwidth, before publishing.
*/
-#define SELFTEST_PRIVATE
-
#include "core/or/or.h"
#include "app/config/config.h"
diff --git a/src/feature/relay/selftest.h b/src/feature/relay/selftest.h
index aea77ec791..94f305f203 100644
--- a/src/feature/relay/selftest.h
+++ b/src/feature/relay/selftest.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/relay/transport_config.c b/src/feature/relay/transport_config.c
new file mode 100644
index 0000000000..7dcce70e30
--- /dev/null
+++ b/src/feature/relay/transport_config.c
@@ -0,0 +1,307 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file transport_config.c
+ * @brief Code to interpret the user's configuration of Tor's server
+ * pluggable transports.
+ **/
+
+#include "orconfig.h"
+#define RELAY_TRANSPORT_CONFIG_PRIVATE
+#include "feature/relay/transport_config.h"
+
+#include "lib/encoding/confline.h"
+#include "lib/encoding/keyval.h"
+
+#include "lib/container/smartlist.h"
+
+/* Required for dirinfo_type_t in or_options_t */
+#include "core/or/or.h"
+#include "app/config/config.h"
+
+#include "feature/relay/ext_orport.h"
+#include "feature/relay/routermode.h"
+
+/* Copied from config.c, we will refactor later in 29211. */
+#define REJECT(arg) \
+ STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
+
+/** Given a ServerTransportListenAddr <b>line</b>, return its
+ * <address:port> string. Return NULL if the line was not
+ * well-formed.
+ *
+ * If <b>transport</b> is set, return NULL if the line is not
+ * referring to <b>transport</b>.
+ *
+ * The returned string is allocated on the heap and it's the
+ * responsibility of the caller to free it. */
+static char *
+get_bindaddr_from_transport_listen_line(const char *line,
+ const char *transport)
+{
+ smartlist_t *items = NULL;
+ const char *parsed_transport = NULL;
+ char *addrport = NULL;
+ tor_addr_t addr;
+ uint16_t port = 0;
+
+ items = smartlist_new();
+ smartlist_split_string(items, line, NULL,
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
+
+ if (smartlist_len(items) < 2) {
+ log_warn(LD_CONFIG,"Too few arguments on ServerTransportListenAddr line.");
+ goto err;
+ }
+
+ parsed_transport = smartlist_get(items, 0);
+ addrport = tor_strdup(smartlist_get(items, 1));
+
+ /* If 'transport' is given, check if it matches the one on the line */
+ if (transport && strcmp(transport, parsed_transport))
+ goto err;
+
+ /* Validate addrport */
+ if (tor_addr_port_parse(LOG_WARN, addrport, &addr, &port, -1)<0) {
+ log_warn(LD_CONFIG, "Error parsing ServerTransportListenAddr "
+ "address '%s'", addrport);
+ goto err;
+ }
+
+ goto done;
+
+ err:
+ tor_free(addrport);
+ addrport = NULL;
+
+ done:
+ SMARTLIST_FOREACH(items, char*, s, tor_free(s));
+ smartlist_free(items);
+
+ return addrport;
+}
+
+/** Given the name of a pluggable transport in <b>transport</b>, check
+ * the configuration file to see if the user has explicitly asked for
+ * it to listen on a specific port. Return a <address:port> string if
+ * so, otherwise NULL. */
+char *
+pt_get_bindaddr_from_config(const char *transport)
+{
+ config_line_t *cl;
+ const or_options_t *options = get_options();
+
+ for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) {
+ char *bindaddr =
+ get_bindaddr_from_transport_listen_line(cl->value, transport);
+ if (bindaddr)
+ return bindaddr;
+ }
+
+ return NULL;
+}
+
+/** Given a ServerTransportOptions <b>line</b>, return a smartlist
+ * with the options. Return NULL if the line was not well-formed.
+ *
+ * If <b>transport</b> is set, return NULL if the line is not
+ * referring to <b>transport</b>.
+ *
+ * The returned smartlist and its strings are allocated on the heap
+ * and it's the responsibility of the caller to free it. */
+STATIC smartlist_t *
+get_options_from_transport_options_line(const char *line,
+ const char *transport)
+{
+ smartlist_t *items = smartlist_new();
+ smartlist_t *pt_options = smartlist_new();
+ const char *parsed_transport = NULL;
+
+ smartlist_split_string(items, line, NULL,
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
+
+ if (smartlist_len(items) < 2) {
+ log_warn(LD_CONFIG,"Too few arguments on ServerTransportOptions line.");
+ goto err;
+ }
+
+ parsed_transport = smartlist_get(items, 0);
+ /* If 'transport' is given, check if it matches the one on the line */
+ if (transport && strcmp(transport, parsed_transport))
+ goto err;
+
+ SMARTLIST_FOREACH_BEGIN(items, const char *, option) {
+ if (option_sl_idx == 0) /* skip the transport field (first field)*/
+ continue;
+
+ /* validate that it's a k=v value */
+ if (!string_is_key_value(LOG_WARN, option)) {
+ log_warn(LD_CONFIG, "%s is not a k=v value.", escaped(option));
+ goto err;
+ }
+
+ /* add it to the options smartlist */
+ smartlist_add_strdup(pt_options, option);
+ log_debug(LD_CONFIG, "Added %s to the list of options", escaped(option));
+ } SMARTLIST_FOREACH_END(option);
+
+ goto done;
+
+ err:
+ SMARTLIST_FOREACH(pt_options, char*, s, tor_free(s));
+ smartlist_free(pt_options);
+ pt_options = NULL;
+
+ done:
+ SMARTLIST_FOREACH(items, char*, s, tor_free(s));
+ smartlist_free(items);
+
+ return pt_options;
+}
+
+/** Given the name of a pluggable transport in <b>transport</b>, check
+ * the configuration file to see if the user has asked us to pass any
+ * parameters to the pluggable transport. Return a smartlist
+ * containing the parameters, otherwise NULL. */
+smartlist_t *
+pt_get_options_for_server_transport(const char *transport)
+{
+ config_line_t *cl;
+ const or_options_t *options = get_options();
+
+ for (cl = options->ServerTransportOptions; cl; cl = cl->next) {
+ smartlist_t *options_sl =
+ get_options_from_transport_options_line(cl->value, transport);
+ if (options_sl)
+ return options_sl;
+ }
+
+ return NULL;
+}
+
+/**
+ * Legacy validation/normalization function for the server transport options.
+ * Uses old_options as the previous options.
+ *
+ * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
+ * on error.
+ */
+int
+options_validate_server_transport(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ config_line_t *cl;
+
+ if (options->ServerTransportPlugin && !server_mode(options)) {
+ log_notice(LD_GENERAL, "Tor is not configured as a relay but you specified"
+ " a ServerTransportPlugin line (%s). The ServerTransportPlugin "
+ "line will be ignored.",
+ escaped(options->ServerTransportPlugin->value));
+ }
+
+ if (options->ServerTransportListenAddr && !options->ServerTransportPlugin) {
+ log_notice(LD_GENERAL, "You need at least a single managed-proxy to "
+ "specify a transport listen address. The "
+ "ServerTransportListenAddr line will be ignored.");
+ }
+
+ for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
+ if (pt_parse_transport_line(options, cl->value, 1, 1) < 0)
+ REJECT("Invalid server transport line. See logs for details.");
+ }
+
+ for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) {
+ /** If get_bindaddr_from_transport_listen_line() fails with
+ 'transport' being NULL, it means that something went wrong
+ while parsing the ServerTransportListenAddr line. */
+ char *bindaddr = get_bindaddr_from_transport_listen_line(cl->value, NULL);
+ if (!bindaddr)
+ REJECT("ServerTransportListenAddr did not parse. See logs for details.");
+ tor_free(bindaddr);
+ }
+
+ for (cl = options->ServerTransportOptions; cl; cl = cl->next) {
+ /** If get_options_from_transport_options_line() fails with
+ 'transport' being NULL, it means that something went wrong
+ while parsing the ServerTransportOptions line. */
+ smartlist_t *options_sl =
+ get_options_from_transport_options_line(cl->value, NULL);
+ if (!options_sl)
+ REJECT("ServerTransportOptions did not parse. See logs for details.");
+
+ SMARTLIST_FOREACH(options_sl, char *, cp, tor_free(cp));
+ smartlist_free(options_sl);
+ }
+
+ return 0;
+}
+
+/** Fetch the active option list, and take server pluggable transport actions
+ * based on it. All of the things we do should survive being done repeatedly.
+ * If present, <b>old_options</b> contains the previous value of the options.
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_server_transport(const or_options_t *old_options)
+{
+ (void)old_options;
+
+ config_line_t *cl;
+ const or_options_t *options = get_options();
+ int running_tor = options->command == CMD_RUN_TOR;
+
+ /* If we are a bridge with a pluggable transport proxy but no
+ Extended ORPort, inform the user that they are missing out. */
+ if (options->ServerTransportPlugin &&
+ !options->ExtORPort_lines) {
+ log_notice(LD_CONFIG, "We use pluggable transports but the Extended "
+ "ORPort is disabled. Tor and your pluggable transports proxy "
+ "communicate with each other via the Extended ORPort so it "
+ "is suggested you enable it: it will also allow your Bridge "
+ "to collect statistics about its clients that use pluggable "
+ "transports. Please enable it using the ExtORPort torrc option "
+ "(e.g. set 'ExtORPort auto').");
+ }
+
+ /* If we have an ExtORPort, initialize its auth cookie. */
+ if (running_tor &&
+ init_ext_or_cookie_authentication(!!options->ExtORPort_lines) < 0) {
+ log_warn(LD_CONFIG,"Error creating Extended ORPort cookie file.");
+ return -1;
+ }
+
+ if (!options->DisableNetwork) {
+ if (options->ServerTransportPlugin) {
+ for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
+ if (pt_parse_transport_line(options, cl->value, 0, 1) < 0) {
+ // LCOV_EXCL_START
+ log_warn(LD_BUG,
+ "Previously validated ServerTransportPlugin line "
+ "could not be added!");
+ return -1;
+ // LCOV_EXCL_STOP
+ }
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/src/feature/relay/transport_config.h b/src/feature/relay/transport_config.h
new file mode 100644
index 0000000000..6d956d9af1
--- /dev/null
+++ b/src/feature/relay/transport_config.h
@@ -0,0 +1,85 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file transport_config.h
+ * @brief Header for feature/relay/transport_config.c
+ **/
+
+#ifndef TOR_FEATURE_RELAY_TRANSPORT_CONFIG_H
+#define TOR_FEATURE_RELAY_TRANSPORT_CONFIG_H
+
+#ifdef HAVE_MODULE_RELAY
+
+#include "lib/testsupport/testsupport.h"
+
+struct or_options_t;
+struct smartlist_t;
+
+int options_validate_server_transport(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+char *pt_get_bindaddr_from_config(const char *transport);
+struct smartlist_t *pt_get_options_for_server_transport(const char *transport);
+
+int options_act_server_transport(const struct or_options_t *old_options);
+
+#ifdef RELAY_TRANSPORT_CONFIG_PRIVATE
+
+STATIC struct smartlist_t *get_options_from_transport_options_line(
+ const char *line,
+ const char *transport);
+
+#endif /* defined(RELAY_TRANSPORT_CONFIG_PRIVATE) */
+
+#else /* !defined(HAVE_MODULE_RELAY) */
+
+/** When tor is compiled with the relay module disabled, it can't be
+ * configured with server pluggable transports.
+ *
+ * Returns -1 and sets msg to a newly allocated string, if ExtORPort,
+ * ServerTransportPlugin, ServerTransportListenAddr, or
+ * ServerTransportOptions are set in options. Otherwise returns 0. */
+static inline int
+options_validate_server_transport(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ /* These ExtORPort checks are too strict, and will reject valid configs
+ * that disable ports, like "ExtORPort 0". */
+ if (options->ServerTransportPlugin ||
+ options->ServerTransportListenAddr ||
+ options->ServerTransportOptions ||
+ options->ExtORPort_lines) {
+ /* REJECT() this configuration */
+ *msg = tor_strdup("This tor was built with relay mode disabled. "
+ "It can not be configured with an ExtORPort, "
+ "a ServerTransportPlugin, a ServerTransportListenAddr, "
+ "or ServerTransportOptions.");
+ return -1;
+ }
+
+ return 0;
+}
+
+#define pt_get_bindaddr_from_config(transport) \
+ (((void)(transport)),NULL)
+
+/* 31851: called from client/transports.c, but only from server code */
+#define pt_get_options_for_server_transport(transport) \
+ (((void)(transport)),NULL)
+
+#define options_validate_server_transport(old_options, options, msg) \
+ (((void)(old_options)),((void)(options)),((void)(msg)),0)
+#define options_act_server_transport(old_options) \
+ (((void)(old_options)),0)
+
+#endif /* defined(HAVE_MODULE_RELAY) */
+
+#endif /* !defined(TOR_FEATURE_RELAY_TRANSPORT_CONFIG_H) */
diff --git a/src/feature/rend/.may_include b/src/feature/rend/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/rend/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/rend/feature_rend.md b/src/feature/rend/feature_rend.md
new file mode 100644
index 0000000000..bfd8ae3dbc
--- /dev/null
+++ b/src/feature/rend/feature_rend.md
@@ -0,0 +1,7 @@
+@dir /feature/rend
+@brief feature/rend: version 2 (old) hidden services
+
+This directory implements the v2 onion service protocol,
+as specified in
+[rend-spec-v2.txt](https://gitweb.torproject.org/torspec.git/tree/rend-spec-v2.txt).
+
diff --git a/src/feature/rend/include.am b/src/feature/rend/include.am
new file mode 100644
index 0000000000..fb12439a90
--- /dev/null
+++ b/src/feature/rend/include.am
@@ -0,0 +1,22 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/rend/rendcache.c \
+ src/feature/rend/rendclient.c \
+ src/feature/rend/rendcommon.c \
+ src/feature/rend/rendmid.c \
+ src/feature/rend/rendparse.c \
+ src/feature/rend/rendservice.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/rend/rend_authorized_client_st.h \
+ src/feature/rend/rend_encoded_v2_service_descriptor_st.h \
+ src/feature/rend/rend_intro_point_st.h \
+ src/feature/rend/rend_service_descriptor_st.h \
+ src/feature/rend/rendcache.h \
+ src/feature/rend/rendclient.h \
+ src/feature/rend/rendcommon.h \
+ src/feature/rend/rendmid.h \
+ src/feature/rend/rendparse.h \
+ src/feature/rend/rendservice.h
diff --git a/src/feature/rend/rend_authorized_client_st.h b/src/feature/rend/rend_authorized_client_st.h
index 51a1798fcb..c6a6676da9 100644
--- a/src/feature/rend/rend_authorized_client_st.h
+++ b/src/feature/rend/rend_authorized_client_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file rend_authorized_client_st.h
+ * @brief Hidden-service authorized client structure.
+ **/
+
#ifndef REND_AUTHORIZED_CLIENT_ST_H
#define REND_AUTHORIZED_CLIENT_ST_H
@@ -15,4 +20,3 @@ struct rend_authorized_client_t {
};
#endif /* !defined(REND_AUTHORIZED_CLIENT_ST_H) */
-
diff --git a/src/feature/rend/rend_encoded_v2_service_descriptor_st.h b/src/feature/rend/rend_encoded_v2_service_descriptor_st.h
index bd8a60f0d9..fea91b876a 100644
--- a/src/feature/rend/rend_encoded_v2_service_descriptor_st.h
+++ b/src/feature/rend/rend_encoded_v2_service_descriptor_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file rend_encoded_v2_service_descriptor_st.h
+ * @brief Encoded v2 HS descriptor structure.
+ **/
+
#ifndef REND_ENCODED_V2_SERVICE_DESCRIPTOR_ST_H
#define REND_ENCODED_V2_SERVICE_DESCRIPTOR_ST_H
@@ -14,4 +19,3 @@ struct rend_encoded_v2_service_descriptor_t {
};
#endif /* !defined(REND_ENCODED_V2_SERVICE_DESCRIPTOR_ST_H) */
-
diff --git a/src/feature/rend/rend_intro_point_st.h b/src/feature/rend/rend_intro_point_st.h
index 4882b62752..4f0aa01523 100644
--- a/src/feature/rend/rend_intro_point_st.h
+++ b/src/feature/rend/rend_intro_point_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file rend_intro_point_st.h
+ * @brief v2 hidden service introduction point structure.
+ **/
+
#ifndef REND_INTRO_POINT_ST_H
#define REND_INTRO_POINT_ST_H
diff --git a/src/feature/rend/rend_service_descriptor_st.h b/src/feature/rend/rend_service_descriptor_st.h
index ff7627ce96..80c8034f46 100644
--- a/src/feature/rend/rend_service_descriptor_st.h
+++ b/src/feature/rend/rend_service_descriptor_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file rend_service_descriptor_st.h
+ * @brief Parsed v2 HS descriptor structure.
+ **/
+
#ifndef REND_SERVICE_DESCRIPTOR_ST_H
#define REND_SERVICE_DESCRIPTOR_ST_H
@@ -31,4 +36,3 @@ struct rend_service_descriptor_t {
};
#endif /* !defined(REND_SERVICE_DESCRIPTOR_ST_H) */
-
diff --git a/src/feature/rend/rendcache.c b/src/feature/rend/rendcache.c
index c3f86d8c82..0890a81d8f 100644
--- a/src/feature/rend/rendcache.c
+++ b/src/feature/rend/rendcache.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2019, The Tor Project, Inc. */
+/* Copyright (c) 2015-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -228,6 +228,17 @@ rend_cache_entry_free_void(void *p)
rend_cache_entry_free_(p);
}
+/** Check if a failure cache entry exists for the given intro point. */
+bool
+rend_cache_intro_failure_exists(const char *service_id,
+ const uint8_t *intro_identity)
+{
+ tor_assert(service_id);
+ tor_assert(intro_identity);
+
+ return cache_failure_intro_lookup(intro_identity, service_id, NULL);
+}
+
/** Free all storage held by the service descriptor cache. */
void
rend_cache_free_all(void)
@@ -515,9 +526,16 @@ rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **e)
rend_cache_entry_t *entry = NULL;
static const int default_version = 2;
- tor_assert(rend_cache);
tor_assert(query);
+ /* This is possible if we are in the shutdown process and the cache was
+ * freed while some other subsystem might do a lookup to the cache for
+ * cleanup reasons such HS circuit cleanup for instance. */
+ if (!rend_cache) {
+ ret = -ENOENT;
+ goto end;
+ }
+
if (!rend_valid_v2_service_id(query)) {
ret = -EINVAL;
goto end;
diff --git a/src/feature/rend/rendcache.h b/src/feature/rend/rendcache.h
index aec97eabb8..45410610b4 100644
--- a/src/feature/rend/rendcache.h
+++ b/src/feature/rend/rendcache.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2019, The Tor Project, Inc. */
+/* Copyright (c) 2015-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -80,6 +80,8 @@ int rend_cache_store_v2_desc_as_client(const char *desc,
rend_cache_entry_t **entry);
size_t rend_cache_get_total_allocation(void);
+bool rend_cache_intro_failure_exists(const char *service_id,
+ const uint8_t *intro_identity);
void rend_cache_intro_failure_note(rend_intro_point_failure_t failure,
const uint8_t *identity,
const char *service_id);
diff --git a/src/feature/rend/rendclient.c b/src/feature/rend/rendclient.c
index 1446dc2269..d33b61851f 100644
--- a/src/feature/rend/rendclient.c
+++ b/src/feature/rend/rendclient.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -1048,18 +1048,30 @@ rend_client_get_random_intro_impl(const rend_cache_entry_t *entry,
const or_options_t *options = get_options();
smartlist_t *usable_nodes;
int n_excluded = 0;
+ char service_id[REND_SERVICE_ID_LEN_BASE32 + 1];
/* We'll keep a separate list of the usable nodes. If this becomes empty,
* no nodes are usable. */
usable_nodes = smartlist_new();
smartlist_add_all(usable_nodes, entry->parsed->intro_nodes);
+ /* Get service ID so we can use it to query the failure cache. If we fail to
+ * parse it, this cache entry is no good. */
+ if (BUG(rend_get_service_id(entry->parsed->pk, service_id) < 0)) {
+ smartlist_free(usable_nodes);
+ return NULL;
+ }
+
/* Remove the intro points that have timed out during this HS
* connection attempt from our list of usable nodes. */
- SMARTLIST_FOREACH(usable_nodes, rend_intro_point_t *, ip,
- if (ip->timed_out) {
- SMARTLIST_DEL_CURRENT(usable_nodes, ip);
- });
+ SMARTLIST_FOREACH_BEGIN(usable_nodes, const rend_intro_point_t *, ip) {
+ bool failed_intro =
+ rend_cache_intro_failure_exists(service_id,
+ (const uint8_t *) ip->extend_info->identity_digest);
+ if (ip->timed_out || failed_intro) {
+ SMARTLIST_DEL_CURRENT(usable_nodes, ip);
+ };
+ } SMARTLIST_FOREACH_END(ip);
again:
if (smartlist_len(usable_nodes) == 0) {
@@ -1238,3 +1250,66 @@ rend_parse_service_authorization(const or_options_t *options,
}
return res;
}
+
+/** The given circuit is being freed. Take appropriate action if it is of
+ * interest to the client subsystem. */
+void
+rend_client_circuit_cleanup_on_free(const circuit_t *circ)
+{
+ int reason, orig_reason;
+ bool has_timed_out, ip_is_redundant;
+ const origin_circuit_t *ocirc = NULL;
+
+ tor_assert(circ);
+ tor_assert(CIRCUIT_IS_ORIGIN(circ));
+
+ reason = circ->marked_for_close_reason;
+ orig_reason = circ->marked_for_close_orig_reason;
+ ocirc = CONST_TO_ORIGIN_CIRCUIT(circ);
+ tor_assert(ocirc->rend_data);
+
+ has_timed_out = (reason == END_CIRC_REASON_TIMEOUT);
+ ip_is_redundant = (orig_reason == END_CIRC_REASON_IP_NOW_REDUNDANT);
+
+ switch (circ->purpose) {
+ case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
+ {
+ if (ip_is_redundant) {
+ break;
+ }
+ tor_assert(circ->state == CIRCUIT_STATE_OPEN);
+ tor_assert(ocirc->build_state->chosen_exit);
+ /* Treat this like getting a nack from it */
+ log_info(LD_REND, "Failed intro circ %s to %s (awaiting ack). %s",
+ safe_str_client(rend_data_get_address(ocirc->rend_data)),
+ safe_str_client(build_state_get_exit_nickname(ocirc->build_state)),
+ has_timed_out ? "Recording timeout." : "Removing from descriptor.");
+ rend_client_report_intro_point_failure(ocirc->build_state->chosen_exit,
+ ocirc->rend_data,
+ has_timed_out ?
+ INTRO_POINT_FAILURE_TIMEOUT :
+ INTRO_POINT_FAILURE_GENERIC);
+ break;
+ }
+ case CIRCUIT_PURPOSE_C_INTRODUCING:
+ {
+ /* Ignore if we were introducing and it timed out, we didn't pick an exit
+ * point yet (IP) or the reason indicate that it was a redundant IP. */
+ if (has_timed_out || !ocirc->build_state->chosen_exit || ip_is_redundant) {
+ break;
+ }
+ log_info(LD_REND, "Failed intro circ %s to %s "
+ "(building circuit to intro point). "
+ "Marking intro point as possibly unreachable.",
+ safe_str_client(rend_data_get_address(ocirc->rend_data)),
+ safe_str_client(build_state_get_exit_nickname(
+ ocirc->build_state)));
+ rend_client_report_intro_point_failure(ocirc->build_state->chosen_exit,
+ ocirc->rend_data,
+ INTRO_POINT_FAILURE_UNREACHABLE);
+ break;
+ }
+ default:
+ break;
+ }
+}
diff --git a/src/feature/rend/rendclient.h b/src/feature/rend/rendclient.h
index e5f333238e..b7aa212487 100644
--- a/src/feature/rend/rendclient.h
+++ b/src/feature/rend/rendclient.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,6 +12,7 @@
#ifndef TOR_RENDCLIENT_H
#define TOR_RENDCLIENT_H
+#include "feature/hs/hs_circuit.h"
#include "feature/rend/rendcache.h"
void rend_client_purge_state(void);
@@ -47,5 +48,7 @@ rend_service_authorization_t *rend_client_lookup_service_authorization(
const char *onion_address);
void rend_service_authorization_free_all(void);
+void rend_client_circuit_cleanup_on_free(const circuit_t *circ);
+
#endif /* !defined(TOR_RENDCLIENT_H) */
diff --git a/src/feature/rend/rendcommon.c b/src/feature/rend/rendcommon.c
index 0a606a9f02..5d04755819 100644
--- a/src/feature/rend/rendcommon.c
+++ b/src/feature/rend/rendcommon.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/rend/rendcommon.h b/src/feature/rend/rendcommon.h
index f136863c7a..d8281e0578 100644
--- a/src/feature/rend/rendcommon.h
+++ b/src/feature/rend/rendcommon.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/rend/rendmid.c b/src/feature/rend/rendmid.c
index 06471b2a7f..a473f0c7e1 100644
--- a/src/feature/rend/rendmid.c
+++ b/src/feature/rend/rendmid.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -59,7 +59,7 @@ rend_mid_establish_intro_legacy(or_circuit_t *circ, const uint8_t *request,
pk = crypto_pk_asn1_decode((char*)(request+2), asn1len);
if (!pk) {
reason = END_CIRC_REASON_TORPROTOCOL;
- log_warn(LD_PROTOCOL, "Couldn't decode public key.");
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Couldn't decode public key.");
goto err;
}
@@ -81,7 +81,7 @@ rend_mid_establish_intro_legacy(or_circuit_t *circ, const uint8_t *request,
(char*)request, 2+asn1len+DIGEST_LEN,
(char*)(request+2+DIGEST_LEN+asn1len),
request_len-(2+DIGEST_LEN+asn1len))<0) {
- log_warn(LD_PROTOCOL,
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Incorrect signature on ESTABLISH_INTRO cell; rejecting.");
reason = END_CIRC_REASON_TORPROTOCOL;
goto err;
@@ -162,9 +162,9 @@ rend_mid_introduce_legacy(or_circuit_t *circ, const uint8_t *request,
if (request_len < (DIGEST_LEN+(MAX_NICKNAME_LEN+1)+REND_COOKIE_LEN+
DH1024_KEY_LEN+CIPHER_KEY_LEN+
PKCS1_OAEP_PADDING_OVERHEAD)) {
- log_warn(LD_PROTOCOL, "Impossibly short INTRODUCE1 cell on circuit %u; "
- "responding with nack.",
- (unsigned)circ->p_circ_id);
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Impossibly short INTRODUCE1 cell on circuit %u; "
+ "responding with nack.", (unsigned)circ->p_circ_id);
goto err;
}
@@ -258,7 +258,7 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request,
}
if (circ->base_.n_chan) {
- log_warn(LD_PROTOCOL,
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Tried to establish rendezvous on non-edge circuit");
goto err;
}
@@ -270,8 +270,8 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request,
}
if (hs_circuitmap_get_rend_circ_relay_side(request)) {
- log_warn(LD_PROTOCOL,
- "Duplicate rendezvous cookie in ESTABLISH_RENDEZVOUS.");
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Duplicate rendezvous cookie in ESTABLISH_RENDEZVOUS.");
goto err;
}
@@ -313,9 +313,9 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request,
int reason = END_CIRC_REASON_INTERNAL;
if (circ->base_.purpose != CIRCUIT_PURPOSE_OR || circ->base_.n_chan) {
- log_info(LD_REND,
- "Tried to complete rendezvous on non-OR or non-edge circuit %u.",
- (unsigned)circ->p_circ_id);
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Tried to complete rendezvous on non-OR or non-edge circuit %u.",
+ (unsigned)circ->p_circ_id);
reason = END_CIRC_REASON_TORPROTOCOL;
goto err;
}
diff --git a/src/feature/rend/rendmid.h b/src/feature/rend/rendmid.h
index 8ae1fa16b8..789596d855 100644
--- a/src/feature/rend/rendmid.h
+++ b/src/feature/rend/rendmid.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/rend/rendparse.c b/src/feature/rend/rendparse.c
index a98cb3ad88..0979d767a7 100644
--- a/src/feature/rend/rendparse.c
+++ b/src/feature/rend/rendparse.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/rend/rendparse.h b/src/feature/rend/rendparse.h
index b1ccce9b6c..75109c204d 100644
--- a/src/feature/rend/rendparse.h
+++ b/src/feature/rend/rendparse.h
@@ -1,12 +1,12 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file rend_parse.h
- * \brief Header file for rend_parse.c.
+ * \file rendparse.h
+ * \brief Header file for rendparse.c.
**/
#ifndef TOR_REND_PARSE_H
diff --git a/src/feature/rend/rendservice.c b/src/feature/rend/rendservice.c
index e0cf06b9df..182e935fa1 100644
--- a/src/feature/rend/rendservice.c
+++ b/src/feature/rend/rendservice.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/rend/rendservice.h b/src/feature/rend/rendservice.h
index a8eb28bee2..8202c4fcd3 100644
--- a/src/feature/rend/rendservice.h
+++ b/src/feature/rend/rendservice.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/stats/.may_include b/src/feature/stats/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/stats/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/stats/feature_stats.md b/src/feature/stats/feature_stats.md
new file mode 100644
index 0000000000..d205fe5571
--- /dev/null
+++ b/src/feature/stats/feature_stats.md
@@ -0,0 +1,10 @@
+@dir /feature/stats
+@brief feature/stats: Relay statistics. Also, port prediction.
+
+This module collects anonymized relay statistics in order to publish them in
+relays' routerinfo and extrainfo documents.
+
+Additionally, it contains predict_ports.c, which remembers which ports we've
+visited recently as a client, so we can make sure we have open circuits that
+support them.
+
diff --git a/src/feature/stats/geoip_stats.c b/src/feature/stats/geoip_stats.c
index 6fb21f4f79..3228b18973 100644
--- a/src/feature/stats/geoip_stats.c
+++ b/src/feature/stats/geoip_stats.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/stats/geoip_stats.h b/src/feature/stats/geoip_stats.h
index 2fc62b5466..fcfe7a31f0 100644
--- a/src/feature/stats/geoip_stats.h
+++ b/src/feature/stats/geoip_stats.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,6 +13,7 @@
#define TOR_GEOIP_STATS_H
#include "core/or/dos.h"
+#include "ext/ht.h"
/** Indicates an action that we might be noting geoip statistics on.
* Note that if we're noticing CONNECT, we're a bridge, and if we're noticing
diff --git a/src/feature/stats/include.am b/src/feature/stats/include.am
new file mode 100644
index 0000000000..8789bc3d96
--- /dev/null
+++ b/src/feature/stats/include.am
@@ -0,0 +1,12 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/stats/geoip_stats.c \
+ src/feature/stats/rephist.c \
+ src/feature/stats/predict_ports.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/stats/geoip_stats.h \
+ src/feature/stats/rephist.h \
+ src/feature/stats/predict_ports.h
diff --git a/src/feature/stats/predict_ports.c b/src/feature/stats/predict_ports.c
index 3cbba2c831..d728f106a2 100644
--- a/src/feature/stats/predict_ports.c
+++ b/src/feature/stats/predict_ports.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/stats/predict_ports.h b/src/feature/stats/predict_ports.h
index 45b206c23a..ed067b6ced 100644
--- a/src/feature/stats/predict_ports.h
+++ b/src/feature/stats/predict_ports.h
@@ -1,11 +1,11 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file predict_portst.h
+ * \file predict_ports.h
* \brief Header file for predict_ports.c.
**/
diff --git a/src/feature/stats/rephist.c b/src/feature/stats/rephist.c
index 3f560fbce7..d229c755b4 100644
--- a/src/feature/stats/rephist.c
+++ b/src/feature/stats/rephist.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -1122,7 +1122,7 @@ static bw_array_t *dir_read_array = NULL;
directory protocol. */
static bw_array_t *dir_write_array = NULL;
-/** Set up [dir-]read_array and [dir-]write_array, freeing them if they
+/** Set up [dir_]read_array and [dir_]write_array, freeing them if they
* already exist. */
static void
bw_arrays_init(void)
diff --git a/src/feature/stats/rephist.h b/src/feature/stats/rephist.h
index 0d72946382..92c3d2a5a5 100644
--- a/src/feature/stats/rephist.h
+++ b/src/feature/stats/rephist.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/include.am b/src/include.am
index 065bdc31cb..f5f868d23f 100644
--- a/src/include.am
+++ b/src/include.am
@@ -1,4 +1,5 @@
include src/ext/include.am
+
include src/lib/arch/include.am
include src/lib/buf/include.am
include src/lib/err/include.am
@@ -42,6 +43,42 @@ include src/lib/version/include.am
include src/lib/wallclock/include.am
include src/trunnel/include.am
+noinst_LIBRARIES += src/core/libtor-app.a
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/core/libtor-app-testing.a
+endif
+
+LIBTOR_APP_A_SOURCES =
+#
+# Sources that we only add for the real libtor_a, and not for testing.
+#
+LIBTOR_APP_A_STUB_SOURCES =
+
+include src/core/crypto/include.am
+include src/core/mainloop/include.am
+include src/core/or/include.am
+include src/core/proto/include.am
+
+include src/feature/api/include.am
+include src/feature/client/include.am
+include src/feature/control/include.am
+include src/feature/dirauth/include.am
+include src/feature/dircache/include.am
+include src/feature/dirclient/include.am
+include src/feature/dircommon/include.am
+include src/feature/dirparse/include.am
+include src/feature/hibernate/include.am
+include src/feature/hs_common/include.am
+include src/feature/hs/include.am
+include src/feature/keymgt/include.am
+include src/feature/nodelist/include.am
+include src/feature/relay/include.am
+include src/feature/rend/include.am
+include src/feature/stats/include.am
+
+include src/app/config/include.am
+include src/app/main/include.am
+
include src/core/include.am
include src/app/include.am
diff --git a/src/lib/arch/bytes.h b/src/lib/arch/bytes.h
index 4756ca2beb..c72ac3eb8e 100644
--- a/src/lib/arch/bytes.h
+++ b/src/lib/arch/bytes.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_BYTES_H
@@ -16,12 +16,17 @@
#include <string.h>
#include "lib/cc/torint.h"
-/* The uint8 variants are defined to make the code more uniform. */
+/**
+ * Read an 8-bit from <b>cp</b>.
+ */
static inline uint8_t
get_uint8(const void *cp)
{
return *(const uint8_t*)(cp);
}
+/**
+ * Store an 8-bit value from <b>v</b> to <b>cp</b>.
+ */
static inline void
set_uint8(void *cp, uint8_t v)
{
@@ -93,7 +98,7 @@ set_uint64(void *cp, uint64_t v)
memcpy(cp,&v,8);
}
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
static inline uint16_t
tor_htons(uint32_t a)
{
@@ -130,6 +135,9 @@ tor_ntohll(uint64_t a)
return a;
}
#else /* !defined(WORDS_BIGENDIAN) */
+/**
+ * Convert a 16-bit value from host order to network order (big-endian).
+ **/
static inline uint16_t
tor_htons(uint16_t a)
{
@@ -139,12 +147,18 @@ tor_htons(uint16_t a)
((a & 0xff00) >> 8);
}
+/**
+ * Convert a 16-bit value from network order (big-endian) to host order.
+ **/
static inline uint16_t
tor_ntohs(uint16_t a)
{
return tor_htons(a);
}
+/**
+ * Convert a 32-bit value from host order to network order (big-endian).
+ **/
static inline uint32_t
tor_htonl(uint32_t a)
{
@@ -156,6 +170,9 @@ tor_htonl(uint32_t a)
((a & 0xff000000) >>24);
}
+/**
+ * Convert a 32-bit value from network order (big-endian) to host order.
+ **/
static inline uint32_t
tor_ntohl(uint32_t a)
{
diff --git a/src/lib/arch/lib_arch.md b/src/lib/arch/lib_arch.md
new file mode 100644
index 0000000000..9b8bccdf16
--- /dev/null
+++ b/src/lib/arch/lib_arch.md
@@ -0,0 +1,2 @@
+@dir /lib/arch
+@brief lib/arch: Compatibility code for handling different CPU architectures.
diff --git a/src/lib/buf/buffers.c b/src/lib/buf/buffers.c
index ace5bdc4a4..d7b73e3807 100644
--- a/src/lib/buf/buffers.c
+++ b/src/lib/buf/buffers.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -99,6 +99,7 @@
#define DBG_S(s) (void)0
#endif
+#ifndef COCCI
#ifdef DISABLE_MEMORY_SENTINELS
#define CHUNK_SET_SENTINEL(chunk, alloclen) STMT_NIL
#else
@@ -109,6 +110,7 @@
memset(a,0,SENTINEL_LEN); \
} while (0)
#endif /* defined(DISABLE_MEMORY_SENTINELS) */
+#endif /* !defined(COCCI) */
/** Move all bytes stored in <b>chunk</b> to the front of <b>chunk</b>->mem,
* to free up space at the end. */
@@ -578,6 +580,7 @@ buf_add_vprintf(buf_t *buf, const char *format, va_list args)
/* XXXX Faster implementations are easy enough, but let's optimize later */
char *tmp;
tor_vasprintf(&tmp, format, args);
+ tor_assert(tmp != NULL);
buf_add(buf, tmp, strlen(tmp));
tor_free(tmp);
}
diff --git a/src/lib/buf/buffers.h b/src/lib/buf/buffers.h
index c103b93a82..fadd4174c0 100644
--- a/src/lib/buf/buffers.h
+++ b/src/lib/buf/buffers.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/buf/lib_buf.md b/src/lib/buf/lib_buf.md
new file mode 100644
index 0000000000..519ab50a2d
--- /dev/null
+++ b/src/lib/buf/lib_buf.md
@@ -0,0 +1,13 @@
+@dir /lib/buf
+@brief lib/buf: An efficient byte queue.
+
+This module defines the buf_t type, which is used throughout our networking
+code. The implementation is a singly-linked queue of buffer chunks, similar
+to the BSD kernel's
+["mbuf"](https://www.freebsd.org/cgi/man.cgi?query=mbuf&sektion=9) structure.
+
+The buf_t type is also reasonable for use in constructing long strings.
+
+See \refdir{lib/net} for networking code that uses buf_t, and
+\refdir{lib/tls} for cryptographic code that uses buf_t.
+
diff --git a/src/lib/cc/compat_compiler.h b/src/lib/cc/compat_compiler.h
index d9ccabb2b3..015b5af320 100644
--- a/src/lib/cc/compat_compiler.h
+++ b/src/lib/cc/compat_compiler.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -65,8 +65,6 @@
/* Temporarily enable and disable warnings. */
#ifdef __GNUC__
-# define PRAGMA_STRINGIFY_(s) #s
-# define PRAGMA_JOIN_STRINGIFY_(a,b) PRAGMA_STRINGIFY_(a ## b)
/* Support for macro-generated pragmas (c99) */
# define PRAGMA_(x) _Pragma (#x)
# ifdef __clang__
@@ -78,15 +76,15 @@
/* we have push/pop support */
# define DISABLE_GCC_WARNING(warningopt) \
PRAGMA_DIAGNOSTIC_(push) \
- PRAGMA_DIAGNOSTIC_(ignored PRAGMA_JOIN_STRINGIFY_(-W,warningopt))
+ PRAGMA_DIAGNOSTIC_(ignored warningopt)
# define ENABLE_GCC_WARNING(warningopt) \
PRAGMA_DIAGNOSTIC_(pop)
#else /* !(defined(__clang__) || GCC_VERSION >= 406) */
/* older version of gcc: no push/pop support. */
# define DISABLE_GCC_WARNING(warningopt) \
- PRAGMA_DIAGNOSTIC_(ignored PRAGMA_JOIN_STRINGIFY_(-W,warningopt))
+ PRAGMA_DIAGNOSTIC_(ignored warningopt)
# define ENABLE_GCC_WARNING(warningopt) \
- PRAGMA_DIAGNOSTIC_(warning PRAGMA_JOIN_STRINGIFY_(-W,warningopt))
+ PRAGMA_DIAGNOSTIC_(warning warningopt)
#endif /* defined(__clang__) || GCC_VERSION >= 406 */
#else /* !defined(__GNUC__) */
/* not gcc at all */
@@ -200,8 +198,8 @@
/** Macro: yield a pointer to the field at position <b>off</b> within the
* structure <b>st</b>. Example:
* <pre>
- * struct a { int foo; int bar; } x;
- * ptrdiff_t bar_offset = offsetof(struct a, bar);
+ * struct a_t { int foo; int bar; } x;
+ * ptrdiff_t bar_offset = offsetof(struct a_t, bar);
* int *bar_p = STRUCT_VAR_P(&x, bar_offset);
* *bar_p = 3;
* </pre>
@@ -211,10 +209,10 @@
/** Macro: yield a pointer to an enclosing structure given a pointer to
* a substructure at offset <b>off</b>. Example:
* <pre>
- * struct base { ... };
- * struct subtype { int x; struct base b; } x;
- * struct base *bp = &x.base;
- * struct *sp = SUBTYPE_P(bp, struct subtype, b);
+ * struct base_t { ... };
+ * struct subtype_t { int x; struct base_t b; } x;
+ * struct base_t *bp = &x.base;
+ * struct *sp = SUBTYPE_P(bp, struct subtype_t, b);
* </pre>
*/
#define SUBTYPE_P(p, subtype, basemember) \
@@ -235,4 +233,17 @@
#define EAT_SEMICOLON \
struct dummy_semicolon_eater__
+/**
+ * Tell our static analysis tool to believe that (clang's scan-build or
+ * coverity scan) that an expression might be true. We use this to suppress
+ * dead-code warnings.
+ **/
+#if defined(__COVERITY__) || defined(__clang_analyzer__)
+/* By calling getenv, we force the analyzer not to conclude that 'expr' is
+ * false. */
+#define POSSIBLE(expr) ((expr) || getenv("STATIC_ANALYZER_DEADCODE_DUMMY_"))
+#else
+#define POSSIBLE(expr) (expr)
+#endif /* defined(__COVERITY__) || defined(__clang_analyzer__) */
+
#endif /* !defined(TOR_COMPAT_COMPILER_H) */
diff --git a/src/lib/cc/ctassert.h b/src/lib/cc/ctassert.h
index bedf0b83a6..d9d3aa40b0 100644
--- a/src/lib/cc/ctassert.h
+++ b/src/lib/cc/ctassert.h
@@ -46,7 +46,7 @@
#define CTASSERT_EXPN(x, a, b) CTASSERT_DECL(x, a, b)
#define CTASSERT_DECL(x, a, b) \
- typedef char tor_ctassert_##a##_##b[(x) ? 1 : -1] ATTR_UNUSED
+ typedef char tor_ctassert_##a##_##b[(x) ? 1 : -1] ATTR_UNUSED; EAT_SEMICOLON
#endif /* __STDC_VERSION__ >= 201112L */
diff --git a/src/lib/cc/include.am b/src/lib/cc/include.am
index 1aa722dd82..d2a415e956 100644
--- a/src/lib/cc/include.am
+++ b/src/lib/cc/include.am
@@ -3,4 +3,5 @@
noinst_HEADERS += \
src/lib/cc/compat_compiler.h \
src/lib/cc/ctassert.h \
+ src/lib/cc/tokpaste.h \
src/lib/cc/torint.h
diff --git a/src/lib/cc/lib_cc.md b/src/lib/cc/lib_cc.md
new file mode 100644
index 0000000000..bd49005ba2
--- /dev/null
+++ b/src/lib/cc/lib_cc.md
@@ -0,0 +1,2 @@
+@dir /lib/cc
+@brief lib/cc: Macros for managing the C compiler and language.
diff --git a/src/lib/cc/tokpaste.h b/src/lib/cc/tokpaste.h
new file mode 100644
index 0000000000..068621b5bd
--- /dev/null
+++ b/src/lib/cc/tokpaste.h
@@ -0,0 +1,30 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file tokpaste.h
+ * @brief Token-pasting macros.
+ **/
+
+#ifndef TOR_LIB_CC_TOKPASTE_H
+#define TOR_LIB_CC_TOKPASTE_H
+
+/**
+ * Concatenate `a` and `b` in a way that allows their result itself to be
+ * expanded by the preprocessor.
+ *
+ * Ordinarily you could just say `a ## b` in a macro definition. But doing so
+ * results in a symbol which the preprocessor will not then expand. If you
+ * wanted to use `a ## b` to create the name of a macro and have the
+ * preprocessor expand _that_ macro, you need to have another level of
+ * indirection, as this macro provides.
+ **/
+#define PASTE(a,b) PASTE__(a,b)
+
+/** Helper for PASTE(). */
+#define PASTE__(a,b) a ## b
+
+#endif /* !defined(TOR_LIB_CC_TOKPASTE_H) */
diff --git a/src/lib/cc/torint.h b/src/lib/cc/torint.h
index 94b79d30a1..cef1482bdc 100644
--- a/src/lib/cc/torint.h
+++ b/src/lib/cc/torint.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/compress.c b/src/lib/compress/compress.c
index 51591410a2..c62d7d5d2a 100644
--- a/src/lib/compress/compress.c
+++ b/src/lib/compress/compress.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/compress.h b/src/lib/compress/compress.h
index 8cea4ead60..f36cdb82aa 100644
--- a/src/lib/compress/compress.h
+++ b/src/lib/compress/compress.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/compress_buf.c b/src/lib/compress/compress_buf.c
index 2e704466f2..d1941c9da6 100644
--- a/src/lib/compress/compress_buf.c
+++ b/src/lib/compress/compress_buf.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/compress_lzma.c b/src/lib/compress/compress_lzma.c
index 915f4949ae..8884b020e8 100644
--- a/src/lib/compress/compress_lzma.c
+++ b/src/lib/compress/compress_lzma.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/compress_lzma.h b/src/lib/compress/compress_lzma.h
index 556ab437dc..de03cda91c 100644
--- a/src/lib/compress/compress_lzma.h
+++ b/src/lib/compress/compress_lzma.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/compress_none.c b/src/lib/compress/compress_none.c
index 0b5760773a..43c021c788 100644
--- a/src/lib/compress/compress_none.c
+++ b/src/lib/compress/compress_none.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/compress_none.h b/src/lib/compress/compress_none.h
index 2bb9c3d66c..df696a11aa 100644
--- a/src/lib/compress/compress_none.h
+++ b/src/lib/compress/compress_none.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/compress_sys.h b/src/lib/compress/compress_sys.h
index 6181072315..dce0549924 100644
--- a/src/lib/compress/compress_sys.h
+++ b/src/lib/compress/compress_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/compress_zlib.c b/src/lib/compress/compress_zlib.c
index df0d1bff5f..3711e46222 100644
--- a/src/lib/compress/compress_zlib.c
+++ b/src/lib/compress/compress_zlib.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/compress_zlib.h b/src/lib/compress/compress_zlib.h
index e4f248cd9b..7328ce899b 100644
--- a/src/lib/compress/compress_zlib.h
+++ b/src/lib/compress/compress_zlib.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/compress_zstd.c b/src/lib/compress/compress_zstd.c
index 9076665295..5913d823e1 100644
--- a/src/lib/compress/compress_zstd.c
+++ b/src/lib/compress/compress_zstd.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -29,11 +29,11 @@
#ifdef HAVE_ZSTD
#ifdef HAVE_CFLAG_WUNUSED_CONST_VARIABLE
-DISABLE_GCC_WARNING(unused-const-variable)
+DISABLE_GCC_WARNING("-Wunused-const-variable")
#endif
#include <zstd.h>
#ifdef HAVE_CFLAG_WUNUSED_CONST_VARIABLE
-ENABLE_GCC_WARNING(unused-const-variable)
+ENABLE_GCC_WARNING("-Wunused-const-variable")
#endif
#endif /* defined(HAVE_ZSTD) */
diff --git a/src/lib/compress/compress_zstd.h b/src/lib/compress/compress_zstd.h
index 47f950b9e0..0fc71db749 100644
--- a/src/lib/compress/compress_zstd.h
+++ b/src/lib/compress/compress_zstd.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/lib_compress.md b/src/lib/compress/lib_compress.md
new file mode 100644
index 0000000000..c43f223fe7
--- /dev/null
+++ b/src/lib/compress/lib_compress.md
@@ -0,0 +1,6 @@
+@dir /lib/compress
+@brief lib/compress: Wraps several compression libraries
+
+Currently supported are zlib (mandatory), zstd (optional), and lzma
+(optional).
+
diff --git a/src/lib/conf/confdecl.h b/src/lib/conf/confdecl.h
new file mode 100644
index 0000000000..c2d3fb335d
--- /dev/null
+++ b/src/lib/conf/confdecl.h
@@ -0,0 +1,221 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file confdecl.h
+ * @brief Macros for generating a configuration struct from a list
+ * of its individual fields.
+ *
+ * This header defines three important macros: BEGIN_CONF_STRUCT(),
+ * END_CONF_STRUCT(), and CONF_VAR(). They're meant to be used together to
+ * define a configuration structure and the means for encoding and decoding
+ * it.
+ *
+ * To use them, make a new header with a name like `MOD_options.inc`. Start
+ * it with a BEGIN_CONF_STRUCT(), then define your variables with CONF_VAR(),
+ * then end the header with END_CONF_STRUCT(), as in:
+ *
+ * BEGIN_CONF_STRUCT(module_options_t)
+ * CONF_VAR(ModuleIsActive, BOOLEAN, 0, "1")
+ * END_CONF_STRUCT(module_options_t)
+ *
+ * Once you've done that, you can use that header to define a configuration
+ * structure by saying:
+ *
+ * typedef struct module_options_t module_options_t;
+ * #define CONF_CONTEXT STRUCT
+ * #include "MOD_options.inc"
+ * #undef CONF_CONTEXT
+ *
+ * And you can define your field definition table by saying:
+ *
+ * #define CONF_CONTEXT TABLE
+ * #include "MOD_options.inc"
+ * #undef CONF_CONTEXT
+ *
+ * The two above snippets will define a structure called `module_options_t`
+ * with appropriate members, and a table of config_var_t objects called
+ * `module_options_t_vars[]`.
+ *
+ * For lower-level modules, you can say <tt>\#define CONF_TABLE LL_TABLE</tt>,
+ * and get a table definition suitable for use in modules that are at a lower
+ * level than lib/confmgt. Note that the types for these tables cannot
+ * include any extended types.
+ **/
+
+#ifndef TOR_LIB_CONF_CONFDECL_H
+#define TOR_LIB_CONF_CONFDECL_H
+
+#undef CONF_CONTEXT
+#include "lib/cc/tokpaste.h"
+#include "lib/cc/torint.h"
+
+/**
+ * Begin the definition of a configuration object called `name`.
+ **/
+#define BEGIN_CONF_STRUCT(name) \
+ PASTE(BEGIN_CONF_STRUCT__, CONF_CONTEXT)(name)
+/**
+ * End the definition of a configuration object called `name`.
+ **/
+#define END_CONF_STRUCT(name) \
+ PASTE(END_CONF_STRUCT__, CONF_CONTEXT)(name)
+/**
+ * Declare a single configuration field with name `varname`, type `vartype`,
+ * flags `varflags`, and initial value `initval`.
+ **/
+#define CONF_VAR(varname, vartype, varflags, initval) \
+ PASTE(CONF_VAR__, CONF_CONTEXT)(varname, vartype, varflags, initval)
+
+#ifndef COCCI
+/**
+ * @defgroup STRUCT_MACROS Internal macros: struct definitions.
+ * Implementation helpers: the regular confdecl macros expand to these
+ * when CONF_CONTEXT is defined to STRUCT. Don't use them directly.
+ * @{*/
+#define BEGIN_CONF_STRUCT__STRUCT(name) \
+ struct name { \
+ uint32_t magic;
+#define END_CONF_STRUCT__STRUCT(name) \
+ };
+#define CONF_VAR__STRUCT(varname, vartype, varflags, initval) \
+ config_decl_ ## vartype varname;
+/** @} */
+
+/**
+ * @defgroup TABLE_MACROS Internal macros: table definitions.
+ * Implementation helpers: the regular confdecl macros expand to these
+ * when CONF_CONTEXT is defined to TABLE. Don't use them directly.
+ * @{*/
+#define BEGIN_CONF_STRUCT__TABLE(structname) \
+ /* We use this typedef so we can refer to the config type */ \
+ /* without having its name as a macro argument to CONF_VAR. */ \
+ typedef struct structname config_var_reference__obj; \
+ static const config_var_t structname##_vars[] = {
+#define END_CONF_STRUCT__TABLE(structname) \
+ { .member = { .name = NULL } } \
+ };
+#define CONF_VAR__TABLE(varname, vartype, varflags, initval) \
+ { \
+ .member = \
+ { .name = #varname, \
+ .type = CONFIG_TYPE_EXTENDED, \
+ .type_def = &vartype ## _type_defn, \
+ .offset=offsetof(config_var_reference__obj, varname), \
+ }, \
+ .flags = varflags, \
+ .initvalue = initval \
+ },
+/**@}*/
+
+/**
+ * @defgroup LL_TABLE_MACROS Internal macros: low-level table definitions.
+ * Implementation helpers: the regular confdecl macros expand to these
+ * when CONF_CONTEXT is defined to LL_TABLE. Don't use them directly.
+ * @{*/
+#define BEGIN_CONF_STRUCT__LL_TABLE(structname) \
+ /* We use this typedef so we can refer to the config type */ \
+ /* without having its name as a macro argument to CONF_VAR. */ \
+ typedef struct structname config_var_reference__obj; \
+ static const config_var_t structname##_vars[] = {
+#define END_CONF_STRUCT__LL_TABLE(structname) \
+ { .member = { .name = NULL } } \
+ };
+#define CONF_VAR__LL_TABLE(varname, vartype, varflags, initval) \
+ { \
+ .member = \
+ { .name = #varname, \
+ .type = CONFIG_TYPE_ ## vartype, \
+ .offset=offsetof(config_var_reference__obj, varname), \
+ }, \
+ .flags = varflags, \
+ .initvalue = initval \
+ },
+/**@}*/
+
+/** @defgroup STUB_TABLE_MACROS Internal macros: stub table declarations,
+ * for use when a module is disabled.
+ * Implementation helpers: the regular confdecl macros expand to these
+ * when CONF_CONTEXT is defined to LL_TABLE. Don't use them directly.
+ * @{ */
+#define BEGIN_CONF_STRUCT__STUB_TABLE(structname) \
+ static const config_var_t structname##_vars[] = {
+#define END_CONF_STRUCT__STUB_TABLE(structname) \
+ { .member = { .name = NULL } } \
+ };
+#define CONF_VAR__STUB_TABLE(varname, vartype, varflags, initval) \
+ { \
+ .member = \
+ { .name = #varname, \
+ .type = CONFIG_TYPE_IGNORE, \
+ .offset = -1, \
+ }, \
+ .flags = CFLG_GROUP_DISABLED, \
+ },
+/**@}*/
+
+#endif /* !defined(COCCI) */
+
+/** Type aliases for the "commonly used" configuration types.
+ *
+ * Defining them in this way allows our CONF_VAR__STRUCT() macro to declare
+ * structure members corresponding to the configuration types. For example,
+ * when the macro sees us declare a configuration option "foo" of type STRING,
+ * it can emit `config_decl_STRING foo;`, which is an alias for `char *foo`.
+ */
+/**@{*/
+typedef char *config_decl_STRING;
+typedef char *config_decl_FILENAME;
+/* Yes, "POSINT" is really an int, and not an unsigned int. For
+ * historical reasons, many configuration values are restricted
+ * to the range [0,INT_MAX], and stored in signed ints.
+ */
+typedef int config_decl_POSINT;
+typedef uint64_t config_decl_UINT64;
+typedef int config_decl_INT;
+typedef int config_decl_INTERVAL;
+typedef int config_decl_MSEC_INTERVAL;
+typedef uint64_t config_decl_MEMUNIT;
+typedef double config_decl_DOUBLE;
+typedef int config_decl_BOOL;
+typedef int config_decl_AUTOBOOL;
+typedef time_t config_decl_ISOTIME;
+typedef struct smartlist_t config_decl_CSV;
+typedef int config_decl_CSV_INTERVAL;
+typedef struct config_line_t *config_decl_LINELIST;
+typedef struct config_line_t *config_decl_LINELIST_V;
+typedef struct nonexistent_struct *config_decl_LINELIST_S;
+/**@}*/
+
+struct var_type_def_t;
+
+/* Forward declarations for configuration type definitions. These are used by
+ * the CONF_VAR__TABLE macro to set the definition of each variable type
+ * correctly.
+ */
+/**@{*/
+extern const struct var_type_def_t STRING_type_defn;
+extern const struct var_type_def_t FILENAME_type_defn;
+extern const struct var_type_def_t POSINT_type_defn;
+extern const struct var_type_def_t UINT64_type_defn;
+extern const struct var_type_def_t INT_type_defn;
+extern const struct var_type_def_t INTERVAL_type_defn;
+extern const struct var_type_def_t MSEC_INTERVAL_type_defn;
+extern const struct var_type_def_t MEMUNIT_type_defn;
+extern const struct var_type_def_t DOUBLE_type_defn;
+extern const struct var_type_def_t BOOL_type_defn;
+extern const struct var_type_def_t AUTOBOOL_type_defn;
+extern const struct var_type_def_t ISOTIME_type_defn;
+extern const struct var_type_def_t CSV_type_defn;
+extern const struct var_type_def_t CSV_INTERVAL_type_defn;
+extern const struct var_type_def_t LINELIST_type_defn;
+extern const struct var_type_def_t LINELIST_V_type_defn;
+extern const struct var_type_def_t LINELIST_S_type_defn;
+extern const struct var_type_def_t IGNORE_type_defn;
+extern const struct var_type_def_t OBSOLETE_type_defn;
+/**@}*/
+
+#endif /* !defined(TOR_LIB_CONF_CONFDECL_H) */
diff --git a/src/lib/conf/config.md b/src/lib/conf/config.md
new file mode 100644
index 0000000000..7741e21f42
--- /dev/null
+++ b/src/lib/conf/config.md
@@ -0,0 +1,126 @@
+
+@page configuration Configuration options and persistent state
+
+@tableofcontents
+
+## Introduction
+
+Tor uses a shared, table-driven mechanism to handle its
+configuration (torrc) files and its state files. Each module can
+declare a set of named fields for these files, and get notified
+whenever the configuration changes, or when the state is about to be
+flushed to disk.
+
+## Declaring options
+
+Most modules will only need to use the macros in confdecl.h to
+declare a configuration or state structure.
+
+You'll write something like this:
+
+ // my_module_config.inc
+ BEGIN_CONF_STRUCT(module_options_t)
+ CONF_VAR(FieldOne, INT, 0, "7")
+ CONF_VAR(FieldTwo, STRING, 0, NULL)
+ END_CONF_STRUCT(module_options_t)
+
+The above example will result in a structure called module_config_t
+with two fields: one an integer called FieldOne and one a string
+called FieldTwo. The integer gets a default value of 7; the
+string's default value is NULL.
+
+After making a definition file like that, you include it twice: once
+in a header, after saying \#define CONF_CONTEXT STRUCT, and once in
+a C file, after saying \#define CONF_CONTEXT TABLE. The first time
+defines a module_options_t structure, and the second time defines a
+table that tells the configuration manager how to use it.
+
+Using the table, you declare a `const` config_format_t, which
+associates the fields with a set of functions for validating and
+normalizing them, a list of abbreviations and deprecations, and
+other features.
+
+See confdecl.h and conftypes.h for more information. For example
+usage, see crypto_options.inc or mainloop_state.inc.
+
+## Getting notifications
+
+After using those macros, you must tell the subsystem management
+code about your module's configuration/state.
+
+If you're writing configuration code, you'll need a function that receives
+the configuration object, and acts upon it. This function needs to be safe
+to call multiple times, since Tor will reconfigure its subsystems whenever it
+re-reads the torrc, gets a configuration change from a controller, or
+restarts in process. This function goes in your subsystem's
+subsys_fns_t.set_options field.
+
+If you're writing state code, you'll need a function that receives
+state (subsys_fns_t.set_state), and a function that flushes the
+application state into a state object (subsys_fns_t.flush_state).
+The `set_state` function will be called once (@ref config_once_per
+"1") when Tor is starting, whereas the `flush_state` function will
+be called whenever Tor is about to save the state to disk.
+
+See subsys_fns_t for more information here, and \ref initialization
+for more information about initialization and subsystems in general.
+
+> @anchor config_once_per 1. Technically, state is set once _per startup_.
+> Remember that Tor can be stopped and started multiple times in
+> the same process. If this happens, then your set_state() function
+> is called once every time Tor starts.
+
+## How it works
+
+The common logic used to handle configuration and state files lives
+in @refdir{lib/confmgt}. At the highest level, a configuration
+manager object (config_mgr_t) maintains a list of each module's
+configuration objects, and a list of all their fields. When the
+user specifies a configuration value, the manager finds out how to
+parse it, where to store it, and which configuration object is
+affected.
+
+The top-level configuration module (config.c) and state module
+(statefile.c) use config_mgr_t to create, initialize, set, compare,
+and free a "top level configuration object". This object contains a
+list of sub-objects: one for each module that participates in the
+configuration/state system. This top-level code then invokes the
+subsystem manager code (subsysmgr.c) to pass the corresponding
+configuration or state objects to each module that has one.
+
+Note that the top level code does not have easy access to the
+configuration objects used by the sub-modules. This is by design. A
+module _may_ expose some or all of its configuration or state object via
+accessor functions, if it likes, but if it does not, that object should
+be considered module-local.
+
+## Adding new types
+
+Configuration and state fields each have a "type". These types
+specify how the fields' values are represented in C; how they are
+stored in files; and how they are encoded back and forth.
+
+There is a set of built-in types listed in conftypes.h, but
+higher-level code can define its own types. To do so, you make an
+instance of var_type_fns_t that describes how to manage your type,
+and an instance of var_type_def_t that wraps your var_type_fns_t
+with a name and optional parameters and flags.
+
+For an example of how a higher-level type is defined, see
+ROUTERSET_type_defn in routerset.c. Also see the typedef
+`config_decl_ROUTERSET`. Together, these let the routerset type be
+used with the macros in confdecl.h.
+
+## Legacy configuration and state
+
+As of this writing (November 2019), most of the configuration and state is
+still handled directly in config.c and statefile.c, and stored in the
+monolithic structures or_options_t and or_state_t respectively.
+
+These top-level structures are accessed with get_options() and
+get_state(), and used throughout much of the code, at the level of
+@refdir{core} and higher.
+
+With time we hope to refactor this configuration into more
+reasonable pieces, so that they are no longer (effectively) global
+variables used throughout the code.
diff --git a/src/lib/conf/confmacros.h b/src/lib/conf/confmacros.h
index 68121891f1..9f85d21740 100644
--- a/src/lib/conf/confmacros.h
+++ b/src/lib/conf/confmacros.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,11 +15,13 @@
#include "orconfig.h"
#include "lib/conf/conftesting.h"
+#ifndef COCCI
/**
* Used to indicate the end of an array of configuration variables.
**/
#define END_OF_CONFIG_VARS \
{ .member = { .name = NULL } DUMMY_CONF_TEST_MEMBERS }
+#endif /* !defined(COCCI) */
/**
* Declare a config_var_t as a member named <b>membername</b> of the structure
@@ -43,7 +45,7 @@
}
/**
- * As CONFIG_VAR_XTYPE, but declares a value using an extension type whose
+ * As CONFIG_VAR_ETYPE, but declares a value using an extension type whose
* type definition is <b>vartype</b>_type_defn.
**/
#define CONFIG_VAR_DEFN(structtype, varname, vartype, membername, \
@@ -59,6 +61,9 @@
CONF_TEST_MEMBERS(structtype, vartype, membername) \
}
+/**
+ * Declare an obsolete configuration variable with a given name.
+ **/
#define CONFIG_VAR_OBSOLETE(varname) \
{ .member = { .name = varname, .type = CONFIG_TYPE_OBSOLETE }, \
.flags = CFLG_GROUP_OBSOLETE \
diff --git a/src/lib/conf/conftesting.h b/src/lib/conf/conftesting.h
index f01f52d59e..4707c919d3 100644
--- a/src/lib/conf/conftesting.h
+++ b/src/lib/conf/conftesting.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,10 +12,14 @@
#ifndef TOR_LIB_CONF_CONFTESTING_H
#define TOR_LIB_CONF_CONFTESTING_H
+#include "lib/cc/torint.h"
+
+#ifndef COCCI
#ifdef TOR_UNIT_TESTS
+#define USE_CONF_TESTING
/**
* Union used when building in test mode typechecking the members of a type
- * used with confparse.c. See CONF_CHECK_VAR_TYPE for a description of how
+ * used with confmgt.c. See CONF_CHECK_VAR_TYPE for a description of how
* it is used. */
typedef union {
char **STRING;
@@ -41,13 +45,11 @@ typedef union {
// XXXX this doesn't belong at this level of abstraction.
struct routerset_t **ROUTERSET;
} confparse_dummy_values_t;
-#endif /* defined(TOR_UNIT_TESTS) */
/* Macros to define extra members inside config_var_t fields, and at the
* end of a list of them.
*/
-#ifdef TOR_UNIT_TESTS
-/* This is a somewhat magic type-checking macro for users of confparse.c.
+/* This is a somewhat magic type-checking macro for users of confmgt.c.
* It initializes a union member "confparse_dummy_values_t.conftype" with
* the address of a static member "tp_dummy.member". This
* will give a compiler warning unless the member field is of the correct
@@ -72,15 +74,16 @@ typedef union {
#define DUMMY_CONF_TEST_MEMBERS , .var_ptr_dummy={ .INT=NULL }
#define DUMMY_TYPECHECK_INSTANCE(tp) \
static tp tp ## _dummy
+#endif /* defined(TOR_UNIT_TESTS) */
+#endif /* !defined(COCCI) */
-#else /* !defined(TOR_UNIT_TESTS) */
-
+#ifndef USE_CONF_TESTING
#define CONF_TEST_MEMBERS(tp, conftype, member)
/* Repeatedly declarable incomplete struct to absorb redundant semicolons */
#define DUMMY_TYPECHECK_INSTANCE(tp) \
struct tor_semicolon_eater
#define DUMMY_CONF_TEST_MEMBERS
-#endif /* defined(TOR_UNIT_TESTS) */
+#endif /* !defined(USE_CONF_TESTING) */
#endif /* !defined(TOR_LIB_CONF_CONFTESTING_H) */
diff --git a/src/lib/conf/conftypes.h b/src/lib/conf/conftypes.h
index 274065cff2..ebc2736aaa 100644
--- a/src/lib/conf/conftypes.h
+++ b/src/lib/conf/conftypes.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -64,7 +64,18 @@ typedef enum config_type_t {
CONFIG_TYPE_LINELIST_V, /**< Catch-all "virtual" option to summarize
* context-sensitive config lines when fetching.
*/
- CONFIG_TYPE_OBSOLETE, /**< Obsolete (ignored) option. */
+ /** Ignored (obsolete) option. Uses no storage.
+ *
+ * Reported as "obsolete" when its type is queried.
+ */
+ CONFIG_TYPE_OBSOLETE,
+ /** Ignored option. Uses no storage.
+ *
+ * Reported as "ignored" when its type is queried. For use with options used
+ * by disabled modules.
+ **/
+ CONFIG_TYPE_IGNORE,
+
/**
* Extended type: definition appears in the <b>type_def</b> pointer
* of the corresponding struct_member_t.
@@ -120,6 +131,9 @@ typedef struct struct_member_t {
*
* These 'magic numbers' are 32-bit values used to tag objects to make sure
* that they have the correct type.
+ *
+ * If all fields in this structure are zero or 0, the magic-number check is
+ * not performed.
*/
typedef struct struct_magic_decl_t {
/** The name of the structure */
@@ -178,12 +192,35 @@ typedef struct struct_magic_decl_t {
* however, setting them appends to their old value.
*/
#define CFLG_NOREPLACE (1u<<5)
+/**
+ * Flag to indicate that an option or type cannot be changed while Tor is
+ * running.
+ **/
+#define CFLG_IMMUTABLE (1u<<6)
+/**
+ * Flag to indicate that we should warn that an option or type is obsolete
+ * whenever the user tries to use it.
+ **/
+#define CFLG_WARN_OBSOLETE (1u<<7)
+/**
+ * Flag to indicate that we should warn that an option applies only to
+ * a disabled module, whenever the user tries to use it.
+ **/
+#define CFLG_WARN_DISABLED (1u<<8)
/**
* A group of flags that should be set on all obsolete options and types.
**/
#define CFLG_GROUP_OBSOLETE \
- (CFLG_NOCOPY|CFLG_NOCMP|CFLG_NODUMP|CFLG_NOSET|CFLG_NOLIST)
+ (CFLG_NOCOPY|CFLG_NOCMP|CFLG_NODUMP|CFLG_NOSET|CFLG_NOLIST|\
+ CFLG_WARN_OBSOLETE)
+
+/**
+ * A group of fflags that should be set on all disabled options.
+ **/
+#define CFLG_GROUP_DISABLED \
+ (CFLG_NOCOPY|CFLG_NOCMP|CFLG_NODUMP|CFLG_NOSET|CFLG_NOLIST|\
+ CFLG_WARN_DISABLED)
/** A variable allowed in the configuration file or on the command line. */
typedef struct config_var_t {
@@ -199,4 +236,146 @@ typedef struct config_var_t {
#endif
} config_var_t;
+/**
+ * An abbreviation or alias for a configuration option.
+ **/
+typedef struct config_abbrev_t {
+ /** The option name as abbreviated. Not case-sensitive. */
+ const char *abbreviated;
+ /** The full name of the option. Not case-sensitive. */
+ const char *full;
+ /** True if this abbreviation should only be allowed on the command line. */
+ int commandline_only;
+ /** True if we should warn whenever this abbreviation is used. */
+ int warn;
+} config_abbrev_t;
+
+/**
+ * A note that a configuration option is deprecated, with an explanation why.
+ */
+typedef struct config_deprecation_t {
+ /** The option that is deprecated. */
+ const char *name;
+ /** A user-facing string explaining why the option is deprecated. */
+ const char *why_deprecated;
+} config_deprecation_t;
+
+/**
+ * Handy macro for declaring "In the config file or on the command line, you
+ * can abbreviate <b>tok</b>s as <b>tok</b>". Used inside an array of
+ * config_abbrev_t.
+ *
+ * For example, to declare "NumCpu" as an abbreviation for "NumCPUs",
+ * you can say PLURAL(NumCpu).
+ **/
+#define PLURAL(tok) { #tok, #tok "s", 0, 0 }
+
+/**
+ * Validation function: verify whether a configuation object is well-formed
+ * and consistent.
+ *
+ * On success, return 0. On failure, set <b>msg_out</b> to a newly allocated
+ * string containing an error message, and return -1. */
+typedef int (*validate_fn_t)(const void *value, char **msg_out);
+/**
+ * Validation function: verify whether a configuration object (`value`) is an
+ * allowable value given the previous configuration value (`old_value`).
+ *
+ * On success, return 0. On failure, set <b>msg_out</b> to a newly allocated
+ * string containing an error message, and return -1. */
+typedef int (*check_transition_fn_t)(const void *old_value, const void *value,
+ char **msg_out);
+/**
+ * Validation function: normalize members of `value`, and compute derived
+ * members.
+ *
+ * This function is called before any other validation of `value`, and must
+ * not assume that validate_fn or check_transition_fn has passed.
+ *
+ * On success, return 0. On failure, set <b>msg_out</b> to a newly allocated
+ * string containing an error message, and return -1. */
+typedef int (*pre_normalize_fn_t)(void *value, char **msg_out);
+/**
+ * Validation function: normalize members of `value`, and compute derived
+ * members.
+ *
+ * This function is called after validation of `value`, and may
+ * assume that validate_fn or check_transition_fn has passed.
+ *
+ * On success, return 0. On failure, set <b>msg_out</b> to a newly allocated
+ * string containing an error message, and return -1. */
+typedef int (*post_normalize_fn_t)(void *value, char **msg_out);
+
+/**
+ * Legacy function to validate whether a given configuration is
+ * well-formed and consistent.
+ *
+ * The configuration to validate is passed as <b>newval</b>. The previous
+ * configuration, if any, is provided in <b>oldval</b>.
+ *
+ * This API is deprecated, since it mixes the responsibilities of
+ * pre_normalize_fn_t, post_normalize_fn_t, validate_fn_t, and
+ * check_transition_fn_t. No new instances of this function type should
+ * be written.
+ *
+ * On success, return 0. On failure, set *<b>msg_out</b> to a newly allocated
+ * error message, and return -1.
+ */
+typedef int (*legacy_validate_fn_t)(const void *oldval,
+ void *newval,
+ char **msg_out);
+
+struct config_mgr_t;
+
+/**
+ * Callback to clear all non-managed fields of a configuration object.
+ *
+ * <b>obj</b> is the configuration object whose non-managed fields should be
+ * cleared.
+ *
+ * (Regular fields get cleared by config_reset(), but you might have fields
+ * in the object that do not correspond to configuration variables. If those
+ * fields need to be cleared or freed, this is where to do it.)
+ */
+typedef void (*clear_cfg_fn_t)(const struct config_mgr_t *mgr, void *obj);
+
+/** Information on the keys, value types, key-to-struct-member mappings,
+ * variable descriptions, validation functions, and abbreviations for a
+ * configuration or storage format. */
+typedef struct config_format_t {
+ size_t size; /**< Size of the struct that everything gets parsed into. */
+ struct_magic_decl_t magic; /**< Magic number info for this struct. */
+ const config_abbrev_t *abbrevs; /**< List of abbreviations that we expand
+ * when parsing this format. */
+ const config_deprecation_t *deprecations; /** List of deprecated options */
+ const config_var_t *vars; /**< List of variables we recognize, their default
+ * values, and where we stick them in the
+ * structure. */
+
+ /** Early-stage normalization callback. Invoked by config_validate(). */
+ pre_normalize_fn_t pre_normalize_fn;
+ /** Configuration validation function. Invoked by config_validate(). */
+ validate_fn_t validate_fn;
+ /** Legacy validation function. Invoked by config_validate(). */
+ legacy_validate_fn_t legacy_validate_fn;
+ /** Transition checking function. Invoked by config_validate(). */
+ check_transition_fn_t check_transition_fn;
+ /** Late-stage normalization callback. Invoked by config_validate(). */
+ post_normalize_fn_t post_normalize_fn;
+
+ clear_cfg_fn_t clear_fn; /**< Function to clear the configuration. */
+ /** If present, extra denotes a LINELIST variable for unrecognized
+ * lines. Otherwise, unrecognized lines are an error. */
+ const struct_member_t *extra;
+ /**
+ * If true, this format describes a top-level configuration, with
+ * a suite containing multiple sub-configuration objects.
+ */
+ bool has_config_suite;
+ /** The position of a config_suite_t pointer within the toplevel object.
+ * Ignored unless have_config_suite is true.
+ */
+ ptrdiff_t config_suite_offset;
+} config_format_t;
+
#endif /* !defined(TOR_SRC_LIB_CONF_CONFTYPES_H) */
diff --git a/src/lib/conf/include.am b/src/lib/conf/include.am
index cb7126184d..cb0b83fa64 100644
--- a/src/lib/conf/include.am
+++ b/src/lib/conf/include.am
@@ -1,6 +1,7 @@
# ADD_C_FILE: INSERT HEADERS HERE.
noinst_HEADERS += \
+ src/lib/conf/confdecl.h \
src/lib/conf/conftesting.h \
src/lib/conf/conftypes.h \
src/lib/conf/confmacros.h
diff --git a/src/lib/conf/lib_conf.md b/src/lib/conf/lib_conf.md
new file mode 100644
index 0000000000..60dd04e99e
--- /dev/null
+++ b/src/lib/conf/lib_conf.md
@@ -0,0 +1,3 @@
+@dir /lib/conf
+@brief lib/conf: Types and macros for declaring configuration options.
+
diff --git a/src/lib/confmgt/.may_include b/src/lib/confmgt/.may_include
index 2564133917..5ff949f103 100644
--- a/src/lib/confmgt/.may_include
+++ b/src/lib/confmgt/.may_include
@@ -4,6 +4,7 @@ lib/conf/*.h
lib/confmgt/*.h
lib/container/*.h
lib/encoding/*.h
+lib/intmath/*.h
lib/log/*.h
lib/malloc/*.h
lib/string/*.h
diff --git a/src/lib/confmgt/confparse.c b/src/lib/confmgt/confmgt.c
index 08e562f654..bf2764160e 100644
--- a/src/lib/confmgt/confparse.c
+++ b/src/lib/confmgt/confmgt.c
@@ -1,11 +1,11 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file confparse.c
+ * \file confmgt.c
*
* \brief Back-end for parsing and generating key-value files, used to
* implement the torrc file format and the state file.
@@ -21,9 +21,9 @@
* specified, and a linked list of key-value pairs.
*/
-#define CONFPARSE_PRIVATE
+#define CONFMGT_PRIVATE
#include "orconfig.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "lib/confmgt/structvar.h"
#include "lib/confmgt/unitparse.h"
@@ -169,9 +169,14 @@ config_mgr_register_fmt(config_mgr_t *mgr,
"it had been frozen.");
if (object_idx != IDX_TOPLEVEL) {
- tor_assertf(fmt->config_suite_offset < 0,
+ tor_assertf(! fmt->has_config_suite,
"Tried to register a toplevel format in a non-toplevel position");
}
+ if (fmt->config_suite_offset) {
+ tor_assertf(fmt->has_config_suite,
+ "config_suite_offset was set, but has_config_suite was not.");
+ }
+
tor_assertf(fmt != mgr->toplevel &&
! smartlist_contains(mgr->subconfigs, fmt),
"Tried to register an already-registered format.");
@@ -223,7 +228,7 @@ config_mgr_add_format(config_mgr_t *mgr,
static inline config_suite_t **
config_mgr_get_suite_ptr(const config_mgr_t *mgr, void *toplevel)
{
- if (mgr->toplevel->config_suite_offset < 0)
+ if (! mgr->toplevel->has_config_suite)
return NULL;
return STRUCT_VAR_P(toplevel, mgr->toplevel->config_suite_offset);
}
@@ -237,7 +242,7 @@ config_mgr_get_suite_ptr(const config_mgr_t *mgr, void *toplevel)
* to configuration objects for other modules. This function gets
* the sub-object for a particular module.
*/
-STATIC void *
+void *
config_mgr_get_obj_mutable(const config_mgr_t *mgr, void *toplevel, int idx)
{
tor_assert(mgr);
@@ -256,7 +261,7 @@ config_mgr_get_obj_mutable(const config_mgr_t *mgr, void *toplevel, int idx)
}
/** As config_mgr_get_obj_mutable(), but return a const pointer. */
-STATIC const void *
+const void *
config_mgr_get_obj(const config_mgr_t *mgr, const void *toplevel, int idx)
{
return config_mgr_get_obj_mutable(mgr, (void*)toplevel, idx);
@@ -334,6 +339,17 @@ config_mgr_list_deprecated_vars(const config_mgr_t *mgr)
return result;
}
+/**
+ * Check the magic number on <b>object</b> to make sure it's a valid toplevel
+ * object, created with <b>mgr</b>. Exit with an assertion if it isn't.
+ **/
+void
+config_check_toplevel_magic(const config_mgr_t *mgr,
+ const void *object)
+{
+ struct_check_magic(object, &mgr->toplevel_magic);
+}
+
/** Assert that the magic fields in <b>options</b> and its subsidiary
* objects are all okay. */
static void
@@ -641,6 +657,14 @@ config_assign_value(const config_mgr_t *mgr, void *options,
tor_assert(!strcmp(c->key, var->cvar->member.name));
void *object = config_mgr_get_obj_mutable(mgr, options, var->object_idx);
+ if (config_var_has_flag(var->cvar, CFLG_WARN_OBSOLETE)) {
+ log_warn(LD_GENERAL, "Skipping obsolete configuration option \"%s\".",
+ var->cvar->member.name);
+ } else if (config_var_has_flag(var->cvar, CFLG_WARN_DISABLED)) {
+ log_warn(LD_GENERAL, "This copy of Tor was built without support for "
+ "the option \"%s\". Skipping.", var->cvar->member.name);
+ }
+
return struct_var_kvassign(object, c, msg, &var->cvar->member);
}
@@ -1142,6 +1166,146 @@ config_init(const config_mgr_t *mgr, void *options)
} SMARTLIST_FOREACH_END(mv);
}
+/**
+ * Helper for config_validate_single: see whether any immutable option
+ * has changed between old_options and new_options.
+ *
+ * On success return 0; on failure set *msg_out to a newly allocated
+ * string explaining what is wrong, and return -1.
+ */
+static int
+config_check_immutable_flags(const config_format_t *fmt,
+ const void *old_options,
+ const void *new_options,
+ char **msg_out)
+{
+ tor_assert(fmt);
+ tor_assert(new_options);
+ if (BUG(! old_options))
+ return 0;
+
+ unsigned i;
+ for (i = 0; fmt->vars[i].member.name; ++i) {
+ const config_var_t *v = &fmt->vars[i];
+ if (! config_var_has_flag(v, CFLG_IMMUTABLE))
+ continue;
+
+ if (! struct_var_eq(old_options, new_options, &v->member)) {
+ tor_asprintf(msg_out,
+ "While Tor is running, changing %s is not allowed",
+ v->member.name);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Normalize and validate a single object `options` within a configuration
+ * suite, according to its format. `options` may be modified as appropriate
+ * in order to set ancillary data. If `old_options` is provided, make sure
+ * that the transition from `old_options` to `options` is permitted.
+ *
+ * On success return VSTAT_OK; on failure set *msg_out to a newly allocated
+ * string explaining what is wrong, and return a different validation_status_t
+ * to describe which step failed.
+ **/
+static validation_status_t
+config_validate_single(const config_format_t *fmt,
+ const void *old_options, void *options,
+ char **msg_out)
+{
+ tor_assert(fmt);
+ tor_assert(options);
+
+ if (fmt->pre_normalize_fn) {
+ if (fmt->pre_normalize_fn(options, msg_out) < 0) {
+ return VSTAT_PRE_NORMALIZE_ERR;
+ }
+ }
+
+ if (fmt->legacy_validate_fn) {
+ if (fmt->legacy_validate_fn(old_options, options, msg_out) < 0) {
+ return VSTAT_LEGACY_ERR;
+ }
+ }
+
+ if (fmt->validate_fn) {
+ if (fmt->validate_fn(options, msg_out) < 0) {
+ return VSTAT_VALIDATE_ERR;
+ }
+ }
+
+ if (old_options) {
+ if (config_check_immutable_flags(fmt, old_options, options, msg_out) < 0) {
+ return VSTAT_TRANSITION_ERR;
+ }
+
+ if (fmt->check_transition_fn) {
+ if (fmt->check_transition_fn(old_options, options, msg_out) < 0) {
+ return VSTAT_TRANSITION_ERR;
+ }
+ }
+ }
+
+ if (fmt->post_normalize_fn) {
+ if (fmt->post_normalize_fn(options, msg_out) < 0) {
+ return VSTAT_POST_NORMALIZE_ERR;
+ }
+ }
+
+ return VSTAT_OK;
+}
+
+/**
+ * Normalize and validate all the options in configuration object `options`
+ * and its sub-objects. `options` may be modified as appropriate in order to
+ * set ancillary data. If `old_options` is provided, make sure that the
+ * transition from `old_options` to `options` is permitted.
+ *
+ * On success return VSTAT_OK; on failure set *msg_out to a newly allocated
+ * string explaining what is wrong, and return a different validation_status_t
+ * to describe which step failed.
+ **/
+validation_status_t
+config_validate(const config_mgr_t *mgr,
+ const void *old_options, void *options,
+ char **msg_out)
+{
+ validation_status_t rv;
+ CONFIG_CHECK(mgr, options);
+ if (old_options) {
+ CONFIG_CHECK(mgr, old_options);
+ }
+
+ config_suite_t **suitep_new = config_mgr_get_suite_ptr(mgr, options);
+ config_suite_t **suitep_old = NULL;
+ if (old_options)
+ suitep_old = config_mgr_get_suite_ptr(mgr, (void*) old_options);
+
+ /* Validate the sub-objects */
+ if (suitep_new) {
+ SMARTLIST_FOREACH_BEGIN(mgr->subconfigs, const config_format_t *, fmt) {
+ void *obj = smartlist_get((*suitep_new)->configs, fmt_sl_idx);
+ const void *obj_old=NULL;
+ if (suitep_old)
+ obj_old = smartlist_get((*suitep_old)->configs, fmt_sl_idx);
+
+ rv = config_validate_single(fmt, obj_old, obj, msg_out);
+ if (rv < 0)
+ return rv;
+ } SMARTLIST_FOREACH_END(fmt);
+ }
+
+ /* Validate the top-level object. */
+ rv = config_validate_single(mgr->toplevel, old_options, options, msg_out);
+ if (rv < 0)
+ return rv;
+
+ return VSTAT_OK;
+}
+
/** Allocate and return a new string holding the written-out values of the vars
* in 'options'. If 'minimal', do not write out any default-valued vars.
* Else, if comment_defaults, write default values as comments.
@@ -1166,7 +1330,7 @@ config_dump(const config_mgr_t *mgr, const void *default_options,
/* XXX use a 1 here so we don't add a new log line while dumping */
if (default_options == NULL) {
- if (fmt->validate_fn(NULL, defaults_tmp, defaults_tmp, 1, &msg) < 0) {
+ if (config_validate(mgr, NULL, defaults_tmp, &msg) < 0) {
// LCOV_EXCL_START
log_err(LD_BUG, "Failed to validate default config: %s", msg);
tor_free(msg);
@@ -1197,9 +1361,10 @@ config_dump(const config_mgr_t *mgr, const void *default_options,
*/
continue;
}
- smartlist_add_asprintf(elements, "%s%s %s\n",
+ int value_exists = line->value && *(line->value);
+ smartlist_add_asprintf(elements, "%s%s%s%s\n",
comment_option ? "# " : "",
- line->key, line->value);
+ line->key, value_exists ? " " : "", line->value);
}
config_free_lines(assigned);
} SMARTLIST_FOREACH_END(mv);
@@ -1207,7 +1372,9 @@ config_dump(const config_mgr_t *mgr, const void *default_options,
if (fmt->extra) {
line = *(config_line_t**)STRUCT_VAR_P(options, fmt->extra->offset);
for (; line; line = line->next) {
- smartlist_add_asprintf(elements, "%s %s\n", line->key, line->value);
+ int value_exists = line->value && *(line->value);
+ smartlist_add_asprintf(elements, "%s%s%s\n",
+ line->key, value_exists ? " " : "", line->value);
}
}
diff --git a/src/lib/confmgt/confparse.h b/src/lib/confmgt/confmgt.h
index 2332f69790..5065c13b60 100644
--- a/src/lib/confmgt/confparse.h
+++ b/src/lib/confmgt/confmgt.h
@@ -1,116 +1,23 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file confparse.h
+ * \file confmgt.h
*
- * \brief Header for confparse.c.
+ * \brief Header for confmgt.c.
*/
-#ifndef TOR_CONFPARSE_H
-#define TOR_CONFPARSE_H
+#ifndef TOR_CONFMGT_H
+#define TOR_CONFMGT_H
#include "lib/conf/conftypes.h"
#include "lib/conf/confmacros.h"
#include "lib/testsupport/testsupport.h"
/**
- * An abbreviation or alias for a configuration option.
- **/
-typedef struct config_abbrev_t {
- /** The option name as abbreviated. Not case-sensitive. */
- const char *abbreviated;
- /** The full name of the option. Not case-sensitive. */
- const char *full;
- /** True if this abbreviation should only be allowed on the command line. */
- int commandline_only;
- /** True if we should warn whenever this abbreviation is used. */
- int warn;
-} config_abbrev_t;
-
-/**
- * A note that a configuration option is deprecated, with an explanation why.
- */
-typedef struct config_deprecation_t {
- /** The option that is deprecated. */
- const char *name;
- /** A user-facing string explaining why the option is deprecated. */
- const char *why_deprecated;
-} config_deprecation_t;
-
-/**
- * Handy macro for declaring "In the config file or on the command line, you
- * can abbreviate <b>tok</b>s as <b>tok</b>". Used inside an array of
- * config_abbrev_t.
- *
- * For example, to declare "NumCpu" as an abbreviation for "NumCPUs",
- * you can say PLURAL(NumCpu).
- **/
-#define PLURAL(tok) { #tok, #tok "s", 0, 0 }
-
-/**
- * Type of a callback to validate whether a given configuration is
- * well-formed and consistent.
- *
- * The configuration to validate is passed as <b>newval</b>. The previous
- * configuration, if any, is provided in <b>oldval</b>. The
- * <b>default_val</b> argument receives a configuration object initialized
- * with default values for all its fields. The <b>from_setconf</b> argument
- * is true iff the input comes from a SETCONF controller command.
- *
- * On success, return 0. On failure, set *<b>msg_out</b> to a newly allocated
- * error message, and return -1.
- *
- * REFACTORING NOTE: Currently, this callback type is only used from inside
- * config_dump(); later in our refactoring, it will be cleaned up and used
- * more generally.
- */
-typedef int (*validate_fn_t)(void *oldval,
- void *newval,
- void *default_val,
- int from_setconf,
- char **msg_out);
-
-struct config_mgr_t;
-
-/**
- * Callback to clear all non-managed fields of a configuration object.
- *
- * <b>obj</b> is the configuration object whose non-managed fields should be
- * cleared.
- *
- * (Regular fields get cleared by config_reset(), but you might have fields
- * in the object that do not correspond to configuration variables. If those
- * fields need to be cleared or freed, this is where to do it.)
- */
-typedef void (*clear_cfg_fn_t)(const struct config_mgr_t *mgr, void *obj);
-
-/** Information on the keys, value types, key-to-struct-member mappings,
- * variable descriptions, validation functions, and abbreviations for a
- * configuration or storage format. */
-typedef struct config_format_t {
- size_t size; /**< Size of the struct that everything gets parsed into. */
- struct_magic_decl_t magic; /**< Magic number info for this struct. */
- const config_abbrev_t *abbrevs; /**< List of abbreviations that we expand
- * when parsing this format. */
- const config_deprecation_t *deprecations; /** List of deprecated options */
- const config_var_t *vars; /**< List of variables we recognize, their default
- * values, and where we stick them in the
- * structure. */
- validate_fn_t validate_fn; /**< Function to validate config. */
- clear_cfg_fn_t clear_fn; /**< Function to clear the configuration. */
- /** If present, extra denotes a LINELIST variable for unrecognized
- * lines. Otherwise, unrecognized lines are an error. */
- const struct_member_t *extra;
- /** The position of a config_suite_t pointer within the toplevel object,
- * or -1 if there is no such pointer. */
- ptrdiff_t config_suite_offset;
-} config_format_t;
-
-/**
* A collection of config_format_t objects to describe several objects
* that are all configured with the same configuration file.
*
@@ -171,10 +78,26 @@ int config_is_same(const config_mgr_t *fmt,
struct config_line_t *config_get_changes(const config_mgr_t *mgr,
const void *options1, const void *options2);
void config_init(const config_mgr_t *mgr, void *options);
+
+/** An enumeration to report which validation step failed. */
+typedef enum {
+ VSTAT_PRE_NORMALIZE_ERR = -5,
+ VSTAT_VALIDATE_ERR = -4,
+ VSTAT_LEGACY_ERR = -3,
+ VSTAT_TRANSITION_ERR = -2,
+ VSTAT_POST_NORMALIZE_ERR = -1,
+ VSTAT_OK = 0,
+} validation_status_t;
+
+validation_status_t config_validate(const config_mgr_t *mgr,
+ const void *old_options, void *options,
+ char **msg_out);
void *config_dup(const config_mgr_t *mgr, const void *old);
char *config_dump(const config_mgr_t *mgr, const void *default_options,
const void *options, int minimal,
int comment_defaults);
+void config_check_toplevel_magic(const config_mgr_t *mgr,
+ const void *object);
bool config_check_ok(const config_mgr_t *mgr, const void *options,
int severity);
int config_assign(const config_mgr_t *mgr, void *options,
@@ -200,13 +123,14 @@ bool config_var_is_listable(const config_var_t *var);
#define CFG_EQ_LINELIST(a,b,opt) config_lines_eq((a)->opt, (b)->opt)
#define CFG_EQ_ROUTERSET(a,b,opt) routerset_equal((a)->opt, (b)->opt)
-#ifdef CONFPARSE_PRIVATE
+void *config_mgr_get_obj_mutable(const config_mgr_t *mgr,
+ void *toplevel, int idx);
+const void *config_mgr_get_obj(const config_mgr_t *mgr,
+ const void *toplevel, int idx);
+
+#ifdef CONFMGT_PRIVATE
STATIC void config_reset_line(const config_mgr_t *mgr, void *options,
const char *key, int use_defaults);
-STATIC void *config_mgr_get_obj_mutable(const config_mgr_t *mgr,
- void *toplevel, int idx);
-STATIC const void *config_mgr_get_obj(const config_mgr_t *mgr,
- const void *toplevel, int idx);
-#endif /* defined(CONFPARSE_PRIVATE) */
+#endif /* defined(CONFMGT_PRIVATE) */
-#endif /* !defined(TOR_CONFPARSE_H) */
+#endif /* !defined(TOR_CONFMGT_H) */
diff --git a/src/lib/confmgt/include.am b/src/lib/confmgt/include.am
index 81cd868e5e..d3a7a7cd69 100644
--- a/src/lib/confmgt/include.am
+++ b/src/lib/confmgt/include.am
@@ -6,7 +6,7 @@ endif
# ADD_C_FILE: INSERT SOURCES HERE.
src_lib_libtor_confmgt_a_SOURCES = \
- src/lib/confmgt/confparse.c \
+ src/lib/confmgt/confmgt.c \
src/lib/confmgt/structvar.c \
src/lib/confmgt/type_defs.c \
src/lib/confmgt/typedvar.c \
@@ -19,7 +19,7 @@ src_lib_libtor_confmgt_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
# ADD_C_FILE: INSERT HEADERS HERE.
noinst_HEADERS += \
- src/lib/confmgt/confparse.h \
+ src/lib/confmgt/confmgt.h \
src/lib/confmgt/structvar.h \
src/lib/confmgt/type_defs.h \
src/lib/confmgt/typedvar.h \
diff --git a/src/lib/confmgt/lib_confmgt.md b/src/lib/confmgt/lib_confmgt.md
new file mode 100644
index 0000000000..861e720f64
--- /dev/null
+++ b/src/lib/confmgt/lib_confmgt.md
@@ -0,0 +1,7 @@
+@dir /lib/confmgt
+@brief lib/confmgt: Parse, encode, manipulate configuration files.
+
+This logic is used in common by our state files (statefile.c) and
+configuration files (config.c) to manage a set of named, typed fields,
+reading and writing them to disk and to the controller.
+
diff --git a/src/lib/confmgt/structvar.c b/src/lib/confmgt/structvar.c
index 7a3b8c7df2..55deb4759c 100644
--- a/src/lib/confmgt/structvar.c
+++ b/src/lib/confmgt/structvar.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -30,13 +30,28 @@
#include <stddef.h>
/**
+ * Return true iff all fields on <b>decl</b> are NULL or 0, indicating that
+ * there is no object or no magic number to check.
+ **/
+static inline bool
+magic_is_null(const struct_magic_decl_t *decl)
+{
+ return decl->typename == NULL &&
+ decl->magic_offset == 0 &&
+ decl->magic_val == 0;
+}
+
+/**
* Set the 'magic number' on <b>object</b> to correspond to decl.
**/
void
struct_set_magic(void *object, const struct_magic_decl_t *decl)
{
- tor_assert(object);
tor_assert(decl);
+ if (magic_is_null(decl))
+ return;
+
+ tor_assert(object);
uint32_t *ptr = STRUCT_VAR_P(object, decl->magic_offset);
*ptr = decl->magic_val;
}
@@ -47,8 +62,11 @@ struct_set_magic(void *object, const struct_magic_decl_t *decl)
void
struct_check_magic(const void *object, const struct_magic_decl_t *decl)
{
- tor_assert(object);
tor_assert(decl);
+ if (magic_is_null(decl))
+ return;
+
+ tor_assert(object);
const uint32_t *ptr = STRUCT_VAR_P(object, decl->magic_offset);
tor_assertf(*ptr == decl->magic_val,
diff --git a/src/lib/confmgt/structvar.h b/src/lib/confmgt/structvar.h
index bcb4b58c3f..91334fa8c5 100644
--- a/src/lib/confmgt/structvar.h
+++ b/src/lib/confmgt/structvar.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/confmgt/type_defs.c b/src/lib/confmgt/type_defs.c
index 5066e12265..d9e5e1e4c2 100644
--- a/src/lib/confmgt/type_defs.c
+++ b/src/lib/confmgt/type_defs.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -17,12 +17,12 @@
#include "orconfig.h"
#include "lib/conf/conftypes.h"
+#include "lib/conf/confdecl.h"
#include "lib/confmgt/typedvar.h"
#include "lib/confmgt/type_defs.h"
#include "lib/confmgt/unitparse.h"
#include "lib/cc/compat_compiler.h"
-#include "lib/conf/conftypes.h"
#include "lib/container/smartlist.h"
#include "lib/encoding/confline.h"
#include "lib/encoding/time_fmt.h"
@@ -52,11 +52,10 @@
static int
string_parse(void *target, const char *value, char **errmsg,
- const void *params, const char *key)
+ const void *params)
{
(void)params;
(void)errmsg;
- (void)key;
char **p = (char**)target;
*p = tor_strdup(value);
return 0;
@@ -91,9 +90,12 @@ static const var_type_fns_t string_fns = {
// These types are implemented as int, possibly with a restricted range.
/////
+/**
+ * Parameters for parsing an integer type.
+ **/
typedef struct int_type_params_t {
- int minval;
- int maxval;
+ int minval; /**< Lowest allowed value */
+ int maxval; /**< Highest allowed value */
} int_parse_params_t;
static const int_parse_params_t INT_PARSE_UNRESTRICTED = {
@@ -107,10 +109,8 @@ static const int_parse_params_t INT_PARSE_POSINT = {
};
static int
-int_parse(void *target, const char *value, char **errmsg, const void *params,
- const char *key)
+int_parse(void *target, const char *value, char **errmsg, const void *params)
{
- (void)key;
const int_parse_params_t *pp;
if (params) {
pp = params;
@@ -121,8 +121,9 @@ int_parse(void *target, const char *value, char **errmsg, const void *params,
int ok=0;
*p = (int)tor_parse_long(value, 10, pp->minval, pp->maxval, &ok, NULL);
if (!ok) {
- tor_asprintf(errmsg, "Integer %s is malformed or out of bounds.",
- value);
+ tor_asprintf(errmsg, "Integer %s is malformed or out of bounds. "
+ "Allowed values are between %d and %d.",
+ value, pp->minval, pp->maxval);
return -1;
}
return 0;
@@ -172,11 +173,10 @@ static const var_type_fns_t int_fns = {
static int
uint64_parse(void *target, const char *value, char **errmsg,
- const void *params, const char *key)
+ const void *params)
{
(void)params;
(void)errmsg;
- (void)key;
uint64_t *p = target;
int ok=0;
*p = tor_parse_uint64(value, 10, 0, UINT64_MAX, &ok, NULL);
@@ -223,35 +223,45 @@ static const var_type_fns_t uint64_fns = {
static int
units_parse_u64(void *target, const char *value, char **errmsg,
- const void *params, const char *key)
+ const void *params)
{
- (void)key;
const unit_table_t *table = params;
tor_assert(table);
uint64_t *v = (uint64_t*)target;
int ok=1;
- *v = config_parse_units(value, table, &ok);
+ char *msg = NULL;
+ *v = config_parse_units(value, table, &ok, &msg);
if (!ok) {
- *errmsg = tor_strdup("Provided value is malformed or out of bounds.");
+ tor_asprintf(errmsg, "Provided value is malformed or out of bounds: %s",
+ msg);
+ tor_free(msg);
return -1;
}
+ if (BUG(msg)) {
+ tor_free(msg);
+ }
return 0;
}
static int
units_parse_int(void *target, const char *value, char **errmsg,
- const void *params, const char *key)
+ const void *params)
{
- (void)key;
const unit_table_t *table = params;
tor_assert(table);
int *v = (int*)target;
int ok=1;
- uint64_t u64 = config_parse_units(value, table, &ok);
+ char *msg = NULL;
+ uint64_t u64 = config_parse_units(value, table, &ok, &msg);
if (!ok) {
- *errmsg = tor_strdup("Provided value is malformed or out of bounds.");
+ tor_asprintf(errmsg, "Provided value is malformed or out of bounds: %s",
+ msg);
+ tor_free(msg);
return -1;
}
+ if (BUG(msg)) {
+ tor_free(msg);
+ }
if (u64 > INT_MAX) {
tor_asprintf(errmsg, "Provided value %s is too large", value);
return -1;
@@ -289,11 +299,10 @@ static const var_type_fns_t interval_fns = {
static int
double_parse(void *target, const char *value, char **errmsg,
- const void *params, const char *key)
+ const void *params)
{
(void)params;
(void)errmsg;
- (void)key;
double *v = (double*)target;
char *endptr=NULL;
errno = 0;
@@ -352,12 +361,17 @@ typedef struct enumeration_table_t {
int value;
} enumeration_table_t;
+typedef struct enumeration_params_t {
+ const char *allowed_val_string;
+ const enumeration_table_t *table;
+} enumeration_params_t;
+
static int
enum_parse(void *target, const char *value, char **errmsg,
- const void *params, const char *key)
+ const void *params_)
{
- (void)key;
- const enumeration_table_t *table = params;
+ const enumeration_params_t *params = params_;
+ const enumeration_table_t *table = params->table;
int *p = (int *)target;
for (; table->name; ++table) {
if (!strcasecmp(value, table->name)) {
@@ -365,15 +379,17 @@ enum_parse(void *target, const char *value, char **errmsg,
return 0;
}
}
- tor_asprintf(errmsg, "Unrecognized value %s.", value);
+ tor_asprintf(errmsg, "Unrecognized value %s. %s",
+ value, params->allowed_val_string);
return -1;
}
static char *
-enum_encode(const void *value, const void *params)
+enum_encode(const void *value, const void *params_)
{
int v = *(const int*)value;
- const enumeration_table_t *table = params;
+ const enumeration_params_t *params = params_;
+ const enumeration_table_t *table = params->table;
for (; table->name; ++table) {
if (v == table->value)
return tor_strdup(table->name);
@@ -382,19 +398,21 @@ enum_encode(const void *value, const void *params)
}
static void
-enum_clear(void *value, const void *params)
+enum_clear(void *value, const void *params_)
{
int *p = (int*)value;
- const enumeration_table_t *table = params;
+ const enumeration_params_t *params = params_;
+ const enumeration_table_t *table = params->table;
tor_assert(table->name);
*p = table->value;
}
static bool
-enum_ok(const void *value, const void *params)
+enum_ok(const void *value, const void *params_)
{
int v = *(const int*)value;
- const enumeration_table_t *table = params;
+ const enumeration_params_t *params = params_;
+ const enumeration_table_t *table = params->table;
for (; table->name; ++table) {
if (v == table->value)
return true;
@@ -408,6 +426,11 @@ static const enumeration_table_t enum_table_bool[] = {
{ NULL, 0 },
};
+static const enumeration_params_t enum_params_bool = {
+ "Allowed values are 0 and 1.",
+ enum_table_bool
+};
+
static const enumeration_table_t enum_table_autobool[] = {
{ "0", 0 },
{ "1", 1 },
@@ -415,6 +438,11 @@ static const enumeration_table_t enum_table_autobool[] = {
{ NULL, 0 },
};
+static const enumeration_params_t enum_params_autobool = {
+ "Allowed values are 0, 1, and auto.",
+ enum_table_autobool
+};
+
static const var_type_fns_t enum_fns = {
.parse = enum_parse,
.encode = enum_encode,
@@ -430,10 +458,9 @@ static const var_type_fns_t enum_fns = {
static int
time_parse(void *target, const char *value, char **errmsg,
- const void *params, const char *key)
+ const void *params)
{
(void) params;
- (void) key;
time_t *p = target;
if (parse_iso_time(value, p) < 0) {
tor_asprintf(errmsg, "Invalid time %s", escaped(value));
@@ -475,11 +502,10 @@ static const var_type_fns_t time_fns = {
static int
csv_parse(void *target, const char *value, char **errmsg,
- const void *params, const char *key)
+ const void *params)
{
(void)params;
(void)errmsg;
- (void)key;
smartlist_t **sl = (smartlist_t**)target;
*sl = smartlist_new();
smartlist_split_string(*sl, value, ",",
@@ -525,7 +551,7 @@ static const var_type_fns_t csv_fns = {
static int
legacy_csv_interval_parse(void *target, const char *value, char **errmsg,
- const void *params, const char *key)
+ const void *params)
{
(void)params;
/* We used to have entire smartlists here. But now that all of our
@@ -539,7 +565,7 @@ legacy_csv_interval_parse(void *target, const char *value, char **errmsg,
val = tmp;
}
- int rv = units_parse_int(target, val, errmsg, &time_units, key);
+ int rv = units_parse_int(target, val, errmsg, &time_units);
tor_free(tmp);
return rv;
}
@@ -688,32 +714,23 @@ static const var_type_fns_t linelist_s_fns = {
/////
// CONFIG_TYPE_ROUTERSET
//
-// XXXX This type is not implemented here, since routerset_t is not available
// XXXX to this module.
/////
/////
-// CONFIG_TYPE_OBSOLETE
-//
-// Used to indicate an obsolete option.
+// CONFIG_TYPE_IGNORE
//
-// XXXX This is not a type, and should be handled at a higher level of
-// XXXX abstraction.
+// Used to indicate an option that cannot be stored or encoded.
/////
static int
ignore_parse(void *target, const char *value, char **errmsg,
- const void *params, const char *key)
+ const void *params)
{
(void)target;
(void)value;
(void)errmsg;
(void)params;
- // XXXX move this to a higher level, once such a level exists.
- log_warn(LD_GENERAL, "Skipping obsolete configuration option%s%s%s",
- key && *key ? " \"" : "",
- key && *key ? key : "",
- key && *key ? "\"." : ".");
return 0;
}
@@ -730,50 +747,91 @@ static const var_type_fns_t ignore_fns = {
.encode = ignore_encode,
};
+const var_type_def_t STRING_type_defn = {
+ .name="String", .fns=&string_fns };
+const var_type_def_t FILENAME_type_defn = {
+ .name="Filename", .fns=&string_fns };
+const var_type_def_t INT_type_defn = {
+ .name="SignedInteger", .fns=&int_fns,
+ .params=&INT_PARSE_UNRESTRICTED };
+const var_type_def_t POSINT_type_defn = {
+ .name="Integer", .fns=&int_fns,
+ .params=&INT_PARSE_POSINT };
+const var_type_def_t UINT64_type_defn = {
+ .name="Integer", .fns=&uint64_fns, };
+const var_type_def_t MEMUNIT_type_defn = {
+ .name="DataSize", .fns=&memunit_fns,
+ .params=&memory_units };
+const var_type_def_t INTERVAL_type_defn = {
+ .name="TimeInterval", .fns=&interval_fns,
+ .params=&time_units };
+const var_type_def_t MSEC_INTERVAL_type_defn = {
+ .name="TimeMsecInterval",
+ .fns=&interval_fns,
+ .params=&time_msec_units };
+const var_type_def_t DOUBLE_type_defn = {
+ .name="Float", .fns=&double_fns, };
+const var_type_def_t BOOL_type_defn = {
+ .name="Boolean", .fns=&enum_fns,
+ .params=&enum_params_bool };
+const var_type_def_t AUTOBOOL_type_defn = {
+ .name="Boolean+Auto", .fns=&enum_fns,
+ .params=&enum_params_autobool };
+const var_type_def_t ISOTIME_type_defn = {
+ .name="Time", .fns=&time_fns, };
+const var_type_def_t CSV_type_defn = {
+ .name="CommaList", .fns=&csv_fns, };
+const var_type_def_t CSV_INTERVAL_type_defn = {
+ .name="TimeInterval",
+ .fns=&legacy_csv_interval_fns, };
+const var_type_def_t LINELIST_type_defn = {
+ .name="LineList", .fns=&linelist_fns,
+ .flags=CFLG_NOREPLACE };
+/*
+ * A "linelist_s" is a derived view of a linelist_v: inspecting
+ * it gets part of a linelist_v, and setting it adds to the linelist_v.
+ */
+const var_type_def_t LINELIST_S_type_defn = {
+ .name="Dependent", .fns=&linelist_s_fns,
+ .flags=CFLG_NOREPLACE|
+ /* The operations we disable here are
+ * handled by the linelist_v. */
+ CFLG_NOCOPY|CFLG_NOCMP|CFLG_NODUMP };
+const var_type_def_t LINELIST_V_type_defn = {
+ .name="Virtual", .fns=&linelist_v_fns,
+ .flags=CFLG_NOREPLACE|CFLG_NOSET };
+const var_type_def_t IGNORE_type_defn = {
+ .name="Ignored", .fns=&ignore_fns,
+ .flags=CFLG_NOCOPY|CFLG_NOCMP|CFLG_NODUMP|CFLG_NOSET,
+};
+const var_type_def_t OBSOLETE_type_defn = {
+ .name="Obsolete", .fns=&ignore_fns,
+ .flags=CFLG_GROUP_OBSOLETE,
+};
+
/**
* Table mapping conf_type_t values to var_type_def_t objects.
**/
-static const var_type_def_t type_definitions_table[] = {
- [CONFIG_TYPE_STRING] = { .name="String", .fns=&string_fns },
- [CONFIG_TYPE_FILENAME] = { .name="Filename", .fns=&string_fns },
- [CONFIG_TYPE_INT] = { .name="SignedInteger", .fns=&int_fns,
- .params=&INT_PARSE_UNRESTRICTED },
- [CONFIG_TYPE_POSINT] = { .name="Integer", .fns=&int_fns,
- .params=&INT_PARSE_POSINT },
- [CONFIG_TYPE_UINT64] = { .name="Integer", .fns=&uint64_fns, },
- [CONFIG_TYPE_MEMUNIT] = { .name="DataSize", .fns=&memunit_fns,
- .params=&memory_units },
- [CONFIG_TYPE_INTERVAL] = { .name="TimeInterval", .fns=&interval_fns,
- .params=&time_units },
- [CONFIG_TYPE_MSEC_INTERVAL] = { .name="TimeMsecInterval",
- .fns=&interval_fns,
- .params=&time_msec_units },
- [CONFIG_TYPE_DOUBLE] = { .name="Float", .fns=&double_fns, },
- [CONFIG_TYPE_BOOL] = { .name="Boolean", .fns=&enum_fns,
- .params=&enum_table_bool },
- [CONFIG_TYPE_AUTOBOOL] = { .name="Boolean+Auto", .fns=&enum_fns,
- .params=&enum_table_autobool },
- [CONFIG_TYPE_ISOTIME] = { .name="Time", .fns=&time_fns, },
- [CONFIG_TYPE_CSV] = { .name="CommaList", .fns=&csv_fns, },
- [CONFIG_TYPE_CSV_INTERVAL] = { .name="TimeInterval",
- .fns=&legacy_csv_interval_fns, },
- [CONFIG_TYPE_LINELIST] = { .name="LineList", .fns=&linelist_fns,
- .flags=CFLG_NOREPLACE },
- /*
- * A "linelist_s" is a derived view of a linelist_v: inspecting
- * it gets part of a linelist_v, and setting it adds to the linelist_v.
- */
- [CONFIG_TYPE_LINELIST_S] = { .name="Dependent", .fns=&linelist_s_fns,
- .flags=CFLG_NOREPLACE|
- /* The operations we disable here are
- * handled by the linelist_v. */
- CFLG_NOCOPY|CFLG_NOCMP|CFLG_NODUMP },
- [CONFIG_TYPE_LINELIST_V] = { .name="Virtual", .fns=&linelist_v_fns,
- .flags=CFLG_NOREPLACE|CFLG_NOSET },
- [CONFIG_TYPE_OBSOLETE] = {
- .name="Obsolete", .fns=&ignore_fns,
- .flags=CFLG_GROUP_OBSOLETE,
- }
+static const var_type_def_t *type_definitions_table[] = {
+ [CONFIG_TYPE_STRING] = &STRING_type_defn,
+ [CONFIG_TYPE_FILENAME] = &FILENAME_type_defn,
+ [CONFIG_TYPE_INT] = &INT_type_defn,
+ [CONFIG_TYPE_POSINT] = &POSINT_type_defn,
+ [CONFIG_TYPE_UINT64] = &UINT64_type_defn,
+ [CONFIG_TYPE_MEMUNIT] = &MEMUNIT_type_defn,
+ [CONFIG_TYPE_INTERVAL] = &INTERVAL_type_defn,
+ [CONFIG_TYPE_MSEC_INTERVAL] = &MSEC_INTERVAL_type_defn,
+ [CONFIG_TYPE_DOUBLE] = &DOUBLE_type_defn,
+ [CONFIG_TYPE_BOOL] = &BOOL_type_defn,
+ [CONFIG_TYPE_AUTOBOOL] = &AUTOBOOL_type_defn,
+ [CONFIG_TYPE_ISOTIME] = &ISOTIME_type_defn,
+ [CONFIG_TYPE_CSV] = &CSV_type_defn,
+ [CONFIG_TYPE_CSV_INTERVAL] = &CSV_INTERVAL_type_defn,
+ [CONFIG_TYPE_LINELIST] = &LINELIST_type_defn,
+ [CONFIG_TYPE_LINELIST_S] = &LINELIST_S_type_defn,
+ [CONFIG_TYPE_LINELIST_V] = &LINELIST_V_type_defn,
+ [CONFIG_TYPE_IGNORE] = &IGNORE_type_defn,
+ [CONFIG_TYPE_OBSOLETE] = &OBSOLETE_type_defn,
};
/**
@@ -787,5 +845,5 @@ lookup_type_def(config_type_t type)
tor_assert(t >= 0);
if (t >= (int)ARRAY_LENGTH(type_definitions_table))
return NULL;
- return &type_definitions_table[t];
+ return type_definitions_table[t];
}
diff --git a/src/lib/confmgt/type_defs.h b/src/lib/confmgt/type_defs.h
index ecf040529e..fec002b1d3 100644
--- a/src/lib/confmgt/type_defs.h
+++ b/src/lib/confmgt/type_defs.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/confmgt/typedvar.c b/src/lib/confmgt/typedvar.c
index ce11a69379..1955302cdc 100644
--- a/src/lib/confmgt/typedvar.c
+++ b/src/lib/confmgt/typedvar.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -24,6 +24,7 @@
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/malloc/malloc.h"
+#include "lib/string/printf.h"
#include "lib/string/util_string.h"
#include "lib/confmgt/var_type_def_st.h"
@@ -33,8 +34,7 @@
/**
* Try to parse a string in <b>value</b> that encodes an object of the type
- * defined by <b>def</b>. If not NULL, <b>key</b> is the name of the option,
- * which may be used for logging.
+ * defined by <b>def</b>.
*
* On success, adjust the lvalue pointed to by <b>target</b> to hold that
* value, and return 0. On failure, set *<b>errmsg</b> to a newly allocated
@@ -42,7 +42,7 @@
**/
int
typed_var_assign(void *target, const char *value, char **errmsg,
- const var_type_def_t *def, const char *key)
+ const var_type_def_t *def)
{
if (BUG(!def))
return -1; // LCOV_EXCL_LINE
@@ -50,7 +50,7 @@ typed_var_assign(void *target, const char *value, char **errmsg,
typed_var_free(target, def);
tor_assert(def->fns->parse);
- return def->fns->parse(target, value, errmsg, def->params, key);
+ return def->fns->parse(target, value, errmsg, def->params);
}
/**
@@ -76,7 +76,15 @@ typed_var_kvassign(void *target, const config_line_t *line,
return def->fns->kv_parse(target, line, errmsg, def->params);
}
- return typed_var_assign(target, line->value, errmsg, def, line->key);
+ int rv = typed_var_assign(target, line->value, errmsg, def);
+ if (rv < 0 && *errmsg != NULL) {
+ /* typed_var_assign() didn't know the line's keyword, but we do.
+ * Let's add it to the error message. */
+ char *oldmsg = *errmsg;
+ tor_asprintf(errmsg, "Could not parse %s: %s", line->key, oldmsg);
+ tor_free(oldmsg);
+ }
+ return rv;
}
/**
@@ -159,7 +167,7 @@ typed_var_copy(void *dest, const void *src, const var_type_def_t *def)
return 0;
}
char *err = NULL;
- int rv = typed_var_assign(dest, enc, &err, def, NULL);
+ int rv = typed_var_assign(dest, enc, &err, def);
if (BUG(rv < 0)) {
// LCOV_EXCL_START
log_warn(LD_BUG, "Encoded value %s was not parseable as a %s: %s",
diff --git a/src/lib/confmgt/typedvar.h b/src/lib/confmgt/typedvar.h
index 4382613833..cc90ed10a3 100644
--- a/src/lib/confmgt/typedvar.h
+++ b/src/lib/confmgt/typedvar.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -21,7 +21,7 @@ typedef struct var_type_fns_t var_type_fns_t;
typedef struct var_type_def_t var_type_def_t;
int typed_var_assign(void *target, const char *value, char **errmsg,
- const var_type_def_t *def, const char *key);
+ const var_type_def_t *def);
void typed_var_free(void *target, const var_type_def_t *def);
char *typed_var_encode(const void *value, const var_type_def_t *def);
int typed_var_copy(void *dest, const void *src, const var_type_def_t *def);
diff --git a/src/lib/confmgt/unitparse.c b/src/lib/confmgt/unitparse.c
index c3ed8285a4..61edc60694 100644
--- a/src/lib/confmgt/unitparse.c
+++ b/src/lib/confmgt/unitparse.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,8 +13,11 @@
#include "lib/confmgt/unitparse.h"
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
+#include "lib/malloc/malloc.h"
#include "lib/string/parse_int.h"
+#include "lib/string/printf.h"
#include "lib/string/util_string.h"
+#include "lib/intmath/muldiv.h"
#include <string.h>
@@ -109,22 +112,30 @@ const struct unit_table_t time_msec_units[] = {
* table <b>u</b>, then multiply the number by the unit multiplier.
* On success, set *<b>ok</b> to 1 and return this product.
* Otherwise, set *<b>ok</b> to 0.
+ *
+ * If an error (like overflow or a negative value is detected), put an error
+ * message in *<b>errmsg_out</b> if that pointer is non-NULL, and otherwise
+ * log a warning.
*/
uint64_t
-config_parse_units(const char *val, const unit_table_t *u, int *ok)
+config_parse_units(const char *val, const unit_table_t *u, int *ok,
+ char **errmsg_out)
{
uint64_t v = 0;
double d = 0;
int use_float = 0;
char *cp;
+ char *errmsg = NULL;
tor_assert(ok);
v = tor_parse_uint64(val, 10, 0, UINT64_MAX, ok, &cp);
if (!*ok || (cp && *cp == '.')) {
d = tor_parse_double(val, 0, (double)UINT64_MAX, ok, &cp);
- if (!*ok)
+ if (!*ok) {
+ tor_asprintf(&errmsg, "Unable to parse %s as a number", val);
goto done;
+ }
use_float = 1;
}
@@ -142,18 +153,55 @@ config_parse_units(const char *val, const unit_table_t *u, int *ok)
for ( ;u->unit;++u) {
if (!strcasecmp(u->unit, cp)) {
- if (use_float)
- v = (uint64_t)(u->multiplier * d);
- else
- v *= u->multiplier;
+ if (use_float) {
+ d = u->multiplier * d;
+
+ if (d < 0) {
+ tor_asprintf(&errmsg, "Got a negative value while parsing %s %s",
+ val, u->unit);
+ *ok = 0;
+ goto done;
+ }
+
+ // Some compilers may warn about casting a double to an unsigned type
+ // because they don't know if d is >= 0
+ if (d >= 0 && (d > (double)INT64_MAX || (uint64_t)d > INT64_MAX)) {
+ tor_asprintf(&errmsg, "Overflow while parsing %s %s",
+ val, u->unit);
+ *ok = 0;
+ goto done;
+ }
+
+ v = (uint64_t) d;
+ } else {
+ v = tor_mul_u64_nowrap(v, u->multiplier);
+
+ if (v > INT64_MAX) {
+ tor_asprintf(&errmsg, "Overflow while parsing %s %s",
+ val, u->unit);
+ *ok = 0;
+ goto done;
+ }
+ }
+
*ok = 1;
goto done;
}
}
- log_warn(LD_CONFIG, "Unknown unit '%s'.", cp);
+ tor_asprintf(&errmsg, "Unknown unit in %s", val);
*ok = 0;
done:
+ if (errmsg) {
+ tor_assert_nonfatal(!*ok);
+ if (errmsg_out) {
+ *errmsg_out = errmsg;
+ } else {
+ log_warn(LD_CONFIG, "%s", errmsg);
+ tor_free(errmsg);
+ }
+ }
+
if (*ok)
return v;
else
@@ -167,7 +215,7 @@ config_parse_units(const char *val, const unit_table_t *u, int *ok)
uint64_t
config_parse_memunit(const char *s, int *ok)
{
- uint64_t u = config_parse_units(s, memory_units, ok);
+ uint64_t u = config_parse_units(s, memory_units, ok, NULL);
return u;
}
@@ -179,7 +227,7 @@ int
config_parse_msec_interval(const char *s, int *ok)
{
uint64_t r;
- r = config_parse_units(s, time_msec_units, ok);
+ r = config_parse_units(s, time_msec_units, ok, NULL);
if (r > INT_MAX) {
log_warn(LD_CONFIG, "Msec interval '%s' is too long", s);
*ok = 0;
@@ -196,7 +244,7 @@ int
config_parse_interval(const char *s, int *ok)
{
uint64_t r;
- r = config_parse_units(s, time_units, ok);
+ r = config_parse_units(s, time_units, ok, NULL);
if (r > INT_MAX) {
log_warn(LD_CONFIG, "Interval '%s' is too long", s);
*ok = 0;
diff --git a/src/lib/confmgt/unitparse.h b/src/lib/confmgt/unitparse.h
index 216361a7d4..047e11b424 100644
--- a/src/lib/confmgt/unitparse.h
+++ b/src/lib/confmgt/unitparse.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -25,7 +25,8 @@ extern const unit_table_t memory_units[];
extern const unit_table_t time_units[];
extern const struct unit_table_t time_msec_units[];
-uint64_t config_parse_units(const char *val, const unit_table_t *u, int *ok);
+uint64_t config_parse_units(const char *val, const unit_table_t *u, int *ok,
+ char **errmsg_out);
uint64_t config_parse_memunit(const char *s, int *ok);
int config_parse_msec_interval(const char *s, int *ok);
diff --git a/src/lib/confmgt/var_type_def_st.h b/src/lib/confmgt/var_type_def_st.h
index aa9ded39e9..2519b86aa0 100644
--- a/src/lib/confmgt/var_type_def_st.h
+++ b/src/lib/confmgt/var_type_def_st.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -52,12 +52,9 @@ struct var_type_fns_t {
* type. On success, adjust the lvalue pointed to by <b>target</b> to hold
* that value, and return 0. On failure, set *<b>errmsg</b> to a newly
* allocated string holding an error message, and return -1.
- *
- * If not NULL, <b>key</b> is the name of the option, which may be used for
- * logging.
**/
int (*parse)(void *target, const char *value, char **errmsg,
- const void *params, const char *key);
+ const void *params);
/**
* Try to parse a single line from the head of<b>line</b> that encodes
* an object of this type. On success and failure, behave as in the parse()
diff --git a/src/lib/container/bitarray.h b/src/lib/container/bitarray.h
index 45992796af..41409e350a 100644
--- a/src/lib/container/bitarray.h
+++ b/src/lib/container/bitarray.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_BITARRAY_H
diff --git a/src/lib/container/bloomfilt.c b/src/lib/container/bloomfilt.c
index 8c61db81d6..34b1265d81 100644
--- a/src/lib/container/bloomfilt.c
+++ b/src/lib/container/bloomfilt.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/container/bloomfilt.h b/src/lib/container/bloomfilt.h
index 0ce18bd3ec..6d36056b5a 100644
--- a/src/lib/container/bloomfilt.h
+++ b/src/lib/container/bloomfilt.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_BLOOMFILT_H
diff --git a/src/lib/container/handles.h b/src/lib/container/handles.h
index ca7c94559e..6b1bbd5167 100644
--- a/src/lib/container/handles.h
+++ b/src/lib/container/handles.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -16,33 +16,33 @@
* To enable a type to have handles, add a HANDLE_ENTRY() field in its
* definition, as in:
*
- * struct walrus {
- * HANDLE_ENTRY(wlr, walrus);
+ * struct walrus_t {
+ * HANDLE_ENTRY(wlr, walrus_t);
* // ...
* };
*
- * And invoke HANDLE_DECL(wlr, walrus, [static]) to declare the handle
+ * And invoke HANDLE_DECL(wlr, walrus_t, [static]) to declare the handle
* manipulation functions (typically in a header):
*
* // opaque handle to walrus.
* typedef struct wlr_handle_t wlr_handle_t;
*
* // make a new handle
- * struct wlr_handle_t *wlr_handle_new(struct walrus *);
+ * struct wlr_handle_t *wlr_handle_new(struct walrus_t *);
*
* // release a handle
* void wlr_handle_free(wlr_handle_t *);
*
* // return the pointed-to walrus, or NULL.
- * struct walrus *wlr_handle_get(wlr_handle_t *).
+ * struct walrus_t *wlr_handle_get(wlr_handle_t *).
*
* // call this function when you're about to free the walrus;
* // it invalidates all handles. (IF YOU DON'T, YOU WILL HAVE
* // DANGLING REFERENCES)
- * void wlr_handles_clear(struct walrus *);
+ * void wlr_handles_clear(struct walrus_t *);
*
* Finally, use HANDLE_IMPL() to define the above functions in some
- * appropriate C file: HANDLE_IMPL(wlr, walrus, [static])
+ * appropriate C file: HANDLE_IMPL(wlr, walrus_t, [static])
*
**/
@@ -57,12 +57,13 @@
#define HANDLE_ENTRY(name, structname) \
struct name ## _handle_head_t *handle_head
-#define HANDLE_DECL(name, structname, linkage) \
+#define HANDLE_DECL(name, structname_t, linkage) \
typedef struct name ## _handle_t name ## _handle_t; \
- linkage name ## _handle_t *name ## _handle_new(struct structname *object); \
+ linkage name ## _handle_t *name ## _handle_new( \
+ struct structname_t *object); \
linkage void name ## _handle_free_(name ## _handle_t *); \
- linkage struct structname *name ## _handle_get(name ## _handle_t *); \
- linkage void name ## _handles_clear(struct structname *object);
+ linkage struct structname_t *name ## _handle_get(name ## _handle_t *); \
+ linkage void name ## _handles_clear(struct structname_t *object);
/*
* Implementation notes: there are lots of possible implementations here. We
diff --git a/doc/HACKING/design/01b-collections.md b/src/lib/container/lib_container.md
index def60b0f15..f4902ca44a 100644
--- a/doc/HACKING/design/01b-collections.md
+++ b/src/lib/container/lib_container.md
@@ -1,30 +1,33 @@
-
-## Collections in tor
+@dir /lib/container
+@brief lib/container: Hash tables, dynamic arrays, bit arrays, etc.
### Smartlists: Neither lists, nor especially smart.
For historical reasons, we call our dynamic-allocated array type
-"smartlist_t". It can grow or shrink as elements are added and removed.
+`smartlist_t`. It can grow or shrink as elements are added and removed.
-All smartlists hold an array of void \*. Whenever you expose a smartlist
+All smartlists hold an array of `void *`. Whenever you expose a smartlist
in an API you *must* document which types its pointers actually hold.
<!-- It would be neat to fix that, wouldn't it? -NM -->
-Smartlists are created empty with smartlist_new() and freed with
-smartlist_free(). See the containers.h module documentation for more
+Smartlists are created empty with `smartlist_new()` and freed with
+`smartlist_free()`. See the `containers.h` header documentation for more
information; there are many convenience functions for commonly needed
operations.
+For low-level operations on smartlists, see also
+\refdir{lib/smartlist_core}.
+
+<!-- TODO: WRITE more about what you can do with smartlists. -->
### Digest maps, string maps, and more.
Tor makes frequent use of maps from 160-bit digests, 256-bit digests,
-or nul-terminated strings to void \*. These types are digestmap_t,
-digest256map_t, and strmap_t respectively. See the containers.h
+or nul-terminated strings to `void *`. These types are `digestmap_t`,
+`digest256map_t`, and `strmap_t` respectively. See the containers.h
module documentation for more information.
-
### Intrusive lists and hashtables
For performance-sensitive cases, we sometimes want to use "intrusive"
@@ -32,12 +35,15 @@ collections: ones where the bookkeeping pointers are stuck inside the
structures that belong to the collection. If you've used the
BSD-style sys/queue.h macros, you'll be familiar with these.
-Unfortunately, the sys/queue.h macros vary significantly between the
+Unfortunately, the `sys/queue.h` macros vary significantly between the
platforms that have them, so we provide our own variants in
-src/ext/tor_queue.h .
+`ext/tor_queue.h`.
-We also provide an intrusive hashtable implementation in src/ext/ht.h
-. When you're using it, you'll need to define your own hash
+We also provide an intrusive hashtable implementation in `ext/ht.h`.
+When you're using it, you'll need to define your own hash
functions. If attacker-induced collisions are a worry here, use the
cryptographic siphash24g function to extract hashes.
+<!-- TODO: WRITE about bloom filters, namemaps, bit-arrays, order functions.
+-->
+
diff --git a/src/lib/container/map.c b/src/lib/container/map.c
index fde33d6ace..c3fb0b5c8a 100644
--- a/src/lib/container/map.c
+++ b/src/lib/container/map.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/container/map.h b/src/lib/container/map.h
index 9da1d3072c..989ecfad80 100644
--- a/src/lib/container/map.h
+++ b/src/lib/container/map.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_MAP_H
@@ -17,22 +17,23 @@
#include "ext/siphash.h"
-#define DECLARE_MAP_FNS(maptype, keytype, prefix) \
- typedef struct maptype maptype; \
+#define DECLARE_MAP_FNS(mapname_t, keytype, prefix) \
+ typedef struct mapname_t mapname_t; \
typedef struct prefix##entry_t *prefix##iter_t; \
- MOCK_DECL(maptype*, prefix##new, (void)); \
- void* prefix##set(maptype *map, keytype key, void *val); \
- void* prefix##get(const maptype *map, keytype key); \
- void* prefix##remove(maptype *map, keytype key); \
- MOCK_DECL(void, prefix##free_, (maptype *map, void (*free_val)(void*))); \
- int prefix##isempty(const maptype *map); \
- int prefix##size(const maptype *map); \
- prefix##iter_t *prefix##iter_init(maptype *map); \
- 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); \
+ MOCK_DECL(mapname_t*, prefix##new, (void)); \
+ void* prefix##set(mapname_t *map, keytype key, void *val); \
+ void* prefix##get(const mapname_t *map, keytype key); \
+ void* prefix##remove(mapname_t *map, keytype key); \
+ MOCK_DECL(void, prefix##free_, (mapname_t *map, void (*free_val)(void*))); \
+ int prefix##isempty(const mapname_t *map); \
+ int prefix##size(const mapname_t *map); \
+ prefix##iter_t *prefix##iter_init(mapname_t *map); \
+ prefix##iter_t *prefix##iter_next(mapname_t *map, prefix##iter_t *iter); \
+ prefix##iter_t *prefix##iter_next_rmv(mapname_t *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(const maptype *map)
+ void prefix##assert_ok(const mapname_t *map)
/* Map from const char * to void *. Implemented with a hash table. */
DECLARE_MAP_FNS(strmap_t, const char *, strmap_);
@@ -42,9 +43,9 @@ DECLARE_MAP_FNS(digestmap_t, const char *, digestmap_);
* table. */
DECLARE_MAP_FNS(digest256map_t, const uint8_t *, digest256map_);
-#define MAP_FREE_AND_NULL(maptype, map, fn) \
+#define MAP_FREE_AND_NULL(mapname_t, map, fn) \
do { \
- maptype ## _free_((map), (fn)); \
+ mapname_t ## _free_((map), (fn)); \
(map) = NULL; \
} while (0)
@@ -183,62 +184,62 @@ void* strmap_set_lc(strmap_t *map, const char *key, void *val);
void* strmap_get_lc(const strmap_t *map, const char *key);
void* strmap_remove_lc(strmap_t *map, const char *key);
-#define DECLARE_TYPED_DIGESTMAP_FNS(prefix, maptype, valtype) \
- typedef struct maptype maptype; \
+#define DECLARE_TYPED_DIGESTMAP_FNS(prefix, mapname_t, valtype) \
+ typedef struct mapname_t mapname_t; \
typedef struct prefix##iter_t *prefix##iter_t; \
- ATTR_UNUSED static inline maptype* \
+ ATTR_UNUSED static inline mapname_t* \
prefix##new(void) \
{ \
- return (maptype*)digestmap_new(); \
+ return (mapname_t*)digestmap_new(); \
} \
ATTR_UNUSED static inline digestmap_t* \
- prefix##to_digestmap(maptype *map) \
+ prefix##to_digestmap(mapname_t *map) \
{ \
return (digestmap_t*)map; \
} \
ATTR_UNUSED static inline valtype* \
- prefix##get(maptype *map, const char *key) \
+ prefix##get(mapname_t *map, const char *key) \
{ \
return (valtype*)digestmap_get((digestmap_t*)map, key); \
} \
ATTR_UNUSED static inline valtype* \
- prefix##set(maptype *map, const char *key, valtype *val) \
+ prefix##set(mapname_t *map, const char *key, valtype *val) \
{ \
return (valtype*)digestmap_set((digestmap_t*)map, key, val); \
} \
ATTR_UNUSED static inline valtype* \
- prefix##remove(maptype *map, const char *key) \
+ prefix##remove(mapname_t *map, const char *key) \
{ \
return (valtype*)digestmap_remove((digestmap_t*)map, key); \
} \
ATTR_UNUSED static inline void \
- prefix##f##ree_(maptype *map, void (*free_val)(void*)) \
+ prefix##f##ree_(mapname_t *map, void (*free_val)(void*)) \
{ \
digestmap_free_((digestmap_t*)map, free_val); \
} \
ATTR_UNUSED static inline int \
- prefix##isempty(maptype *map) \
+ prefix##isempty(mapname_t *map) \
{ \
return digestmap_isempty((digestmap_t*)map); \
} \
ATTR_UNUSED static inline int \
- prefix##size(maptype *map) \
+ prefix##size(mapname_t *map) \
{ \
return digestmap_size((digestmap_t*)map); \
} \
ATTR_UNUSED static inline \
- prefix##iter_t *prefix##iter_init(maptype *map) \
+ prefix##iter_t *prefix##iter_init(mapname_t *map) \
{ \
return (prefix##iter_t*) digestmap_iter_init((digestmap_t*)map); \
} \
ATTR_UNUSED static inline \
- prefix##iter_t *prefix##iter_next(maptype *map, prefix##iter_t *iter) \
+ prefix##iter_t *prefix##iter_next(mapname_t *map, prefix##iter_t *iter) \
{ \
return (prefix##iter_t*) digestmap_iter_next( \
(digestmap_t*)map, (digestmap_iter_t*)iter); \
} \
ATTR_UNUSED static inline prefix##iter_t* \
- prefix##iter_next_rmv(maptype *map, prefix##iter_t *iter) \
+ prefix##iter_next_rmv(mapname_t *map, prefix##iter_t *iter) \
{ \
return (prefix##iter_t*) digestmap_iter_next_rmv( \
(digestmap_t*)map, (digestmap_iter_t*)iter); \
diff --git a/src/lib/container/namemap.c b/src/lib/container/namemap.c
index a90057b32c..28695ee3a1 100644
--- a/src/lib/container/namemap.c
+++ b/src/lib/container/namemap.c
@@ -1,8 +1,13 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file namemap.c
+ * @brief Mappings between identifiers and 16-bit ints.
+ **/
+
#include "orconfig.h"
#include "lib/container/smartlist.h"
#include "lib/container/namemap.h"
diff --git a/src/lib/container/namemap.h b/src/lib/container/namemap.h
index b96bc13f3a..b451c18c68 100644
--- a/src/lib/container/namemap.h
+++ b/src/lib/container/namemap.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_NAMEMAP_H
diff --git a/src/lib/container/namemap_st.h b/src/lib/container/namemap_st.h
index 5008fd5855..39aa85cc09 100644
--- a/src/lib/container/namemap_st.h
+++ b/src/lib/container/namemap_st.h
@@ -1,11 +1,16 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef NAMEMAP_ST_H
#define NAMEMAP_ST_H
+/**
+ * @file namemap_st.h
+ * @brief Internal declarations for namemap structure.
+ **/
+
#include "lib/cc/compat_compiler.h"
#include "ext/ht.h"
@@ -28,7 +33,9 @@ struct namemap_t {
struct smartlist_t *names;
};
+#ifndef COCCI
/** Macro to initialize a namemap. */
#define NAMEMAP_INIT() { HT_INITIALIZER(), NULL }
+#endif
#endif /* !defined(NAMEMAP_ST_H) */
diff --git a/src/lib/container/order.c b/src/lib/container/order.c
index f6503a124e..cac241f027 100644
--- a/src/lib/container/order.c
+++ b/src/lib/container/order.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/container/order.h b/src/lib/container/order.h
index 3f2fd054a0..5bca095f35 100644
--- a/src/lib/container/order.h
+++ b/src/lib/container/order.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_ORDER_H
diff --git a/src/lib/container/smartlist.c b/src/lib/container/smartlist.c
index 2b71c11287..7784f83957 100644
--- a/src/lib/container/smartlist.c
+++ b/src/lib/container/smartlist.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -652,7 +652,7 @@ smartlist_sort_pointers(smartlist_t *sl)
#define LEFT_CHILD(i) ( 2*(i) + 1 )
#define RIGHT_CHILD(i) ( 2*(i) + 2 )
#define PARENT(i) ( ((i)-1) / 2 )
-/** }@ */
+/** @} */
/** @{ */
/** Helper macros for heaps: Given a local variable <b>idx_field_offset</b>
diff --git a/src/lib/container/smartlist.h b/src/lib/container/smartlist.h
index 25638e4b22..458d564cd5 100644
--- a/src/lib/container/smartlist.h
+++ b/src/lib/container/smartlist.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_SMARTLIST_H
@@ -92,6 +92,7 @@ char *smartlist_join_strings2(smartlist_t *sl, const char *join,
size_t join_len, int terminate, size_t *len_out)
ATTR_MALLOC;
+#ifndef COCCI
/* Helper: Given two lists of items, possibly of different types, such that
* both lists are sorted on some common field (as determined by a comparison
* expression <b>cmpexpr</b>), and such that one list (<b>sl1</b>) has no
@@ -165,5 +166,6 @@ char *smartlist_join_strings2(smartlist_t *sl, const char *join,
#define SMARTLIST_FOREACH_JOIN_END(var1, var2) \
} \
STMT_END
+#endif /* !defined(COCCI) */
#endif /* !defined(TOR_SMARTLIST_H) */
diff --git a/src/lib/crypt_ops/.may_include b/src/lib/crypt_ops/.may_include
index 0739699686..810e777271 100644
--- a/src/lib/crypt_ops/.may_include
+++ b/src/lib/crypt_ops/.may_include
@@ -1,6 +1,7 @@
orconfig.h
lib/arch/*.h
lib/cc/*.h
+lib/conf/*.h
lib/container/*.h
lib/crypt_ops/*.h
lib/ctime/*.h
@@ -17,6 +18,8 @@ lib/testsupport/*.h
lib/thread/*.h
lib/log/*.h
+lib/crypt_ops/*.inc
+
trunnel/pwbox.h
keccak-tiny/*.h
diff --git a/src/lib/crypt_ops/aes.h b/src/lib/crypt_ops/aes.h
index 7c774062d9..c25417b4e6 100644
--- a/src/lib/crypt_ops/aes.h
+++ b/src/lib/crypt_ops/aes.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/* Implements a minimal interface to counter-mode AES. */
@@ -16,7 +16,7 @@
#include "lib/cc/torint.h"
#include "lib/malloc/malloc.h"
-typedef struct aes_cnt_cipher aes_cnt_cipher_t;
+typedef struct aes_cnt_cipher_t aes_cnt_cipher_t;
aes_cnt_cipher_t* aes_new_cipher(const uint8_t *key, const uint8_t *iv,
int key_bits);
diff --git a/src/lib/crypt_ops/aes_nss.c b/src/lib/crypt_ops/aes_nss.c
index 4eda5e5902..71d2f01449 100644
--- a/src/lib/crypt_ops/aes_nss.c
+++ b/src/lib/crypt_ops/aes_nss.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,10 +15,10 @@
#include "lib/crypt_ops/crypto_util.h"
#include "lib/log/util_bug.h"
-DISABLE_GCC_WARNING(strict-prototypes)
+DISABLE_GCC_WARNING("-Wstrict-prototypes")
#include <pk11pub.h>
#include <secerr.h>
-ENABLE_GCC_WARNING(strict-prototypes)
+ENABLE_GCC_WARNING("-Wstrict-prototypes")
aes_cnt_cipher_t *
aes_new_cipher(const uint8_t *key, const uint8_t *iv,
diff --git a/src/lib/crypt_ops/aes_openssl.c b/src/lib/crypt_ops/aes_openssl.c
index 64564892ad..502f7703bd 100644
--- a/src/lib/crypt_ops/aes_openssl.c
+++ b/src/lib/crypt_ops/aes_openssl.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -28,7 +28,7 @@
#error "We require OpenSSL >= 1.0.0"
#endif
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <stdlib.h>
#include <string.h>
@@ -37,9 +37,8 @@ DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/engine.h>
#include <openssl/modes.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
-#include "lib/crypt_ops/aes.h"
#include "lib/log/log.h"
#include "lib/ctime/di_ops.h"
@@ -154,7 +153,7 @@ evaluate_ctr_for_aes(void)
/* Interface to AES code, and counter implementation */
/** Implements an AES counter-mode cipher. */
-struct aes_cnt_cipher {
+struct aes_cnt_cipher_t {
/** This next element (however it's defined) is the AES key. */
union {
EVP_CIPHER_CTX evp;
diff --git a/src/lib/crypt_ops/certs.md b/src/lib/crypt_ops/certs.md
new file mode 100644
index 0000000000..2768548b2a
--- /dev/null
+++ b/src/lib/crypt_ops/certs.md
@@ -0,0 +1,30 @@
+
+@page certificates Certificates in Tor.
+
+We have, alas, several certificate types in Tor.
+
+The tor_x509_cert_t type represents an X.509 certificate. This document
+won't explain X.509 to you -- possibly, no document can. (OTOH, Peter
+Gutmann's "x.509 style guide", though severely dated, does a good job of
+explaining how awful x.509 can be.) Do not introduce any new usages of
+X.509. Right now we only use it in places where TLS forces us to do so.
+See x509.c for more information about using this type.
+
+
+The authority_cert_t type is used only for directory authority keys. It
+has a medium-term signing key (which the authorities actually keep
+online) signed by a long-term identity key (which the authority operator
+had really better be keeping offline). Don't use it for any new kind of
+certificate.
+
+For new places where you need a certificate, consider tor_cert_t: it
+represents a typed and dated _something_ signed by an Ed25519 key. The
+format is described in tor-spec. Unlike x.509, you can write it on a
+napkin. The torcert.c file is used for manipulating these certificates and
+their associated keys.
+
+(Additionally, the Tor directory design uses a fairly wide variety of
+documents that include keys and which are signed by keys. You can
+consider these documents to be an additional kind of certificate if you
+want.)
+
diff --git a/src/lib/crypt_ops/compat_openssl.h b/src/lib/crypt_ops/compat_openssl.h
index 61ca51315f..5fd073bea1 100644
--- a/src/lib/crypt_ops/compat_openssl.h
+++ b/src/lib/crypt_ops/compat_openssl.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_COMPAT_OPENSSL_H
diff --git a/src/lib/crypt_ops/crypto_cipher.c b/src/lib/crypt_ops/crypto_cipher.c
index 7bc2edad54..0a24a580ae 100644
--- a/src/lib/crypt_ops/crypto_cipher.c
+++ b/src/lib/crypt_ops/crypto_cipher.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_cipher.h b/src/lib/crypt_ops/crypto_cipher.h
index 88d63c1df2..1e22a7c138 100644
--- a/src/lib/crypt_ops/crypto_cipher.h
+++ b/src/lib/crypt_ops/crypto_cipher.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -25,7 +25,7 @@
/** Length of our symmetric cipher's keys of 256-bit. */
#define CIPHER256_KEY_LEN 32
-typedef struct aes_cnt_cipher crypto_cipher_t;
+typedef struct aes_cnt_cipher_t crypto_cipher_t;
/* environment setup */
crypto_cipher_t *crypto_cipher_new(const char *key);
diff --git a/src/lib/crypt_ops/crypto_curve25519.c b/src/lib/crypt_ops/crypto_curve25519.c
index de4e17a296..2a2589f07d 100644
--- a/src/lib/crypt_ops/crypto_curve25519.c
+++ b/src/lib/crypt_ops/crypto_curve25519.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_curve25519.h b/src/lib/crypt_ops/crypto_curve25519.h
index cd23169cd5..154a0b94bc 100644
--- a/src/lib/crypt_ops/crypto_curve25519.h
+++ b/src/lib/crypt_ops/crypto_curve25519.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_dh.c b/src/lib/crypt_ops/crypto_dh.c
index 4be7948761..086aceed6f 100644
--- a/src/lib/crypt_ops/crypto_dh.c
+++ b/src/lib/crypt_ops/crypto_dh.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_dh.h b/src/lib/crypt_ops/crypto_dh.h
index 850d50c7ae..2a0e1f6912 100644
--- a/src/lib/crypt_ops/crypto_dh.h
+++ b/src/lib/crypt_ops/crypto_dh.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_dh_nss.c b/src/lib/crypt_ops/crypto_dh_nss.c
index 379eb84a4f..018db8bf43 100644
--- a/src/lib/crypt_ops/crypto_dh_nss.c
+++ b/src/lib/crypt_ops/crypto_dh_nss.c
@@ -1,11 +1,11 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file crypto_dh_nss.h
+ * \file crypto_dh_nss.c
*
* \brief NSS implementation of Diffie-Hellman over Z_p.
**/
diff --git a/src/lib/crypt_ops/crypto_dh_openssl.c b/src/lib/crypt_ops/crypto_dh_openssl.c
index 8ae97373e8..c5f7271596 100644
--- a/src/lib/crypt_ops/crypto_dh_openssl.c
+++ b/src/lib/crypt_ops/crypto_dh_openssl.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -17,11 +17,11 @@
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/dh.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/bn.h>
#include <string.h>
@@ -103,7 +103,7 @@ crypto_validate_dh_params(const BIGNUM *p, const BIGNUM *g)
#endif /* 0 */
/**
- * Helper: convert <b>hex<b> to a bignum, and return it. Assert that the
+ * Helper: convert <b>hex</b> to a bignum, and return it. Assert that the
* operation was successful.
*/
static BIGNUM *
diff --git a/src/lib/crypt_ops/crypto_digest.c b/src/lib/crypt_ops/crypto_digest.c
index ba226f8756..7775e69410 100644
--- a/src/lib/crypt_ops/crypto_digest.c
+++ b/src/lib/crypt_ops/crypto_digest.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -150,6 +150,9 @@ struct crypto_xof_t {
*/
EVP_MD_CTX *ctx;
#else /* !defined(OPENSSL_HAS_SHAKE3_EVP) */
+ /**
+ * State of the Keccak sponge for the SHAKE-256 computation.
+ **/
keccak_state s;
#endif /* defined(OPENSSL_HAS_SHAKE3_EVP) */
};
diff --git a/src/lib/crypt_ops/crypto_digest.h b/src/lib/crypt_ops/crypto_digest.h
index 5869db7800..eefd2e3f0a 100644
--- a/src/lib/crypt_ops/crypto_digest.h
+++ b/src/lib/crypt_ops/crypto_digest.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -38,6 +38,9 @@
/** Length of hex encoding of SHA512 digest, not including final NUL. */
#define HEX_DIGEST512_LEN 128
+/**
+ * An identifier for a cryptographic digest algorithm.
+ **/
typedef enum {
DIGEST_SHA1 = 0,
DIGEST_SHA256 = 1,
@@ -45,16 +48,31 @@ typedef enum {
DIGEST_SHA3_256 = 3,
DIGEST_SHA3_512 = 4,
} digest_algorithm_t;
+/** Number of digest algorithms that we know */
#define N_DIGEST_ALGORITHMS (DIGEST_SHA3_512+1)
+/** Number of digest algorithms to compute when computing "all the
+ * commonly used digests."
+ *
+ * (This is used in common_digests_t and related functions.)
+ */
#define N_COMMON_DIGEST_ALGORITHMS (DIGEST_SHA256+1)
+/**
+ * Bytes of storage needed to record the state of an in-progress SHA-1 digest.
+ *
+ * This is a deliberate overestimate.
+ **/
#define DIGEST_CHECKPOINT_BYTES (SIZEOF_VOID_P + 512)
+
/** Structure used to temporarily save the a digest object. Only implemented
* for SHA1 digest for now. */
typedef struct crypto_digest_checkpoint_t {
#ifdef ENABLE_NSS
+ /** The number of bytes used in <b>mem</b>. */
unsigned int bytes_used;
#endif
+ /** A buffer to store the SHA1 state. Its contents are unspecified, and
+ * are managed by the underlying crypto library.*/
uint8_t mem[DIGEST_CHECKPOINT_BYTES];
} crypto_digest_checkpoint_t;
@@ -67,10 +85,19 @@ typedef struct crypto_digest_checkpoint_t {
* once.
**/
typedef struct {
+ /** An array of digest outputs, one for each "common" digest algorithm. */
char d[N_COMMON_DIGEST_ALGORITHMS][DIGEST256_LEN];
} common_digests_t;
+/**
+ * State for computing a digest over a stream of data.
+ **/
typedef struct crypto_digest_t crypto_digest_t;
+
+/**
+ * State for computing an "extendable-output function" (like SHAKE) over a
+ * stream of data, and/or streaming the output.
+ **/
typedef struct crypto_xof_t crypto_xof_t;
struct smartlist_t;
@@ -97,6 +124,9 @@ crypto_digest_t *crypto_digest_new(void);
crypto_digest_t *crypto_digest256_new(digest_algorithm_t algorithm);
crypto_digest_t *crypto_digest512_new(digest_algorithm_t algorithm);
void crypto_digest_free_(crypto_digest_t *digest);
+/**
+ * Release all storage held in <b>d</b>, and set it to NULL.
+ **/
#define crypto_digest_free(d) \
FREE_AND_NULL(crypto_digest_t, crypto_digest_free_, (d))
void crypto_digest_add_bytes(crypto_digest_t *digest, const char *data,
@@ -122,6 +152,9 @@ crypto_xof_t *crypto_xof_new(void);
void crypto_xof_add_bytes(crypto_xof_t *xof, const uint8_t *data, size_t len);
void crypto_xof_squeeze_bytes(crypto_xof_t *xof, uint8_t *out, size_t len);
void crypto_xof_free_(crypto_xof_t *xof);
+/**
+ * Release all storage held in <b>xof</b>, and set it to NULL.
+ **/
#define crypto_xof_free(xof) \
FREE_AND_NULL(crypto_xof_t, crypto_xof_free_, (xof))
void crypto_xof(uint8_t *output, size_t output_len,
diff --git a/src/lib/crypt_ops/crypto_digest_nss.c b/src/lib/crypt_ops/crypto_digest_nss.c
index afa8f6d5ef..92c20fe9e8 100644
--- a/src/lib/crypt_ops/crypto_digest_nss.c
+++ b/src/lib/crypt_ops/crypto_digest_nss.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -23,9 +23,9 @@
#include "lib/arch/bytes.h"
-DISABLE_GCC_WARNING(strict-prototypes)
+DISABLE_GCC_WARNING("-Wstrict-prototypes")
#include <pk11pub.h>
-ENABLE_GCC_WARNING(strict-prototypes)
+ENABLE_GCC_WARNING("-Wstrict-prototypes")
/**
* Convert a digest_algorithm_t (used by tor) to a HashType (used by NSS).
@@ -44,7 +44,11 @@ digest_alg_to_nss_oid(digest_algorithm_t alg)
}
}
-/* Helper: get an unkeyed digest via pk11wrap */
+/** Helper: Compute an unkeyed digest of the <b>msg_len</b> bytes at
+ * <b>msg</b>, using the digest algorithm specified by <b>alg</b>.
+ * Store the result in the <b>len_out</b>-byte buffer at <b>digest</b>.
+ * Return the number of bytes written on success, and -1 on failure.
+ **/
static int
digest_nss_internal(SECOidTag alg,
char *digest, unsigned len_out,
diff --git a/src/lib/crypt_ops/crypto_digest_openssl.c b/src/lib/crypt_ops/crypto_digest_openssl.c
index 50a8ff4d27..11189c7fb2 100644
--- a/src/lib/crypt_ops/crypto_digest_openssl.c
+++ b/src/lib/crypt_ops/crypto_digest_openssl.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -25,12 +25,12 @@
#include "lib/crypt_ops/crypto_openssl_mgt.h"
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/hmac.h>
#include <openssl/sha.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
/* Crypto digest functions */
@@ -147,9 +147,9 @@ crypto_digest_get_algorithm(crypto_digest_t *digest)
static size_t
crypto_digest_alloc_bytes(digest_algorithm_t alg)
{
- /* Helper: returns the number of bytes in the 'f' field of 'st' */
+ /** Helper: returns the number of bytes in the 'f' field of 'st' */
#define STRUCT_FIELD_SIZE(st, f) (sizeof( ((st*)0)->f ))
- /* Gives the length of crypto_digest_t through the end of the field 'd' */
+ /** Gives the length of crypto_digest_t through the end of the field 'd' */
#define END_OF_FIELD(f) (offsetof(crypto_digest_t, f) + \
STRUCT_FIELD_SIZE(crypto_digest_t, f))
switch (alg) {
@@ -519,4 +519,3 @@ crypto_hmac_sha256(char *hmac_out,
(unsigned char*)hmac_out, NULL);
tor_assert(rv);
}
-
diff --git a/src/lib/crypt_ops/crypto_ed25519.c b/src/lib/crypt_ops/crypto_ed25519.c
index c28111a5a5..f242c7011e 100644
--- a/src/lib/crypt_ops/crypto_ed25519.c
+++ b/src/lib/crypt_ops/crypto_ed25519.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_ed25519.h b/src/lib/crypt_ops/crypto_ed25519.h
index 325b28244d..346de464e3 100644
--- a/src/lib/crypt_ops/crypto_ed25519.h
+++ b/src/lib/crypt_ops/crypto_ed25519.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_format.c b/src/lib/crypt_ops/crypto_format.c
index 118cd79045..92b8b9372e 100644
--- a/src/lib/crypt_ops/crypto_format.c
+++ b/src/lib/crypt_ops/crypto_format.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_format.h b/src/lib/crypt_ops/crypto_format.h
index b4b3aa189c..91da137e1c 100644
--- a/src/lib/crypt_ops/crypto_format.h
+++ b/src/lib/crypt_ops/crypto_format.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_hkdf.c b/src/lib/crypt_ops/crypto_hkdf.c
index e0d241d4ea..7b02820087 100644
--- a/src/lib/crypt_ops/crypto_hkdf.c
+++ b/src/lib/crypt_ops/crypto_hkdf.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_hkdf.h b/src/lib/crypt_ops/crypto_hkdf.h
index 2994d18e3d..404f548774 100644
--- a/src/lib/crypt_ops/crypto_hkdf.h
+++ b/src/lib/crypt_ops/crypto_hkdf.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_init.c b/src/lib/crypt_ops/crypto_init.c
index a16bf4e11a..f09bf07c4d 100644
--- a/src/lib/crypt_ops/crypto_init.c
+++ b/src/lib/crypt_ops/crypto_init.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -23,6 +23,9 @@
#include "lib/crypt_ops/crypto_nss_mgt.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_sys.h"
+#include "lib/crypt_ops/crypto_options_st.h"
+#include "lib/conf/conftypes.h"
+#include "lib/log/util_bug.h"
#include "lib/subsys/subsys.h"
@@ -252,6 +255,66 @@ subsys_crypto_thread_cleanup(void)
crypto_thread_cleanup();
}
+/** Magic number for crypto_options_t. */
+#define CRYPTO_OPTIONS_MAGIC 0x68757368
+
+/**
+ * Return 0 if <b>arg</b> is a valid crypto_options_t. Otherwise return -1
+ * and set *<b>msg_out</b> to a freshly allocated error string.
+ **/
+static int
+crypto_options_validate(const void *arg, char **msg_out)
+{
+ const crypto_options_t *opt = arg;
+ tor_assert(opt->magic == CRYPTO_OPTIONS_MAGIC);
+ tor_assert(msg_out);
+
+ if (opt->AccelDir && !opt->AccelName) {
+ *msg_out = tor_strdup("Can't use hardware crypto accelerator dir "
+ "without engine name.");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Declare the options field table for crypto_options */
+#define CONF_CONTEXT LL_TABLE
+#include "lib/crypt_ops/crypto_options.inc"
+#undef CONF_CONTEXT
+
+/**
+ * Declares the configuration options for this module.
+ **/
+static const config_format_t crypto_options_fmt = {
+ .size = sizeof(crypto_options_t),
+ .magic = { "crypto_options_t",
+ CRYPTO_OPTIONS_MAGIC,
+ offsetof(crypto_options_t, magic) },
+ .vars = crypto_options_t_vars,
+ .validate_fn = crypto_options_validate,
+};
+
+/**
+ * Invoked from subsysmgr.c when a new set of options arrives.
+ **/
+static int
+crypto_set_options(void *arg)
+{
+ const crypto_options_t *options = arg;
+ const bool hardware_accel = options->HardwareAccel || options->AccelName;
+
+ // This call already checks for crypto_global_initialized_, so it
+ // will only initialize the subsystem the first time it's called.
+ if (crypto_global_init(hardware_accel,
+ options->AccelName,
+ options->AccelDir)) {
+ log_err(LD_BUG, "Unable to initialize the crypto subsystem. Exiting.");
+ return -1;
+ }
+ return 0;
+}
+
const struct subsys_fns_t sys_crypto = {
.name = "crypto",
.supported = true,
@@ -261,4 +324,7 @@ const struct subsys_fns_t sys_crypto = {
.prefork = subsys_crypto_prefork,
.postfork = subsys_crypto_postfork,
.thread_cleanup = subsys_crypto_thread_cleanup,
+
+ .options_format = &crypto_options_fmt,
+ .set_options = crypto_set_options,
};
diff --git a/src/lib/crypt_ops/crypto_init.h b/src/lib/crypt_ops/crypto_init.h
index 8de3eb03ed..b11e2e34bf 100644
--- a/src/lib/crypt_ops/crypto_init.h
+++ b/src/lib/crypt_ops/crypto_init.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_nss_mgt.c b/src/lib/crypt_ops/crypto_nss_mgt.c
index 0179126e38..d82e51249c 100644
--- a/src/lib/crypt_ops/crypto_nss_mgt.c
+++ b/src/lib/crypt_ops/crypto_nss_mgt.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -16,7 +16,7 @@
#include "lib/log/util_bug.h"
#include "lib/string/printf.h"
-DISABLE_GCC_WARNING(strict-prototypes)
+DISABLE_GCC_WARNING("-Wstrict-prototypes")
#include <nss.h>
#include <pk11func.h>
#include <ssl.h>
@@ -24,7 +24,7 @@ DISABLE_GCC_WARNING(strict-prototypes)
#include <prerror.h>
#include <prtypes.h>
#include <prinit.h>
-ENABLE_GCC_WARNING(strict-prototypes)
+ENABLE_GCC_WARNING("-Wstrict-prototypes")
const char *
crypto_nss_get_version_str(void)
diff --git a/src/lib/crypt_ops/crypto_nss_mgt.h b/src/lib/crypt_ops/crypto_nss_mgt.h
index 4cfa9b42a4..8686b1b8aa 100644
--- a/src/lib/crypt_ops/crypto_nss_mgt.h
+++ b/src/lib/crypt_ops/crypto_nss_mgt.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_ope.c b/src/lib/crypt_ops/crypto_ope.c
index ed832d852e..4cacb3dd98 100644
--- a/src/lib/crypt_ops/crypto_ope.c
+++ b/src/lib/crypt_ops/crypto_ope.c
@@ -1,8 +1,9 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * A rudimentary order-preserving encryption scheme.
+ * @file crypto_ope.c
+ * @brief A rudimentary order-preserving encryption scheme.
*
* To compute the encryption of N, this scheme uses an AES-CTR stream to
* generate M-byte values, and adds the first N of them together. (+1 each to
@@ -143,7 +144,7 @@ crypto_ope_new(const uint8_t *key)
return ope;
}
-/** Free all storage held in <>ope</b>. */
+/** Free all storage held in <b>ope</b>. */
void
crypto_ope_free_(crypto_ope_t *ope)
{
diff --git a/src/lib/crypt_ops/crypto_ope.h b/src/lib/crypt_ops/crypto_ope.h
index 9778dfe0f0..7498ea6a2e 100644
--- a/src/lib/crypt_ops/crypto_ope.h
+++ b/src/lib/crypt_ops/crypto_ope.h
@@ -1,6 +1,11 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file crypto_ope.h
+ * @brief header for crypto_ope.c
+ **/
+
#ifndef CRYPTO_OPE_H
#define CRYPTO_OPE_H
@@ -37,10 +42,10 @@ void crypto_ope_free_(crypto_ope_t *ope);
uint64_t crypto_ope_encrypt(const crypto_ope_t *ope, int plaintext);
#ifdef CRYPTO_OPE_PRIVATE
-struct aes_cnt_cipher;
-STATIC struct aes_cnt_cipher *ope_get_cipher(const crypto_ope_t *ope,
+struct aes_cnt_cipher_t;
+STATIC struct aes_cnt_cipher_t *ope_get_cipher(const crypto_ope_t *ope,
uint32_t initial_idx);
-STATIC uint64_t sum_values_from_cipher(struct aes_cnt_cipher *c, size_t n);
+STATIC uint64_t sum_values_from_cipher(struct aes_cnt_cipher_t *c, size_t n);
#endif /* defined(CRYPTO_OPE_PRIVATE) */
#endif /* !defined(CRYPTO_OPE_H) */
diff --git a/src/lib/crypt_ops/crypto_openssl_mgt.c b/src/lib/crypt_ops/crypto_openssl_mgt.c
index f51309219a..f2f5a55d05 100644
--- a/src/lib/crypt_ops/crypto_openssl_mgt.c
+++ b/src/lib/crypt_ops/crypto_openssl_mgt.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -21,7 +21,7 @@
#include "lib/testsupport/testsupport.h"
#include "lib/thread/threads.h"
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/err.h>
#include <openssl/rsa.h>
@@ -36,7 +36,7 @@ DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/crypto.h>
#include <openssl/ssl.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
#include <string.h>
@@ -121,10 +121,12 @@ crypto_openssl_get_header_version_str(void)
return crypto_openssl_header_version_str;
}
+#ifndef COCCI
#ifndef OPENSSL_THREADS
-#error OpenSSL has been built without thread support. Tor requires an \
- OpenSSL library with thread support enabled.
+#error "OpenSSL has been built without thread support. Tor requires an \
+ OpenSSL library with thread support enabled."
#endif
+#endif /* !defined(COCCI) */
#ifndef NEW_THREAD_API
/** Helper: OpenSSL uses this callback to manipulate mutexes. */
@@ -273,8 +275,14 @@ log_engine(const char *fn, ENGINE *e)
}
#endif /* !defined(DISABLE_ENGINES) */
-/** Initialize engines for openssl (if enabled). */
-static void
+/** Initialize engines for openssl (if enabled). Load all the built-in
+ * engines, along with the one called <b>accelName</b> (which may be NULL).
+ * If <b>accelName</b> is prefixed with "!", then it is required: return -1
+ * if it can't be loaded. Otherwise return 0.
+ *
+ * If <b>accelDir</b> is not NULL, it is the path from which the engine should
+ * be loaded. */
+static int
crypto_openssl_init_engines(const char *accelName,
const char *accelDir)
{
@@ -282,7 +290,13 @@ crypto_openssl_init_engines(const char *accelName,
(void)accelName;
(void)accelDir;
log_warn(LD_CRYPTO, "No OpenSSL hardware acceleration support enabled.");
-#else
+ if (accelName && accelName[0] == '!') {
+ log_warn(LD_CRYPTO, "Unable to load required dynamic OpenSSL engine "
+ "\"%s\".", accelName+1);
+ return -1;
+ }
+ return 0;
+#else /* !defined(DISABLE_ENGINES) */
ENGINE *e = NULL;
log_info(LD_CRYPTO, "Initializing OpenSSL engine support.");
@@ -290,6 +304,9 @@ crypto_openssl_init_engines(const char *accelName,
ENGINE_register_all_complete();
if (accelName) {
+ const bool required = accelName[0] == '!';
+ if (required)
+ ++accelName;
if (accelDir) {
log_info(LD_CRYPTO, "Trying to load dynamic OpenSSL engine \"%s\""
" via path \"%s\".", accelName, accelDir);
@@ -300,8 +317,11 @@ crypto_openssl_init_engines(const char *accelName,
e = ENGINE_by_id(accelName);
}
if (!e) {
- log_warn(LD_CRYPTO, "Unable to load dynamic OpenSSL engine \"%s\".",
+ log_warn(LD_CRYPTO, "Unable to load %sdynamic OpenSSL engine \"%s\".",
+ required?"required ":"",
accelName);
+ if (required)
+ return -1;
} else {
log_info(LD_CRYPTO, "Loaded dynamic OpenSSL engine \"%s\".",
accelName);
@@ -338,6 +358,7 @@ crypto_openssl_init_engines(const char *accelName,
#ifdef NID_aes_256_gcm
log_engine("AES-256-GCM", ENGINE_get_cipher_engine(NID_aes_256_gcm));
#endif
+ return 0;
#endif /* defined(DISABLE_ENGINES) */
}
@@ -348,7 +369,8 @@ crypto_openssl_late_init(int useAccel, const char *accelName,
const char *accelDir)
{
if (useAccel > 0) {
- crypto_openssl_init_engines(accelName, accelDir);
+ if (crypto_openssl_init_engines(accelName, accelDir) < 0)
+ return -1;
} else {
log_info(LD_CRYPTO, "NOT using OpenSSL engine support.");
}
@@ -377,7 +399,7 @@ crypto_openssl_thread_cleanup(void)
void
crypto_openssl_global_cleanup(void)
{
- #ifndef OPENSSL_1_1_API
+#ifndef OPENSSL_1_1_API
EVP_cleanup();
#endif
#ifndef NEW_THREAD_API
diff --git a/src/lib/crypt_ops/crypto_openssl_mgt.h b/src/lib/crypt_ops/crypto_openssl_mgt.h
index 111a2d12ed..083df00033 100644
--- a/src/lib/crypt_ops/crypto_openssl_mgt.h
+++ b/src/lib/crypt_ops/crypto_openssl_mgt.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_options.inc b/src/lib/crypt_ops/crypto_options.inc
new file mode 100644
index 0000000000..5bee0daacd
--- /dev/null
+++ b/src/lib/crypt_ops/crypto_options.inc
@@ -0,0 +1,19 @@
+
+/**
+ * @file crypto_options.inc
+ * @brief Declare configuration options for the crypto_ops module.
+ **/
+
+/** Holds configuration about our cryptography options. */
+BEGIN_CONF_STRUCT(crypto_options_t)
+
+/** Should we enable extra OpenSSL hardware acceleration (where available)? */
+CONF_VAR(HardwareAccel, BOOL, CFLG_IMMUTABLE, "0")
+
+/** Optional OpenSSL hardware-acceleration engine name */
+CONF_VAR(AccelName, STRING, CFLG_IMMUTABLE, NULL)
+
+/** Optional OpenSSL hardware-acceleration engine search directory. */
+CONF_VAR(AccelDir, FILENAME, CFLG_IMMUTABLE, NULL)
+
+END_CONF_STRUCT(crypto_options_t)
diff --git a/src/lib/crypt_ops/crypto_options_st.h b/src/lib/crypt_ops/crypto_options_st.h
new file mode 100644
index 0000000000..a453c451fe
--- /dev/null
+++ b/src/lib/crypt_ops/crypto_options_st.h
@@ -0,0 +1,23 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file crypto_options_st.h
+ * @brief Header for lib/crypt_ops/crypto_options_st.c
+ **/
+
+#ifndef TOR_LIB_CRYPT_OPS_CRYPTO_OPTIONS_ST_H
+#define TOR_LIB_CRYPT_OPS_CRYPTO_OPTIONS_ST_H
+
+#include "lib/conf/confdecl.h"
+
+#define CONF_CONTEXT STRUCT
+#include "lib/crypt_ops/crypto_options.inc"
+#undef CONF_CONTEXT
+
+typedef struct crypto_options_t crypto_options_t;
+
+#endif /* !defined(TOR_LIB_CRYPT_OPS_CRYPTO_OPTIONS_ST_H) */
diff --git a/src/lib/crypt_ops/crypto_pwbox.c b/src/lib/crypt_ops/crypto_pwbox.c
index a8db08f7b7..bfad27d9fc 100644
--- a/src/lib/crypt_ops/crypto_pwbox.c
+++ b/src/lib/crypt_ops/crypto_pwbox.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_pwbox.h b/src/lib/crypt_ops/crypto_pwbox.h
index 5a26889fb2..0a85b1230a 100644
--- a/src/lib/crypt_ops/crypto_pwbox.h
+++ b/src/lib/crypt_ops/crypto_pwbox.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_rand.c b/src/lib/crypt_ops/crypto_rand.c
index afbafbfa35..ac5f10da64 100644
--- a/src/lib/crypt_ops/crypto_rand.c
+++ b/src/lib/crypt_ops/crypto_rand.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -43,10 +43,10 @@
#endif
#ifdef ENABLE_OPENSSL
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/rand.h>
#include <openssl/sha.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
#endif /* defined(ENABLE_OPENSSL) */
#ifdef ENABLE_NSS
diff --git a/src/lib/crypt_ops/crypto_rand.h b/src/lib/crypt_ops/crypto_rand.h
index a019287aa9..99aff5d4a9 100644
--- a/src/lib/crypt_ops/crypto_rand.h
+++ b/src/lib/crypt_ops/crypto_rand.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_rand_fast.c b/src/lib/crypt_ops/crypto_rand_fast.c
index e6ceb42ccb..172ea48bdb 100644
--- a/src/lib/crypt_ops/crypto_rand_fast.c
+++ b/src/lib/crypt_ops/crypto_rand_fast.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -32,7 +32,6 @@
* request.
*/
-#define CRYPTO_RAND_FAST_PRIVATE
#define CRYPTO_PRIVATE
#include "lib/crypt_ops/crypto_rand.h"
@@ -102,16 +101,16 @@ struct crypto_fast_rng_t {
* crypto_strongest_rand().
*/
int16_t n_till_reseed;
- /** How many bytes are remaining in cbuf.bytes? */
+ /** How many bytes are remaining in cbuf_t.bytes? */
uint16_t bytes_left;
#ifdef CHECK_PID
/** Which process owns this fast_rng? If this value is zero, we do not
* need to test the owner. */
pid_t owner;
#endif
- struct cbuf {
+ struct cbuf_t {
/** The seed (key and IV) that we will use the next time that we refill
- * cbuf. */
+ * cbuf_t. */
uint8_t seed[SEED_LEN];
/**
* Bytes that we are yielding to the user. The next byte to be
@@ -122,9 +121,9 @@ struct crypto_fast_rng_t {
} buf;
};
-/* alignof(uint8_t) should be 1, so there shouldn't be any padding in cbuf.
+/* alignof(uint8_t) should be 1, so there shouldn't be any padding in cbuf_t.
*/
-CTASSERT(sizeof(struct cbuf) == BUFLEN+SEED_LEN);
+CTASSERT(sizeof(struct cbuf_t) == BUFLEN+SEED_LEN);
/* We're trying to fit all of the RNG state into a nice mmapable chunk.
*/
CTASSERT(sizeof(crypto_fast_rng_t) <= MAPLEN);
diff --git a/src/lib/crypt_ops/crypto_rsa.c b/src/lib/crypt_ops/crypto_rsa.c
index 1289a82e62..195e4bbaf9 100644
--- a/src/lib/crypt_ops/crypto_rsa.c
+++ b/src/lib/crypt_ops/crypto_rsa.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_rsa.h b/src/lib/crypt_ops/crypto_rsa.h
index 01e6d10906..ab2e9db80d 100644
--- a/src/lib/crypt_ops/crypto_rsa.h
+++ b/src/lib/crypt_ops/crypto_rsa.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_rsa_nss.c b/src/lib/crypt_ops/crypto_rsa_nss.c
index fd8fda486e..66f325e868 100644
--- a/src/lib/crypt_ops/crypto_rsa_nss.c
+++ b/src/lib/crypt_ops/crypto_rsa_nss.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -645,7 +645,7 @@ crypto_pk_asn1_decode(const char *str, size_t len)
return result;
}
-DISABLE_GCC_WARNING(unused-parameter)
+DISABLE_GCC_WARNING("-Wunused-parameter")
/** Given a crypto_pk_t <b>pk</b>, allocate a new buffer containing the Base64
* encoding of the DER representation of the private key into the
diff --git a/src/lib/crypt_ops/crypto_rsa_openssl.c b/src/lib/crypt_ops/crypto_rsa_openssl.c
index 41d936d25b..d54db43b92 100644
--- a/src/lib/crypt_ops/crypto_rsa_openssl.c
+++ b/src/lib/crypt_ops/crypto_rsa_openssl.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -16,7 +16,7 @@
#include "lib/log/util_bug.h"
#include "lib/fs/files.h"
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/err.h>
#include <openssl/rsa.h>
@@ -27,7 +27,7 @@ DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/bn.h>
#include <openssl/conf.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
#include "lib/log/log.h"
#include "lib/encoding/binascii.h"
diff --git a/src/lib/crypt_ops/crypto_s2k.c b/src/lib/crypt_ops/crypto_s2k.c
index 361db18927..3a9ed5ef58 100644
--- a/src/lib/crypt_ops/crypto_s2k.c
+++ b/src/lib/crypt_ops/crypto_s2k.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -380,7 +380,7 @@ secret_to_key_derivekey(uint8_t *key_out, size_t key_out_len,
#ifndef HAVE_SCRYPT
if (type == S2K_TYPE_SCRYPT)
return S2K_NO_SCRYPT_SUPPORT;
- #endif
+#endif
if (! legacy_format) {
++spec;
diff --git a/src/lib/crypt_ops/crypto_s2k.h b/src/lib/crypt_ops/crypto_s2k.h
index a16a3d781e..181a17acb1 100644
--- a/src/lib/crypt_ops/crypto_s2k.h
+++ b/src/lib/crypt_ops/crypto_s2k.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_sys.h b/src/lib/crypt_ops/crypto_sys.h
index 894243b175..2115d4fc99 100644
--- a/src/lib/crypt_ops/crypto_sys.h
+++ b/src/lib/crypt_ops/crypto_sys.h
@@ -1,8 +1,8 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file log_crypto.h
+ * \file crypto_sys.h
* \brief Declare subsystem object for the crypto module.
**/
diff --git a/src/lib/crypt_ops/crypto_util.c b/src/lib/crypt_ops/crypto_util.c
index 5e3f4a87a1..60e81af165 100644
--- a/src/lib/crypt_ops/crypto_util.c
+++ b/src/lib/crypt_ops/crypto_util.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -10,8 +10,6 @@
* \brief Common cryptographic utilities.
**/
-#define CRYPTO_UTIL_PRIVATE
-
#include "lib/crypt_ops/crypto_util.h"
#include "lib/cc/compat_compiler.h"
@@ -26,10 +24,10 @@
#include <stdlib.h>
#ifdef ENABLE_OPENSSL
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/err.h>
#include <openssl/crypto.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
#endif /* defined(ENABLE_OPENSSL) */
#include "lib/log/log.h"
diff --git a/src/lib/crypt_ops/crypto_util.h b/src/lib/crypt_ops/crypto_util.h
index 613a1bd0dd..4c08180f92 100644
--- a/src/lib/crypt_ops/crypto_util.h
+++ b/src/lib/crypt_ops/crypto_util.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/digestset.c b/src/lib/crypt_ops/digestset.c
index c931b58369..5162d6d8bd 100644
--- a/src/lib/crypt_ops/digestset.c
+++ b/src/lib/crypt_ops/digestset.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/digestset.h b/src/lib/crypt_ops/digestset.h
index 7d6d687342..505ac10395 100644
--- a/src/lib/crypt_ops/digestset.h
+++ b/src/lib/crypt_ops/digestset.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/include.am b/src/lib/crypt_ops/include.am
index 1f58a33d38..7644cab412 100644
--- a/src/lib/crypt_ops/include.am
+++ b/src/lib/crypt_ops/include.am
@@ -68,6 +68,8 @@ noinst_HEADERS += \
src/lib/crypt_ops/crypto_nss_mgt.h \
src/lib/crypt_ops/crypto_openssl_mgt.h \
src/lib/crypt_ops/crypto_ope.h \
+ src/lib/crypt_ops/crypto_options.inc \
+ src/lib/crypt_ops/crypto_options_st.h \
src/lib/crypt_ops/crypto_pwbox.h \
src/lib/crypt_ops/crypto_rand.h \
src/lib/crypt_ops/crypto_rsa.h \
diff --git a/doc/HACKING/design/01d-crypto.md b/src/lib/crypt_ops/lib_crypt_ops.md
index d4def947d1..4e675e4871 100644
--- a/doc/HACKING/design/01d-crypto.md
+++ b/src/lib/crypt_ops/lib_crypt_ops.md
@@ -1,9 +1,16 @@
+@dir /lib/crypt_ops
+@brief lib/crypt_ops: Cryptographic operations.
-## Lower-level cryptography functionality in Tor ##
+This module contains wrappers around the cryptographic libraries that we
+support, and implementations for some higher-level cryptographic
+constructions that we use.
-Generally speaking, Tor code shouldn't be calling OpenSSL (or any
-other crypto library) directly. Instead, we should indirect through
-one of the functions in src/common/crypto\*.c or src/common/tortls.c.
+It wraps our two major cryptographic backends (OpenSSL or NSS, as configured
+by the user), and also wraps other cryptographic code in src/ext.
+
+Generally speaking, Tor code shouldn't be calling OpenSSL or NSS
+(or any other crypto library) directly. Instead, we should indirect through
+one of the functions in this directory, or through \refdir{lib/tls}.
Cryptography functionality that's available is described below.
@@ -55,7 +62,7 @@ these.
We have several ways to derive keys from cryptographically strong secret
inputs (like diffie-hellman outputs). The old
-crypto_expand_key_material-TAP() performs an ad-hoc KDF based on SHA1 -- you
+crypto_expand_key_material_TAP() performs an ad-hoc KDF based on SHA1 -- you
shouldn't use it for implementing anything but old versions of the Tor
protocol. You can use HKDF-SHA256 (as defined in RFC5869) for more modern
protocols. Also consider SHAKE256.
@@ -128,42 +135,3 @@ secret object to disk, encrypted with a passphrase. The crypto_pwbox
and crypto_unpwbox functions do so in a way that's likely to be
readable by future versions of Tor.
-### Certificates ###
-
-We have, alas, several certificate types in Tor.
-
-The tor_x509_cert_t type represents an X.509 certificate. This document
-won't explain X.509 to you -- possibly, no document can. (OTOH, Peter
-Gutmann's "x.509 style guide", though severely dated, does a good job of
-explaining how awful x.509 can be.) Do not introduce any new usages of
-X.509. Right now we only use it in places where TLS forces us to do so.
-
-The authority_cert_t type is used only for directory authority keys. It
-has a medium-term signing key (which the authorities actually keep
-online) signed by a long-term identity key (which the authority operator
-had really better be keeping offline). Don't use it for any new kind of
-certificate.
-
-For new places where you need a certificate, consider tor_cert_t: it
-represents a typed and dated _something_ signed by an Ed25519 key. The
-format is described in tor-spec. Unlike x.509, you can write it on a
-napkin.
-
-(Additionally, the Tor directory design uses a fairly wide variety of
-documents that include keys and which are signed by keys. You can
-consider these documents to be an additional kind of certificate if you
-want.)
-
-### TLS ###
-
-Tor's TLS implementation is more tightly coupled to OpenSSL than we'd
-prefer. You can read most of it in tortls.c.
-
-Unfortunately, TLS's state machine and our requirement for nonblocking
-IO support means that using TLS in practice is a bit hairy, since
-logical writes can block on a physical reads, and vice versa.
-
-If you are lucky, you will never have to look at the code here.
-
-
-
diff --git a/src/lib/ctime/di_ops.c b/src/lib/ctime/di_ops.c
index 89e0837ae9..7448a9973e 100644
--- a/src/lib/ctime/di_ops.c
+++ b/src/lib/ctime/di_ops.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2019, The Tor Project, Inc. */
+/* Copyright (c) 2011-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -145,8 +145,11 @@ tor_memeq(const void *a, const void *b, size_t sz)
/* Implement di_digest256_map_t as a linked list of entries. */
struct di_digest256_map_t {
+ /** Pointer to the next entry in the list. */
struct di_digest256_map_t *next;
+ /** Key for this entry. */
uint8_t key[32];
+ /** Value for this entry. */
void *val;
};
diff --git a/src/lib/ctime/di_ops.h b/src/lib/ctime/di_ops.h
index 264b56a8c1..4ff8f03165 100644
--- a/src/lib/ctime/di_ops.h
+++ b/src/lib/ctime/di_ops.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -16,6 +16,8 @@
int tor_memcmp(const void *a, const void *b, size_t sz);
int tor_memeq(const void *a, const void *b, size_t sz);
+/** Perform a constant-time comparison of the <b>sz</b> bytes at <b>a</b> and
+ * <b>b</b>, yielding true if they are different, and false otherwise. */
#define tor_memneq(a,b,sz) (!tor_memeq((a),(b),(sz)))
/** Alias for the platform's memcmp() function. This function is
@@ -24,7 +26,19 @@ int tor_memeq(const void *a, const void *b, size_t sz);
* implementation.
*/
#define fast_memcmp(a,b,c) (memcmp((a),(b),(c)))
+/** Alias for the platform's memcmp() function, for use in testing equality.
+ *
+ * This function is <em>not</em> data-independent: we define this alias so
+ * that we can mark cases where we are deliberately using a data-dependent
+ * memcmp() implementation.
+ */
#define fast_memeq(a,b,c) (0==memcmp((a),(b),(c)))
+/** Alias for the platform's memcmp() function, for use in testing inequality.
+ *
+ * This function is <em>not</em> data-independent: we define this alias so
+ * that we can mark cases where we are deliberately using a data-dependent
+ * memcmp() implementation.
+ */
#define fast_memneq(a,b,c) (0!=memcmp((a),(b),(c)))
int safe_mem_is_zero(const void *mem, size_t sz);
@@ -35,9 +49,17 @@ int safe_mem_is_zero(const void *mem, size_t sz);
*
* Not efficient for large maps! */
typedef struct di_digest256_map_t di_digest256_map_t;
+/**
+ * Type for a function used to free members of a di_digest256_map_t.
+ **/
typedef void (*dimap_free_fn)(void *);
void dimap_free_(di_digest256_map_t *map, dimap_free_fn free_fn);
+/**
+ * @copydoc dimap_free_
+ *
+ * Additionally, set the pointer <b>map</b> to NULL.
+ **/
#define dimap_free(map, free_fn) \
do { \
dimap_free_((map), (free_fn)); \
@@ -52,4 +74,3 @@ int select_array_member_cumulative_timei(const uint64_t *entries,
uint64_t total, uint64_t rand_val);
#endif /* !defined(TOR_DI_OPS_H) */
-
diff --git a/src/lib/ctime/lib_ctime.md b/src/lib/ctime/lib_ctime.md
new file mode 100644
index 0000000000..913199f6a5
--- /dev/null
+++ b/src/lib/ctime/lib_ctime.md
@@ -0,0 +1,14 @@
+@dir /lib/ctime
+@brief lib/ctime: Constant-time code to avoid side-channels.
+
+This module contains constant-time implementations of various
+data comparison and table lookup functions. We use these in preference to
+memcmp() and so forth, since memcmp() can leak information about its inputs
+based on how fast it returns. In general, your code should call tor_memeq()
+and tor_memneq(), not memcmp().
+
+We also define some _non_-constant-time wrappers for memcmp() here: Since we
+consider calls to memcmp() to be in error, we require that code that actually
+doesn't need to be constant-time to use the fast_memeq() / fast_memneq() /
+fast_memcmp() aliases instead.
+
diff --git a/src/lib/defs/dh_sizes.h b/src/lib/defs/dh_sizes.h
index b0d1eba0c5..bc2707b36f 100644
--- a/src/lib/defs/dh_sizes.h
+++ b/src/lib/defs/dh_sizes.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/defs/digest_sizes.h b/src/lib/defs/digest_sizes.h
index a0dd97a74d..7eef1747db 100644
--- a/src/lib/defs/digest_sizes.h
+++ b/src/lib/defs/digest_sizes.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_DIGEST_SIZES_H
diff --git a/src/lib/defs/lib_defs.md b/src/lib/defs/lib_defs.md
new file mode 100644
index 0000000000..5762e4550b
--- /dev/null
+++ b/src/lib/defs/lib_defs.md
@@ -0,0 +1,2 @@
+@dir /lib/defs
+@brief lib/defs: Lowest-level constants, used in many places.
diff --git a/src/lib/defs/logging_types.h b/src/lib/defs/logging_types.h
index d3eacde464..33aa46186b 100644
--- a/src/lib/defs/logging_types.h
+++ b/src/lib/defs/logging_types.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/defs/time.h b/src/lib/defs/time.h
index 459afbf42d..5707330795 100644
--- a/src/lib/defs/time.h
+++ b/src/lib/defs/time.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_TIME_DEFS_H
@@ -17,7 +17,7 @@
#define TOR_USEC_PER_SEC (1000000)
/** How many nanoseconds per microsecond */
#define TOR_NSEC_PER_USEC (1000)
-/* How many nanoseconds per millisecond */
+/** How many nanoseconds per millisecond */
#define TOR_NSEC_PER_MSEC (1000*1000)
#endif /* !defined(TOR_TIME_DEFS_H) */
diff --git a/src/lib/defs/x25519_sizes.h b/src/lib/defs/x25519_sizes.h
index 6431f0a2dd..acb08c5e6a 100644
--- a/src/lib/defs/x25519_sizes.h
+++ b/src/lib/defs/x25519_sizes.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -23,14 +23,22 @@
/** Length of the result of a curve25519 handshake. */
#define CURVE25519_OUTPUT_LEN 32
+/** Length of an Ed25519 public key */
#define ED25519_PUBKEY_LEN 32
+/** Length of an Ed25519 secret key */
#define ED25519_SECKEY_LEN 64
+/** Length of the seed that is ordinarily expanded to an Ed25519 secret
+ * key. */
#define ED25519_SECKEY_SEED_LEN 32
+/** Length of an Ed25519 signature. */
#define ED25519_SIG_LEN 64
+/** Length of a Curve25519 key when encoded in base 64, with padding. */
#define CURVE25519_BASE64_PADDED_LEN 44
+/** Length of a Ed25519 key when encoded in base 64, without padding. */
#define ED25519_BASE64_LEN 43
+/** Length of a Ed25519 signature when encoded in base 64, without padding. */
#define ED25519_SIG_BASE64_LEN 86
#endif /* !defined(TOR_X25519_SIZES_H) */
diff --git a/src/lib/dispatch/dispatch.h b/src/lib/dispatch/dispatch.h
index a9e655409a..9c7c4833c2 100644
--- a/src/lib/dispatch/dispatch.h
+++ b/src/lib/dispatch/dispatch.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_DISPATCH_H
diff --git a/src/lib/dispatch/dispatch_cfg.c b/src/lib/dispatch/dispatch_cfg.c
index b3a72ec22f..a54188dcaa 100644
--- a/src/lib/dispatch/dispatch_cfg.c
+++ b/src/lib/dispatch/dispatch_cfg.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/dispatch/dispatch_cfg.h b/src/lib/dispatch/dispatch_cfg.h
index 348dce8d40..a4f1948eac 100644
--- a/src/lib/dispatch/dispatch_cfg.h
+++ b/src/lib/dispatch/dispatch_cfg.h
@@ -1,12 +1,17 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_DISPATCH_CFG_H
#define TOR_DISPATCH_CFG_H
+/**
+ * @file dispatch_cfg.h
+ * @brief Header for distpach_cfg.c
+ **/
+
#include "lib/dispatch/msgtypes.h"
#include "lib/testsupport/testsupport.h"
diff --git a/src/lib/dispatch/dispatch_cfg_st.h b/src/lib/dispatch/dispatch_cfg_st.h
index 57b6f0347f..3c99adf2f7 100644
--- a/src/lib/dispatch/dispatch_cfg_st.h
+++ b/src/lib/dispatch/dispatch_cfg_st.h
@@ -1,16 +1,24 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dispatch_cfg_st.h
+ * @brief Declarations for dispatch-configuration types.
+ **/
+
#ifndef TOR_DISPATCH_CFG_ST_H
#define TOR_DISPATCH_CFG_ST_H
struct smartlist_t;
-/* Information needed to create a dispatcher, but in a less efficient, more
- * mutable format. */
+/** Information needed to create a dispatcher, but in a less efficient, more
+ * mutable format.
+ *
+ * Nearly everybody should use the \refdir{lib/pubsub} module to configure
+ * dispatchers, instead of using this. */
struct dispatch_cfg_t {
/** A list of msg_type_id_t (cast to void*), indexed by msg_t. */
struct smartlist_t *type_by_msg;
diff --git a/src/lib/dispatch/dispatch_core.c b/src/lib/dispatch/dispatch_core.c
index da54f9b437..3d51c876a7 100644
--- a/src/lib/dispatch/dispatch_core.c
+++ b/src/lib/dispatch/dispatch_core.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/dispatch/dispatch_naming.c b/src/lib/dispatch/dispatch_naming.c
index 83d9a2d604..bb49343712 100644
--- a/src/lib/dispatch/dispatch_naming.c
+++ b/src/lib/dispatch/dispatch_naming.c
@@ -1,9 +1,14 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dispatch_naming.c
+ * @brief Name-to-ID maps for our message dispatch system.
+ **/
+
#include "orconfig.h"
#include "lib/cc/compat_compiler.h"
@@ -33,6 +38,7 @@ dispatch_naming_init(void)
{
}
+#ifndef COCCI
/* Helper macro: declare functions to map IDs to and from names for a given
* type in a namemap_t.
*/
@@ -56,6 +62,7 @@ dispatch_naming_init(void)
return namemap_get_size(&type##_id_map); \
} \
EAT_SEMICOLON
+#endif /* !defined(COCCI) */
DECLARE_ID_MAP_FNS(message);
DECLARE_ID_MAP_FNS(channel);
diff --git a/src/lib/dispatch/dispatch_naming.h b/src/lib/dispatch/dispatch_naming.h
index fd6c83cc12..72206d3ed5 100644
--- a/src/lib/dispatch/dispatch_naming.h
+++ b/src/lib/dispatch/dispatch_naming.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dispatch_naming.h
+ * @brief Header for dispatch_naming.c
+ **/
+
#ifndef TOR_DISPATCH_NAMING_H
#define TOR_DISPATCH_NAMING_H
diff --git a/src/lib/dispatch/dispatch_new.c b/src/lib/dispatch/dispatch_new.c
index d8e59d610a..e1dbb1c4b8 100644
--- a/src/lib/dispatch/dispatch_new.c
+++ b/src/lib/dispatch/dispatch_new.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/dispatch/dispatch_st.h b/src/lib/dispatch/dispatch_st.h
index ee42518b5a..ad5b4efc40 100644
--- a/src/lib/dispatch/dispatch_st.h
+++ b/src/lib/dispatch/dispatch_st.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/dispatch/lib_dispatch.md b/src/lib/dispatch/lib_dispatch.md
new file mode 100644
index 0000000000..153ca50080
--- /dev/null
+++ b/src/lib/dispatch/lib_dispatch.md
@@ -0,0 +1,14 @@
+@dir /lib/dispatch
+@brief lib/dispatch: In-process message delivery.
+
+This module provides a general in-process "message dispatch" system in which
+typed messages are sent on channels. The dispatch.h header has far more
+information.
+
+It is used by by \refdir{lib/pubsub} to implement our general
+inter-module publish/subscribe system.
+
+This is not a fancy multi-threaded many-to-many dispatcher as you may be used
+to from more sophisticated architectures: this dispatcher is intended only
+for use in improving Tor's architecture.
+
diff --git a/src/lib/dispatch/msgtypes.h b/src/lib/dispatch/msgtypes.h
index b4c4a10248..01d969dcb5 100644
--- a/src/lib/dispatch/msgtypes.h
+++ b/src/lib/dispatch/msgtypes.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/binascii.c b/src/lib/encoding/binascii.c
index fc64e014e7..3e549eb8e3 100644
--- a/src/lib/encoding/binascii.c
+++ b/src/lib/encoding/binascii.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/binascii.h b/src/lib/encoding/binascii.h
index 40c5593b11..9cb03bab62 100644
--- a/src/lib/encoding/binascii.h
+++ b/src/lib/encoding/binascii.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/confline.c b/src/lib/encoding/confline.c
index 0d8384db13..ff8bacba3c 100644
--- a/src/lib/encoding/confline.c
+++ b/src/lib/encoding/confline.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/confline.h b/src/lib/encoding/confline.h
index 12c554c6e7..cd343e0e99 100644
--- a/src/lib/encoding/confline.h
+++ b/src/lib/encoding/confline.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/cstring.c b/src/lib/encoding/cstring.c
index 29d3714126..54c330fca3 100644
--- a/src/lib/encoding/cstring.c
+++ b/src/lib/encoding/cstring.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/cstring.h b/src/lib/encoding/cstring.h
index 904a2c9c1c..2a3f6d0fc4 100644
--- a/src/lib/encoding/cstring.h
+++ b/src/lib/encoding/cstring.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/keyval.c b/src/lib/encoding/keyval.c
index c5da5a0bfc..0eb1219d43 100644
--- a/src/lib/encoding/keyval.c
+++ b/src/lib/encoding/keyval.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/keyval.h b/src/lib/encoding/keyval.h
index dcddfa3396..b4966b01de 100644
--- a/src/lib/encoding/keyval.h
+++ b/src/lib/encoding/keyval.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/kvline.c b/src/lib/encoding/kvline.c
index d4a8f510ba..5b220605d6 100644
--- a/src/lib/encoding/kvline.c
+++ b/src/lib/encoding/kvline.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -29,12 +29,20 @@
#include <string.h>
/** Return true iff we need to quote and escape the string <b>s</b> to encode
- * it. */
+ * it.
+ *
+ * kvline_can_encode_lines() also uses this (with
+ * <b>as_keyless_val</b> true) to check whether a key would require
+ * quoting.
+ */
static bool
needs_escape(const char *s, bool as_keyless_val)
{
if (as_keyless_val && *s == 0)
return true;
+ /* Keyless values containing '=' need to be escaped. */
+ if (as_keyless_val && strchr(s, '='))
+ return true;
for (; *s; ++s) {
if (*s >= 127 || TOR_ISSPACE(*s) || ! TOR_ISPRINT(*s) ||
@@ -72,23 +80,17 @@ kvline_can_encode_lines(const config_line_t *line, unsigned flags)
{
for ( ; line; line = line->next) {
const bool keyless = line_has_no_key(line);
- if (keyless) {
- if (! (flags & KV_OMIT_KEYS)) {
- /* If KV_OMIT_KEYS is not set, we can't encode a line with no key. */
- return false;
- }
- if (strchr(line->value, '=') && !( flags & KV_QUOTED)) {
- /* We can't have a keyless value with = without quoting it. */
- return false;
- }
+ if (keyless && ! (flags & KV_OMIT_KEYS)) {
+ /* If KV_OMIT_KEYS is not set, we can't encode a line with no key. */
+ return false;
}
- if (needs_escape(line->value, keyless) && ! (flags & KV_QUOTED)) {
- /* If KV_QUOTED is false, we can't encode a value that needs quotes. */
+ if (needs_escape(line->value, keyless) && ! (flags & (KV_QUOTED|KV_RAW))) {
+ /* If both KV_QUOTED and KV_RAW are false, we can't encode a
+ value that needs quotes. */
return false;
}
- if (line->key && strlen(line->key) &&
- (needs_escape(line->key, false) || strchr(line->key, '='))) {
+ if (!keyless && needs_escape(line->key, true)) {
/* We can't handle keys that need quoting. */
return false;
}
@@ -103,7 +105,7 @@ kvline_can_encode_lines(const config_line_t *line, unsigned flags)
*
* If KV_QUOTED is set in <b>flags</b>, then all values that contain
* spaces or unusual characters are escaped and quoted. Otherwise, such
- * values are not allowed.
+ * values are not allowed. Mutually exclusive with KV_RAW.
*
* If KV_OMIT_KEYS is set in <b>flags</b>, then pairs with empty keys are
* allowed, and are encoded as 'Value'. Otherwise, such pairs are not
@@ -113,6 +115,11 @@ kvline_can_encode_lines(const config_line_t *line, unsigned flags)
* encoded as 'Key', not as 'Key=' or 'Key=""'. Mutually exclusive with
* KV_OMIT_KEYS.
*
+ * If KV_RAW is set in <b>flags</b>, then don't apply any quoting to
+ * the value, and assume that the caller has adequately quoted it.
+ * (The control protocol has some quirks that make this necessary.)
+ * Mutually exclusive with KV_QUOTED.
+ *
* KV_QUOTED_QSTRING is not supported.
*/
char *
@@ -121,11 +128,12 @@ kvline_encode(const config_line_t *line,
{
tor_assert(! (flags & KV_QUOTED_QSTRING));
- if (!kvline_can_encode_lines(line, flags))
- return NULL;
-
tor_assert((flags & (KV_OMIT_KEYS|KV_OMIT_VALS)) !=
(KV_OMIT_KEYS|KV_OMIT_VALS));
+ tor_assert((flags & (KV_QUOTED|KV_RAW)) != (KV_QUOTED|KV_RAW));
+
+ if (!kvline_can_encode_lines(line, flags))
+ return NULL;
smartlist_t *elements = smartlist_new();
@@ -142,15 +150,12 @@ kvline_encode(const config_line_t *line,
k = line->key;
} else {
eq = "";
- if (strchr(line->value, '=')) {
- esc = true;
- }
}
if ((flags & KV_OMIT_VALS) && line_has_no_val(line)) {
eq = "";
v = "";
- } else if (esc) {
+ } else if (!(flags & KV_RAW) && esc) {
tmp = esc_for_log(line->value);
v = tmp;
} else {
@@ -187,12 +192,15 @@ kvline_encode(const config_line_t *line,
* If KV_QUOTED_QSTRING is set in <b>flags</b>, then double-quoted values
* are allowed and handled as QuotedStrings per qstring.c. Do not add
* new users of this flag.
+ *
+ * KV_RAW is not supported.
*/
config_line_t *
kvline_parse(const char *line, unsigned flags)
{
tor_assert((flags & (KV_OMIT_KEYS|KV_OMIT_VALS)) !=
(KV_OMIT_KEYS|KV_OMIT_VALS));
+ tor_assert(!(flags & KV_RAW));
const char *cp = line, *cplast = NULL;
const bool omit_keys = (flags & KV_OMIT_KEYS) != 0;
diff --git a/src/lib/encoding/kvline.h b/src/lib/encoding/kvline.h
index dea2ce1809..34c52908e3 100644
--- a/src/lib/encoding/kvline.h
+++ b/src/lib/encoding/kvline.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -19,6 +19,7 @@ struct config_line_t;
#define KV_OMIT_KEYS (1u<<1)
#define KV_OMIT_VALS (1u<<2)
#define KV_QUOTED_QSTRING (1u<<3)
+#define KV_RAW (1u<<4)
struct config_line_t *kvline_parse(const char *line, unsigned flags);
char *kvline_encode(const struct config_line_t *line, unsigned flags);
diff --git a/src/lib/encoding/lib_encoding.md b/src/lib/encoding/lib_encoding.md
new file mode 100644
index 0000000000..66dd9d8caf
--- /dev/null
+++ b/src/lib/encoding/lib_encoding.md
@@ -0,0 +1,6 @@
+@dir /lib/encoding
+@brief lib/encoding: Encoding data in various forms, types, and transformations
+
+Here we have time formats (timefmt.c), quoted strings (qstring.c), C strings
+(string.c) base-16/32/64 (binascii.c), and more.
+
diff --git a/src/lib/encoding/pem.c b/src/lib/encoding/pem.c
index 51f37d0840..6c9f10e085 100644
--- a/src/lib/encoding/pem.c
+++ b/src/lib/encoding/pem.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -42,7 +42,7 @@ pem_encoded_size(size_t src_len, const char *objtype)
/**
* PEM-encode the <b>srclen</b>-byte object at <b>src</b> into the
- * <b>destlen<\b>-byte buffer at <b>dest</b>, tagging it with <b>objtype</b>.
+ * <b>destlen</b>-byte buffer at <b>dest</b>, tagging it with <b>objtype</b>.
* Return 0 on success and -1 on failure.
*/
int
diff --git a/src/lib/encoding/pem.h b/src/lib/encoding/pem.h
index 6b20350aa8..027c31c315 100644
--- a/src/lib/encoding/pem.h
+++ b/src/lib/encoding/pem.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/qstring.c b/src/lib/encoding/qstring.c
index a92d28c706..5a34924eab 100644
--- a/src/lib/encoding/qstring.c
+++ b/src/lib/encoding/qstring.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/qstring.h b/src/lib/encoding/qstring.h
index 840e1044ce..f19a7dad87 100644
--- a/src/lib/encoding/qstring.h
+++ b/src/lib/encoding/qstring.h
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/time_fmt.c b/src/lib/encoding/time_fmt.c
index 40543d41e0..573dfaad82 100644
--- a/src/lib/encoding/time_fmt.c
+++ b/src/lib/encoding/time_fmt.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/time_fmt.h b/src/lib/encoding/time_fmt.h
index d14bc1f902..80e47c5332 100644
--- a/src/lib/encoding/time_fmt.h
+++ b/src/lib/encoding/time_fmt.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/err/backtrace.c b/src/lib/err/backtrace.c
index ce8ddcd7c0..afb6b9503f 100644
--- a/src/lib/err/backtrace.c
+++ b/src/lib/err/backtrace.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -54,7 +54,7 @@
#include "lib/cc/ctassert.h"
-#define EXPOSE_CLEAN_BACKTRACE
+#define BACKTRACE_PRIVATE
#include "lib/err/backtrace.h"
#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
diff --git a/src/lib/err/backtrace.h b/src/lib/err/backtrace.h
index 7e09a0a5a7..d02e6960b5 100644
--- a/src/lib/err/backtrace.h
+++ b/src/lib/err/backtrace.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_BACKTRACE_H
@@ -29,11 +29,11 @@ const char *get_tor_backtrace_version(void);
#define log_backtrace(sev, dom, msg) \
log_backtrace_impl((sev), (dom), (msg), tor_log)
-#ifdef EXPOSE_CLEAN_BACKTRACE
+#ifdef BACKTRACE_PRIVATE
#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
void clean_backtrace(void **stack, size_t depth, const ucontext_t *ctx);
#endif
-#endif /* defined(EXPOSE_CLEAN_BACKTRACE) */
+#endif /* defined(BACKTRACE_PRIVATE) */
#endif /* !defined(TOR_BACKTRACE_H) */
diff --git a/src/lib/err/lib_err.md b/src/lib/err/lib_err.md
new file mode 100644
index 0000000000..cb4eba2e0d
--- /dev/null
+++ b/src/lib/err/lib_err.md
@@ -0,0 +1,13 @@
+@dir /lib/err
+@brief lib/err: Lowest-level error handling code.
+
+This module is responsible for generating stack traces, handling raw
+assertion failures, and otherwise reporting problems that might not be
+safe to report via the regular logging module.
+
+There are three kinds of users for the functions in this module:
+ * Code that needs a way to assert(), but which cannot use the regular
+ `tor_assert()` macros in logging module.
+ * Code that needs signal-safe error reporting.
+ * Higher-level error handling code.
+
diff --git a/src/lib/err/torerr.c b/src/lib/err/torerr.c
index a5c00ca389..2de75c0be4 100644
--- a/src/lib/err/torerr.c
+++ b/src/lib/err/torerr.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -151,6 +151,30 @@ tor_log_reset_sigsafe_err_fds(void)
}
/**
+ * Flush the list of fds that get errors from inside a signal handler or
+ * other emergency condition. These fds are shared with the logging code:
+ * flushing them also flushes the log buffers.
+ *
+ * This function is safe to call during signal handlers.
+ */
+void
+tor_log_flush_sigsafe_err_fds(void)
+{
+ /* If we don't have fsync() in unistd.h, we can't flush the logs. */
+#ifdef HAVE_FSYNC
+ int n_fds, i;
+ const int *fds = NULL;
+
+ n_fds = tor_log_get_sigsafe_err_fds(&fds);
+ for (i = 0; i < n_fds; ++i) {
+ /* This function is called on error and on shutdown, so we don't log, or
+ * take any other action, if fsync() fails. */
+ (void)fsync(fds[i]);
+ }
+#endif /* defined(HAVE_FSYNC) */
+}
+
+/**
* Set the granularity (in ms) to use when reporting fatal errors outside
* the logging system.
*/
@@ -191,12 +215,13 @@ tor_raw_assertion_failed_msg_(const char *file, int line, const char *expr,
/**
* Call the abort() function to kill the current process with a fatal
- * error. This is a separate function, so that log users don't have to include
- * the header for abort().
+ * error. But first, flush the raw error file descriptors, so error messages
+ * are written before process termination.
**/
void
tor_raw_abort_(void)
{
+ tor_log_flush_sigsafe_err_fds();
abort();
}
diff --git a/src/lib/err/torerr.h b/src/lib/err/torerr.h
index a1822d9c9a..ce1b049c47 100644
--- a/src/lib/err/torerr.h
+++ b/src/lib/err/torerr.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -40,6 +40,7 @@ void tor_log_err_sigsafe(const char *m, ...);
int tor_log_get_sigsafe_err_fds(const int **out);
void tor_log_set_sigsafe_err_fds(const int *fds, int n);
void tor_log_reset_sigsafe_err_fds(void);
+void tor_log_flush_sigsafe_err_fds(void);
void tor_log_sigsafe_err_set_granularity(int ms);
void tor_raw_abort_(void) ATTR_NORETURN;
diff --git a/src/lib/err/torerr_sys.c b/src/lib/err/torerr_sys.c
index c42e958093..46fc853550 100644
--- a/src/lib/err/torerr_sys.c
+++ b/src/lib/err/torerr_sys.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -27,8 +27,9 @@ subsys_torerr_initialize(void)
static void
subsys_torerr_shutdown(void)
{
- /* Stop handling signals with backtraces. */
+ /* Stop handling signals with backtraces, then flush the logs. */
clean_up_backtrace_handler();
+ tor_log_flush_sigsafe_err_fds();
}
const subsys_fns_t sys_torerr = {
diff --git a/src/lib/err/torerr_sys.h b/src/lib/err/torerr_sys.h
index c947695689..b86ccd2790 100644
--- a/src/lib/err/torerr_sys.h
+++ b/src/lib/err/torerr_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/evloop/compat_libevent.c b/src/lib/evloop/compat_libevent.c
index 939d77f857..0fd247d331 100644
--- a/src/lib/evloop/compat_libevent.c
+++ b/src/lib/evloop/compat_libevent.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2019, The Tor Project, Inc. */
+/* Copyright (c) 2009-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -130,7 +130,7 @@ rescan_mainloop_cb(evutil_socket_t fd, short events, void *arg)
/** Initialize the Libevent library and set up the event base. */
void
-tor_libevent_initialize(tor_libevent_cfg *torcfg)
+tor_libevent_initialize(tor_libevent_cfg_t *torcfg)
{
tor_assert(the_event_base == NULL);
/* some paths below don't use torcfg, so avoid unused variable warnings */
@@ -432,7 +432,7 @@ mainloop_event_activate(mainloop_event_t *event)
*
* If the event is scheduled for a different time, cancel it and run
* after this delay instead. If the event is currently pending to run
- * <em>now</b>, has no effect.
+ * <b>now</b>, has no effect.
*
* Do not call this function with <b>tv</b> == NULL -- use
* mainloop_event_activate() instead.
diff --git a/src/lib/evloop/compat_libevent.h b/src/lib/evloop/compat_libevent.h
index 92724c369c..277ba3add6 100644
--- a/src/lib/evloop/compat_libevent.h
+++ b/src/lib/evloop/compat_libevent.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2019, The Tor Project, Inc. */
+/* Copyright (c) 2009-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -61,15 +61,15 @@ void mainloop_event_free_(mainloop_event_t *event);
/** Defines a configuration for using libevent with Tor: passed as an argument
* to tor_libevent_initialize() to describe how we want to set up. */
-typedef struct tor_libevent_cfg {
+typedef struct tor_libevent_cfg_t {
/** How many CPUs should we use (not currently useful). */
int num_cpus;
/** How many milliseconds should we allow between updating bandwidth limits?
* (Not currently useful). */
int msec_per_tick;
-} tor_libevent_cfg;
+} tor_libevent_cfg_t;
-void tor_libevent_initialize(tor_libevent_cfg *cfg);
+void tor_libevent_initialize(tor_libevent_cfg_t *cfg);
bool tor_libevent_is_initialized(void);
MOCK_DECL(struct event_base *, tor_libevent_get_base, (void));
const char *tor_libevent_get_method(void);
diff --git a/src/lib/evloop/evloop_sys.c b/src/lib/evloop/evloop_sys.c
index 56641a3175..fecec2f264 100644
--- a/src/lib/evloop/evloop_sys.c
+++ b/src/lib/evloop/evloop_sys.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/evloop/evloop_sys.h b/src/lib/evloop/evloop_sys.h
index e6155c25b0..a37440e7a6 100644
--- a/src/lib/evloop/evloop_sys.h
+++ b/src/lib/evloop/evloop_sys.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/evloop/lib_evloop.md b/src/lib/evloop/lib_evloop.md
new file mode 100644
index 0000000000..830be88148
--- /dev/null
+++ b/src/lib/evloop/lib_evloop.md
@@ -0,0 +1,7 @@
+@dir /lib/evloop
+@brief lib/evloop: Low-level event loop.
+
+This modules has tools to manage the [libevent](https://libevent.org/) event
+loop and related functionality, in order to implement asynchronous
+networking, timers, periodic events, and other scheduling tasks.
+
diff --git a/src/lib/evloop/procmon.c b/src/lib/evloop/procmon.c
index b2d81fc14b..718c7d4777 100644
--- a/src/lib/evloop/procmon.c
+++ b/src/lib/evloop/procmon.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2019, The Tor Project, Inc. */
+/* Copyright (c) 2011-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -165,8 +165,8 @@ tor_validate_process_specifier(const char *process_spec,
return parse_process_specifier(process_spec, &ppspec, msg);
}
-/* DOCDOC poll_interval_tv */
-static const struct timeval poll_interval_tv = {15, 0};
+/* We check this often for presence of owning controller process. */
+static const struct timeval poll_interval_tv = {15, 0}; // 15 seconds.
/** Create a process-termination monitor for the process specifier
* given in <b>process_spec</b>. Return a newly allocated
diff --git a/src/lib/evloop/procmon.h b/src/lib/evloop/procmon.h
index 6caae5be86..28f443da18 100644
--- a/src/lib/evloop/procmon.h
+++ b/src/lib/evloop/procmon.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2019, The Tor Project, Inc. */
+/* Copyright (c) 2011-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/doc/HACKING/design/01c-time.md b/src/lib/evloop/time_periodic.md
index 5cd0b354fd..8b3589d9db 100644
--- a/doc/HACKING/design/01c-time.md
+++ b/src/lib/evloop/time_periodic.md
@@ -1,5 +1,5 @@
-## Time in tor ##
+@page time_periodic Time and periodic events in Tor
### What time is it? ###
@@ -33,28 +33,28 @@ tor_gettimeofday_cached().
Tor has functions to parse and format time in these formats:
- * RFC1123 format. ("Fri, 29 Sep 2006 15:54:20 GMT"). For this,
- use format_rfc1123_time() and parse_rfc1123_time.
+ - RFC1123 format. ("Fri, 29 Sep 2006 15:54:20 GMT"). For this,
+ use format_rfc1123_time() and parse_rfc1123_time.
- * ISO8601 format. ("2006-10-29 10:57:20") For this, use
- format_local_iso_time and format_iso_time. We also support the
- variant format "2006-10-29T10:57:20" with format_iso_time_nospace, and
- "2006-10-29T10:57:20.123456" with format_iso_time_nospace_usec.
+ - ISO8601 format. ("2006-10-29 10:57:20") For this, use
+ format_local_iso_time() and format_iso_time(). We also support the
+ variant format "2006-10-29T10:57:20" with format_iso_time_nospace(), and
+ "2006-10-29T10:57:20.123456" with format_iso_time_nospace_usec().
- * HTTP format collections (preferably "Mon, 25 Jul 2016 04:01:11
- GMT" or possibly "Wed Jun 30 21:49:08 1993" or even "25-Jul-16
- 04:01:11 GMT"). For this, use parse_http_time. Don't generate anything
- but the first format.
+ - HTTP format collections (preferably "Mon, 25 Jul 2016 04:01:11
+ GMT" or possibly "Wed Jun 30 21:49:08 1993" or even "25-Jul-16
+ 04:01:11 GMT"). For this, use parse_http_time(). Don't generate anything
+ but the first format.
Some of these functions use struct tm. You can use the standard
-tor_localtime_r and tor_gmtime_r() to wrap these in a safe way. We
+tor_localtime_r() and tor_gmtime_r() to wrap these in a safe way. We
also have a tor_timegm() function.
### Scheduling events ###
The main way to schedule a not-too-frequent periodic event with
respect to the Tor mainloop is via the mechanism in periodic.c.
-There's a big table of periodic_events in main.c, each of which gets
+There's a big table of periodic_events in mainloop.c, each of which gets
invoked on its own schedule. You should not expect more than about
one second of accuracy with these timers.
@@ -73,3 +73,4 @@ accurate within a handful of milliseconds -- possibly better on some
platforms. (The timers.c module uses William Ahern's timeout.c
implementation as its backend, which is based on a hierarchical timing
wheel algorithm. It's cool stuff; check it out.)
+
diff --git a/src/lib/evloop/timers.c b/src/lib/evloop/timers.c
index 4b2a96ef7d..7be9bae08e 100644
--- a/src/lib/evloop/timers.c
+++ b/src/lib/evloop/timers.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -48,7 +48,7 @@
#include <winsock2.h>
#endif
-struct timeout_cb {
+struct timeout_cb_t {
timer_cb_fn_t cb;
void *arg;
};
@@ -56,19 +56,21 @@ struct timeout_cb {
/*
* These definitions are for timeouts.c and timeouts.h.
*/
-#ifdef __GNUC__
+#ifdef COCCI
+#define TIMEOUT_PUBLIC
+#elif defined(__GNUC__)
/* We're not exposing any of the functions outside this file. */
#define TIMEOUT_PUBLIC __attribute__((__unused__)) static
#else
/* We're not exposing any of the functions outside this file. */
#define TIMEOUT_PUBLIC static
-#endif /* defined(__GNUC__) */
+#endif /* defined(COCCI) || ... */
/* We're not using periodic events. */
#define TIMEOUT_DISABLE_INTERVALS
/* We always know the global_timeouts object, so we don't need each timeout
* to keep a pointer to it. */
#define TIMEOUT_DISABLE_RELATIVE_ACCESS
-/* We're providing our own struct timeout_cb. */
+/* We're providing our own struct timeout_cb_t. */
#define TIMEOUT_CB_OVERRIDE
/* We're going to support timers that are pretty far out in advance. Making
* this big can be inefficient, but having a significant number of timers
diff --git a/src/lib/evloop/timers.h b/src/lib/evloop/timers.h
index 7595554204..dd55446121 100644
--- a/src/lib/evloop/timers.h
+++ b/src/lib/evloop/timers.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,6 +13,7 @@
#include "lib/testsupport/testsupport.h"
struct monotime_t;
+struct timeval;
typedef struct timeout tor_timer_t;
typedef void (*timer_cb_fn_t)(tor_timer_t *, void *,
const struct monotime_t *);
diff --git a/src/lib/evloop/token_bucket.c b/src/lib/evloop/token_bucket.c
index ec62d1b018..a2b330fddb 100644
--- a/src/lib/evloop/token_bucket.c
+++ b/src/lib/evloop/token_bucket.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/evloop/token_bucket.h b/src/lib/evloop/token_bucket.h
index dde9bd65a4..460dad23e4 100644
--- a/src/lib/evloop/token_bucket.h
+++ b/src/lib/evloop/token_bucket.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/evloop/workqueue.c b/src/lib/evloop/workqueue.c
index 015b694290..603dddd5a3 100644
--- a/src/lib/evloop/workqueue.c
+++ b/src/lib/evloop/workqueue.c
@@ -44,13 +44,13 @@
#define WORKQUEUE_PRIORITY_LAST WQ_PRI_LOW
#define WORKQUEUE_N_PRIORITIES (((int) WORKQUEUE_PRIORITY_LAST)+1)
-TOR_TAILQ_HEAD(work_tailq_t, workqueue_entry_s);
+TOR_TAILQ_HEAD(work_tailq_t, workqueue_entry_t);
typedef struct work_tailq_t work_tailq_t;
-struct threadpool_s {
+struct threadpool_t {
/** An array of pointers to workerthread_t: one for each running worker
* thread. */
- struct workerthread_s **threads;
+ struct workerthread_t **threads;
/** Condition variable that we wait on when we have no work, and which
* gets signaled when our queue becomes nonempty. */
@@ -92,14 +92,14 @@ struct threadpool_s {
/** Number of bits needed to hold all legal values of workqueue_priority_t */
#define WORKQUEUE_PRIORITY_BITS 2
-struct workqueue_entry_s {
+struct workqueue_entry_t {
/** The next workqueue_entry_t that's pending on the same thread or
* reply queue. */
- TOR_TAILQ_ENTRY(workqueue_entry_s) next_work;
+ TOR_TAILQ_ENTRY(workqueue_entry_t) next_work;
/** The threadpool to which this workqueue_entry_t was assigned. This field
* is set when the workqueue_entry_t is created, and won't be cleared until
* after it's handled in the main thread. */
- struct threadpool_s *on_pool;
+ struct threadpool_t *on_pool;
/** True iff this entry is waiting for a worker to start processing it. */
uint8_t pending;
/** Priority of this entry. */
@@ -112,22 +112,22 @@ struct workqueue_entry_s {
void *arg;
};
-struct replyqueue_s {
+struct replyqueue_t {
/** Mutex to protect the answers field */
tor_mutex_t lock;
/** Doubly-linked list of answers that the reply queue needs to handle. */
- TOR_TAILQ_HEAD(, workqueue_entry_s) answers;
+ TOR_TAILQ_HEAD(, workqueue_entry_t) answers;
/** Mechanism to wake up the main thread when it is receiving answers. */
alert_sockets_t alert;
};
/** A worker thread represents a single thread in a thread pool. */
-typedef struct workerthread_s {
+typedef struct workerthread_t {
/** Which thread it this? In range 0..in_pool->n_threads-1 */
int index;
/** The pool this thread is a part of. */
- struct threadpool_s *in_pool;
+ struct threadpool_t *in_pool;
/** User-supplied state field that we pass to the worker functions of each
* work item. */
void *state;
diff --git a/src/lib/evloop/workqueue.h b/src/lib/evloop/workqueue.h
index d0ee8f2be2..43cfebf788 100644
--- a/src/lib/evloop/workqueue.h
+++ b/src/lib/evloop/workqueue.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,12 +13,12 @@
/** A replyqueue is used to tell the main thread about the outcome of
* work that we queued for the workers. */
-typedef struct replyqueue_s replyqueue_t;
+typedef struct replyqueue_t replyqueue_t;
/** A thread-pool manages starting threads and passing work to them. */
-typedef struct threadpool_s threadpool_t;
+typedef struct threadpool_t threadpool_t;
/** A workqueue entry represents a request that has been passed to a thread
* pool. */
-typedef struct workqueue_entry_s workqueue_entry_t;
+typedef struct workqueue_entry_t workqueue_entry_t;
/** Possible return value from a work function: */
typedef enum workqueue_reply_t {
diff --git a/src/lib/fdio/fdio.c b/src/lib/fdio/fdio.c
index 2d0864cc19..56e3818f5c 100644
--- a/src/lib/fdio/fdio.c
+++ b/src/lib/fdio/fdio.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -28,9 +28,10 @@
#include <stdlib.h>
#include <stdio.h>
-/** @{ */
-/** Some old versions of Unix didn't define constants for these values,
+/* Some old versions of Unix didn't define constants for these values,
* and instead expect you to say 0, 1, or 2. */
+
+/** @cond */
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
@@ -40,7 +41,7 @@
#ifndef SEEK_END
#define SEEK_END 2
#endif
-/** @} */
+/** @endcond */
/** Return the position of <b>fd</b> with respect to the start of the file. */
off_t
diff --git a/src/lib/fdio/fdio.h b/src/lib/fdio/fdio.h
index 8395af353b..99bc33c64b 100644
--- a/src/lib/fdio/fdio.h
+++ b/src/lib/fdio/fdio.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,6 +13,9 @@
#define TOR_FDIO_H
#include <stddef.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
off_t tor_fd_getpos(int fd);
int tor_fd_setpos(int fd, off_t pos);
diff --git a/src/lib/fdio/lib_fdio.md b/src/lib/fdio/lib_fdio.md
new file mode 100644
index 0000000000..9fe4b4d2be
--- /dev/null
+++ b/src/lib/fdio/lib_fdio.md
@@ -0,0 +1,5 @@
+@dir /lib/fdio
+@brief lib/fdio: Code to read/write on file descriptors.
+
+(This module also handles sockets, on platforms where a socket is not a kind
+of fd.)
diff --git a/src/lib/fs/conffile.c b/src/lib/fs/conffile.c
index 0d5d56b335..392b2f4541 100644
--- a/src/lib/fs/conffile.c
+++ b/src/lib/fs/conffile.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/fs/conffile.h b/src/lib/fs/conffile.h
index 29115e1085..cbfe4ec7c9 100644
--- a/src/lib/fs/conffile.h
+++ b/src/lib/fs/conffile.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_CONFFILE_H
diff --git a/src/lib/fs/dir.c b/src/lib/fs/dir.c
index 390836b048..3432df0299 100644
--- a/src/lib/fs/dir.c
+++ b/src/lib/fs/dir.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/fs/dir.h b/src/lib/fs/dir.h
index 9ff81faa42..c4ab430891 100644
--- a/src/lib/fs/dir.h
+++ b/src/lib/fs/dir.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_DIR_H
diff --git a/src/lib/fs/files.c b/src/lib/fs/files.c
index b98a51a287..aeaeb5daea 100644
--- a/src/lib/fs/files.c
+++ b/src/lib/fs/files.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/fs/files.h b/src/lib/fs/files.h
index ed983f3b3c..a109cd6248 100644
--- a/src/lib/fs/files.h
+++ b/src/lib/fs/files.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/fs/freespace.c b/src/lib/fs/freespace.c
index ee0f93073d..511f2a0b98 100644
--- a/src/lib/fs/freespace.c
+++ b/src/lib/fs/freespace.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/fs/lib_fs.md b/src/lib/fs/lib_fs.md
new file mode 100644
index 0000000000..3b5b0ac7d5
--- /dev/null
+++ b/src/lib/fs/lib_fs.md
@@ -0,0 +1,9 @@
+@dir /lib/fs
+@brief lib/fs: Files, filenames, directories, etc.
+
+This module is mostly a set of compatibility wrappers around
+operating-system-specific filesystem access.
+
+It also contains a set of convenience functions for safely writing to files,
+creating directories, and so on.
+
diff --git a/src/lib/fs/lockfile.c b/src/lib/fs/lockfile.c
index 933ff1e02f..c081f57a5d 100644
--- a/src/lib/fs/lockfile.c
+++ b/src/lib/fs/lockfile.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/fs/lockfile.h b/src/lib/fs/lockfile.h
index fc0281e253..91effd701d 100644
--- a/src/lib/fs/lockfile.h
+++ b/src/lib/fs/lockfile.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/fs/mmap.c b/src/lib/fs/mmap.c
index f71c0cff7a..cc1c40b7ab 100644
--- a/src/lib/fs/mmap.c
+++ b/src/lib/fs/mmap.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -42,8 +42,8 @@
* failure, return NULL. Sets errno properly, using ERANGE to mean
* "empty file". Must only be called on trusted Tor-owned files, as changing
* the underlying file's size causes unspecified behavior. */
-tor_mmap_t *
-tor_mmap_file(const char *filename)
+MOCK_IMPL(tor_mmap_t *,
+tor_mmap_file,(const char *filename))
{
int fd; /* router file */
char *string;
@@ -111,8 +111,8 @@ tor_mmap_file(const char *filename)
}
/** Release storage held for a memory mapping; returns 0 on success,
* or -1 on failure (and logs a warning). */
-int
-tor_munmap_file(tor_mmap_t *handle)
+MOCK_IMPL(int,
+tor_munmap_file,(tor_mmap_t *handle))
{
int res;
@@ -132,8 +132,8 @@ tor_munmap_file(tor_mmap_t *handle)
return res;
}
#elif defined(_WIN32)
-tor_mmap_t *
-tor_mmap_file(const char *filename)
+MOCK_IMPL(tor_mmap_t *,
+tor_mmap_file,(const char *filename))
{
TCHAR tfilename[MAX_PATH]= {0};
tor_mmap_t *res = tor_malloc_zero(sizeof(tor_mmap_t));
@@ -213,8 +213,8 @@ tor_mmap_file(const char *filename)
}
/* Unmap the file, and return 0 for success or -1 for failure */
-int
-tor_munmap_file(tor_mmap_t *handle)
+MOCK_IMPL(int,
+tor_munmap_file,(tor_mmap_t *handle))
{
if (handle == NULL)
return 0;
diff --git a/src/lib/fs/mmap.h b/src/lib/fs/mmap.h
index 61aad544b2..e142bd78c3 100644
--- a/src/lib/fs/mmap.h
+++ b/src/lib/fs/mmap.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,6 +13,7 @@
#define TOR_MMAP_H
#include "lib/cc/compat_compiler.h"
+#include "lib/testsupport/testsupport.h"
#include <stddef.h>
#ifdef _WIN32
@@ -35,7 +36,7 @@ typedef struct tor_mmap_t {
} tor_mmap_t;
-tor_mmap_t *tor_mmap_file(const char *filename);
-int tor_munmap_file(tor_mmap_t *handle);
+MOCK_DECL(tor_mmap_t *, tor_mmap_file, (const char *filename));
+MOCK_DECL(int, tor_munmap_file, (tor_mmap_t *handle));
#endif /* !defined(TOR_MMAP_H) */
diff --git a/src/lib/fs/path.c b/src/lib/fs/path.c
index 28dde62aea..0d57be4b06 100644
--- a/src/lib/fs/path.c
+++ b/src/lib/fs/path.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -255,9 +255,10 @@ alloc_getcwd(void)
#endif /* !defined(_WIN32) */
/** Expand possibly relative path <b>fname</b> to an absolute path.
- * Return a newly allocated string, possibly equal to <b>fname</b>. */
+ * Return a newly allocated string, which may be a duplicate of <b>fname</b>.
+ */
char *
-make_path_absolute(char *fname)
+make_path_absolute(const char *fname)
{
#ifdef _WIN32
char *absfname_malloced = _fullpath(NULL, fname, 1);
diff --git a/src/lib/fs/path.h b/src/lib/fs/path.h
index 28a1838b88..f0e253c556 100644
--- a/src/lib/fs/path.h
+++ b/src/lib/fs/path.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -25,6 +25,6 @@ char *expand_filename(const char *filename);
int path_is_relative(const char *filename);
void clean_fname_for_stat(char *name);
int get_parent_directory(char *fname);
-char *make_path_absolute(char *fname);
+char *make_path_absolute(const char *fname);
#endif /* !defined(TOR_PATH_H) */
diff --git a/src/lib/fs/storagedir.c b/src/lib/fs/storagedir.c
index 2caddf1ad9..5e4f9ee257 100644
--- a/src/lib/fs/storagedir.c
+++ b/src/lib/fs/storagedir.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/fs/storagedir.h b/src/lib/fs/storagedir.h
index 7e6633a0bb..9997550b8f 100644
--- a/src/lib/fs/storagedir.h
+++ b/src/lib/fs/storagedir.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,7 +15,7 @@
typedef struct storage_dir_t storage_dir_t;
struct config_line_t;
-struct sandbox_cfg_elem;
+struct sandbox_cfg_elem_t;
struct tor_mmap_t;
struct smartlist_t;
@@ -25,7 +25,7 @@ void storage_dir_free_(storage_dir_t *d);
FREE_AND_NULL(storage_dir_t, storage_dir_free_, (d))
int storage_dir_register_with_sandbox(storage_dir_t *d,
- struct sandbox_cfg_elem **cfg);
+ struct sandbox_cfg_elem_t **cfg);
const struct smartlist_t *storage_dir_list(storage_dir_t *d);
uint64_t storage_dir_get_usage(storage_dir_t *d);
struct tor_mmap_t *storage_dir_map(storage_dir_t *d, const char *fname);
diff --git a/src/lib/fs/userdb.c b/src/lib/fs/userdb.c
index 95205c670e..40fc4dae97 100644
--- a/src/lib/fs/userdb.c
+++ b/src/lib/fs/userdb.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/fs/userdb.h b/src/lib/fs/userdb.h
index 5e5ddb89a3..4341237c5f 100644
--- a/src/lib/fs/userdb.h
+++ b/src/lib/fs/userdb.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/fs/winlib.c b/src/lib/fs/winlib.c
index b7302bd4ca..65ccdae40b 100644
--- a/src/lib/fs/winlib.c
+++ b/src/lib/fs/winlib.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/fs/winlib.h b/src/lib/fs/winlib.h
index 7237226c76..27837ac46e 100644
--- a/src/lib/fs/winlib.h
+++ b/src/lib/fs/winlib.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/geoip/country.h b/src/lib/geoip/country.h
index a24a1c4c0d..feab554a16 100644
--- a/src/lib/geoip/country.h
+++ b/src/lib/geoip/country.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file country.h
+ * @brief Country type for geoip.
+ **/
+
#ifndef TOR_COUNTRY_H
#define TOR_COUNTRY_H
@@ -11,6 +16,7 @@
/** A signed integer representing a country code. */
typedef int16_t country_t;
+/** Maximum value for country_t. */
#define COUNTRY_MAX INT16_MAX
#endif /* !defined(TOR_COUNTRY_H) */
diff --git a/src/lib/geoip/geoip.c b/src/lib/geoip/geoip.c
index 70b1c2dc8c..ee03d5baa1 100644
--- a/src/lib/geoip/geoip.c
+++ b/src/lib/geoip/geoip.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -70,12 +70,18 @@ static smartlist_t *geoip_countries = NULL;
* The index is encoded in the pointer, and 1 is added so that NULL can mean
* not found. */
static strmap_t *country_idxplus1_by_lc_code = NULL;
-/** Lists of all known geoip_ipv4_entry_t and geoip_ipv6_entry_t, sorted
- * by their respective ip_low. */
-static smartlist_t *geoip_ipv4_entries = NULL, *geoip_ipv6_entries = NULL;
-
-/** SHA1 digest of the GeoIP files to include in extra-info descriptors. */
+/** List of all known geoip_ipv4_entry_t sorted
+ * by their respective ip_low values. */
+static smartlist_t *geoip_ipv4_entries = NULL;
+/** List of all known geoip_ipv6_entry_t, sorted by their respective
+ * ip_low values. */
+static smartlist_t *geoip_ipv6_entries = NULL;
+
+/** SHA1 digest of the IPv4 GeoIP file to include in extra-info
+ * descriptors. */
static char geoip_digest[DIGEST_LEN];
+/** SHA1 digest of the IPv6 GeoIP file to include in extra-info
+ * descriptors. */
static char geoip6_digest[DIGEST_LEN];
/** Return a list of geoip_country_t for all known countries. */
diff --git a/src/lib/geoip/geoip.h b/src/lib/geoip/geoip.h
index f872ebd25f..2fc7fae754 100644
--- a/src/lib/geoip/geoip.h
+++ b/src/lib/geoip/geoip.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -31,6 +31,7 @@ int geoip_get_country_by_ipv6(const struct in6_addr *addr);
/** A per-country GeoIP record. */
typedef struct geoip_country_t {
+ /** A nul-terminated two-letter country-code. */
char countrycode[3];
} geoip_country_t;
diff --git a/src/lib/geoip/lib_geoip.md b/src/lib/geoip/lib_geoip.md
new file mode 100644
index 0000000000..a3ee39d574
--- /dev/null
+++ b/src/lib/geoip/lib_geoip.md
@@ -0,0 +1,3 @@
+@dir /lib/geoip
+@brief lib/geoip: IP-to-country mapping
+
diff --git a/src/lib/intmath/addsub.c b/src/lib/intmath/addsub.c
index 12146f4e72..44613417fa 100644
--- a/src/lib/intmath/addsub.c
+++ b/src/lib/intmath/addsub.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/intmath/addsub.h b/src/lib/intmath/addsub.h
index 3f745d457d..bca911103b 100644
--- a/src/lib/intmath/addsub.h
+++ b/src/lib/intmath/addsub.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/intmath/bits.c b/src/lib/intmath/bits.c
index 2158790e3f..dace9ffe18 100644
--- a/src/lib/intmath/bits.c
+++ b/src/lib/intmath/bits.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/intmath/bits.h b/src/lib/intmath/bits.h
index c1483a18b8..687651ba35 100644
--- a/src/lib/intmath/bits.h
+++ b/src/lib/intmath/bits.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/intmath/cmp.h b/src/lib/intmath/cmp.h
index 67a738861b..4e6c2b649a 100644
--- a/src/lib/intmath/cmp.h
+++ b/src/lib/intmath/cmp.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/intmath/lib_intmath.md b/src/lib/intmath/lib_intmath.md
new file mode 100644
index 0000000000..4446b715cb
--- /dev/null
+++ b/src/lib/intmath/lib_intmath.md
@@ -0,0 +1,2 @@
+@dir /lib/intmath
+@brief lib/intmath: Integer mathematics.
diff --git a/src/lib/intmath/logic.h b/src/lib/intmath/logic.h
index b2f77462e1..b5fb79f66e 100644
--- a/src/lib/intmath/logic.h
+++ b/src/lib/intmath/logic.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/intmath/muldiv.c b/src/lib/intmath/muldiv.c
index 6a292db7ba..875cf1bbf2 100644
--- a/src/lib/intmath/muldiv.c
+++ b/src/lib/intmath/muldiv.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -69,6 +69,20 @@ gcd64(uint64_t a, uint64_t b)
return a;
}
+/** Return the unsigned integer product of <b>a</b> and <b>b</b>. If overflow
+ * is detected, return UINT64_MAX instead. */
+uint64_t
+tor_mul_u64_nowrap(uint64_t a, uint64_t b)
+{
+ if (a == 0 || b == 0) {
+ return 0;
+ } else if (PREDICT_UNLIKELY(UINT64_MAX / a < b)) {
+ return UINT64_MAX;
+ } else {
+ return a*b;
+ }
+}
+
/* Given a fraction *<b>numer</b> / *<b>denom</b>, simplify it.
* Requires that the denominator is greater than 0. */
void
diff --git a/src/lib/intmath/muldiv.h b/src/lib/intmath/muldiv.h
index 64500b6dce..43700cf1dc 100644
--- a/src/lib/intmath/muldiv.h
+++ b/src/lib/intmath/muldiv.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -18,6 +18,8 @@ unsigned round_to_next_multiple_of(unsigned number, unsigned divisor);
uint32_t round_uint32_to_next_multiple_of(uint32_t number, uint32_t divisor);
uint64_t round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor);
+uint64_t tor_mul_u64_nowrap(uint64_t a, uint64_t b);
+
void simplify_fraction64(uint64_t *numer, uint64_t *denom);
/* Compute the CEIL of <b>a</b> divided by <b>b</b>, for nonnegative <b>a</b>
diff --git a/src/lib/intmath/weakrng.c b/src/lib/intmath/weakrng.c
index 99c9252c2b..a29a6a086b 100644
--- a/src/lib/intmath/weakrng.c
+++ b/src/lib/intmath/weakrng.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/intmath/weakrng.h b/src/lib/intmath/weakrng.h
index 40941e59b2..0394e05f79 100644
--- a/src/lib/intmath/weakrng.h
+++ b/src/lib/intmath/weakrng.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -19,8 +19,11 @@ typedef struct tor_weak_rng_t {
uint32_t state;
} tor_weak_rng_t;
+#ifndef COCCI
#define TOR_WEAK_RNG_INIT {383745623}
+#endif
#define TOR_WEAK_RANDOM_MAX (INT_MAX)
+
void tor_init_weak_random(tor_weak_rng_t *weak_rng, unsigned seed);
int32_t tor_weak_random(tor_weak_rng_t *weak_rng);
int32_t tor_weak_random_range(tor_weak_rng_t *rng, int32_t top);
diff --git a/src/lib/lib.md b/src/lib/lib.md
new file mode 100644
index 0000000000..4f77a4c1d0
--- /dev/null
+++ b/src/lib/lib.md
@@ -0,0 +1,131 @@
+@dir /lib
+@brief lib: low-level functionality.
+
+The "lib" directory contains low-level functionality. In general, this
+code is not necessarily Tor-specific, but is instead possibly useful for
+other applications.
+
+The modules in `lib` are currently well-factored: each one depends
+only on lower-level modules. You can see an up-to-date list of the
+modules, sorted from lowest to highest level, by running
+`./scripts/maint/practracker/includes.py --toposort`.
+
+As of this writing, the library modules are (from lowest to highest
+level):
+
+ - \refdir{lib/cc} -- Macros for managing the C compiler and
+ language.
+
+ - \refdir{lib/version} -- Holds the current version of Tor.
+
+ - \refdir{lib/testsupport} -- Helpers for making
+ test-only code, and test mocking support.
+
+ - \refdir{lib/defs} -- Lowest-level constants.
+
+ - \refdir{lib/subsys} -- Types used for declaring a
+ "subsystem". (_A subsystem is a module with support for initialization,
+ shutdown, configuration, and so on._)
+
+ - \refdir{lib/conf} -- For declaring configuration options.
+
+ - \refdir{lib/arch} -- For handling differences in CPU
+ architecture.
+
+ - \refdir{lib/err} -- Lowest-level error handling code.
+
+ - \refdir{lib/malloc} -- Memory management.
+ management.
+
+ - \refdir{lib/intmath} -- Integer mathematics.
+
+ - \refdir{lib/fdio} -- For
+ reading and writing n file descriptors.
+
+ - \refdir{lib/lock} -- Simple locking support.
+ (_Lower-level than the rest of the threading code._)
+
+ - \refdir{lib/ctime} -- Constant-time code to avoid
+ side-channels.
+
+ - \refdir{lib/string} -- Low-level string manipulation.
+
+ - \refdir{lib/wallclock} --
+ For inspecting and manipulating the current (UTC) time.
+
+ - \refdir{lib/osinfo} -- For inspecting the OS version
+ and capabilities.
+
+ - \refdir{lib/smartlist_core} -- The bare-bones
+ pieces of our dynamic array ("smartlist") implementation.
+
+ - \refdir{lib/log} -- Log messages to files, syslogs, etc.
+
+ - \refdir{lib/container} -- General purpose containers,
+ including dynamic arrays ("smartlists"), hashtables, bit arrays,
+ etc.
+
+ - \refdir{lib/trace} -- A general-purpose API
+ function-tracing functionality Tor. (_Currently not much used._)
+
+ - \refdir{lib/thread} -- Mid-level Threading.
+
+ - \refdir{lib/term} -- Terminal manipulation
+ (like reading a password from the user).
+
+ - \refdir{lib/memarea} -- A fast
+ "arena" style allocator, where the data is freed all at once.
+
+ - \refdir{lib/encoding} -- Encoding
+ data in various formats, datatypes, and transformations.
+
+ - \refdir{lib/dispatch} -- A general-purpose in-process
+ message delivery system.
+
+ - \refdir{lib/sandbox} -- Our Linux seccomp2 sandbox
+ implementation.
+
+ - \refdir{lib/pubsub} -- A publish/subscribe message passing system.
+
+ - \refdir{lib/fs} -- Files, filenames, directories, etc.
+
+ - \refdir{lib/confmgt} -- Parse, encode, and manipulate onfiguration files.
+
+ - \refdir{lib/crypt_ops} -- Cryptographic operations.
+
+ - \refdir{lib/meminfo} -- Functions for inspecting our
+ memory usage, if the malloc implementation exposes that to us.
+
+ - \refdir{lib/time} -- Higher level time functions, including
+ fine-gained and monotonic timers.
+
+ - \refdir{lib/math} -- Floating-point mathematical utilities.
+
+ - \refdir{lib/buf} -- An efficient byte queue.
+
+ - \refdir{lib/net} -- Networking code, including address
+ manipulation, compatibility wrappers, etc.
+
+ - \refdir{lib/compress} -- Wraps several compression libraries.
+
+ - \refdir{lib/geoip} -- IP-to-country mapping.
+
+ - \refdir{lib/tls} -- TLS library wrappers.
+
+ - \refdir{lib/evloop} -- Low-level event-loop.
+
+ - \refdir{lib/process} -- Launch and manage subprocesses.
+
+### What belongs in lib?
+
+In general, if you can imagine some program wanting the functionality
+you're writing, even if that program had nothing to do with Tor, your
+functionality belongs in lib.
+
+If it falls into one of the existing "lib" categories, your
+functionality belongs in lib.
+
+If you are using platform-specific `ifdef`s to manage compatibility
+issues among platforms, you should probably consider whether you can
+put your code into lib.
+
diff --git a/src/lib/lock/compat_mutex.c b/src/lib/lock/compat_mutex.c
index 670bd0174c..b0084a3484 100644
--- a/src/lib/lock/compat_mutex.c
+++ b/src/lib/lock/compat_mutex.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/lock/compat_mutex.h b/src/lib/lock/compat_mutex.h
index e0c3d7cb78..5631993cc4 100644
--- a/src/lib/lock/compat_mutex.h
+++ b/src/lib/lock/compat_mutex.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -58,6 +58,11 @@ void tor_mutex_init_nonrecursive(tor_mutex_t *m);
void tor_mutex_acquire(tor_mutex_t *m);
void tor_mutex_release(tor_mutex_t *m);
void tor_mutex_free_(tor_mutex_t *m);
+/**
+ * @copydoc tor_mutex_free_
+ *
+ * Additionally, set the pointer <b>m</b> to NULL.
+ **/
#define tor_mutex_free(m) FREE_AND_NULL(tor_mutex_t, tor_mutex_free_, (m))
void tor_mutex_uninit(tor_mutex_t *m);
diff --git a/src/lib/lock/compat_mutex_pthreads.c b/src/lib/lock/compat_mutex_pthreads.c
index f82ad9f0e8..ac83c42a47 100644
--- a/src/lib/lock/compat_mutex_pthreads.c
+++ b/src/lib/lock/compat_mutex_pthreads.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -17,8 +17,14 @@
* "recursive" mutexes (i.e., once we can re-lock if we're already holding
* them.) */
static pthread_mutexattr_t attr_recursive;
+/**
+ * True iff <b>attr_recursive</b> has been initialized.
+ **/
static int attr_initialized = 0;
+/**
+ * Initialize the locking module, if it is not already initialized.
+ **/
void
tor_locking_init(void)
{
diff --git a/src/lib/lock/compat_mutex_winthreads.c b/src/lib/lock/compat_mutex_winthreads.c
index b0f5999e42..5fe6870a93 100644
--- a/src/lib/lock/compat_mutex_winthreads.c
+++ b/src/lib/lock/compat_mutex_winthreads.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/lock/lib_lock.md b/src/lib/lock/lib_lock.md
new file mode 100644
index 0000000000..6f6727bfc2
--- /dev/null
+++ b/src/lib/lock/lib_lock.md
@@ -0,0 +1,6 @@
+@dir /lib/lock
+@brief lib/lock: Simple locking support.
+
+This module is more low-level than the rest of the threading code, since it
+is needed by more intermediate-level modules.
+
diff --git a/src/lib/log/escape.c b/src/lib/log/escape.c
index 6ca01c6963..88ca52a78c 100644
--- a/src/lib/log/escape.c
+++ b/src/lib/log/escape.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/log/escape.h b/src/lib/log/escape.h
index 0b9fc3406b..0d1eaef4c1 100644
--- a/src/lib/log/escape.h
+++ b/src/lib/log/escape.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/log/lib_log.md b/src/lib/log/lib_log.md
new file mode 100644
index 0000000000..8740d6a02f
--- /dev/null
+++ b/src/lib/log/lib_log.md
@@ -0,0 +1,10 @@
+@dir /lib/log
+@brief lib/log: Log messages to files, syslogs, etc.
+
+You can think of this as the logical "midpoint" of the
+\refdir{lib} code": much of the higher-level code is higher-level
+_because_ it uses the logging module, and much of the lower-level code is
+specifically written to avoid having to log, because the logging module
+depends on it.
+
+
diff --git a/src/lib/log/log.c b/src/lib/log/log.c
index c53db46a8c..eb81515746 100644
--- a/src/lib/log/log.c
+++ b/src/lib/log/log.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -276,8 +276,8 @@ static int log_time_granularity = 1;
/** Define log time granularity for all logs to be <b>granularity_msec</b>
* milliseconds. */
-void
-set_log_time_granularity(int granularity_msec)
+MOCK_IMPL(void,
+set_log_time_granularity,(int granularity_msec))
{
log_time_granularity = granularity_msec;
tor_log_sigsafe_err_set_granularity(granularity_msec);
@@ -523,7 +523,7 @@ logfile_deliver(logfile_t *lf, const char *buf, size_t msg_len,
* pass them, and some very old ones do not detect overflow so well.
* Regrettably, they call their maximum line length MAXLINE. */
#if MAXLINE < 64
-#warn "MAXLINE is a very low number; it might not be from syslog.h after all"
+#warning "MAXLINE is a very low number; it might not be from syslog.h."
#endif
char *m = msg_after_prefix;
if (msg_len >= MAXLINE)
@@ -665,20 +665,15 @@ tor_log_update_sigsafe_err_fds(void)
const logfile_t *lf;
int found_real_stderr = 0;
- /* log_fds and err_fds contain matching entries: log_fds are the fds used by
- * the log module, and err_fds are the fds used by the err module.
- * For stdio logs, the log_fd and err_fd values are identical.
- * For file logs, the err_fd is a dup() of the log_fd.
- */
- int log_fds[TOR_SIGSAFE_LOG_MAX_FDS];
- int err_fds[TOR_SIGSAFE_LOG_MAX_FDS];
+ /* The fds are the file descriptors of tor's stdout, stderr, and file
+ * logs. The log and err modules flush these fds during their shutdowns. */
+ int fds[TOR_SIGSAFE_LOG_MAX_FDS];
int n_fds;
LOCK_LOGS();
/* Reserve the first one for stderr. This is safe because when we daemonize,
- * we dup2 /dev/null to stderr.
- * For stderr, log_fds and err_fds are the same. */
- log_fds[0] = err_fds[0] = STDERR_FILENO;
+ * we dup2 /dev/null to stderr. */
+ fds[0] = STDERR_FILENO;
n_fds = 1;
for (lf = logfiles; lf; lf = lf->next) {
@@ -693,19 +688,11 @@ tor_log_update_sigsafe_err_fds(void)
(LD_BUG|LD_GENERAL)) {
if (lf->fd == STDERR_FILENO)
found_real_stderr = 1;
- /* Avoid duplicates by checking the log module fd against log_fds */
- if (int_array_contains(log_fds, n_fds, lf->fd))
+ /* Avoid duplicates by checking the log module fd against fds */
+ if (int_array_contains(fds, n_fds, lf->fd))
continue;
- /* Update log_fds using the log module's fd */
- log_fds[n_fds] = lf->fd;
- if (lf->needs_close) {
- /* File log fds are duplicated, because close_log() closes the log
- * module's fd. Both refer to the same file. */
- err_fds[n_fds] = dup(lf->fd);
- } else {
- /* stdio log fds are not closed by the log module. */
- err_fds[n_fds] = lf->fd;
- }
+ /* Update fds using the log module's fd */
+ fds[n_fds] = lf->fd;
n_fds++;
if (n_fds == TOR_SIGSAFE_LOG_MAX_FDS)
break;
@@ -713,20 +700,19 @@ tor_log_update_sigsafe_err_fds(void)
}
if (!found_real_stderr &&
- int_array_contains(log_fds, n_fds, STDOUT_FILENO)) {
+ int_array_contains(fds, n_fds, STDOUT_FILENO)) {
/* Don't use a virtual stderr when we're also logging to stdout.
* If we reached max_fds logs, we'll now have (max_fds - 1) logs.
* That's ok, max_fds is large enough that most tor instances don't exceed
* it. */
raw_assert(n_fds >= 2); /* Don't tor_assert inside log fns */
--n_fds;
- log_fds[0] = log_fds[n_fds];
- err_fds[0] = err_fds[n_fds];
+ fds[0] = fds[n_fds];
}
UNLOCK_LOGS();
- tor_log_set_sigsafe_err_fds(err_fds, n_fds);
+ tor_log_set_sigsafe_err_fds(fds, n_fds);
}
/** Add to <b>out</b> a copy of every currently configured log file name. Used
@@ -835,6 +821,32 @@ logs_free_all(void)
* log mutex. */
}
+/** Flush the signal-safe log files.
+ *
+ * This function is safe to call from a signal handler. It is currenly called
+ * by the BUG() macros, when terminating the process on an abnormal condition.
+ */
+void
+logs_flush_sigsafe(void)
+{
+ /* If we don't have fsync() in unistd.h, we can't flush the logs. */
+#ifdef HAVE_FSYNC
+ logfile_t *victim, *next;
+ /* We can't LOCK_LOGS() in a signal handler, because it may call
+ * signal-unsafe functions. And we can't deallocate memory, either. */
+ next = logfiles;
+ logfiles = NULL;
+ while (next) {
+ victim = next;
+ next = next->next;
+ if (victim->needs_close) {
+ /* We can't do anything useful if the flush fails. */
+ (void)fsync(victim->fd);
+ }
+ }
+#endif /* defined(HAVE_FSYNC) */
+}
+
/** 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
@@ -907,9 +919,9 @@ set_log_severity_config(int loglevelMin, int loglevelMax,
/** Add a log handler named <b>name</b> to send all messages in <b>severity</b>
* to <b>fd</b>. Copies <b>severity</b>. Helper: does no locking. */
-static void
-add_stream_log_impl(const log_severity_list_t *severity,
- const char *name, int fd)
+MOCK_IMPL(STATIC void,
+add_stream_log_impl,(const log_severity_list_t *severity,
+ const char *name, int fd))
{
logfile_t *lf;
lf = tor_malloc_zero(sizeof(logfile_t));
@@ -965,18 +977,16 @@ logs_set_domain_logging(int enabled)
UNLOCK_LOGS();
}
-/** Add a log handler to receive messages during startup (before the real
- * logs are initialized).
+/** Add a log handler to accept messages when no other log is configured.
*/
void
-add_temp_log(int min_severity)
+add_default_log(int min_severity)
{
log_severity_list_t *s = tor_malloc_zero(sizeof(log_severity_list_t));
set_log_severity_config(min_severity, LOG_ERR, s);
LOCK_LOGS();
- add_stream_log_impl(s, "<temp>", fileno(stdout));
+ add_stream_log_impl(s, "<default>", fileno(stdout));
tor_free(s);
- logfiles->is_temporary = 1;
UNLOCK_LOGS();
}
@@ -1119,8 +1129,7 @@ flush_log_messages_from_startup(void)
UNLOCK_LOGS();
}
-/** Close any log handlers added by add_temp_log() or marked by
- * mark_logs_temp(). */
+/** Close any log handlers marked by mark_logs_temp(). */
void
close_temp_logs(void)
{
@@ -1172,10 +1181,10 @@ mark_logs_temp(void)
* opening the logfile failed, -1 is returned and errno is set appropriately
* (by open(2)). Takes ownership of fd.
*/
-int
-add_file_log(const log_severity_list_t *severity,
- const char *filename,
- int fd)
+MOCK_IMPL(int,
+add_file_log,(const log_severity_list_t *severity,
+ const char *filename,
+ int fd))
{
logfile_t *lf;
diff --git a/src/lib/log/log.h b/src/lib/log/log.h
index f09c63cdd9..aafbf9be2f 100644
--- a/src/lib/log/log.h
+++ b/src/lib/log/log.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -23,9 +23,11 @@
#include <syslog.h>
#define LOG_WARN LOG_WARNING
#if LOG_DEBUG < LOG_ERR
+#ifndef COCCI
#error "Your syslog.h thinks high numbers are more important. " \
"We aren't prepared to deal with that."
#endif
+#endif /* LOG_DEBUG < LOG_ERR */
#else /* !defined(HAVE_SYSLOG_H) */
/* 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
@@ -163,11 +165,11 @@ int parse_log_severity_config(const char **cfg,
log_severity_list_t *severity_out);
void set_log_severity_config(int minSeverity, int maxSeverity,
log_severity_list_t *severity_out);
-void add_stream_log(const log_severity_list_t *severity, const char *name,
- int fd);
-int add_file_log(const log_severity_list_t *severity,
- const char *filename,
- int fd);
+void add_stream_log(const log_severity_list_t *severity,
+ const char *name, int fd);
+MOCK_DECL(int, add_file_log,(const log_severity_list_t *severity,
+ const char *filename,
+ int fd));
#ifdef HAVE_SYSLOG_H
int add_syslog_log(const log_severity_list_t *severity,
@@ -184,7 +186,8 @@ void logs_set_domain_logging(int enabled);
int get_min_log_level(void);
void switch_logs_debug(void);
void logs_free_all(void);
-void add_temp_log(int min_severity);
+void logs_flush_sigsafe(void);
+void add_default_log(int min_severity);
void close_temp_logs(void);
void rollback_log_changes(void);
void mark_logs_temp(void);
@@ -193,7 +196,7 @@ void change_callback_log_severity(int loglevelMin, int loglevelMax,
void flush_pending_log_callbacks(void);
void flush_log_messages_from_startup(void);
void log_set_application_name(const char *name);
-void set_log_time_granularity(int granularity_msec);
+MOCK_DECL(void, set_log_time_granularity,(int granularity_msec));
void truncate_logs(void);
void tor_log(int severity, log_domain_mask_t domain, const char *format, ...)
@@ -305,7 +308,9 @@ extern const log_domain_mask_t LD_GENERAL_;
MOCK_DECL(STATIC void, logv, (int severity, log_domain_mask_t domain,
const char *funcname, const char *suffix, const char *format,
va_list ap) CHECK_PRINTF(5,0));
-#endif
+MOCK_DECL(STATIC void, add_stream_log_impl,(
+ const log_severity_list_t *severity, const char *name, int fd));
+#endif /* defined(LOG_PRIVATE) */
#if defined(LOG_PRIVATE) || defined(TOR_UNIT_TESTS)
/** Given a severity, yields an index into log_severity_list_t.masks to use
diff --git a/src/lib/log/log_sys.c b/src/lib/log/log_sys.c
index 826358546a..1be4f5b7d8 100644
--- a/src/lib/log/log_sys.c
+++ b/src/lib/log/log_sys.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/log/log_sys.h b/src/lib/log/log_sys.h
index 7043253066..523c2e5008 100644
--- a/src/lib/log/log_sys.h
+++ b/src/lib/log/log_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/log/ratelim.c b/src/lib/log/ratelim.c
index 5eec742aa7..ac401fb398 100644
--- a/src/lib/log/ratelim.c
+++ b/src/lib/log/ratelim.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/log/ratelim.h b/src/lib/log/ratelim.h
index 1db54ba726..e9b55d40dc 100644
--- a/src/lib/log/ratelim.h
+++ b/src/lib/log/ratelim.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -45,7 +45,9 @@ typedef struct ratelim_t {
int n_calls_since_last_time;
} ratelim_t;
+#ifndef COCCI
#define RATELIM_INIT(r) { (r), 0, 0 }
+#endif
#define RATELIM_TOOMANY (16*1000*1000)
char *rate_limit_log(ratelim_t *lim, time_t now);
diff --git a/src/lib/log/util_bug.c b/src/lib/log/util_bug.c
index af1ac40732..581ae85f47 100644
--- a/src/lib/log/util_bug.c
+++ b/src/lib/log/util_bug.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -163,7 +163,8 @@ tor_bug_occurred_(const char *fname, unsigned int line,
/**
* Call the tor_raw_abort_() function to close raw logs, then kill the current
- * process with a fatal error.
+ * process with a fatal error. But first, close the file-based log file
+ * descriptors, so error messages are written before process termination.
*
* (This is a separate function so that we declare it in util_bug.h without
* including torerr.h in all the users of util_bug.h)
@@ -171,6 +172,7 @@ tor_bug_occurred_(const char *fname, unsigned int line,
void
tor_abort_(void)
{
+ logs_flush_sigsafe();
tor_raw_abort_();
}
diff --git a/src/lib/log/util_bug.h b/src/lib/log/util_bug.h
index 7eaa6173c8..ae3d125a08 100644
--- a/src/lib/log/util_bug.h
+++ b/src/lib/log/util_bug.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -131,7 +131,9 @@
#undef BUG
// Coverity defines this in global headers; let's override it. This is a
// magic coverity-only preprocessor thing.
+#ifndef COCCI
#nodef BUG(x) (x)
+#endif
#endif /* defined(__COVERITY__) */
#if defined(__COVERITY__) || defined(__clang_analyzer__)
@@ -200,6 +202,7 @@
: 0)
#endif /* defined(ALL_BUGS_ARE_FATAL) || ... */
+#ifndef COCCI
#ifdef __GNUC__
#define IF_BUG_ONCE__(cond,var) \
if (( { \
@@ -208,7 +211,7 @@
if (bool_result && !var) { \
var = 1; \
tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \
- "!("#cond")", 1, NULL); \
+ ("!("#cond")"), 1, NULL); \
} \
bool_result; } ))
#else /* !defined(__GNUC__) */
@@ -218,10 +221,12 @@
(var ? 1 : \
(var=1, \
tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \
- "!("#cond")", 1, NULL), \
+ ("!("#cond")"), 1, NULL), \
1)) \
: 0)
#endif /* defined(__GNUC__) */
+#endif /* !defined(COCCI) */
+
#define IF_BUG_ONCE_VARNAME_(a) \
warning_logged_on_ ## a ## __
#define IF_BUG_ONCE_VARNAME__(a) \
diff --git a/src/lib/log/win32err.c b/src/lib/log/win32err.c
index 03d5c9fad2..8136813aab 100644
--- a/src/lib/log/win32err.c
+++ b/src/lib/log/win32err.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/log/win32err.h b/src/lib/log/win32err.h
index ecfa88792d..5c1386a64d 100644
--- a/src/lib/log/win32err.h
+++ b/src/lib/log/win32err.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/malloc/lib_malloc.md b/src/lib/malloc/lib_malloc.md
new file mode 100644
index 0000000000..ff61722f02
--- /dev/null
+++ b/src/lib/malloc/lib_malloc.md
@@ -0,0 +1,76 @@
+@dir /lib/malloc
+@brief lib/malloc: Wrappers and utilities for memory management.
+
+
+Tor imposes a few light wrappers over C's native malloc and free
+functions, to improve convenience, and to allow wholescale replacement
+of malloc and free as needed.
+
+You should never use 'malloc', 'calloc', 'realloc, or 'free' on their
+own; always use the variants prefixed with 'tor_'.
+They are the same as the standard C functions, with the following
+exceptions:
+
+ * `tor_free(NULL)` is a no-op.
+ * `tor_free()` is a macro that takes an lvalue as an argument and sets it to
+ NULL after freeing it. To avoid this behavior, you can use `tor_free_()`
+ instead.
+ * tor_malloc() and friends fail with an assertion if they are asked to
+ allocate a value so large that it is probably an underflow.
+ * It is always safe to `tor_malloc(0)`, regardless of whether your libc
+ allows it.
+ * `tor_malloc()`, `tor_realloc()`, and friends are never allowed to fail.
+ Instead, Tor will die with an assertion. This means that you never
+ need to check their return values. See the next subsection for
+ information on why we think this is a good idea.
+
+We define additional general-purpose memory allocation functions as well:
+
+ * `tor_malloc_zero(x)` behaves as `calloc(1, x)`, except the it makes clear
+ the intent to allocate a single zeroed-out value.
+ * `tor_reallocarray(x,y)` behaves as the OpenBSD reallocarray function.
+ Use it for cases when you need to realloc() in a multiplication-safe
+ way.
+
+And specific-purpose functions as well:
+
+ * `tor_strdup()` and `tor_strndup()` behaves as the underlying libc
+ functions, but use `tor_malloc()` instead of the underlying function.
+ * `tor_memdup()` copies a chunk of memory of a given size.
+ * `tor_memdup_nulterm()` copies a chunk of memory of a given size, then
+ NUL-terminates it just to be safe.
+
+#### Why assert on allocation failure?
+
+Why don't we allow `tor_malloc()` and its allies to return NULL?
+
+First, it's error-prone. Many programmers forget to check for NULL return
+values, and testing for `malloc()` failures is a major pain.
+
+Second, it's not necessarily a great way to handle OOM conditions. It's
+probably better (we think) to have a memory target where we dynamically free
+things ahead of time in order to stay under the target. Trying to respond to
+an OOM at the point of `tor_malloc()` failure, on the other hand, would involve
+a rare operation invoked from deep in the call stack. (Again, that's
+error-prone and hard to debug.)
+
+Third, thanks to the rise of Linux and other operating systems that allow
+memory to be overcommitted, you can't actually ever rely on getting a NULL
+from `malloc()` when you're out of memory; instead you have to use an approach
+closer to tracking the total memory usage.
+
+#### Conventions for your own allocation functions.
+
+Whenever you create a new type, the convention is to give it a pair of
+`x_new()` and `x_free_()` functions, named after the type.
+
+Calling `x_free(NULL)` should always be a no-op.
+
+There should additionally be an `x_free()` macro, defined in terms of
+`x_free_()`. This macro should set its lvalue to NULL. You can define it
+using the FREE_AND_NULL macro, as follows:
+
+```
+#define x_free(ptr) FREE_AND_NULL(x_t, x_free_, (ptr))
+```
+
diff --git a/src/lib/malloc/malloc.c b/src/lib/malloc/malloc.c
index 8628acfc97..9c9d600260 100644
--- a/src/lib/malloc/malloc.c
+++ b/src/lib/malloc/malloc.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/malloc/malloc.h b/src/lib/malloc/malloc.h
index 39a45901a1..80e8091adc 100644
--- a/src/lib/malloc/malloc.h
+++ b/src/lib/malloc/malloc.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/malloc/map_anon.c b/src/lib/malloc/map_anon.c
index 9559cbe2d4..1926b61f07 100644
--- a/src/lib/malloc/map_anon.c
+++ b/src/lib/malloc/map_anon.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -78,8 +78,8 @@
#endif /* defined(HAVE_MINHERIT) || ... */
#if defined(HAVE_MINHERIT) && !defined(FLAG_ZERO) && !defined(FLAG_NOINHERIT)
-#warn "minherit() is defined, but we couldn't find the right flag for it."
-#warn "This is probably a bug in Tor's support for this platform."
+#warning "minherit() is defined, but we couldn't find the right flag for it."
+#warning "This is probably a bug in Tor's support for this platform."
#endif
/**
diff --git a/src/lib/malloc/map_anon.h b/src/lib/malloc/map_anon.h
index 4c4690e12f..0354668d65 100644
--- a/src/lib/malloc/map_anon.h
+++ b/src/lib/malloc/map_anon.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/math/fp.c b/src/lib/math/fp.c
index 49a2a6a2ca..c09555209e 100644
--- a/src/lib/math/fp.c
+++ b/src/lib/math/fp.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -74,7 +74,7 @@ clamp_double_to_int64(double number)
branches that are not taken.
*/
#define PROBLEMATIC_FLOAT_CONVERSION_WARNING
-DISABLE_GCC_WARNING(float-conversion)
+DISABLE_GCC_WARNING("-Wfloat-conversion")
#endif /* (defined(MINGW_ANY)||defined(__FreeBSD__)) && GCC_VERSION >= 409 */
/*
@@ -84,7 +84,7 @@ DISABLE_GCC_WARNING(float-conversion)
#if defined(__clang__)
#if __has_warning("-Wdouble-promotion")
#define PROBLEMATIC_DOUBLE_PROMOTION_WARNING
-DISABLE_GCC_WARNING(double-promotion)
+DISABLE_GCC_WARNING("-Wdouble-promotion")
#endif
#endif /* defined(__clang__) */
@@ -115,10 +115,10 @@ DISABLE_GCC_WARNING(double-promotion)
return signbit(number) ? INT64_MIN : INT64_MAX;
#ifdef PROBLEMATIC_DOUBLE_PROMOTION_WARNING
-ENABLE_GCC_WARNING(double-promotion)
+ENABLE_GCC_WARNING("-Wdouble-promotion")
#endif
#ifdef PROBLEMATIC_FLOAT_CONVERSION_WARNING
-ENABLE_GCC_WARNING(float-conversion)
+ENABLE_GCC_WARNING("-Wfloat-conversion")
#endif
}
@@ -128,16 +128,16 @@ tor_isinf(double x)
{
/* Same as above, work around the "double promotion" warnings */
#ifdef PROBLEMATIC_FLOAT_CONVERSION_WARNING
-DISABLE_GCC_WARNING(float-conversion)
+DISABLE_GCC_WARNING("-Wfloat-conversion")
#endif
#ifdef PROBLEMATIC_DOUBLE_PROMOTION_WARNING
-DISABLE_GCC_WARNING(double-promotion)
+DISABLE_GCC_WARNING("-Wdouble-promotion")
#endif
return isinf(x);
#ifdef PROBLEMATIC_DOUBLE_PROMOTION_WARNING
-ENABLE_GCC_WARNING(double-promotion)
+ENABLE_GCC_WARNING("-Wdouble-promotion")
#endif
#ifdef PROBLEMATIC_FLOAT_CONVERSION_WARNING
-ENABLE_GCC_WARNING(float-conversion)
+ENABLE_GCC_WARNING("-Wfloat-conversion")
#endif
}
diff --git a/src/lib/math/fp.h b/src/lib/math/fp.h
index a73789c945..0a7a685485 100644
--- a/src/lib/math/fp.h
+++ b/src/lib/math/fp.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/math/laplace.c b/src/lib/math/laplace.c
index 302edb20b8..5c1d686a9c 100644
--- a/src/lib/math/laplace.c
+++ b/src/lib/math/laplace.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/math/laplace.h b/src/lib/math/laplace.h
index 02b0e890f0..e0dd166bbd 100644
--- a/src/lib/math/laplace.h
+++ b/src/lib/math/laplace.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/math/lib_math.md b/src/lib/math/lib_math.md
new file mode 100644
index 0000000000..9cc256d24b
--- /dev/null
+++ b/src/lib/math/lib_math.md
@@ -0,0 +1,6 @@
+@dir /lib/math
+@brief lib/math: Floating-point math utilities.
+
+This module includes a bunch of floating-point compatibility code, and
+implementations for several probability distributions.
+
diff --git a/src/lib/math/prob_distr.c b/src/lib/math/prob_distr.c
index d44dc28265..548d256023 100644
--- a/src/lib/math/prob_distr.c
+++ b/src/lib/math/prob_distr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -52,14 +52,15 @@
#include <math.h>
#include <stddef.h>
+#ifndef COCCI
/** Declare a function that downcasts from a generic dist struct to the actual
* subtype probablity distribution it represents. */
#define DECLARE_PROB_DISTR_DOWNCAST_FN(name) \
static inline \
- const struct name * \
- dist_to_const_##name(const struct dist *obj) { \
+ const struct name##_t * \
+ dist_to_const_##name(const struct dist_t *obj) { \
tor_assert(obj->ops == &name##_ops); \
- return SUBTYPE_P(obj, struct name, base); \
+ return SUBTYPE_P(obj, struct name ## _t, base); \
}
DECLARE_PROB_DISTR_DOWNCAST_FN(uniform)
DECLARE_PROB_DISTR_DOWNCAST_FN(geometric)
@@ -67,6 +68,7 @@ DECLARE_PROB_DISTR_DOWNCAST_FN(logistic)
DECLARE_PROB_DISTR_DOWNCAST_FN(log_logistic)
DECLARE_PROB_DISTR_DOWNCAST_FN(genpareto)
DECLARE_PROB_DISTR_DOWNCAST_FN(weibull)
+#endif /* !defined(COCCI) */
/**
* Count number of one bits in 32-bit word.
@@ -178,8 +180,8 @@ clz32(uint32_t x)
/**
* Compute the logistic function: f(x) = 1/(1 + e^{-x}) = e^x/(1 + e^x).
- * Maps a log-odds-space probability in [-\infty, +\infty] into a direct-space
- * probability in [0,1]. Inverse of logit.
+ * Maps a log-odds-space probability in [-infinity, +infinity] into a
+ * direct-space probability in [0,1]. Inverse of logit.
*
* Ill-conditioned for large x; the identity logistic(-x) = 1 -
* logistic(x) and the function logistichalf(x) = logistic(x) - 1/2 may
@@ -266,7 +268,7 @@ logistic(double x)
/**
* Compute the logit function: log p/(1 - p). Defined on [0,1]. Maps
* a direct-space probability in [0,1] to a log-odds-space probability
- * in [-\infty, +\infty]. Inverse of logistic.
+ * in [-infinity, +infinity]. Inverse of logistic.
*
* Ill-conditioned near 1/2 and 1; the identity logit(1 - p) =
* -logit(p) and the function logithalf(p0) = logit(1/2 + p0) may help
@@ -488,7 +490,7 @@ random_uniform_01(void)
/* Functions for specific probability distributions start here: */
/*
- * Logistic(mu, sigma) distribution, supported on (-\infty,+\infty)
+ * Logistic(mu, sigma) distribution, supported on (-infinity,+infinity)
*
* This is the uniform distribution on [0,1] mapped into log-odds
* space, scaled by sigma and translated by mu.
@@ -546,7 +548,7 @@ isf_logistic(double p, double mu, double sigma)
}
/*
- * LogLogistic(alpha, beta) distribution, supported on (0, +\infty).
+ * LogLogistic(alpha, beta) distribution, supported on (0, +infinity).
*
* This is the uniform distribution on [0,1] mapped into odds space,
* scaled by positive alpha and shaped by positive beta.
@@ -687,7 +689,7 @@ isf_log_logistic(double p, double alpha, double beta)
}
/*
- * Weibull(lambda, k) distribution, supported on (0, +\infty).
+ * Weibull(lambda, k) distribution, supported on (0, +infinity).
*
* pdf(x) = (k/lambda) (x/lambda)^{k - 1} e^{-(x/lambda)^k}
* cdf(x) = 1 - e^{-(x/lambda)^k}
@@ -753,7 +755,7 @@ isf_weibull(double p, double lambda, double k)
}
/*
- * GeneralizedPareto(mu, sigma, xi), supported on (mu, +\infty) for
+ * GeneralizedPareto(mu, sigma, xi), supported on (mu, +infinity) for
* nonnegative xi, or (mu, mu - sigma/xi) for negative xi.
*
* Samples:
@@ -793,19 +795,19 @@ cdf_genpareto(double x, double mu, double sigma, double xi)
/*
* log(1 + xi x_0)/xi
- * = (-1/xi) \sum_{n=1}^\infty (-xi x_0)^n/n
- * = (-1/xi) (-xi x_0 + \sum_{n=2}^\infty (-xi x_0)^n/n)
- * = x_0 - (1/xi) \sum_{n=2}^\infty (-xi x_0)^n/n
- * = x_0 - x_0 \sum_{n=2}^\infty (-xi x_0)^{n-1}/n
+ * = (-1/xi) \sum_{n=1}^infinity (-xi x_0)^n/n
+ * = (-1/xi) (-xi x_0 + \sum_{n=2}^infinity (-xi x_0)^n/n)
+ * = x_0 - (1/xi) \sum_{n=2}^infinity (-xi x_0)^n/n
+ * = x_0 - x_0 \sum_{n=2}^infinity (-xi x_0)^{n-1}/n
* = x_0 (1 - d),
*
- * where d = \sum_{n=2}^\infty (-xi x_0)^{n-1}/n. If |xi| <
+ * where d = \sum_{n=2}^infinity (-xi x_0)^{n-1}/n. If |xi| <
* eps/4|x_0|, then
*
- * |d| <= \sum_{n=2}^\infty (eps/4)^{n-1}/n
- * <= \sum_{n=2}^\infty (eps/4)^{n-1}
- * = \sum_{n=1}^\infty (eps/4)^n
- * = (eps/4) \sum_{n=0}^\infty (eps/4)^n
+ * |d| <= \sum_{n=2}^infinity (eps/4)^{n-1}/n
+ * <= \sum_{n=2}^infinity (eps/4)^{n-1}
+ * = \sum_{n=1}^infinity (eps/4)^n
+ * = (eps/4) \sum_{n=0}^infinity (eps/4)^n
* = (eps/4)/(1 - eps/4)
* < eps/2
*
@@ -855,20 +857,20 @@ icdf_genpareto(double p, double mu, double sigma, double xi)
* for xi near zero (note f(xi) --> -log U as xi --> 0), write
* the absolutely convergent Taylor expansion
*
- * f(xi) = (1/xi)*(-xi log U + \sum_{n=2}^\infty (-xi log U)^n/n!
- * = -log U + (1/xi)*\sum_{n=2}^\infty (-xi log U)^n/n!
- * = -log U + \sum_{n=2}^\infty xi^{n-1} (-log U)^n/n!
- * = -log U - log U \sum_{n=2}^\infty (-xi log U)^{n-1}/n!
- * = -log U (1 + \sum_{n=2}^\infty (-xi log U)^{n-1}/n!).
+ * f(xi) = (1/xi)*(-xi log U + \sum_{n=2}^infinity (-xi log U)^n/n!
+ * = -log U + (1/xi)*\sum_{n=2}^infinity (-xi log U)^n/n!
+ * = -log U + \sum_{n=2}^infinity xi^{n-1} (-log U)^n/n!
+ * = -log U - log U \sum_{n=2}^infinity (-xi log U)^{n-1}/n!
+ * = -log U (1 + \sum_{n=2}^infinity (-xi log U)^{n-1}/n!).
*
- * Let d = \sum_{n=2}^\infty (-xi log U)^{n-1}/n!. What do we
+ * Let d = \sum_{n=2}^infinity (-xi log U)^{n-1}/n!. What do we
* lose if we discard it and use -log U as an approximation to
* f(xi)? If |xi| < eps/-4log U, then
*
- * |d| <= \sum_{n=2}^\infty |xi log U|^{n-1}/n!
- * <= \sum_{n=2}^\infty (eps/4)^{n-1}/n!
- * <= \sum_{n=1}^\infty (eps/4)^n
- * = (eps/4) \sum_{n=0}^\infty (eps/4)^n
+ * |d| <= \sum_{n=2}^infinity |xi log U|^{n-1}/n!
+ * <= \sum_{n=2}^infinity (eps/4)^{n-1}/n!
+ * <= \sum_{n=1}^infinity (eps/4)^n
+ * = (eps/4) \sum_{n=0}^infinity (eps/4)^n
* = (eps/4)/(1 - eps/4)
* < eps/2,
*
@@ -1098,10 +1100,10 @@ sample_logistic(uint32_t s, double t, double p0)
* We carve up the interval (0, 1) into subregions to compute
* the inverse CDF precisely:
*
- * A = (0, 1/(1 + e)] ---> (-\infty, -1]
+ * A = (0, 1/(1 + e)] ---> (-infinity, -1]
* B = [1/(1 + e), 1/2] ---> [-1, 0]
* C = [1/2, 1 - 1/(1 + e)] ---> [0, 1]
- * D = [1 - 1/(1 + e), 1) ---> [1, +\infty)
+ * D = [1 - 1/(1 + e), 1) ---> [1, +infinity)
*
* Cases D and C are mirror images of cases A and B,
* respectively, so we choose between them by the sign chosen
@@ -1234,19 +1236,19 @@ sample_genpareto(uint32_t s, double p0, double xi)
* Write f(xi) = (e^{xi x} - 1)/xi for xi near zero as the
* absolutely convergent Taylor series
*
- * f(x) = (1/xi) (xi x + \sum_{n=2}^\infty (xi x)^n/n!)
- * = x + (1/xi) \sum_{n=2}^\inty (xi x)^n/n!
- * = x + \sum_{n=2}^\infty xi^{n-1} x^n/n!
- * = x + x \sum_{n=2}^\infty (xi x)^{n-1}/n!
- * = x (1 + \sum_{n=2}^\infty (xi x)^{n-1}/n!).
+ * f(x) = (1/xi) (xi x + \sum_{n=2}^infinity (xi x)^n/n!)
+ * = x + (1/xi) \sum_{n=2}^infinity (xi x)^n/n!
+ * = x + \sum_{n=2}^infinity xi^{n-1} x^n/n!
+ * = x + x \sum_{n=2}^infinity (xi x)^{n-1}/n!
+ * = x (1 + \sum_{n=2}^infinity (xi x)^{n-1}/n!).
*
- * d = \sum_{n=2}^\infty (xi x)^{n-1}/n! is the relative error
+ * d = \sum_{n=2}^infinity (xi x)^{n-1}/n! is the relative error
* of f(x) from x. If |xi| < eps/4x, then
*
- * |d| <= \sum_{n=2}^\infty |xi x|^{n-1}/n!
- * <= \sum_{n=2}^\infty (eps/4)^{n-1}/n!
- * <= \sum_{n=1}^\infty (eps/4)
- * = (eps/4) \sum_{n=0}^\infty (eps/4)^n
+ * |d| <= \sum_{n=2}^infinity |xi x|^{n-1}/n!
+ * <= \sum_{n=2}^infinity (eps/4)^{n-1}/n!
+ * <= \sum_{n=1}^infinity (eps/4)
+ * = (eps/4) \sum_{n=0}^infinity (eps/4)^n
* = (eps/4)/(1 - eps/4)
* < eps/2,
*
@@ -1324,42 +1326,42 @@ sample_geometric(uint32_t s, double p0, double p)
/** Returns the name of the distribution in <b>dist</b>. */
const char *
-dist_name(const struct dist *dist)
+dist_name(const struct dist_t *dist)
{
return dist->ops->name;
}
/* Sample a value from <b>dist</b> and return it. */
double
-dist_sample(const struct dist *dist)
+dist_sample(const struct dist_t *dist)
{
return dist->ops->sample(dist);
}
/** Compute the CDF of <b>dist</b> at <b>x</b>. */
double
-dist_cdf(const struct dist *dist, double x)
+dist_cdf(const struct dist_t *dist, double x)
{
return dist->ops->cdf(dist, x);
}
/** Compute the SF (Survival function) of <b>dist</b> at <b>x</b>. */
double
-dist_sf(const struct dist *dist, double x)
+dist_sf(const struct dist_t *dist, double x)
{
return dist->ops->sf(dist, x);
}
/** Compute the iCDF (Inverse CDF) of <b>dist</b> at <b>x</b>. */
double
-dist_icdf(const struct dist *dist, double p)
+dist_icdf(const struct dist_t *dist, double p)
{
return dist->ops->icdf(dist, p);
}
/** Compute the iSF (Inverse Survival function) of <b>dist</b> at <b>x</b>. */
double
-dist_isf(const struct dist *dist, double p)
+dist_isf(const struct dist_t *dist, double p)
{
return dist->ops->isf(dist, p);
}
@@ -1367,18 +1369,18 @@ dist_isf(const struct dist *dist, double p)
/** Functions for uniform distribution */
static double
-uniform_sample(const struct dist *dist)
+uniform_sample(const struct dist_t *dist)
{
- const struct uniform *U = dist_to_const_uniform(dist);
+ const struct uniform_t *U = dist_to_const_uniform(dist);
double p0 = random_uniform_01();
return sample_uniform_interval(p0, U->a, U->b);
}
static double
-uniform_cdf(const struct dist *dist, double x)
+uniform_cdf(const struct dist_t *dist, double x)
{
- const struct uniform *U = dist_to_const_uniform(dist);
+ const struct uniform_t *U = dist_to_const_uniform(dist);
if (x < U->a)
return 0;
else if (x < U->b)
@@ -1388,9 +1390,9 @@ uniform_cdf(const struct dist *dist, double x)
}
static double
-uniform_sf(const struct dist *dist, double x)
+uniform_sf(const struct dist_t *dist, double x)
{
- const struct uniform *U = dist_to_const_uniform(dist);
+ const struct uniform_t *U = dist_to_const_uniform(dist);
if (x > U->b)
return 0;
@@ -1401,24 +1403,24 @@ uniform_sf(const struct dist *dist, double x)
}
static double
-uniform_icdf(const struct dist *dist, double p)
+uniform_icdf(const struct dist_t *dist, double p)
{
- const struct uniform *U = dist_to_const_uniform(dist);
+ const struct uniform_t *U = dist_to_const_uniform(dist);
double w = U->b - U->a;
return (p < 0.5 ? (U->a + w*p) : (U->b - w*(1 - p)));
}
static double
-uniform_isf(const struct dist *dist, double p)
+uniform_isf(const struct dist_t *dist, double p)
{
- const struct uniform *U = dist_to_const_uniform(dist);
+ const struct uniform_t *U = dist_to_const_uniform(dist);
double w = U->b - U->a;
return (p < 0.5 ? (U->b - w*p) : (U->a + w*(1 - p)));
}
-const struct dist_ops uniform_ops = {
+const struct dist_ops_t uniform_ops = {
.name = "uniform",
.sample = uniform_sample,
.cdf = uniform_cdf,
@@ -1434,9 +1436,9 @@ const struct dist_ops uniform_ops = {
/** Functions for logistic distribution: */
static double
-logistic_sample(const struct dist *dist)
+logistic_sample(const struct dist_t *dist)
{
- const struct logistic *L = dist_to_const_logistic(dist);
+ const struct logistic_t *L = dist_to_const_logistic(dist);
uint32_t s = crypto_fast_rng_get_u32(get_thread_fast_rng());
double t = random_uniform_01();
double p0 = random_uniform_01();
@@ -1445,34 +1447,34 @@ logistic_sample(const struct dist *dist)
}
static double
-logistic_cdf(const struct dist *dist, double x)
+logistic_cdf(const struct dist_t *dist, double x)
{
- const struct logistic *L = dist_to_const_logistic(dist);
+ const struct logistic_t *L = dist_to_const_logistic(dist);
return cdf_logistic(x, L->mu, L->sigma);
}
static double
-logistic_sf(const struct dist *dist, double x)
+logistic_sf(const struct dist_t *dist, double x)
{
- const struct logistic *L = dist_to_const_logistic(dist);
+ const struct logistic_t *L = dist_to_const_logistic(dist);
return sf_logistic(x, L->mu, L->sigma);
}
static double
-logistic_icdf(const struct dist *dist, double p)
+logistic_icdf(const struct dist_t *dist, double p)
{
- const struct logistic *L = dist_to_const_logistic(dist);
+ const struct logistic_t *L = dist_to_const_logistic(dist);
return icdf_logistic(p, L->mu, L->sigma);
}
static double
-logistic_isf(const struct dist *dist, double p)
+logistic_isf(const struct dist_t *dist, double p)
{
- const struct logistic *L = dist_to_const_logistic(dist);
+ const struct logistic_t *L = dist_to_const_logistic(dist);
return isf_logistic(p, L->mu, L->sigma);
}
-const struct dist_ops logistic_ops = {
+const struct dist_ops_t logistic_ops = {
.name = "logistic",
.sample = logistic_sample,
.cdf = logistic_cdf,
@@ -1484,9 +1486,9 @@ const struct dist_ops logistic_ops = {
/** Functions for log-logistic distribution: */
static double
-log_logistic_sample(const struct dist *dist)
+log_logistic_sample(const struct dist_t *dist)
{
- const struct log_logistic *LL = dist_to_const_log_logistic(dist);
+ const struct log_logistic_t *LL = dist_to_const_log_logistic(dist);
uint32_t s = crypto_fast_rng_get_u32(get_thread_fast_rng());
double p0 = random_uniform_01();
@@ -1494,34 +1496,34 @@ log_logistic_sample(const struct dist *dist)
}
static double
-log_logistic_cdf(const struct dist *dist, double x)
+log_logistic_cdf(const struct dist_t *dist, double x)
{
- const struct log_logistic *LL = dist_to_const_log_logistic(dist);
+ const struct log_logistic_t *LL = dist_to_const_log_logistic(dist);
return cdf_log_logistic(x, LL->alpha, LL->beta);
}
static double
-log_logistic_sf(const struct dist *dist, double x)
+log_logistic_sf(const struct dist_t *dist, double x)
{
- const struct log_logistic *LL = dist_to_const_log_logistic(dist);
+ const struct log_logistic_t *LL = dist_to_const_log_logistic(dist);
return sf_log_logistic(x, LL->alpha, LL->beta);
}
static double
-log_logistic_icdf(const struct dist *dist, double p)
+log_logistic_icdf(const struct dist_t *dist, double p)
{
- const struct log_logistic *LL = dist_to_const_log_logistic(dist);
+ const struct log_logistic_t *LL = dist_to_const_log_logistic(dist);
return icdf_log_logistic(p, LL->alpha, LL->beta);
}
static double
-log_logistic_isf(const struct dist *dist, double p)
+log_logistic_isf(const struct dist_t *dist, double p)
{
- const struct log_logistic *LL = dist_to_const_log_logistic(dist);
+ const struct log_logistic_t *LL = dist_to_const_log_logistic(dist);
return isf_log_logistic(p, LL->alpha, LL->beta);
}
-const struct dist_ops log_logistic_ops = {
+const struct dist_ops_t log_logistic_ops = {
.name = "log logistic",
.sample = log_logistic_sample,
.cdf = log_logistic_cdf,
@@ -1533,9 +1535,9 @@ const struct dist_ops log_logistic_ops = {
/** Functions for Weibull distribution */
static double
-weibull_sample(const struct dist *dist)
+weibull_sample(const struct dist_t *dist)
{
- const struct weibull *W = dist_to_const_weibull(dist);
+ const struct weibull_t *W = dist_to_const_weibull(dist);
uint32_t s = crypto_fast_rng_get_u32(get_thread_fast_rng());
double p0 = random_uniform_01();
@@ -1543,34 +1545,34 @@ weibull_sample(const struct dist *dist)
}
static double
-weibull_cdf(const struct dist *dist, double x)
+weibull_cdf(const struct dist_t *dist, double x)
{
- const struct weibull *W = dist_to_const_weibull(dist);
+ const struct weibull_t *W = dist_to_const_weibull(dist);
return cdf_weibull(x, W->lambda, W->k);
}
static double
-weibull_sf(const struct dist *dist, double x)
+weibull_sf(const struct dist_t *dist, double x)
{
- const struct weibull *W = dist_to_const_weibull(dist);
+ const struct weibull_t *W = dist_to_const_weibull(dist);
return sf_weibull(x, W->lambda, W->k);
}
static double
-weibull_icdf(const struct dist *dist, double p)
+weibull_icdf(const struct dist_t *dist, double p)
{
- const struct weibull *W = dist_to_const_weibull(dist);
+ const struct weibull_t *W = dist_to_const_weibull(dist);
return icdf_weibull(p, W->lambda, W->k);
}
static double
-weibull_isf(const struct dist *dist, double p)
+weibull_isf(const struct dist_t *dist, double p)
{
- const struct weibull *W = dist_to_const_weibull(dist);
+ const struct weibull_t *W = dist_to_const_weibull(dist);
return isf_weibull(p, W->lambda, W->k);
}
-const struct dist_ops weibull_ops = {
+const struct dist_ops_t weibull_ops = {
.name = "Weibull",
.sample = weibull_sample,
.cdf = weibull_cdf,
@@ -1582,9 +1584,9 @@ const struct dist_ops weibull_ops = {
/** Functions for generalized Pareto distributions */
static double
-genpareto_sample(const struct dist *dist)
+genpareto_sample(const struct dist_t *dist)
{
- const struct genpareto *GP = dist_to_const_genpareto(dist);
+ const struct genpareto_t *GP = dist_to_const_genpareto(dist);
uint32_t s = crypto_fast_rng_get_u32(get_thread_fast_rng());
double p0 = random_uniform_01();
@@ -1592,34 +1594,34 @@ genpareto_sample(const struct dist *dist)
}
static double
-genpareto_cdf(const struct dist *dist, double x)
+genpareto_cdf(const struct dist_t *dist, double x)
{
- const struct genpareto *GP = dist_to_const_genpareto(dist);
+ const struct genpareto_t *GP = dist_to_const_genpareto(dist);
return cdf_genpareto(x, GP->mu, GP->sigma, GP->xi);
}
static double
-genpareto_sf(const struct dist *dist, double x)
+genpareto_sf(const struct dist_t *dist, double x)
{
- const struct genpareto *GP = dist_to_const_genpareto(dist);
+ const struct genpareto_t *GP = dist_to_const_genpareto(dist);
return sf_genpareto(x, GP->mu, GP->sigma, GP->xi);
}
static double
-genpareto_icdf(const struct dist *dist, double p)
+genpareto_icdf(const struct dist_t *dist, double p)
{
- const struct genpareto *GP = dist_to_const_genpareto(dist);
+ const struct genpareto_t *GP = dist_to_const_genpareto(dist);
return icdf_genpareto(p, GP->mu, GP->sigma, GP->xi);
}
static double
-genpareto_isf(const struct dist *dist, double p)
+genpareto_isf(const struct dist_t *dist, double p)
{
- const struct genpareto *GP = dist_to_const_genpareto(dist);
+ const struct genpareto_t *GP = dist_to_const_genpareto(dist);
return isf_genpareto(p, GP->mu, GP->sigma, GP->xi);
}
-const struct dist_ops genpareto_ops = {
+const struct dist_ops_t genpareto_ops = {
.name = "generalized Pareto",
.sample = genpareto_sample,
.cdf = genpareto_cdf,
@@ -1631,9 +1633,9 @@ const struct dist_ops genpareto_ops = {
/** Functions for geometric distribution on number of trials before success */
static double
-geometric_sample(const struct dist *dist)
+geometric_sample(const struct dist_t *dist)
{
- const struct geometric *G = dist_to_const_geometric(dist);
+ const struct geometric_t *G = dist_to_const_geometric(dist);
uint32_t s = crypto_fast_rng_get_u32(get_thread_fast_rng());
double p0 = random_uniform_01();
@@ -1641,9 +1643,9 @@ geometric_sample(const struct dist *dist)
}
static double
-geometric_cdf(const struct dist *dist, double x)
+geometric_cdf(const struct dist_t *dist, double x)
{
- const struct geometric *G = dist_to_const_geometric(dist);
+ const struct geometric_t *G = dist_to_const_geometric(dist);
if (x < 1)
return 0;
@@ -1652,9 +1654,9 @@ geometric_cdf(const struct dist *dist, double x)
}
static double
-geometric_sf(const struct dist *dist, double x)
+geometric_sf(const struct dist_t *dist, double x)
{
- const struct geometric *G = dist_to_const_geometric(dist);
+ const struct geometric_t *G = dist_to_const_geometric(dist);
if (x < 1)
return 0;
@@ -1663,22 +1665,22 @@ geometric_sf(const struct dist *dist, double x)
}
static double
-geometric_icdf(const struct dist *dist, double p)
+geometric_icdf(const struct dist_t *dist, double p)
{
- const struct geometric *G = dist_to_const_geometric(dist);
+ const struct geometric_t *G = dist_to_const_geometric(dist);
return log1p(-p)/log1p(-G->p);
}
static double
-geometric_isf(const struct dist *dist, double p)
+geometric_isf(const struct dist_t *dist, double p)
{
- const struct geometric *G = dist_to_const_geometric(dist);
+ const struct geometric_t *G = dist_to_const_geometric(dist);
return log(p)/log1p(-G->p);
}
-const struct dist_ops geometric_ops = {
+const struct dist_ops_t geometric_ops = {
.name = "geometric (1-based)",
.sample = geometric_sample,
.cdf = geometric_cdf,
diff --git a/src/lib/math/prob_distr.h b/src/lib/math/prob_distr.h
index 7254dc8623..a036073b93 100644
--- a/src/lib/math/prob_distr.h
+++ b/src/lib/math/prob_distr.h
@@ -15,13 +15,13 @@
/**
* Container for distribution parameters for sampling, CDF, &c.
*/
-struct dist {
- const struct dist_ops *ops;
+struct dist_t {
+ const struct dist_ops_t *ops;
};
/**
- * Untyped initializer element for struct dist using the specified
- * struct dist_ops pointer. Don't actually use this directly -- use
+ * Untyped initializer element for struct dist_t using the specified
+ * struct dist_ops_t pointer. Don't actually use this directly -- use
* the type-specific macro built out of DIST_BASE_TYPED below -- but if
* you did use this directly, it would be something like:
*
@@ -61,46 +61,46 @@ struct dist {
#endif /* defined(__COVERITY__) */
/**
-* Typed initializer element for struct dist using the specified struct
-* dist_ops pointer. Don't actually use this directly -- use a
+* Typed initializer element for struct dist_t using the specified struct
+* dist_ops_t pointer. Don't actually use this directly -- use a
* type-specific macro built out of it -- but if you did use this
* directly, it would be something like:
*
-* struct weibull mydist = {
-* DIST_BASE_TYPED(&weibull_ops, mydist, struct weibull),
-* .lambda = ...,
-* .k = ...,
-* };
+* struct weibull mydist = {
+* DIST_BASE_TYPED(&weibull_ops, mydist, struct weibull_t),
+* .lambda = ...,
+* .k = ...,
+* };
*
* If you want to define a distribution type, define a canonical set of
* operations and define a type-specific initializer element like so:
*
-* struct foo {
-* struct dist base;
-* int omega;
-* double tau;
-* double phi;
-* };
+* struct foo_t {
+* struct dist_t base;
+* int omega;
+* double tau;
+* double phi;
+* };
*
-* struct dist_ops foo_ops = ...;
+* struct dist_ops_t foo_ops = ...;
*
-* #define FOO(OBJ) DIST_BASE_TYPED(&foo_ops, OBJ, struct foo)
+* #define FOO(OBJ) DIST_BASE_TYPED(&foo_ops, OBJ, struct foo_t)
*
* Then users can do:
*
-* struct foo mydist = {
-* FOO(mydist),
-* .omega = ...,
-* .tau = ...,
-* .phi = ...,
-* };
+* struct foo_t mydist = {
+* FOO(mydist),
+* .omega = ...,
+* .tau = ...,
+* .phi = ...,
+* };
*
* If you accidentally write
*
-* struct bar mydist = {
-* FOO(mydist),
-* ...
-* };
+* struct bar_t mydist = {
+* FOO(mydist),
+* ...
+* };
*
* then the compiler will report a type mismatch in the sizeof
* expression, which otherwise evaporates at runtime.
@@ -110,107 +110,107 @@ struct dist {
/**
* Generic operations on distributions. These simply defer to the
- * corresponding dist_ops function. In the parlance of C++, these call
+ * corresponding dist_ops_t function. In the parlance of C++, these call
* virtual member functions.
*/
-const char *dist_name(const struct dist *);
-double dist_sample(const struct dist *);
-double dist_cdf(const struct dist *, double x);
-double dist_sf(const struct dist *, double x);
-double dist_icdf(const struct dist *, double p);
-double dist_isf(const struct dist *, double p);
+const char *dist_name(const struct dist_t *);
+double dist_sample(const struct dist_t *);
+double dist_cdf(const struct dist_t *, double x);
+double dist_sf(const struct dist_t *, double x);
+double dist_icdf(const struct dist_t *, double p);
+double dist_isf(const struct dist_t *, double p);
/**
* Set of operations on a potentially parametric family of
* distributions. In the parlance of C++, this would be called a
* `vtable' and the members are virtual member functions.
*/
-struct dist_ops {
+struct dist_ops_t {
const char *name;
- double (*sample)(const struct dist *);
- double (*cdf)(const struct dist *, double x);
- double (*sf)(const struct dist *, double x);
- double (*icdf)(const struct dist *, double p);
- double (*isf)(const struct dist *, double p);
+ double (*sample)(const struct dist_t *);
+ double (*cdf)(const struct dist_t *, double x);
+ double (*sf)(const struct dist_t *, double x);
+ double (*icdf)(const struct dist_t *, double p);
+ double (*isf)(const struct dist_t *, double p);
};
/* Geometric distribution on positive number of trials before first success */
-struct geometric {
- struct dist base;
+struct geometric_t {
+ struct dist_t base;
double p; /* success probability */
};
-extern const struct dist_ops geometric_ops;
+extern const struct dist_ops_t geometric_ops;
#define GEOMETRIC(OBJ) \
- DIST_BASE_TYPED(&geometric_ops, OBJ, struct geometric)
+ DIST_BASE_TYPED(&geometric_ops, OBJ, struct geometric_t)
/* Pareto distribution */
-struct genpareto {
- struct dist base;
+struct genpareto_t {
+ struct dist_t base;
double mu;
double sigma;
double xi;
};
-extern const struct dist_ops genpareto_ops;
+extern const struct dist_ops_t genpareto_ops;
#define GENPARETO(OBJ) \
- DIST_BASE_TYPED(&genpareto_ops, OBJ, struct genpareto)
+ DIST_BASE_TYPED(&genpareto_ops, OBJ, struct genpareto_t)
/* Weibull distribution */
-struct weibull {
- struct dist base;
+struct weibull_t {
+ struct dist_t base;
double lambda;
double k;
};
-extern const struct dist_ops weibull_ops;
+extern const struct dist_ops_t weibull_ops;
#define WEIBULL(OBJ) \
- DIST_BASE_TYPED(&weibull_ops, OBJ, struct weibull)
+ DIST_BASE_TYPED(&weibull_ops, OBJ, struct weibull_t)
/* Log-logistic distribution */
-struct log_logistic {
- struct dist base;
+struct log_logistic_t {
+ struct dist_t base;
double alpha;
double beta;
};
-extern const struct dist_ops log_logistic_ops;
+extern const struct dist_ops_t log_logistic_ops;
#define LOG_LOGISTIC(OBJ) \
- DIST_BASE_TYPED(&log_logistic_ops, OBJ, struct log_logistic)
+ DIST_BASE_TYPED(&log_logistic_ops, OBJ, struct log_logistic_t)
/* Logistic distribution */
-struct logistic {
- struct dist base;
+struct logistic_t {
+ struct dist_t base;
double mu;
double sigma;
};
-extern const struct dist_ops logistic_ops;
+extern const struct dist_ops_t logistic_ops;
#define LOGISTIC(OBJ) \
- DIST_BASE_TYPED(&logistic_ops, OBJ, struct logistic)
+ DIST_BASE_TYPED(&logistic_ops, OBJ, struct logistic_t)
/* Uniform distribution */
-struct uniform {
- struct dist base;
+struct uniform_t {
+ struct dist_t base;
double a;
double b;
};
-extern const struct dist_ops uniform_ops;
+extern const struct dist_ops_t uniform_ops;
#define UNIFORM(OBJ) \
- DIST_BASE_TYPED(&uniform_ops, OBJ, struct uniform)
+ DIST_BASE_TYPED(&uniform_ops, OBJ, struct uniform_t)
/** Only by unittests */
diff --git a/src/lib/memarea/lib_memarea.md b/src/lib/memarea/lib_memarea.md
new file mode 100644
index 0000000000..fe5cb8293f
--- /dev/null
+++ b/src/lib/memarea/lib_memarea.md
@@ -0,0 +1,28 @@
+@dir /lib/memarea
+@brief lib/memarea: A fast arena-style allocator.
+
+This module has a fast "arena" style allocator, where memory is freed all at
+once. This kind of allocation is very fast and avoids fragmentation, at the
+expense of requiring all the data to be freed at the same time. We use this
+for parsing and diff calculations.
+
+It's often handy to allocate a large number of tiny objects, all of which
+need to disappear at the same time. You can do this in tor using the
+memarea.c abstraction, which uses a set of grow-only buffers for allocation,
+and only supports a single "free" operation at the end.
+
+Using memareas also helps you avoid memory fragmentation. You see, some libc
+malloc implementations perform badly on the case where a large number of
+small temporary objects are allocated at the same time as a few long-lived
+objects of similar size. But if you use tor_malloc() for the long-lived ones
+and a memarea for the temporary object, the malloc implementation is likelier
+to do better.
+
+To create a new memarea, use `memarea_new()`. To drop all the storage from a
+memarea, and invalidate its pointers, use `memarea_drop_all()`.
+
+The allocation functions `memarea_alloc()`, `memarea_alloc_zero()`,
+`memarea_memdup()`, `memarea_strdup()`, and `memarea_strndup()` are analogous
+to the similarly-named malloc() functions. There is intentionally no
+`memarea_free()` or `memarea_realloc()`.
+
diff --git a/src/lib/memarea/memarea.c b/src/lib/memarea/memarea.c
index f3bb79a1e2..d677c364a4 100644
--- a/src/lib/memarea/memarea.c
+++ b/src/lib/memarea/memarea.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2019, The Tor Project, Inc. */
+/* Copyright (c) 2008-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/memarea/memarea.h b/src/lib/memarea/memarea.h
index 9c23cf62e9..8b5e63e6b3 100644
--- a/src/lib/memarea/memarea.h
+++ b/src/lib/memarea/memarea.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2019, The Tor Project, Inc. */
+/* Copyright (c) 2008-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -16,6 +16,9 @@ typedef struct memarea_t memarea_t;
memarea_t *memarea_new(void);
void memarea_drop_all_(memarea_t *area);
+/** @copydoc memarea_drop_all_
+ *
+ * Additionally, set <b>area</b> to NULL. */
#define memarea_drop_all(area) \
do { \
memarea_drop_all_(area); \
diff --git a/src/lib/meminfo/lib_meminfo.md b/src/lib/meminfo/lib_meminfo.md
new file mode 100644
index 0000000000..87f509d648
--- /dev/null
+++ b/src/lib/meminfo/lib_meminfo.md
@@ -0,0 +1,5 @@
+@dir /lib/meminfo
+@brief lib/meminfo: Inspecting malloc() usage.
+
+Only available when malloc() provides mallinfo() or something similar.
+
diff --git a/src/lib/meminfo/meminfo.c b/src/lib/meminfo/meminfo.c
index bff71c2f05..0c5e0ed665 100644
--- a/src/lib/meminfo/meminfo.c
+++ b/src/lib/meminfo/meminfo.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -37,7 +37,7 @@
#include <sys/sysctl.h>
#endif
-DISABLE_GCC_WARNING(aggregate-return)
+DISABLE_GCC_WARNING("-Waggregate-return")
/** Call the platform malloc info function, and dump the results to the log at
* level <b>severity</b>. If no such function exists, do nothing. */
void
@@ -58,7 +58,7 @@ tor_log_mallinfo(int severity)
(void)severity;
#endif /* defined(HAVE_MALLINFO) */
}
-ENABLE_GCC_WARNING(aggregate-return)
+ENABLE_GCC_WARNING("-Waggregate-return")
#if defined(HW_PHYSMEM64)
/* OpenBSD and NetBSD define this */
diff --git a/src/lib/meminfo/meminfo.h b/src/lib/meminfo/meminfo.h
index 9580640f4d..a5ebfd5a6a 100644
--- a/src/lib/meminfo/meminfo.h
+++ b/src/lib/meminfo/meminfo.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/address.c b/src/lib/net/address.c
index 41017935e1..d623cdd131 100644
--- a/src/lib/net/address.c
+++ b/src/lib/net/address.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -1393,7 +1393,7 @@ get_interface_addresses_win32(int severity, sa_family_t family)
/* This is defined on Mac OS X */
#ifndef _SIZEOF_ADDR_IFREQ
-#define _SIZEOF_ADDR_IFREQ sizeof
+#define _SIZEOF_ADDR_IFREQ(x) sizeof(x)
#endif
/* Free ifc->ifc_buf safely. */
@@ -2002,7 +2002,7 @@ tor_addr_port_new(const tor_addr_t *addr, uint16_t port)
return ap;
}
-/** Return true iff <a>a</b> and <b>b</b> are the same address and port */
+/** Return true iff <b>a</b> and <b>b</b> are the same address and port */
int
tor_addr_port_eq(const tor_addr_port_t *a,
const tor_addr_port_t *b)
diff --git a/src/lib/net/address.h b/src/lib/net/address.h
index 9b826c8359..815fb02283 100644
--- a/src/lib/net/address.h
+++ b/src/lib/net/address.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -62,6 +62,7 @@
typedef uint8_t maskbits_t;
struct in_addr;
+
/** Holds an IPv4 or IPv6 address. (Uses less memory than struct
* sockaddr_storage.) */
typedef struct tor_addr_t
@@ -133,6 +134,7 @@ tor_addr_to_in6_assert(const tor_addr_t *a)
* Requires that <b>x</b> is actually an IPv6 address.
*/
#define tor_addr_to_in6_addr16(x) S6_ADDR16(*tor_addr_to_in6_assert(x))
+
/** Given an IPv6 address <b>x</b>, yield it as an array of uint32_t.
*
* Requires that <b>x</b> is actually an IPv6 address.
@@ -146,6 +148,7 @@ tor_addr_to_ipv4n(const tor_addr_t *a)
{
return a->family == AF_INET ? a->addr.in_addr.s_addr : 0;
}
+
/** Return an IPv4 address in host order for <b>a</b>, or 0 if
* <b>a</b> is not an IPv4 address. */
static inline uint32_t
@@ -153,10 +156,11 @@ tor_addr_to_ipv4h(const tor_addr_t *a)
{
return ntohl(tor_addr_to_ipv4n(a));
}
+
/** Given an IPv6 address, return its mapped IPv4 address in host order, or
* 0 if <b>a</b> is not an IPv6 address.
*
- * (Does not check whether the address is really a mapped address */
+ * (Does not check whether the address is really a mapped address.) */
static inline uint32_t
tor_addr_to_mapped_ipv4h(const tor_addr_t *a)
{
@@ -165,14 +169,13 @@ tor_addr_to_mapped_ipv4h(const tor_addr_t *a)
// Work around an incorrect NULL pointer dereference warning in
// "clang --analyze" due to limited analysis depth
addr32 = tor_addr_to_in6_addr32(a);
- // To improve performance, wrap this assertion in:
- // #if !defined(__clang_analyzer__) || PARANOIA
tor_assert(addr32);
return ntohl(addr32[3]);
} else {
return 0;
}
}
+
/** Return the address family of <b>a</b>. Possible values are:
* AF_INET6, AF_INET, AF_UNSPEC. */
static inline sa_family_t
@@ -180,6 +183,7 @@ tor_addr_family(const tor_addr_t *a)
{
return a->family;
}
+
/** Return an in_addr* equivalent to <b>a</b>, or NULL if <b>a</b> is not
* an IPv4 address. */
static inline const struct in_addr *
@@ -187,6 +191,7 @@ tor_addr_to_in(const tor_addr_t *a)
{
return a->family == AF_INET ? &a->addr.in_addr : NULL;
}
+
/** Return true iff <b>a</b> is an IPv4 address equal to the host-ordered
* address in <b>u</b>. */
static inline int
@@ -209,19 +214,23 @@ char *tor_addr_to_str_dup(const tor_addr_t *addr) ATTR_MALLOC;
/** Wrapper function of fmt_addr_impl(). It does not decorate IPv6
* addresses. */
#define fmt_addr(a) fmt_addr_impl((a), 0)
+
/** Wrapper function of fmt_addr_impl(). It decorates IPv6
* addresses. */
#define fmt_and_decorate_addr(a) fmt_addr_impl((a), 1)
+
const char *fmt_addr_impl(const tor_addr_t *addr, int decorate);
const char *fmt_addrport(const tor_addr_t *addr, uint16_t port);
const char * fmt_addr32(uint32_t addr);
MOCK_DECL(int,get_interface_address6,(int severity, sa_family_t family,
tor_addr_t *addr));
+
struct smartlist_t;
-void interface_address6_list_free_(struct smartlist_t * addrs);// XXXX
+void interface_address6_list_free_(struct smartlist_t * addrs);
#define interface_address6_list_free(addrs) \
FREE_AND_NULL(struct smartlist_t, interface_address6_list_free_, (addrs))
+
MOCK_DECL(struct smartlist_t *,get_interface_address6_list,(int severity,
sa_family_t family,
int include_internal));
@@ -246,6 +255,7 @@ int tor_addr_compare_masked(const tor_addr_t *addr1, const tor_addr_t *addr2,
uint64_t tor_addr_hash(const tor_addr_t *addr);
struct sipkey;
uint64_t tor_addr_keyed_hash(const struct sipkey *key, const tor_addr_t *addr);
+
int tor_addr_is_v4(const tor_addr_t *addr);
int tor_addr_is_internal_(const tor_addr_t *ip, int for_listening,
const char *filename, int lineno);
@@ -276,11 +286,13 @@ int tor_addr_parse_PTR_name(tor_addr_t *result, const char *address,
int tor_addr_parse_mask_ports(const char *s, unsigned flags,
tor_addr_t *addr_out, maskbits_t *mask_out,
uint16_t *port_min_out, uint16_t *port_max_out);
+
const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len,
int decorate);
int tor_addr_parse(tor_addr_t *addr, const char *src);
void tor_addr_copy(tor_addr_t *dest, const tor_addr_t *src);
void tor_addr_copy_tight(tor_addr_t *dest, const tor_addr_t *src);
+
void tor_addr_from_ipv4n(tor_addr_t *dest, uint32_t v4addr);
/** Set <b>dest</b> to the IPv4 address encoded in <b>v4addr</b> in host
* order. */
@@ -291,6 +303,7 @@ void tor_addr_from_ipv6_bytes(tor_addr_t *dest, const char *bytes);
#define tor_addr_from_in(dest, in) \
tor_addr_from_ipv4n((dest), (in)->s_addr);
void tor_addr_from_in6(tor_addr_t *dest, const struct in6_addr *in6);
+
int tor_addr_is_null(const tor_addr_t *addr);
int tor_addr_is_loopback(const tor_addr_t *addr);
@@ -299,6 +312,7 @@ int tor_addr_is_valid_ipv4n(uint32_t v4n_addr, int for_listening);
#define tor_addr_is_valid_ipv4h(v4h_addr, for_listening) \
tor_addr_is_valid_ipv4n(htonl(v4h_addr), (for_listening))
int tor_port_is_valid(uint16_t port, int for_listening);
+
/* Are addr and port both valid? */
#define tor_addr_port_is_valid(addr, port, for_listening) \
(tor_addr_is_valid((addr), (for_listening)) && \
@@ -329,9 +343,11 @@ int parse_port_range(const char *port, uint16_t *port_min_out,
uint16_t *port_max_out);
int addr_mask_get_bits(uint32_t mask);
char *tor_dup_ip(uint32_t addr) ATTR_MALLOC;
+
MOCK_DECL(int,get_interface_address,(int severity, uint32_t *addr));
#define interface_address_list_free(lst)\
interface_address6_list_free(lst)
+
/** Return a smartlist of the IPv4 addresses of all interfaces on the server.
* Excludes loopback and multicast addresses. Only includes internal addresses
* if include_internal is true. (Note that a relay behind NAT may use an
diff --git a/src/lib/net/alertsock.c b/src/lib/net/alertsock.c
index cc59d7d893..537fdcaee4 100644
--- a/src/lib/net/alertsock.c
+++ b/src/lib/net/alertsock.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/alertsock.h b/src/lib/net/alertsock.h
index 4d0d0dd57c..dab4273cf1 100644
--- a/src/lib/net/alertsock.h
+++ b/src/lib/net/alertsock.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/buffers_net.c b/src/lib/net/buffers_net.c
index cfe1a7dc26..aa84451074 100644
--- a/src/lib/net/buffers_net.c
+++ b/src/lib/net/buffers_net.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/buffers_net.h b/src/lib/net/buffers_net.h
index 5058dd0a26..a45c23a273 100644
--- a/src/lib/net/buffers_net.h
+++ b/src/lib/net/buffers_net.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/gethostname.c b/src/lib/net/gethostname.c
index e54a1ea16e..001d95391d 100644
--- a/src/lib/net/gethostname.c
+++ b/src/lib/net/gethostname.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/gethostname.h b/src/lib/net/gethostname.h
index b3b77b0589..90f8056779 100644
--- a/src/lib/net/gethostname.h
+++ b/src/lib/net/gethostname.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/inaddr.c b/src/lib/net/inaddr.c
index d9ae7cd562..0d20d88901 100644
--- a/src/lib/net/inaddr.c
+++ b/src/lib/net/inaddr.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -35,11 +35,11 @@
* (Like inet_aton(str,addr), but works on Windows and Solaris.)
*/
int
-tor_inet_aton(const char *str, struct in_addr* addr)
+tor_inet_aton(const char *str, struct in_addr *addr)
{
- unsigned a,b,c,d;
+ unsigned a, b, c, d;
char more;
- if (tor_sscanf(str, "%3u.%3u.%3u.%3u%c", &a,&b,&c,&d,&more) != 4)
+ if (tor_sscanf(str, "%3u.%3u.%3u.%3u%c", &a, &b, &c, &d, &more) != 4)
return 0;
if (a > 255) return 0;
if (b > 255) return 0;
diff --git a/src/lib/net/inaddr.h b/src/lib/net/inaddr.h
index 602573944c..8d6766eb5d 100644
--- a/src/lib/net/inaddr.h
+++ b/src/lib/net/inaddr.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/inaddr_st.h b/src/lib/net/inaddr_st.h
index 230f29a63a..b9ee2b86cf 100644
--- a/src/lib/net/inaddr_st.h
+++ b/src/lib/net/inaddr_st.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/lib_net.md b/src/lib/net/lib_net.md
new file mode 100644
index 0000000000..b61878d827
--- /dev/null
+++ b/src/lib/net/lib_net.md
@@ -0,0 +1,6 @@
+@dir /lib/net
+@brief lib/net: Low-level network-related code.
+
+This module includes address manipulation, compatibility wrappers,
+convenience functions, and so on.
+
diff --git a/src/lib/net/nettypes.h b/src/lib/net/nettypes.h
index 60039bac09..953673d4c3 100644
--- a/src/lib/net/nettypes.h
+++ b/src/lib/net/nettypes.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/network_sys.c b/src/lib/net/network_sys.c
index e0a2625d73..012fc56bba 100644
--- a/src/lib/net/network_sys.c
+++ b/src/lib/net/network_sys.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/network_sys.h b/src/lib/net/network_sys.h
index 43e62592ca..734533c7e8 100644
--- a/src/lib/net/network_sys.h
+++ b/src/lib/net/network_sys.h
@@ -1,8 +1,8 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file log_network.h
+ * \file network_sys.h
* \brief Declare subsystem object for the network module.
**/
diff --git a/src/lib/net/resolve.c b/src/lib/net/resolve.c
index 442bc4a6b3..df079d5db3 100644
--- a/src/lib/net/resolve.c
+++ b/src/lib/net/resolve.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/resolve.h b/src/lib/net/resolve.h
index b979b2fb41..ef3d9fa176 100644
--- a/src/lib/net/resolve.h
+++ b/src/lib/net/resolve.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/socket.c b/src/lib/net/socket.c
index e1b82251ed..adc060a735 100644
--- a/src/lib/net/socket.c
+++ b/src/lib/net/socket.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,7 +9,6 @@
* sockets.
**/
-#define SOCKET_PRIVATE
#include "lib/net/socket.h"
#include "lib/net/socketpair.h"
#include "lib/net/address.h"
diff --git a/src/lib/net/socket.h b/src/lib/net/socket.h
index 53a9f1bb92..46735fdef0 100644
--- a/src/lib/net/socket.h
+++ b/src/lib/net/socket.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/socketpair.c b/src/lib/net/socketpair.c
index f3a0c3770a..d4310020cb 100644
--- a/src/lib/net/socketpair.c
+++ b/src/lib/net/socketpair.c
@@ -1,6 +1,11 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+
+/**
+ * @file socketpair.c
+ * @brief Replacement socketpair() for systems that lack it
+ **/
#include "lib/cc/torint.h"
#include "lib/net/socketpair.h"
diff --git a/src/lib/net/socketpair.h b/src/lib/net/socketpair.h
index 5820606973..b07016ab94 100644
--- a/src/lib/net/socketpair.h
+++ b/src/lib/net/socketpair.h
@@ -1,11 +1,16 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_SOCKETPAIR_H
#define TOR_SOCKETPAIR_H
+/**
+ * @file socketpair.h
+ * @brief Header for socketpair.c
+ **/
+
#include "orconfig.h"
#include "lib/testsupport/testsupport.h"
#include "lib/net/nettypes.h"
diff --git a/src/lib/net/socks5_status.h b/src/lib/net/socks5_status.h
index e55119e0b0..2b663e00c4 100644
--- a/src/lib/net/socks5_status.h
+++ b/src/lib/net/socks5_status.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -27,6 +27,16 @@ typedef enum {
SOCKS5_TTL_EXPIRED = 0x06,
SOCKS5_COMMAND_NOT_SUPPORTED = 0x07,
SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED = 0x08,
+
+ /* Extended error code (see prop304). Only used if the SocksPort flag
+ * "ExtendedErrors" is set. */
+ SOCKS5_HS_NOT_FOUND = 0xF0,
+ SOCKS5_HS_IS_INVALID = 0xF1,
+ SOCKS5_HS_INTRO_FAILED = 0xF2,
+ SOCKS5_HS_REND_FAILED = 0xF3,
+ SOCKS5_HS_MISSING_CLIENT_AUTH = 0xF4,
+ SOCKS5_HS_BAD_CLIENT_AUTH = 0xF5,
+ SOCKS5_HS_BAD_ADDRESS = 0xF6,
} socks5_reply_status_t;
#endif /* !defined(TOR_SOCKS5_STATUS_H) */
diff --git a/src/lib/osinfo/lib_osinfo.md b/src/lib/osinfo/lib_osinfo.md
new file mode 100644
index 0000000000..0678ecc21e
--- /dev/null
+++ b/src/lib/osinfo/lib_osinfo.md
@@ -0,0 +1,8 @@
+@dir /lib/osinfo
+@brief lib/osinfo: For inspecting the OS version and capabilities.
+
+In general, we use this module when we're telling the user what operating
+system they are running. We shouldn't make decisions based on the output of
+these checks: instead, we should have more specific checks, either at compile
+time or run time, based on the observed system behavior.
+
diff --git a/src/lib/osinfo/uname.c b/src/lib/osinfo/uname.c
index 34860c407a..ac99726f51 100644
--- a/src/lib/osinfo/uname.c
+++ b/src/lib/osinfo/uname.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/osinfo/uname.h b/src/lib/osinfo/uname.h
index 443a30d358..c6b1f43235 100644
--- a/src/lib/osinfo/uname.h
+++ b/src/lib/osinfo/uname.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/daemon.c b/src/lib/process/daemon.c
index ae34b5bcb8..b3b98a297e 100644
--- a/src/lib/process/daemon.c
+++ b/src/lib/process/daemon.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/daemon.h b/src/lib/process/daemon.h
index 423c498837..23f3117898 100644
--- a/src/lib/process/daemon.h
+++ b/src/lib/process/daemon.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/env.c b/src/lib/process/env.c
index 3912ade197..517b655a5e 100644
--- a/src/lib/process/env.c
+++ b/src/lib/process/env.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -16,7 +16,6 @@
#include "lib/container/smartlist.h"
#include "lib/log/util_bug.h"
#include "lib/log/log.h"
-#include "lib/malloc/malloc.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
diff --git a/src/lib/process/env.h b/src/lib/process/env.h
index 19c2235970..7838dcaa90 100644
--- a/src/lib/process/env.h
+++ b/src/lib/process/env.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/lib_process.md b/src/lib/process/lib_process.md
new file mode 100644
index 0000000000..354129e70e
--- /dev/null
+++ b/src/lib/process/lib_process.md
@@ -0,0 +1,2 @@
+@dir /lib/process
+@brief lib/process: Launch and manage subprocesses.
diff --git a/src/lib/process/pidfile.c b/src/lib/process/pidfile.c
index 1b9d1c6d25..e7d9d2c47a 100644
--- a/src/lib/process/pidfile.c
+++ b/src/lib/process/pidfile.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/pidfile.h b/src/lib/process/pidfile.h
index af59041f80..d04302df3a 100644
--- a/src/lib/process/pidfile.h
+++ b/src/lib/process/pidfile.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/process.c b/src/lib/process/process.c
index 2194a603ff..12c1f9a772 100644
--- a/src/lib/process/process.c
+++ b/src/lib/process/process.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -550,6 +550,7 @@ process_vprintf(process_t *process,
char *data;
size = tor_vasprintf(&data, format, args);
+ tor_assert(data != NULL);
process_write(process, (uint8_t *)data, size);
tor_free(data);
}
diff --git a/src/lib/process/process.h b/src/lib/process/process.h
index 05c091a5bf..8879ec4f21 100644
--- a/src/lib/process/process.h
+++ b/src/lib/process/process.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,6 +15,8 @@
#include "lib/malloc/malloc.h"
#include "lib/string/printf.h"
+#include <stdbool.h>
+
/** Maximum number of bytes to write to a process' stdin. */
#define PROCESS_MAX_WRITE (1024)
@@ -35,8 +37,8 @@ typedef enum {
const char *process_status_to_string(process_status_t status);
typedef enum {
- /** Pass complete \n-terminated lines to the
- * callback (with the \n or \r\n removed). */
+ /** Pass complete newline-terminated lines to the
+ * callback (with the LF or CRLF removed). */
PROCESS_PROTOCOL_LINE,
/** Pass the raw response from read() to the callback. */
@@ -127,18 +129,19 @@ void process_notify_event_exit(process_t *process,
process_exit_code_t);
#ifdef PROCESS_PRIVATE
-MOCK_DECL(STATIC int, process_read_stdout, (process_t *, buf_t *));
-MOCK_DECL(STATIC int, process_read_stderr, (process_t *, buf_t *));
-MOCK_DECL(STATIC void, process_write_stdin, (process_t *, buf_t *));
+struct buf_t;
+MOCK_DECL(STATIC int, process_read_stdout, (process_t *, struct buf_t *));
+MOCK_DECL(STATIC int, process_read_stderr, (process_t *, struct buf_t *));
+MOCK_DECL(STATIC void, process_write_stdin, (process_t *, struct buf_t *));
STATIC void process_read_data(process_t *process,
- buf_t *buffer,
+ struct buf_t *buffer,
process_read_callback_t callback);
STATIC void process_read_buffer(process_t *process,
- buf_t *buffer,
+ struct buf_t *buffer,
process_read_callback_t callback);
STATIC void process_read_lines(process_t *process,
- buf_t *buffer,
+ struct buf_t *buffer,
process_read_callback_t callback);
#endif /* defined(PROCESS_PRIVATE) */
diff --git a/src/lib/process/process_sys.c b/src/lib/process/process_sys.c
index 3c809a00e8..283064cbfe 100644
--- a/src/lib/process/process_sys.c
+++ b/src/lib/process/process_sys.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/process_sys.h b/src/lib/process/process_sys.h
index b7a116d838..97b3aaebd0 100644
--- a/src/lib/process/process_sys.h
+++ b/src/lib/process/process_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/process_unix.c b/src/lib/process/process_unix.c
index 8191bdc1f0..2b47e1874d 100644
--- a/src/lib/process/process_unix.c
+++ b/src/lib/process/process_unix.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/process_unix.h b/src/lib/process/process_unix.h
index da40b3e567..a6b8304d48 100644
--- a/src/lib/process/process_unix.h
+++ b/src/lib/process/process_unix.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/process_win32.c b/src/lib/process/process_win32.c
index 7e4082ad13..8683e17fc2 100644
--- a/src/lib/process/process_win32.c
+++ b/src/lib/process/process_win32.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/process_win32.h b/src/lib/process/process_win32.h
index a50d86df5b..0f264c8710 100644
--- a/src/lib/process/process_win32.h
+++ b/src/lib/process/process_win32.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/restrict.c b/src/lib/process/restrict.c
index fda284f3d9..a3ce52deaa 100644
--- a/src/lib/process/restrict.c
+++ b/src/lib/process/restrict.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/restrict.h b/src/lib/process/restrict.h
index 8491c99044..6173d5a438 100644
--- a/src/lib/process/restrict.h
+++ b/src/lib/process/restrict.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/setuid.c b/src/lib/process/setuid.c
index 3c94ce4bac..3cfd520a4f 100644
--- a/src/lib/process/setuid.c
+++ b/src/lib/process/setuid.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -64,7 +64,7 @@ log_credential_status(void)
/* log UIDs */
#ifdef HAVE_GETRESUID
- if (getresuid(&ruid, &euid, &suid) != 0 ) {
+ if (getresuid(&ruid, &euid, &suid) != 0) {
log_warn(LD_GENERAL, "Error getting changed UIDs: %s", strerror(errno));
return -1;
} else {
@@ -85,7 +85,7 @@ log_credential_status(void)
/* log GIDs */
#ifdef HAVE_GETRESGID
- if (getresgid(&rgid, &egid, &sgid) != 0 ) {
+ if (getresgid(&rgid, &egid, &sgid) != 0) {
log_warn(LD_GENERAL, "Error getting changed GIDs: %s", strerror(errno));
return -1;
} else {
diff --git a/src/lib/process/setuid.h b/src/lib/process/setuid.h
index a2125d2d06..fec35a1216 100644
--- a/src/lib/process/setuid.h
+++ b/src/lib/process/setuid.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/waitpid.c b/src/lib/process/waitpid.c
index 2b38481aeb..89ffe9fcfe 100644
--- a/src/lib/process/waitpid.c
+++ b/src/lib/process/waitpid.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/waitpid.h b/src/lib/process/waitpid.h
index 5faef468c1..171cf206fb 100644
--- a/src/lib/process/waitpid.h
+++ b/src/lib/process/waitpid.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2019, The Tor Project, Inc. */
+/* Copyright (c) 2011-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/winprocess_sys.c b/src/lib/process/winprocess_sys.c
index ad65886422..e43a77e467 100644
--- a/src/lib/process/winprocess_sys.c
+++ b/src/lib/process/winprocess_sys.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/winprocess_sys.h b/src/lib/process/winprocess_sys.h
index 7ab2aa04a6..bece1b3da9 100644
--- a/src/lib/process/winprocess_sys.h
+++ b/src/lib/process/winprocess_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/pubsub/lib_pubsub.md b/src/lib/pubsub/lib_pubsub.md
new file mode 100644
index 0000000000..3f4c473436
--- /dev/null
+++ b/src/lib/pubsub/lib_pubsub.md
@@ -0,0 +1,14 @@
+@dir /lib/pubsub
+@brief lib/pubsub: Publish-subscribe message passing.
+
+This module wraps the \refdir{lib/dispatch} module, to provide a more
+ergonomic and type-safe approach to message passing.
+
+In general, we favor this mechanism for cases where higher-level modules
+need to be notified when something happens in lower-level modules. (The
+alternative would be calling up from the lower-level modules, which
+would be error-prone; or maintaining lists of function-pointers, which
+would be clumsy and tend to complicate the call graph.)
+
+See pubsub.c for more information.
+
diff --git a/src/lib/pubsub/pub_binding_st.h b/src/lib/pubsub/pub_binding_st.h
index d841bf3f54..d7c562fc35 100644
--- a/src/lib/pubsub/pub_binding_st.h
+++ b/src/lib/pubsub/pub_binding_st.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/pubsub/publish_subscribe.md b/src/lib/pubsub/publish_subscribe.md
new file mode 100644
index 0000000000..bb05b100b1
--- /dev/null
+++ b/src/lib/pubsub/publish_subscribe.md
@@ -0,0 +1,144 @@
+
+@page publish_subscribe Publish-subscribe message passing in Tor
+
+@tableofcontents
+
+## Introduction
+
+Tor has introduced a generic publish-subscribe mechanism for delivering
+messages internally. It is meant to help us improve the modularity of
+our code, by avoiding direct coupling between modules that don't
+actually need to invoke one another.
+
+This publish-subscribe mechanism is *not* meant for handing
+multithreading or multiprocess issues, thought we hope that eventually
+it might be extended and adapted for that purpose. Instead, we use
+publish-subscribe today to decouple modules that shouldn't be calling
+each other directly.
+
+For example, there are numerous parts of our code that might need to
+take action when a circuit is completed: a controller might need to be
+informed, an onion service negotiation might need to be attached, a
+guard might need to be marked as working, or a client connection might
+need to be attached. But many of those actions occur at a higher layer
+than circuit completion: calling them directly is a layering violation,
+and makes our code harder to understand and analyze.
+
+But with message-passing, we can invert this layering violation: circuit
+completion can become a "message" that the circuit code publishes, and
+to which higher-level layers subscribe. This means that circuit
+handling can be decoupled from higher-level modules, and stay nice and
+simple. (@ref pubsub_notyet "1")
+
+> @anchor pubsub_notyet 1. Unfortunately, like most of our code, circuit
+> handling is _not_ yet refactored to use publish-subscribe throughout.
+> Instead, layer violations of the type described here are pretty common
+> in Tor today. To see a small part of what happens when a circuit is
+> completed today, have a look at circuit_build_no_more_hops() and its
+> associated code.
+
+## Channels and delivery policies
+
+To work with messages, especially when refactoring existing code, you'll
+need to understand "channels" and "delivery policies".
+
+Every message is delivered on a "message channel". Each channel
+(conceptually) a queue-like structure that can support an arbitrarily
+number of message types. Where channels vary is their delivery
+mechanisms, and their guarantees about when messages are processed.
+
+Currently, three delivery policies are possible:
+
+ - `DELIV_PROMPT` -- causes messages to be processed via a callback in
+ Tor's event loop. This is generally the best choice, since it
+ avoids unexpected growth of the stack.
+
+ - `DELIV_IMMEDIATE` -- causes messages to be processed immediately
+ on the call stack when they are published. This choice grows the
+ stack, and can lead to unexpected complexity in the call graph.
+ We should only use it when necessary.
+
+ - `DELIV_NEVER` -- causes messages not to be delivered by the message
+ dispatch system at all. Instead, some other part of the code must
+ call dispatch_flush() to get the messages delivered.
+
+See mainloop_pubsub.c and mainloop_pubsub.h for more information and
+implementation details.
+
+## Layers: Dispatch vs publish-subsubscribe vs mainloop.
+
+At the lowest level, messages are sent via the "dispatcher" module in
+@refdir{lib/dispatch}. For performance, this dispatcher works with a
+untyped messages. Publishers, subscribers, channels, and messages are
+distinguished by short integers. Associated data is handled as
+dynamically-typed data pointers, and its types are also stored as short
+integers.
+
+Naturally, this results in a type-unsafe C API, so most other modules
+shouldn't invoke @refdir{lib/dispatch} directly. At a higher level,
+@refdir{lib/pubsub} defines a set of functions and macros that make
+messages named and type-safe. This is the one that other modules should
+use when they want to send or receive a message.
+
+The two modules above do not handle message delivery. Instead, the
+dispatch module takes a callback that it can invoke when a channel
+becomes nonempty, and defines a dispatch_flush() function to deliver all
+the messages queued in a channel. The work of actually making sure that
+dispatch_flush() is called when appropriate falls to the main loop,
+which needs to integrate the message dispatcher with the rest of our
+events and callbacks. This work happens in mainloop_pubsub.c.
+
+
+## How to publish and subscribe
+
+This section gives an overview of how to make new messages and how to
+use them. For full details, see pubsub_macros.h.
+
+Before anybody can publish or subscribe to a message, the message must
+be declared, typically in a header. This uses DECLARE_MESSAGE() or
+DECLARE_MESSAGE_INT().
+
+Only subsystems can publish or subscribe messages. For more information
+about the subsystems architecture, see @ref initialization.
+
+To publish a message, you must:
+ - Include the header that declares the message.
+ - Declare a set of helper functions via DECLARE_PUBLISH(). These
+ must be visible wherever you call PUBLISH().
+ - Call PUBLISH() to actually send a message.
+ - Connect your subsystem to the dispatcher by calling
+ DISPATCH_ADD_PUB() from your subsystem's subsys_fns_t.add_pubsub
+ callback.
+
+To subscribe to a message, you must:
+ - Include the header that declares the message.
+ - Declare a callback function to be invoked when the message is delivered.
+ - Use DISPATCH_SUBSCRIBE at file scope to define a set of wrapper
+ functions to call your callback function with the appropriate type.
+ - Connect your subsystem to the dispatcher by calling
+ DISPATCH_ADD_SUB() from your subsystem's subsys_fns_t.add_pubsub
+ callback.
+
+Again, the file-level documentation for pubsub_macros.h describes how to
+declare a message, how to publish it, and how to subscribe to it.
+
+## Designing good messages
+
+**Frequency**:
+The publish-subscribe system uses a few function calls
+and allocations for each message sent. This makes it unsuitable for
+very-high-bandwidth events, like "receiving a single data cell" or "a
+socket has become writable." It's fine, however, for events that
+ordinarily happen a bit less frequently than that, like a circuit
+getting finished, a new connection getting opened, or so on.
+
+**Semantics**:
+A message should declare that something has happened or is happening,
+not that something in particular should be done.
+
+For example, suppose you want to set up a message so that onion services
+clean up their replay caches whenever we're low on memory. The event
+should be something like `memory_low`, not `clean_up_replay_caches`.
+The latter name would imply that the publisher knew who was subscribing
+to the message and what they intended to do about it, which would be a
+layering violation.
diff --git a/src/lib/pubsub/pubsub.h b/src/lib/pubsub/pubsub.h
index 5346b07517..d0a4d317f3 100644
--- a/src/lib/pubsub/pubsub.h
+++ b/src/lib/pubsub/pubsub.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/pubsub/pubsub_build.c b/src/lib/pubsub/pubsub_build.c
index e44b7d76ec..3c134f015c 100644
--- a/src/lib/pubsub/pubsub_build.c
+++ b/src/lib/pubsub/pubsub_build.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/pubsub/pubsub_build.h b/src/lib/pubsub/pubsub_build.h
index 5a0c5f5bd3..2781b8251a 100644
--- a/src/lib/pubsub/pubsub_build.h
+++ b/src/lib/pubsub/pubsub_build.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -85,6 +85,11 @@ struct dispatch_t *pubsub_builder_finalize(pubsub_builder_t *,
**/
void pubsub_items_clear_bindings(pubsub_items_t *items);
+/**
+ * @copydoc pubsub_items_free_
+ *
+ * Additionally, set the pointer <b>cfg</b> to NULL.
+ **/
#define pubsub_items_free(cfg) \
FREE_AND_NULL(pubsub_items_t, pubsub_items_free_, (cfg))
void pubsub_items_free_(pubsub_items_t *cfg);
diff --git a/src/lib/pubsub/pubsub_builder_st.h b/src/lib/pubsub/pubsub_builder_st.h
index 545aa3f3ef..57de1240ee 100644
--- a/src/lib/pubsub/pubsub_builder_st.h
+++ b/src/lib/pubsub/pubsub_builder_st.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/pubsub/pubsub_check.c b/src/lib/pubsub/pubsub_check.c
index bf1196df2c..dbcbb14746 100644
--- a/src/lib/pubsub/pubsub_check.c
+++ b/src/lib/pubsub/pubsub_check.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,7 +9,9 @@
* @brief Enforce various requirements on a pubsub_builder.
**/
+/** @{ */
#define PUBSUB_PRIVATE
+/** @} */
#include "lib/dispatch/dispatch_naming.h"
#include "lib/dispatch/msgtypes.h"
diff --git a/src/lib/pubsub/pubsub_connect.h b/src/lib/pubsub/pubsub_connect.h
index 0ad106044e..b0d6ae7e92 100644
--- a/src/lib/pubsub/pubsub_connect.h
+++ b/src/lib/pubsub/pubsub_connect.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/pubsub/pubsub_flags.h b/src/lib/pubsub/pubsub_flags.h
index 53c6e49565..9912c1ae89 100644
--- a/src/lib/pubsub/pubsub_flags.h
+++ b/src/lib/pubsub/pubsub_flags.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/pubsub/pubsub_macros.h b/src/lib/pubsub/pubsub_macros.h
index 357e59fd54..e5ffbe501a 100644
--- a/src/lib/pubsub/pubsub_macros.h
+++ b/src/lib/pubsub/pubsub_macros.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -163,7 +163,7 @@
* hookfn with the appropriate arguments.
*/
-/* Macro to declare common elements shared by DECLARE_MESSAGE and
+/** Macro to declare common elements shared by DECLARE_MESSAGE and
* DECLARE_MESSAGE_INT. Don't call this directly.
*
* Note that the "msg_arg_name" string constant is defined in each
@@ -288,7 +288,7 @@
( 0 ? (publish_fn__ ##messagename((msg_arg_type__##messagename)0), 1) \
: 1)
-/*
+/**
* This macro is for internal use. It backs DISPATCH_ADD_PUB*()
*/
#define DISPATCH_ADD_PUB_(connector, channel, messagename, flags) \
@@ -322,7 +322,7 @@
#define DISPATCH_ADD_PUB_EXCL(connector, channel, messagename) \
DISPATCH_ADD_PUB_(connector, channel, messagename, DISP_FLAG_EXCL)
-/*
+/**
* This macro is for internal use. It backs DISPATCH_ADD_SUB*()
*/
#define DISPATCH_ADD_SUB_(connector, channel, messagename, flags) \
@@ -334,7 +334,7 @@
(flags), \
__FILE__, \
__LINE__)
-/*
+/**
* Use a given connector and channel name to declare that this subsystem will
* receive a given message type.
*
diff --git a/src/lib/pubsub/pubsub_publish.c b/src/lib/pubsub/pubsub_publish.c
index 454a335a78..84c7dae02c 100644
--- a/src/lib/pubsub/pubsub_publish.c
+++ b/src/lib/pubsub/pubsub_publish.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/pubsub/pubsub_publish.h b/src/lib/pubsub/pubsub_publish.h
index 0686a465de..d9d6fa9ba5 100644
--- a/src/lib/pubsub/pubsub_publish.h
+++ b/src/lib/pubsub/pubsub_publish.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file pubsub_publish.h
+ * @brief Header for pubsub_publish.c
+ **/
+
#ifndef TOR_PUBSUB_PUBLISH_H
#define TOR_PUBSUB_PUBLISH_H
diff --git a/src/lib/sandbox/lib_sandbox.md b/src/lib/sandbox/lib_sandbox.md
new file mode 100644
index 0000000000..dd168c9b13
--- /dev/null
+++ b/src/lib/sandbox/lib_sandbox.md
@@ -0,0 +1,15 @@
+@dir /lib/sandbox
+@brief lib/sandbox: Linux seccomp2-based sandbox.
+
+This module uses Linux's seccomp2 facility via the
+[`libseccomp` library](https://github.com/seccomp/libseccomp), to restrict
+the set of system calls that Tor is allowed to invoke while it is running.
+
+Because there are many libc versions that invoke different system calls, and
+because handling strings is quite complex, this module is more complex and
+less portable than it needs to be.
+
+A better architecture would put the responsibility for invoking tricky system
+calls (like open()) in another, less restricted process, and give that
+process responsibility for enforcing our sandbox rules.
+
diff --git a/src/lib/sandbox/sandbox.c b/src/lib/sandbox/sandbox.c
index 3515e8854e..b917912f4d 100644
--- a/src/lib/sandbox/sandbox.c
+++ b/src/lib/sandbox/sandbox.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -82,7 +82,7 @@
#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
#define USE_BACKTRACE
-#define EXPOSE_CLEAN_BACKTRACE
+#define BACKTRACE_PRIVATE
#include "lib/err/backtrace.h"
#endif /* defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && ... */
@@ -166,6 +166,7 @@ static int filter_nopar_gen[] = {
#ifdef __NR_fstat64
SCMP_SYS(fstat64),
#endif
+ SCMP_SYS(fsync),
SCMP_SYS(futex),
SCMP_SYS(getdents),
SCMP_SYS(getdents64),
@@ -265,6 +266,11 @@ static int filter_nopar_gen[] = {
SCMP_SYS(listen),
SCMP_SYS(connect),
SCMP_SYS(getsockname),
+#ifdef ENABLE_NSS
+#ifdef __NR_getpeername
+ SCMP_SYS(getpeername),
+#endif
+#endif
SCMP_SYS(recvmsg),
SCMP_SYS(recvfrom),
SCMP_SYS(sendto),
@@ -648,6 +654,15 @@ sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
}
}
+#ifdef ENABLE_NSS
+ rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
+ SCMP_CMP(0, SCMP_CMP_EQ, PF_INET),
+ SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM),
+ SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_IP));
+ if (rc)
+ return rc;
+#endif
+
rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
SCMP_CMP(0, SCMP_CMP_EQ, PF_UNIX),
SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM),
diff --git a/src/lib/sandbox/sandbox.h b/src/lib/sandbox/sandbox.h
index b4ae6e5c07..b50df48255 100644
--- a/src/lib/sandbox/sandbox.h
+++ b/src/lib/sandbox/sandbox.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -29,10 +29,10 @@
#define USE_LIBSECCOMP
#endif
-struct sandbox_cfg_elem;
+struct sandbox_cfg_elem_t;
/** Typedef to structure used to manage a sandbox configuration. */
-typedef struct sandbox_cfg_elem sandbox_cfg_t;
+typedef struct sandbox_cfg_elem_t sandbox_cfg_t;
/**
* Linux definitions
@@ -58,7 +58,7 @@ typedef enum {
* Configuration parameter structure associated with the LIBSECCOMP2
* implementation.
*/
-typedef struct smp_param {
+typedef struct smp_param_t {
/** syscall associated with parameter. */
int syscall;
@@ -77,7 +77,7 @@ typedef struct smp_param {
* It is implemented as a linked list of parameters. Currently only controls
* parameters for open, openat, execve, stat64.
*/
-struct sandbox_cfg_elem {
+struct sandbox_cfg_elem_t {
/** Sandbox implementation which dictates the parameter type. */
SB_IMPL implem;
@@ -85,7 +85,7 @@ struct sandbox_cfg_elem {
smp_param_t *param;
/** Next element of the configuration*/
- struct sandbox_cfg_elem *next;
+ struct sandbox_cfg_elem_t *next;
};
/** Function pointer defining the prototype of a filter function.*/
diff --git a/src/lib/smartlist_core/lib_smartlist_core.md b/src/lib/smartlist_core/lib_smartlist_core.md
new file mode 100644
index 0000000000..c031dd6f24
--- /dev/null
+++ b/src/lib/smartlist_core/lib_smartlist_core.md
@@ -0,0 +1,10 @@
+@dir /lib/smartlist_core
+@brief lib/smartlist_core: Minimal dynamic array implementation
+
+A `smartlist_t` is a dynamic array type for holding `void *`. We use it
+throughout the rest of the codebase.
+
+There are higher-level pieces in \refdir{lib/container} but
+the ones in lib/smartlist_core are used by the logging code, and therefore
+cannot use the logging code.
+
diff --git a/src/lib/smartlist_core/smartlist_core.c b/src/lib/smartlist_core/smartlist_core.c
index 6b0a305a93..571d17aa5d 100644
--- a/src/lib/smartlist_core/smartlist_core.c
+++ b/src/lib/smartlist_core/smartlist_core.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/smartlist_core/smartlist_core.h b/src/lib/smartlist_core/smartlist_core.h
index 36f23e2009..de6fe69d3a 100644
--- a/src/lib/smartlist_core/smartlist_core.h
+++ b/src/lib/smartlist_core/smartlist_core.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/smartlist_core/smartlist_foreach.h b/src/lib/smartlist_core/smartlist_foreach.h
index a1fbcd444c..03edb80f05 100644
--- a/src/lib/smartlist_core/smartlist_foreach.h
+++ b/src/lib/smartlist_core/smartlist_foreach.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/smartlist_core/smartlist_split.c b/src/lib/smartlist_core/smartlist_split.c
index c9cf59851f..b76b87406d 100644
--- a/src/lib/smartlist_core/smartlist_split.c
+++ b/src/lib/smartlist_core/smartlist_split.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/smartlist_core/smartlist_split.h b/src/lib/smartlist_core/smartlist_split.h
index e2cc7245b7..fc964201e9 100644
--- a/src/lib/smartlist_core/smartlist_split.h
+++ b/src/lib/smartlist_core/smartlist_split.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/string/compat_ctype.c b/src/lib/string/compat_ctype.c
index f5d82be3ae..a7668bfbfb 100644
--- a/src/lib/string/compat_ctype.c
+++ b/src/lib/string/compat_ctype.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -29,6 +29,7 @@ const uint32_t TOR_ISPRINT_TABLE[8] =
{ 0, 0xffffffff, 0xffffffff, 0x7fffffff, 0, 0, 0, 0x0 };
const uint32_t TOR_ISUPPER_TABLE[8] = { 0, 0, 0x7fffffe, 0, 0, 0, 0, 0 };
const uint32_t TOR_ISLOWER_TABLE[8] = { 0, 0, 0, 0x7fffffe, 0, 0, 0, 0 };
+/**@}*/
/** Upper-casing and lowercasing tables to map characters to upper/lowercase
* equivalents. Used by tor_toupper() and tor_tolower(). */
diff --git a/src/lib/string/compat_ctype.h b/src/lib/string/compat_ctype.h
index dbddd356c1..53ee6066f8 100644
--- a/src/lib/string/compat_ctype.h
+++ b/src/lib/string/compat_ctype.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/string/compat_string.c b/src/lib/string/compat_string.c
index 187f784be5..2bd3c2f2b4 100644
--- a/src/lib/string/compat_string.c
+++ b/src/lib/string/compat_string.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/string/compat_string.h b/src/lib/string/compat_string.h
index ffc892c3e5..f05265bdcc 100644
--- a/src/lib/string/compat_string.h
+++ b/src/lib/string/compat_string.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/string/lib_string.md b/src/lib/string/lib_string.md
new file mode 100644
index 0000000000..98e3e652ed
--- /dev/null
+++ b/src/lib/string/lib_string.md
@@ -0,0 +1,13 @@
+@dir /lib/string
+@brief lib/string: Low-level string manipulation.
+
+We have a number of compatibility functions here: some are for handling
+functionality that is not implemented (or not implemented the same) on every
+platform; some are for providing locale-independent versions of libc
+functions that would otherwise be defined differently for different users.
+
+Other functions here are for common string-manipulation operations that we do
+in the rest of the codebase.
+
+Any string function high-level enough to need logging belongs in a
+higher-level module.
diff --git a/src/lib/string/parse_int.c b/src/lib/string/parse_int.c
index fbdd554a47..11ce0fa415 100644
--- a/src/lib/string/parse_int.c
+++ b/src/lib/string/parse_int.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,6 +9,7 @@
**/
#include "lib/string/parse_int.h"
+#include "lib/cc/compat_compiler.h"
#include <errno.h>
#include <stdlib.h>
@@ -17,6 +18,7 @@
/* Helper: common code to check whether the result of a strtol or strtoul or
* strtoll is correct. */
#define CHECK_STRTOX_RESULT() \
+ STMT_BEGIN \
/* Did an overflow occur? */ \
if (errno == ERANGE) \
goto err; \
@@ -38,7 +40,8 @@
err: \
if (ok) *ok = 0; \
if (next) *next = endptr; \
- return 0
+ return 0; \
+ STMT_END
/** Extract a long from the start of <b>s</b>, in the given numeric
* <b>base</b>. If <b>base</b> is 0, <b>s</b> is parsed as a decimal,
diff --git a/src/lib/string/parse_int.h b/src/lib/string/parse_int.h
index 50d48b44c5..27939ade61 100644
--- a/src/lib/string/parse_int.h
+++ b/src/lib/string/parse_int.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/string/printf.c b/src/lib/string/printf.c
index 26203932e4..86d860935e 100644
--- a/src/lib/string/printf.c
+++ b/src/lib/string/printf.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/string/printf.h b/src/lib/string/printf.h
index 6e90770f81..5ab751b338 100644
--- a/src/lib/string/printf.h
+++ b/src/lib/string/printf.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/string/scanf.c b/src/lib/string/scanf.c
index 1bc39b5182..89d1683204 100644
--- a/src/lib/string/scanf.c
+++ b/src/lib/string/scanf.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/string/scanf.h b/src/lib/string/scanf.h
index b642e242db..67e9c5eb78 100644
--- a/src/lib/string/scanf.h
+++ b/src/lib/string/scanf.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/doc/HACKING/design/01g-strings.md b/src/lib/string/strings.md
index 145a35cd6f..b22574a05a 100644
--- a/doc/HACKING/design/01g-strings.md
+++ b/src/lib/string/strings.md
@@ -1,5 +1,5 @@
-## String processing in Tor ##
+@page strings String processing in Tor
Since you're reading about a C program, you probably expected this
section: it's full of functions for manipulating the (notoriously
@@ -77,6 +77,11 @@ full of substrings in order. Then you can concatenate them into a
single string with smartlist_join_strings(), which also takes optional
separator and terminator arguments.
+Alternatively, you might find it more convenient (and more
+allocation-efficient) to use the buffer API in buffers.c: Construct a buf_t
+object, add your data to it with buf_add_string(), buf_add_printf(), and so
+on, then call buf_extract() to get the resulting output.
+
As a convenience, we provide smartlist_add_asprintf(), which combines
the two methods above together. Many of the cryptographic digest
functions also accept a not-yet-concatenated smartlist of strings.
@@ -93,3 +98,5 @@ you can use hex_str(memory, length) for that.
The escaped() and hex_str() functions both provide outputs that are
only valid till they are next invoked; they are not threadsafe.
+
+*/
diff --git a/src/lib/string/util_string.c b/src/lib/string/util_string.c
index f5061a11d2..c8f12d780e 100644
--- a/src/lib/string/util_string.c
+++ b/src/lib/string/util_string.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -506,6 +506,23 @@ validate_char(const uint8_t *c, uint8_t len)
int
string_is_utf8(const char *str, size_t len)
{
+ // If str is NULL, don't try to read it
+ if (!str) {
+ // We could test for this case, but the low-level logs would produce
+ // confusing test output.
+ // LCOV_EXCL_START
+ if (len) {
+ // Use the low-level logging function, so that the log module can
+ // validate UTF-8 (if needed in future code)
+ tor_log_err_sigsafe(
+ "BUG: string_is_utf8() called with NULL str but non-zero len.");
+ // Since it's a bug, we should probably reject this string
+ return false;
+ }
+ // LCOV_EXCL_STOP
+ return true;
+ }
+
for (size_t i = 0; i < len;) {
uint8_t num_bytes = bytes_in_char(str[i]);
if (num_bytes == 0) // Invalid leading byte found.
@@ -530,8 +547,8 @@ string_is_utf8(const char *str, size_t len)
int
string_is_utf8_no_bom(const char *str, size_t len)
{
- if (len >= 3 && (!strcmpstart(str, "\uFEFF") ||
- !strcmpstart(str, "\uFFFE"))) {
+ if (str && len >= 3 && (!strcmpstart(str, "\uFEFF") ||
+ !strcmpstart(str, "\uFFFE"))) {
return false;
}
return string_is_utf8(str, len);
diff --git a/src/lib/string/util_string.h b/src/lib/string/util_string.h
index b3c6841d41..e89233df88 100644
--- a/src/lib/string/util_string.h
+++ b/src/lib/string/util_string.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/subsys/initialization.md b/src/lib/subsys/initialization.md
new file mode 100644
index 0000000000..012ab7000d
--- /dev/null
+++ b/src/lib/subsys/initialization.md
@@ -0,0 +1,75 @@
+
+@page initialization Initialization and shutdown
+
+@tableofcontents
+
+@section overview Overview
+
+Tor has a single entry point: tor_run_main() in main.c. All the ways of
+starting a Tor process (ntmain.c, tor_main.c, and tor_api.c) work by invoking tor_run_main().
+
+The tor_run_main() function normally exits (@ref init_exceptwhen "1") by
+returning: not by calling abort() or exit(). Before it returns, it calls
+tor_cleanup() in shutdown.c.
+
+Conceptually, there are several stages in running Tor.
+
+1. First, we initialize those modules that do not depend on the
+ configuration. This happens in the first half of tor_run_main(), and the
+ first half of tor_init(). (@ref init_pending_refactor "2")
+
+2. Second, we parse the command line and our configuration, and configure
+ systems that depend on our configuration or state. This configuration
+ happens midway through tor_init(), which invokes
+ options_init_from_torrc(). We then initialize more systems from the
+ second half of tor_init().
+
+3. At this point we may exit early if we have been asked to do something
+ requiring no further initialization, like printing our version number or
+ creating a new signing key. Otherwise, we proceed to run_tor_main_loop(),
+ which initializes some network-specific parts of Tor, grabs some
+ daemon-only resources (like the data directory lock) and starts Tor itself
+ running.
+
+
+> @anchor init_exceptwhen 1. tor_run_main() _can_ terminate with a call to
+> abort() or exit(), but only when crashing due to a bug, or when forking to
+> run as a daemon.
+
+> @anchor init_pending_refactor 2. The pieces of code that I'm describing as
+> "the first part of tor_init()" and so on deserve to be functions with their
+> own name. I'd like to refactor them, but before I do so, there is some
+> slight reorganization that needs to happen. Notably, the
+> nt_service_parse_options() call ought logically to be later in our
+> initialization sequence. See @ticket{32447} for our refactoring progress.
+
+
+@section subsys Subsystems and initialization
+
+Our current convention is to use the subsystem mechanism to initialize and
+clean up pieces of Tor. The more recently updated pieces of Tor will use
+this mechanism. For examples, see e.g. time_sys.c or log_sys.c.
+
+In simplest terms, a **subsytem** is a logically separate part of Tor that
+can be initialized, shut down, managed, and configured somewhat independently
+of the rest of the program.
+
+The subsys_fns_t type describes a subsystem and a set of functions that
+initialize it, desconstruct it, and so on. To define a subsystem, we declare
+a `const` instance of subsys_fns_t. See the documentation for subsys_fns_t
+for a full list of these functions.
+
+After defining a subsytem, it must be inserted in subsystem_list.c. At that
+point, table-driven mechanisms in subsysmgr.c will invoke its functions when
+appropriate.
+
+@subsection vsconfig Initialization versus configuration
+
+We note that the initialization phase of Tor occurs before any configuration
+is read from disk -- and therefore before any other files are read from
+disk. Therefore, any behavior that depends on Tor's configuration or state
+must occur _after_ the initialization process, during configuration.
+
+
+
+
diff --git a/src/lib/subsys/lib_subsys.md b/src/lib/subsys/lib_subsys.md
new file mode 100644
index 0000000000..764d25d1b6
--- /dev/null
+++ b/src/lib/subsys/lib_subsys.md
@@ -0,0 +1,32 @@
+@dir /lib/subsys
+@brief lib/subsys: Types for declaring a "subsystem".
+
+## Subsystems in Tor
+
+A subsystem is a module with support for initialization, shutdown,
+configuration, and so on.
+
+Many parts of Tor can be initialized, cleaned up, and configured somewhat
+independently through a table-driven mechanism. Each such part is called a
+"subsystem".
+
+To declare a subsystem, make a global `const` instance of the `subsys_fns_t`
+type, filling in the function pointer fields that you require with ones
+corresponding to your subsystem. Any function pointers left as "NULL" will
+be a no-op. Each system must have a name and a "level", which corresponds to
+the order in which it is initialized. (See `app/main/subsystem_list.c` for a
+list of current subsystems and their levels.)
+
+Then, insert your subsystem in the list in `app/main/subsystem_list.c`. It
+will need to occupy a position corresponding to its level.
+
+At this point, your subsystem will be handled like the others: it will get
+initialized at startup, torn down at exit, and so on.
+
+Historical note: Not all of Tor's code is currently handled as
+subsystems. As you work with older code, you may see some parts of the code
+that are initialized from `tor_init()` or `run_tor_main_loop()` or
+`tor_run_main()`; and torn down from `tor_cleanup()`. We aim to migrate
+these to subsystems over time; please don't add any new code that follows
+this pattern.
+
diff --git a/src/lib/subsys/subsys.h b/src/lib/subsys/subsys.h
index 21f984f32d..c05b69af39 100644
--- a/src/lib/subsys/subsys.h
+++ b/src/lib/subsys/subsys.h
@@ -1,14 +1,20 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file subsys.h
+ * @brief Types used to declare a subsystem.
+ **/
+
#ifndef TOR_SUBSYS_T
#define TOR_SUBSYS_T
#include <stdbool.h>
struct pubsub_connector_t;
+struct config_format_t;
/**
* A subsystem is a part of Tor that is initialized, shut down, configured,
@@ -17,8 +23,16 @@ struct pubsub_connector_t;
* All callbacks are optional -- if a callback is set to NULL, the subsystem
* manager will treat it as a no-op.
*
- * You should use c99 named-field initializers with this structure: we
- * will be adding more fields, often in the middle of the structure.
+ * You should use c99 named-field initializers with this structure, for
+ * readability and safety. (There are a lot of functions here, all of them
+ * optional, and many of them with similar signatures.)
+ *
+ * See @ref initialization for more information about initialization and
+ * shutdown in Tor.
+ *
+ * To make a new subsystem, you declare a const instance of this type, and
+ * include it on the list in subsystem_list.c. The code that manages these
+ * subsystems is in subsysmgr.c.
**/
typedef struct subsys_fns_t {
/**
@@ -49,7 +63,7 @@ typedef struct subsys_fns_t {
* it is only for global state or pre-configuration state.
*
* (If you need to do any setup that depends on configuration, you'll need
- * to declare a configuration callback. (Not yet designed))
+ * to declare a configuration callback instead. (Not yet designed))
*
* This function MUST NOT have any parts that can fail.
**/
@@ -57,22 +71,49 @@ typedef struct subsys_fns_t {
/**
* Connect a subsystem to the message dispatch system.
+ *
+ * This function should use the macros in @refdir{lib/pubsub} to register a
+ * set of messages that this subsystem may publish, and may subscribe to.
+ *
+ * See pubsub_macros.h for more information, and for examples.
**/
int (*add_pubsub)(struct pubsub_connector_t *);
/**
* Perform any necessary pre-fork cleanup. This function may not fail.
+ *
+ * On Windows (and any other platforms without fork()), this function will
+ * never be invoked. Otherwise it is used when we are about to start
+ * running as a background daemon, or when we are about to run a unit test
+ * in a subprocess. Unlike the subsys_fns_t.postfork callback, it is run
+ * from the parent process.
+ *
+ * Note that we do not invoke this function when the child process's only
+ * purpose is to call exec() and run another program.
*/
void (*prefork)(void);
/**
* Perform any necessary post-fork setup. This function may not fail.
+ *
+ * On Windows (and any other platforms without fork()), this function will
+ * never be invoked. Otherwise it is used when we are about to start
+ * running as a background daemon, or when we are about to run a unit test
+ * in a subprocess. Unlike the subsys_fns_t.prefork callback, it is run
+ * from the child process.
+ *
+ * Note that we do not invoke this function when the child process's only
+ * purpose is to call exec() and run another program.
*/
void (*postfork)(void);
/**
* Free any thread-local resources held by this subsystem. Called before
* the thread exits.
+ *
+ * This function is not allowed to fail.
+ *
+ * \bug Note that this callback is currently buggy: See \ticket{32103}.
*/
void (*thread_cleanup)(void);
@@ -80,16 +121,85 @@ typedef struct subsys_fns_t {
* Free all resources held by this subsystem.
*
* This function is not allowed to fail.
+ *
+ * Subsystems are shut down when Tor is about to exit or return control to
+ * an embedding program. This callback must return the process to a state
+ * such that subsys_fns_t.init will succeed if invoked again.
**/
void (*shutdown)(void);
+ /**
+ * A config_format_t describing all of the torrc fields owned by this
+ * subsystem.
+ *
+ * This object, if present, is registered in a confmgr_t for Tor's options,
+ * and used to parse option fields from the command line and torrc file.
+ **/
+ const struct config_format_t *options_format;
+
+ /**
+ * A config_format_t describing all of the DataDir/state fields owned by
+ * this subsystem.
+ *
+ * This object, if present, is registered in a confmgr_t for Tor's state,
+ * and used to parse state fields from the DataDir/state file.
+ **/
+ const struct config_format_t *state_format;
+
+ /**
+ * Receive an options object as defined by options_format. Return 0
+ * on success, -1 on failure.
+ *
+ * It is safe to store the pointer to the object until set_options()
+ * is called again.
+ *
+ * This function is only called after all the validation code defined
+ * by subsys_fns_t.options_format has passed.
+ **/
+ int (*set_options)(void *);
+
+ /* XXXX Add an implementation for options_act_reversible() later in this
+ * branch. */
+
+ /**
+ * Receive a state object as defined by state_format. Return 0 on success,
+ * -1 on failure.
+ *
+ * It is safe to store the pointer to the object; set_state() is only
+ * called on startup.
+ *
+ * This function is only called after all the validation code defined
+ * by subsys_fns_t.state_format has passed.
+ *
+ * This function will only be called once per invocation of Tor, since
+ * Tor does not reload its state while it is running.
+ **/
+ int (*set_state)(void *);
+
+ /**
+ * Update any information that needs to be stored in the provided state
+ * object (as defined by state_format). Return 0 on success, -1 on failure.
+ *
+ * The object provided here will be the same one as provided earlier to
+ * set_state(). This method is called when we are about to save the state
+ * to disk.
+ **/
+ int (*flush_state)(void *);
} subsys_fns_t;
+/**
+ * Lowest allowed subsystem level.
+ **/
#define MIN_SUBSYS_LEVEL -100
+/**
+ * Highest allowed subsystem level.
+ **/
#define MAX_SUBSYS_LEVEL 100
-/* All tor "libraries" (in src/libs) should have a subsystem level equal to or
- * less than this value. */
+/**
+ * All tor "libraries" (in src/libs) should have a subsystem level equal to or
+ * less than this value.
+ */
#define SUBSYS_LEVEL_LIBS -10
#endif /* !defined(TOR_SUBSYS_T) */
diff --git a/src/lib/term/getpass.c b/src/lib/term/getpass.c
index 8741344acf..d2d6cb2b7b 100644
--- a/src/lib/term/getpass.c
+++ b/src/lib/term/getpass.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/term/getpass.h b/src/lib/term/getpass.h
index aa597ec423..b080ad2473 100644
--- a/src/lib/term/getpass.h
+++ b/src/lib/term/getpass.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/term/lib_term.md b/src/lib/term/lib_term.md
new file mode 100644
index 0000000000..f96d25ffe8
--- /dev/null
+++ b/src/lib/term/lib_term.md
@@ -0,0 +1,2 @@
+@dir /lib/term
+@brief lib/term: Terminal operations (password input).
diff --git a/src/lib/testsupport/lib_testsupport.md b/src/lib/testsupport/lib_testsupport.md
new file mode 100644
index 0000000000..7358e6a80f
--- /dev/null
+++ b/src/lib/testsupport/lib_testsupport.md
@@ -0,0 +1,2 @@
+@dir /lib/testsupport
+@brief lib/testsupport: Helpers for test-only code and for function mocking.
diff --git a/src/lib/testsupport/testsupport.h b/src/lib/testsupport/testsupport.h
index 90b7c43b19..165c497f71 100644
--- a/src/lib/testsupport/testsupport.h
+++ b/src/lib/testsupport/testsupport.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,17 +15,42 @@
#ifndef TOR_TESTSUPPORT_H
#define TOR_TESTSUPPORT_H
-#ifdef TOR_UNIT_TESTS
/** The "STATIC" macro marks a function or variable that is static when
* building Tor for production, but non-static when building the unit
- * tests. */
+ * tests.
+ *
+ * For example, a function declared as:
+ *
+ * STATIC int internal_function(void);
+ *
+ * should be only visible for the file on which it is declared, and in the
+ * unit tests.
+ */
+#ifdef TOR_UNIT_TESTS
#define STATIC
-#define EXTERN(type, name) extern type name;
#else /* !defined(TOR_UNIT_TESTS) */
#define STATIC static
-#define EXTERN(type, name)
#endif /* defined(TOR_UNIT_TESTS) */
+/** The "EXTERN" macro is used along with "STATIC" for variables declarations:
+ * it expands to an extern declaration when Tor building unit tests, and to
+ * nothing otherwise.
+ *
+ * For example, to declare a variable as visible only visible in one
+ * file and in the unit tests, you would put this in the header:
+ *
+ * EXTERN(int, local_variable)
+ *
+ * and this in the source:
+ *
+ * STATIC int local_variable;
+ */
+#ifdef TOR_UNIT_TESTS
+#define EXTERN(type, name) extern type name;
+#else
+#define EXTERN(type, name)
+#endif
+
/** Quick and dirty macros to implement test mocking.
*
* To use them, suppose that you have a function you'd like to mock
@@ -70,32 +95,42 @@
*
* @{ */
#ifdef TOR_UNIT_TESTS
+/** Declare a mocked function. For use in headers. */
#define MOCK_DECL(rv, funcname, arglist) \
rv funcname ##__real arglist; \
extern rv(*funcname) arglist
+/** Define the implementation of a mocked function. */
#define MOCK_IMPL(rv, funcname, arglist) \
rv(*funcname) arglist = funcname ##__real; \
rv funcname ##__real arglist
+/** As MOCK_DECL(), but allow attributes. */
#define MOCK_DECL_ATTR(rv, funcname, arglist, attr) \
rv funcname ##__real arglist attr; \
extern rv(*funcname) arglist
-#define MOCK_IMPL(rv, funcname, arglist) \
- rv(*funcname) arglist = funcname ##__real; \
- rv funcname ##__real arglist
+/**
+ * Replace <b>func</b> (a mockable function) with a replacement function.
+ *
+ * Only usable when Tor has been built for unit tests. */
#define MOCK(func, replacement) \
do { \
(func) = (replacement); \
} while (0)
+/** Replace <b>func</b> (a mockable function) with its original value.
+ *
+ * Only usable when Tor has been built for unit tests. */
#define UNMOCK(func) \
do { \
func = func ##__real; \
} while (0)
#else /* !defined(TOR_UNIT_TESTS) */
+/** Declare a mocked function. For use in headers. */
#define MOCK_DECL(rv, funcname, arglist) \
rv funcname arglist
-#define MOCK_DECL_ATTR(rv, funcname, arglist, attr) \
+/** As MOCK_DECL(), but allow */
+#define MOCK_DECL_ATTR(rv, funcname, arglist, attr) \
rv funcname arglist attr
-#define MOCK_IMPL(rv, funcname, arglist) \
+/** Define the implementation of a mocked function. */
+#define MOCK_IMPL(rv, funcname, arglist) \
rv funcname arglist
#endif /* defined(TOR_UNIT_TESTS) */
/** @} */
diff --git a/src/lib/thread/compat_pthreads.c b/src/lib/thread/compat_pthreads.c
index 6f7ecd17da..d143b80252 100644
--- a/src/lib/thread/compat_pthreads.c
+++ b/src/lib/thread/compat_pthreads.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/thread/compat_threads.c b/src/lib/thread/compat_threads.c
index 5c8ffa55c6..d56e8a3f76 100644
--- a/src/lib/thread/compat_threads.c
+++ b/src/lib/thread/compat_threads.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/thread/compat_winthreads.c b/src/lib/thread/compat_winthreads.c
index f0b1430e84..2ca5620d23 100644
--- a/src/lib/thread/compat_winthreads.c
+++ b/src/lib/thread/compat_winthreads.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/thread/lib_thread.md b/src/lib/thread/lib_thread.md
new file mode 100644
index 0000000000..5870ad790f
--- /dev/null
+++ b/src/lib/thread/lib_thread.md
@@ -0,0 +1,7 @@
+@dir /lib/thread
+@brief lib/thread: Mid-level threading.
+
+This module contains compatibility and convenience code for multithreading,
+except for low-level locks (which are in \refdir{lib/lock} and
+workqueue/threadpool code (which belongs in \refdir{lib/evloop}.)
+
diff --git a/src/lib/thread/numcpus.c b/src/lib/thread/numcpus.c
index b293d965d2..18454ce3ad 100644
--- a/src/lib/thread/numcpus.c
+++ b/src/lib/thread/numcpus.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/thread/numcpus.h b/src/lib/thread/numcpus.h
index 2f1ea16eb9..65e6c430cf 100644
--- a/src/lib/thread/numcpus.h
+++ b/src/lib/thread/numcpus.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/thread/thread_sys.h b/src/lib/thread/thread_sys.h
index c0daf2b5e9..6206fac9d6 100644
--- a/src/lib/thread/thread_sys.h
+++ b/src/lib/thread/thread_sys.h
@@ -1,8 +1,8 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file threads_sys.h
+ * \file thread_sys.h
* \brief Declare subsystem object for threads library
**/
diff --git a/doc/HACKING/design/01f-threads.md b/src/lib/thread/threading.md
index a0dfa2d40e..a1058c97de 100644
--- a/doc/HACKING/design/01f-threads.md
+++ b/src/lib/thread/threading.md
@@ -1,24 +1,24 @@
-## Threads in Tor ##
+@page threading Threading in Tor
Tor is based around a single main thread and one or more worker
threads. We aim (with middling success) to use worker threads for
CPU-intensive activities and the main thread for our networking.
-Fortunately (?) we have enough cryptography that moving what we can of the
-cryptographic processes to the workers should achieve good parallelism under most
-loads. Unfortunately, we only have a small fraction of our
-cryptography done in our worker threads right now.
+Fortunately (?) we have enough cryptography that moving what we can
+of the cryptographic processes to the workers should achieve good
+parallelism under most loads. Unfortunately, we only have a small
+fraction of our cryptography done in our worker threads right now.
Our threads-and-workers abstraction is defined in workqueue.c, which
combines a work queue with a thread pool, and integrates the
-signalling with libevent. Tor main instance of a work queue is
+signalling with libevent. Tor's main instance of a work queue is
instantiated in cpuworker.c. It will probably need some refactoring
as more types of work are added.
-On a lower level, we provide locks with tor_mutex_t, conditions with
-tor_cond_t, and thread-local storage with tor_threadlocal_t, all of
-which are specified in compat_threads.h and implemented in an OS-
-specific compat_\*threads.h module.
+On a lower level, we provide locks with tor_mutex_t in \refdir{lib/lock}, and
+higher-level locking/threading tools in \refdir{lib/thread}, including
+conditions (tor_cond_t), thread-local storage (tor_threadlocal_t), and more.
+
Try to minimize sharing between threads: it is usually best to simply
make the worker "own" all the data it needs while the work is in
diff --git a/src/lib/thread/threads.h b/src/lib/thread/threads.h
index 4b42b9abd9..fcc0c23a87 100644
--- a/src/lib/thread/threads.h
+++ b/src/lib/thread/threads.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -63,7 +63,7 @@ int tor_cond_wait(tor_cond_t *cond, tor_mutex_t *mutex,
void tor_cond_signal_one(tor_cond_t *cond);
void tor_cond_signal_all(tor_cond_t *cond);
-typedef struct tor_threadlocal_s {
+typedef struct tor_threadlocal_t {
#ifdef _WIN32
DWORD index;
#else
@@ -106,7 +106,9 @@ void tor_threadlocal_set(tor_threadlocal_t *threadlocal, void *value);
typedef struct atomic_counter_t {
atomic_size_t val;
} atomic_counter_t;
+#ifndef COCCI
#define ATOMIC_LINKAGE static
+#endif
#else /* !defined(HAVE_WORKING_STDATOMIC) */
typedef struct atomic_counter_t {
tor_mutex_t mutex;
diff --git a/src/lib/time/compat_time.c b/src/lib/time/compat_time.c
index ab45224a7f..6bbad4f98a 100644
--- a/src/lib/time/compat_time.c
+++ b/src/lib/time/compat_time.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/time/compat_time.h b/src/lib/time/compat_time.h
index 4d16effd29..5089e16ca5 100644
--- a/src/lib/time/compat_time.h
+++ b/src/lib/time/compat_time.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/time/lib_time.md b/src/lib/time/lib_time.md
new file mode 100644
index 0000000000..8e58aafcd8
--- /dev/null
+++ b/src/lib/time/lib_time.md
@@ -0,0 +1,9 @@
+@dir /lib/time
+@brief lib/time: Higher-level time functions
+
+This includes both fine-grained timers and monotonic timers, along with
+wrappers for them to try to improve efficiency.
+
+For "what time is it" in UTC, see \refdir{lib/wallclock}. For parsing and
+encoding times and dates, see \refdir{lib/encoding}.
+
diff --git a/src/lib/time/time_sys.c b/src/lib/time/time_sys.c
index 8b9aa2856c..044d328f81 100644
--- a/src/lib/time/time_sys.c
+++ b/src/lib/time/time_sys.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/time/time_sys.h b/src/lib/time/time_sys.h
index 6a860ffd08..f2401e1911 100644
--- a/src/lib/time/time_sys.h
+++ b/src/lib/time/time_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/time/tvdiff.c b/src/lib/time/tvdiff.c
index d7c245f57a..cbad5a48b8 100644
--- a/src/lib/time/tvdiff.c
+++ b/src/lib/time/tvdiff.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/time/tvdiff.h b/src/lib/time/tvdiff.h
index 657cb99553..e779e758f1 100644
--- a/src/lib/time/tvdiff.h
+++ b/src/lib/time/tvdiff.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/tls/buffers_tls.c b/src/lib/tls/buffers_tls.c
index ed0f821ce8..87055744a7 100644
--- a/src/lib/tls/buffers_tls.c
+++ b/src/lib/tls/buffers_tls.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -69,9 +69,9 @@ buf_read_from_tls(buf_t *buf, tor_tls_t *tls, size_t at_most)
check_no_tls_errors();
IF_BUG_ONCE(buf->datalen >= INT_MAX)
- return -1;
+ return TOR_TLS_ERROR_MISC;
IF_BUG_ONCE(buf->datalen >= INT_MAX - at_most)
- return -1;
+ return TOR_TLS_ERROR_MISC;
while (at_most > total_read) {
size_t readlen = at_most - total_read;
diff --git a/src/lib/tls/buffers_tls.h b/src/lib/tls/buffers_tls.h
index 65788c3f34..587426801d 100644
--- a/src/lib/tls/buffers_tls.h
+++ b/src/lib/tls/buffers_tls.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/tls/lib_tls.md b/src/lib/tls/lib_tls.md
new file mode 100644
index 0000000000..26fea723f9
--- /dev/null
+++ b/src/lib/tls/lib_tls.md
@@ -0,0 +1,11 @@
+@dir /lib/tls
+@brief lib/tls: TLS library wrappers
+
+This module has compatibility wrappers around the library (NSS or OpenSSL,
+depending on configuration) that Tor uses to implement the TLS link security
+protocol.
+
+It also implements the logic for some legacy TLS protocol usage we used to
+support in old versions of Tor, involving conditional delivery of certificate
+chains (v1 link protocol) and conditional renegotiation (v2 link protocol).
+
diff --git a/src/lib/tls/nss_countbytes.c b/src/lib/tls/nss_countbytes.c
index 7761727acd..4b98df80ec 100644
--- a/src/lib/tls/nss_countbytes.c
+++ b/src/lib/tls/nss_countbytes.c
@@ -1,4 +1,4 @@
-/* Copyright 2018-2019, The Tor Project Inc. */
+/* Copyright 2018-2020, The Tor Project Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/tls/nss_countbytes.h b/src/lib/tls/nss_countbytes.h
index 47f220c4c1..36ed55e10d 100644
--- a/src/lib/tls/nss_countbytes.h
+++ b/src/lib/tls/nss_countbytes.h
@@ -1,4 +1,4 @@
-/* Copyright 2018-2019, The Tor Project, Inc. */
+/* Copyright 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/tls/tortls.c b/src/lib/tls/tortls.c
index 1aff40c437..fd41a84cfa 100644
--- a/src/lib/tls/tortls.c
+++ b/src/lib/tls/tortls.c
@@ -1,8 +1,13 @@
/* Copyright (c) 2003, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file tortls.c
+ * @brief Shared functionality for our TLS backends.
+ **/
+
#define TORTLS_PRIVATE
#define TOR_X509_PRIVATE
#include "lib/tls/x509.h"
diff --git a/src/lib/tls/tortls.h b/src/lib/tls/tortls.h
index 799bd6aaeb..e8dbbf5279 100644
--- a/src/lib/tls/tortls.h
+++ b/src/lib/tls/tortls.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_TORTLS_H
diff --git a/src/lib/tls/tortls_internal.h b/src/lib/tls/tortls_internal.h
index 866483a94c..3f56f181ee 100644
--- a/src/lib/tls/tortls_internal.h
+++ b/src/lib/tls/tortls_internal.h
@@ -1,11 +1,18 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file tortls_internal.h
+ * @brief Declare internal functions for lib/tls
+ **/
+
#ifndef TORTLS_INTERNAL_H
#define TORTLS_INTERNAL_H
+#include "lib/tls/x509.h"
+
int tor_errno_to_tls_error(int e);
#ifdef ENABLE_OPENSSL
int tor_tls_get_error(tor_tls_t *tls, int r, int extra,
diff --git a/src/lib/tls/tortls_nss.c b/src/lib/tls/tortls_nss.c
index 1436442e1c..38c7efe107 100644
--- a/src/lib/tls/tortls_nss.c
+++ b/src/lib/tls/tortls_nss.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -34,7 +34,7 @@
#include "lib/tls/nss_countbytes.h"
#include "lib/log/util_bug.h"
-DISABLE_GCC_WARNING(strict-prototypes)
+DISABLE_GCC_WARNING("-Wstrict-prototypes")
#include <prio.h>
// For access to rar sockets.
#include <private/pprio.h>
@@ -42,7 +42,7 @@ DISABLE_GCC_WARNING(strict-prototypes)
#include <sslt.h>
#include <sslproto.h>
#include <certt.h>
-ENABLE_GCC_WARNING(strict-prototypes)
+ENABLE_GCC_WARNING("-Wstrict-prototypes")
static SECStatus always_accept_cert_cb(void *, PRFileDesc *, PRBool, PRBool);
diff --git a/src/lib/tls/tortls_openssl.c b/src/lib/tls/tortls_openssl.c
index 5bafcf676d..68d6e2aa50 100644
--- a/src/lib/tls/tortls_openssl.c
+++ b/src/lib/tls/tortls_openssl.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -37,7 +37,7 @@
/* Some versions of OpenSSL declare SSL_get_selected_srtp_profile twice in
* srtp.h. Suppress the GCC warning so we can build with -Wredundant-decl. */
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/opensslv.h>
@@ -54,7 +54,7 @@ DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/bn.h>
#include <openssl/rsa.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
#include "lib/tls/tortls.h"
#include "lib/tls/tortls_st.h"
@@ -464,7 +464,9 @@ static const char UNRESTRICTED_SERVER_CIPHER_LIST[] =
/** List of ciphers that clients should advertise, omitting items that
* our OpenSSL doesn't know about. */
static const char CLIENT_CIPHER_LIST[] =
+#ifndef COCCI
#include "lib/tls/ciphers.inc"
+#endif
/* Tell it not to use SSLv2 ciphers, so that it can select an SSLv3 version
* of any cipher we say. */
"!SSLv2"
diff --git a/src/lib/tls/tortls_st.h b/src/lib/tls/tortls_st.h
index 73f6e6ecca..925896d493 100644
--- a/src/lib/tls/tortls_st.h
+++ b/src/lib/tls/tortls_st.h
@@ -1,11 +1,19 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_TORTLS_ST_H
#define TOR_TORTLS_ST_H
+/**
+ * @file tortls_st.h
+ * @brief Structure declarations for internal TLS types.
+ *
+ * These should generally be treated as opaque outside of the
+ * lib/tls module.
+ **/
+
#include "lib/net/socket.h"
#define TOR_TLS_MAGIC 0x71571571
diff --git a/src/lib/tls/tortls_sys.h b/src/lib/tls/tortls_sys.h
index 4b04f85f0c..177c198f71 100644
--- a/src/lib/tls/tortls_sys.h
+++ b/src/lib/tls/tortls_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/tls/x509.c b/src/lib/tls/x509.c
index b4a0f8dabf..2515499298 100644
--- a/src/lib/tls/x509.c
+++ b/src/lib/tls/x509.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/tls/x509.h b/src/lib/tls/x509.h
index 0390a5464d..5919b9089d 100644
--- a/src/lib/tls/x509.h
+++ b/src/lib/tls/x509.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_X509_H
diff --git a/src/lib/tls/x509_internal.h b/src/lib/tls/x509_internal.h
index f858baae98..145be7e71c 100644
--- a/src/lib/tls/x509_internal.h
+++ b/src/lib/tls/x509_internal.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_X509_INTERNAL_H
diff --git a/src/lib/tls/x509_nss.c b/src/lib/tls/x509_nss.c
index e04afaf07b..341bb57104 100644
--- a/src/lib/tls/x509_nss.c
+++ b/src/lib/tls/x509_nss.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/tls/x509_openssl.c b/src/lib/tls/x509_openssl.c
index 7724288279..2abf02851d 100644
--- a/src/lib/tls/x509_openssl.c
+++ b/src/lib/tls/x509_openssl.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -19,7 +19,7 @@
/* Some versions of OpenSSL declare SSL_get_selected_srtp_profile twice in
* srtp.h. Suppress the GCC warning so we can build with -Wredundant-decl. */
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/opensslv.h>
@@ -36,7 +36,7 @@ DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/rsa.h>
#include <openssl/x509.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
diff --git a/src/lib/trace/debug.h b/src/lib/trace/debug.h
index 92bb95c883..87b3074e0b 100644
--- a/src/lib/trace/debug.h
+++ b/src/lib/trace/debug.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/trace/events.h b/src/lib/trace/events.h
index 9de86d63f2..368f85dd02 100644
--- a/src/lib/trace/events.h
+++ b/src/lib/trace/events.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/trace/lib_trace.md b/src/lib/trace/lib_trace.md
new file mode 100644
index 0000000000..a7a32529b0
--- /dev/null
+++ b/src/lib/trace/lib_trace.md
@@ -0,0 +1,6 @@
+@dir /lib/trace
+@brief lib/trace: Function-tracing functionality API.
+
+This module is used for adding "trace" support (low-granularity function
+logging) to Tor. Right now it doesn't have many users.
+
diff --git a/src/lib/trace/trace.c b/src/lib/trace/trace.c
index 18be63c5a8..4e5c66b4c6 100644
--- a/src/lib/trace/trace.c
+++ b/src/lib/trace/trace.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/trace/trace.h b/src/lib/trace/trace.h
index 5001b28a1d..5e24678c3c 100644
--- a/src/lib/trace/trace.h
+++ b/src/lib/trace/trace.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/version/git_revision.c b/src/lib/version/git_revision.c
index 900a1e12a0..09f11aa316 100644
--- a/src/lib/version/git_revision.c
+++ b/src/lib/version/git_revision.c
@@ -1,24 +1,39 @@
/* Copyright 2001-2004 Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#include "lib/version/git_revision.h"
+/**
+ * @file git_revision.c
+ * @brief Strings to describe the current Git commit.
+ **/
+
/** String describing which Tor Git repository version the source was
* built from. This string is generated by a bit of shell kludging in
* src/core/include.am, and is usually right.
*/
const char tor_git_revision[] =
+#ifndef COCCI
#ifndef _MSC_VER
#include "micro-revision.i"
#endif
+#endif
"";
+/**
+ * String appended to Tor bug messages describing the Tor version.
+ *
+ * It has the form "(on Tor 0.4.3.1-alpha)" or
+ * "(on Tor 0.4.3.1-alpha git-b994397f1af193f8)"
+ **/
const char tor_bug_suffix[] = " (on Tor " VERSION
+#ifndef COCCI
#ifndef _MSC_VER
" "
#include "micro-revision.i"
#endif
+#endif /* !defined(COCCI) */
")";
diff --git a/src/lib/version/git_revision.h b/src/lib/version/git_revision.h
index 79e3c6684b..80b6c4734e 100644
--- a/src/lib/version/git_revision.h
+++ b/src/lib/version/git_revision.h
@@ -1,11 +1,16 @@
/* Copyright 2001-2004 Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_GIT_REVISION_H
#define TOR_GIT_REVISION_H
+/**
+ * @file git_revision.h
+ * @brief Header for git_revision.c
+ **/
+
extern const char tor_git_revision[];
extern const char tor_bug_suffix[];
diff --git a/src/lib/version/lib_version.md b/src/lib/version/lib_version.md
new file mode 100644
index 0000000000..ccc45920f9
--- /dev/null
+++ b/src/lib/version/lib_version.md
@@ -0,0 +1,2 @@
+@dir /lib/version
+@brief lib/version: holds the current version of Tor.
diff --git a/src/lib/version/torversion.h b/src/lib/version/torversion.h
index 7b0fb66ec0..679df74381 100644
--- a/src/lib/version/torversion.h
+++ b/src/lib/version/torversion.h
@@ -1,11 +1,16 @@
/* Copyright 2001-2004 Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_VERSION_H
#define TOR_VERSION_H
+/**
+ * @file torversion.h
+ * @brief Header for version.c.
+ **/
+
const char *get_version(void);
const char *get_short_version(void);
diff --git a/src/lib/version/version.c b/src/lib/version/version.c
index 434e6fb424..ec1d0bea2f 100644
--- a/src/lib/version/version.c
+++ b/src/lib/version/version.c
@@ -1,6 +1,6 @@
/* Copyright 2001-2004 Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -10,6 +10,11 @@
#include <stdio.h>
#include <string.h>
+/**
+ * @file version.c
+ * @brief Functions to get the version of Tor.
+ **/
+
/** A shorter version of this Tor process's version, for export in our router
* descriptor. (Does not include the git version, if any.) */
static const char the_short_tor_version[] =
@@ -19,6 +24,10 @@ static const char the_short_tor_version[] =
#endif
"";
+/**
+ * Longest possible version length. We make this a constant so that we
+ * can statically allocate the_tor_version.
+ **/
#define MAX_VERSION_LEN 128
/** The version of this Tor process, possibly including git version */
diff --git a/src/lib/wallclock/approx_time.c b/src/lib/wallclock/approx_time.c
index 77eeddaf56..d9f90ab2f7 100644
--- a/src/lib/wallclock/approx_time.c
+++ b/src/lib/wallclock/approx_time.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -44,6 +44,9 @@ update_approx_time(time_t now)
}
#endif /* !defined(TIME_IS_FAST) */
+/**
+ * Initialize the "wallclock" subsystem by setting the current cached time.
+ **/
static int
subsys_wallclock_initialize(void)
{
@@ -51,6 +54,9 @@ subsys_wallclock_initialize(void)
return 0;
}
+/**
+ * Subsystem function table describing the "wallclock" subsystem.
+ **/
const subsys_fns_t sys_wallclock = {
.name = "wallclock",
.supported = true,
diff --git a/src/lib/wallclock/approx_time.h b/src/lib/wallclock/approx_time.h
index e7da160122..42040a1f52 100644
--- a/src/lib/wallclock/approx_time.h
+++ b/src/lib/wallclock/approx_time.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/wallclock/lib_wallclock.md b/src/lib/wallclock/lib_wallclock.md
new file mode 100644
index 0000000000..f21721f6f6
--- /dev/null
+++ b/src/lib/wallclock/lib_wallclock.md
@@ -0,0 +1,11 @@
+@dir /lib/wallclock
+@brief lib/wallclock: Inspect and manipulate the current time.
+
+This module handles our concept of "what time is it" or "what time does the
+world agree it is?" Generally, if you want something derived from UTC, this
+is the module for you.
+
+For versions of the time that are more local, more monotonic, or more
+accurate, see \refdir{lib/time}. For parsing and encoding times and dates,
+see \refdir{lib/encoding}.
+
diff --git a/src/lib/wallclock/time_to_tm.c b/src/lib/wallclock/time_to_tm.c
index f7cb21827b..8c747b4c7b 100644
--- a/src/lib/wallclock/time_to_tm.c
+++ b/src/lib/wallclock/time_to_tm.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -198,3 +198,4 @@ tor_gmtime_r_msg(const time_t *timep, struct tm *result, char **err_out)
return correct_tm(0, timep, result, r, err_out);
}
#endif /* defined(HAVE_GMTIME_R) || ... */
+/**@}*/
diff --git a/src/lib/wallclock/time_to_tm.h b/src/lib/wallclock/time_to_tm.h
index da27fcaba1..bfa8fa3689 100644
--- a/src/lib/wallclock/time_to_tm.h
+++ b/src/lib/wallclock/time_to_tm.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/wallclock/timeval.h b/src/lib/wallclock/timeval.h
index e632d04a04..d7d5bda99f 100644
--- a/src/lib/wallclock/timeval.h
+++ b/src/lib/wallclock/timeval.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -69,6 +69,7 @@
} while (0)
#endif /* !defined(timersub) */
+#ifndef COCCI
#ifndef timercmp
/** Replacement for timercmp on platforms that do not have it: returns true
* iff the relational operator "op" makes the expression tv1 op tv2 true.
@@ -82,5 +83,6 @@
((tv1)->tv_usec op (tv2)->tv_usec) : \
((tv1)->tv_sec op (tv2)->tv_sec))
#endif /* !defined(timercmp) */
+#endif /* !defined(COCCI) */
#endif /* !defined(TOR_TIMEVAL_H) */
diff --git a/src/lib/wallclock/tor_gettimeofday.c b/src/lib/wallclock/tor_gettimeofday.c
index 63538f3b81..a07f83220d 100644
--- a/src/lib/wallclock/tor_gettimeofday.c
+++ b/src/lib/wallclock/tor_gettimeofday.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/wallclock/tor_gettimeofday.h b/src/lib/wallclock/tor_gettimeofday.h
index 6fec2fc893..c1a8afca3a 100644
--- a/src/lib/wallclock/tor_gettimeofday.h
+++ b/src/lib/wallclock/tor_gettimeofday.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/wallclock/wallclock_sys.h b/src/lib/wallclock/wallclock_sys.h
index a30912b8fb..3997d11e7a 100644
--- a/src/lib/wallclock/wallclock_sys.h
+++ b/src/lib/wallclock/wallclock_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/mainpage.md b/src/mainpage.md
new file mode 100644
index 0000000000..8a73578819
--- /dev/null
+++ b/src/mainpage.md
@@ -0,0 +1,147 @@
+@mainpage Tor source reference
+
+@tableofcontents
+
+@section welcome Welcome to Tor
+
+This documentation describes the general structure of the Tor codebase, how
+it fits together, what functionality is available for extending Tor, and
+gives some notes on how Tor got that way. It also includes a reference for
+nearly every function, type, file, and module in the Tor source code. The
+high-level documentation is a work in progress.
+
+Tor itself remains a work in progress too: We've been working on it for
+nearly two decades, and we've learned a lot about good coding since we first
+started. This means, however, that some of the older pieces of Tor will have
+some "code smell" in them that could stand a brisk refactoring. So when we
+describe a piece of code, we'll sometimes give a note on how it got that way,
+and whether we still think that's a good idea.
+
+This document is not an overview of the Tor protocol. For that, see the
+design paper and the specifications at https://spec.torproject.org/ .
+
+For more information about Tor's coding standards and some helpful
+development tools, see
+[doc/HACKING](https://gitweb.torproject.org/tor.git/tree/doc/HACKING) in the
+Tor repository.
+
+@section topics Topic-related documentation
+
+@subpage intro
+
+@subpage arch_goals
+
+@subpage initialization
+
+@subpage dataflow
+
+@subpage certificates
+
+@subpage threading
+
+@subpage strings
+
+@subpage time_periodic
+
+@subpage configuration
+
+@subpage publish_subscribe
+
+@page intro A high-level overview
+
+@tableofcontents
+
+@section highlevel The very high level
+
+Ultimately, Tor runs as an event-driven network daemon: it responds to
+network events, signals, and timers by sending and receiving things over
+the network. Clients, relays, and directory authorities all use the
+same codebase: the Tor process will run as a client, relay, or authority
+depending on its configuration.
+
+Tor has a few major dependencies, including Libevent (used to tell which
+sockets are readable and writable), OpenSSL or NSS (used for many encryption
+functions, and to implement the TLS protocol), and zlib (used to
+compress and uncompress directory information).
+
+Most of Tor's work today is done in a single event-driven main thread.
+Tor also spawns one or more worker threads to handle CPU-intensive
+tasks. (Right now, this only includes circuit encryption and the more
+expensive compression algorithms.)
+
+On startup, Tor initializes its libraries, reads and responds to its
+configuration files, and launches a main event loop. At first, the only
+events that Tor listens for are a few signals (like TERM and HUP), and
+one or more listener sockets (for different kinds of incoming
+connections). Tor also configures several timers to handle periodic
+events. As Tor runs over time, other events will open, and new events
+will be scheduled.
+
+The codebase is divided into a few top-level subdirectories, each of
+which contains several sub-modules.
+
+ - `ext` -- Code maintained elsewhere that we include in the Tor
+ source distribution.
+
+ - \refdir{lib} -- Lower-level utility code, not necessarily
+ tor-specific.
+
+ - `trunnel` -- Automatically generated code (from the Trunnel
+ tool): used to parse and encode binary formats.
+
+ - \refdir{core} -- Networking code that is implements the central
+ parts of the Tor protocol and main loop.
+
+ - \refdir{feature} -- Aspects of Tor (like directory management,
+ running a relay, running a directory authorities, managing a list of
+ nodes, running and using onion services) that are built on top of the
+ mainloop code.
+
+ - \refdir{app} -- Highest-level functionality; responsible for setting
+ up and configuring the Tor daemon, making sure all the lower-level
+ modules start up when required, and so on.
+
+ - \refdir{tools} -- Binaries other than Tor that we produce.
+ Currently this is tor-resolve, tor-gencert, and the tor_runner.o helper
+ module.
+
+ - `test` -- unit tests, regression tests, and a few integration
+ tests.
+
+In theory, the above parts of the codebase are sorted from highest-level to
+lowest-level, where high-level code is only allowed to invoke lower-level
+code, and lower-level code never includes or depends on code of a higher
+level. In practice, this refactoring is incomplete: The modules in
+\refdir{lib} are well-factored, but there are many layer violations ("upward
+dependencies") in \refdir{core} and \refdir{feature}.
+We aim to eliminate those over time.
+
+@section keyabstractions Some key high-level abstractions
+
+The most important abstractions at Tor's high-level are Connections,
+Channels, Circuits, and Nodes.
+
+A 'Connection' (connection_t) represents a stream-based information flow.
+Most connections are TCP connections to remote Tor servers and clients. (But
+as a shortcut, a relay will sometimes make a connection to itself without
+actually using a TCP connection. More details later on.) Connections exist
+in different varieties, depending on what functionality they provide. The
+principle types of connection are edge_connection_t (eg a socks connection or
+a connection from an exit relay to a destination), or_connection_t (a TLS
+stream connecting to a relay), dir_connection_t (an HTTP connection to learn
+about the network), and control_connection_t (a connection from a
+controller).
+
+A 'Circuit' (circuit_t) is persistent tunnel through the Tor network,
+established with public-key cryptography, and used to send cells one or more
+hops. Clients keep track of multi-hop circuits (origin_circuit_t), and the
+cryptography associated with each hop. Relays, on the other hand, keep track
+only of their hop of each circuit (or_circuit_t).
+
+A 'Channel' (channel_t) is an abstract view of sending cells to and from a
+Tor relay. Currently, all channels are implemented using OR connections
+(channel_tls_t). If we switch to other strategies in the future, we'll have
+more connection types.
+
+A 'Node' (node_t) is a view of a Tor instance's current knowledge and opinions
+about a Tor relay or bridge.
diff --git a/src/test/.may_include b/src/test/.may_include
new file mode 100644
index 0000000000..11c5ffbb14
--- /dev/null
+++ b/src/test/.may_include
@@ -0,0 +1,2 @@
+*.h
+*.inc
diff --git a/src/test/bench.c b/src/test/bench.c
index cf732df593..7a8c04e802 100644
--- a/src/test/bench.c
+++ b/src/test/bench.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/bt_test.py b/src/test/bt_test.py
index f9ca79efde..d728f13596 100755
--- a/src/test/bt_test.py
+++ b/src/test/bt_test.py
@@ -15,7 +15,11 @@ OK
"""
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
from __future__ import print_function
+from __future__ import unicode_literals
+
import sys
diff --git a/src/test/conf_examples/badnick_1/expected_log_no_dirauth_relay b/src/test/conf_examples/badnick_1/expected_log_no_dirauth_relay
new file mode 100644
index 0000000000..9190a3326b
--- /dev/null
+++ b/src/test/conf_examples/badnick_1/expected_log_no_dirauth_relay
@@ -0,0 +1 @@
+Read configuration file .*badnick_1[./]*torrc
diff --git a/src/test/conf_examples/badnick_1/expected_no_dirauth_relay b/src/test/conf_examples/badnick_1/expected_no_dirauth_relay
new file mode 100644
index 0000000000..b00be15c2e
--- /dev/null
+++ b/src/test/conf_examples/badnick_1/expected_no_dirauth_relay
@@ -0,0 +1 @@
+Nickname TooManyCharactersInThisNickname
diff --git a/src/test/conf_examples/badnick_1/torrc b/src/test/conf_examples/badnick_1/torrc
index 41ee4894f1..087e3f2ff1 100644
--- a/src/test/conf_examples/badnick_1/torrc
+++ b/src/test/conf_examples/badnick_1/torrc
@@ -1,2 +1,4 @@
# This nickname is too long; we won't accept it.
+# (Unless the relay module is disabled, because Nickname is a
+# relay-only option. We'll ignore all relay-only options in #32395.)
Nickname TooManyCharactersInThisNickname
diff --git a/src/test/conf_examples/badnick_2/expected_log_no_dirauth_relay b/src/test/conf_examples/badnick_2/expected_log_no_dirauth_relay
new file mode 100644
index 0000000000..a15c7b02cb
--- /dev/null
+++ b/src/test/conf_examples/badnick_2/expected_log_no_dirauth_relay
@@ -0,0 +1 @@
+Read configuration file .*badnick_2[./]*torrc
diff --git a/src/test/conf_examples/badnick_2/expected_no_dirauth_relay b/src/test/conf_examples/badnick_2/expected_no_dirauth_relay
new file mode 100644
index 0000000000..08dcdc33a9
--- /dev/null
+++ b/src/test/conf_examples/badnick_2/expected_no_dirauth_relay
@@ -0,0 +1 @@
+Nickname has a space
diff --git a/src/test/conf_examples/badnick_2/torrc b/src/test/conf_examples/badnick_2/torrc
index 07acc61698..51a5f96c00 100644
--- a/src/test/conf_examples/badnick_2/torrc
+++ b/src/test/conf_examples/badnick_2/torrc
@@ -1,2 +1,4 @@
# this nickname has spaces in it and won't work.
+# (Unless the relay module is disabled, because Nickname is a
+# relay-only option. We'll ignore all relay-only options in #32395.)
Nickname has a space
diff --git a/src/test/conf_examples/bridgeauth_1/error_no_dirauth b/src/test/conf_examples/bridgeauth_1/error_no_dirauth
new file mode 100644
index 0000000000..e6bd5db69c
--- /dev/null
+++ b/src/test/conf_examples/bridgeauth_1/error_no_dirauth
@@ -0,0 +1 @@
+This tor was built with dirauth mode disabled.
diff --git a/src/test/conf_examples/bridgeauth_1/error_no_dirauth_relay b/src/test/conf_examples/bridgeauth_1/error_no_dirauth_relay
new file mode 100644
index 0000000000..e6bd5db69c
--- /dev/null
+++ b/src/test/conf_examples/bridgeauth_1/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with dirauth mode disabled.
diff --git a/src/test/conf_examples/bridgeauth_1/expected b/src/test/conf_examples/bridgeauth_1/expected
new file mode 100644
index 0000000000..d43aaf2c8b
--- /dev/null
+++ b/src/test/conf_examples/bridgeauth_1/expected
@@ -0,0 +1,7 @@
+Address 198.51.100.123
+AuthoritativeDirectory 1
+BridgeAuthoritativeDir 1
+ContactInfo tor_parse_test@example.com
+DirPort 80
+Nickname Unnamed
+ORPort 443
diff --git a/src/test/conf_examples/bridgeauth_1/expected_log b/src/test/conf_examples/bridgeauth_1/expected_log
new file mode 100644
index 0000000000..cabe9d3f89
--- /dev/null
+++ b/src/test/conf_examples/bridgeauth_1/expected_log
@@ -0,0 +1 @@
+Read configuration file .*bridgeauth_1[./]*torrc
diff --git a/src/test/conf_examples/bridgeauth_1/torrc b/src/test/conf_examples/bridgeauth_1/torrc
new file mode 100644
index 0000000000..740bc6c2eb
--- /dev/null
+++ b/src/test/conf_examples/bridgeauth_1/torrc
@@ -0,0 +1,8 @@
+AuthoritativeDirectory 1
+BridgeAuthoritativeDir 1
+
+ContactInfo tor_parse_test@example.com
+
+Address 198.51.100.123
+ORPort 443
+DirPort 80
diff --git a/src/test/conf_examples/contactinfo_notutf8/expected_log_no_dirauth_relay b/src/test/conf_examples/contactinfo_notutf8/expected_log_no_dirauth_relay
new file mode 100644
index 0000000000..caa07aca40
--- /dev/null
+++ b/src/test/conf_examples/contactinfo_notutf8/expected_log_no_dirauth_relay
@@ -0,0 +1 @@
+Read configuration file .*contactinfo_notutf8[./]*torrc
diff --git a/src/test/conf_examples/contactinfo_notutf8/expected_no_dirauth_relay b/src/test/conf_examples/contactinfo_notutf8/expected_no_dirauth_relay
new file mode 100644
index 0000000000..cc8bd7b8e3
--- /dev/null
+++ b/src/test/conf_examples/contactinfo_notutf8/expected_no_dirauth_relay
@@ -0,0 +1 @@
+ContactInfo "\304\353\304\353\304\353@example.com"
diff --git a/src/test/conf_examples/contactinfo_notutf8/torrc b/src/test/conf_examples/contactinfo_notutf8/torrc
index 2ee4d093c5..0176a56a97 100644
--- a/src/test/conf_examples/contactinfo_notutf8/torrc
+++ b/src/test/conf_examples/contactinfo_notutf8/torrc
@@ -1 +1,5 @@
+# We only accept ContactInfo in UTF-8 (or 7-bit ASCII)
+# (Unless the relay module is disabled, because ContactInfo is a
+# relay-only option. We'll ignore all relay-only options in #32395.
+# But at the moment, tor canonicalises and quotes the string.)
ContactInfo ÄëÄëÄë@example.com
diff --git a/src/test/conf_examples/controlsock/error b/src/test/conf_examples/controlsock/error
new file mode 100644
index 0000000000..8fbea37894
--- /dev/null
+++ b/src/test/conf_examples/controlsock/error
@@ -0,0 +1 @@
+not supported on this OS\|without setting a ControlSocket
diff --git a/src/test/conf_examples/controlsock/torrc b/src/test/conf_examples/controlsock/torrc
new file mode 100644
index 0000000000..dd3cb7ede5
--- /dev/null
+++ b/src/test/conf_examples/controlsock/torrc
@@ -0,0 +1 @@
+ControlSocketsGroupWritable 1
diff --git a/src/test/conf_examples/crypto_accel/expected b/src/test/conf_examples/crypto_accel/expected
new file mode 100644
index 0000000000..ea80ca19dc
--- /dev/null
+++ b/src/test/conf_examples/crypto_accel/expected
@@ -0,0 +1,2 @@
+AccelName nonexistent_chartreuse_accelerator
+HardwareAccel 1
diff --git a/src/test/conf_examples/crypto_accel/expected_log b/src/test/conf_examples/crypto_accel/expected_log
new file mode 100644
index 0000000000..7fab0c8dad
--- /dev/null
+++ b/src/test/conf_examples/crypto_accel/expected_log
@@ -0,0 +1 @@
+Unable to load dynamic OpenSSL engine "nonexistent_chartreuse_accelerator"
diff --git a/src/test/conf_examples/crypto_accel/expected_log_nss b/src/test/conf_examples/crypto_accel/expected_log_nss
new file mode 100644
index 0000000000..c0fe7b003c
--- /dev/null
+++ b/src/test/conf_examples/crypto_accel/expected_log_nss
@@ -0,0 +1 @@
+Tor 0.* running on .* with Libevent .*, NSS .*, Zlib .*, Liblzma .*, and Libzstd .*
diff --git a/src/test/conf_examples/crypto_accel/expected_nss b/src/test/conf_examples/crypto_accel/expected_nss
new file mode 100644
index 0000000000..ea80ca19dc
--- /dev/null
+++ b/src/test/conf_examples/crypto_accel/expected_nss
@@ -0,0 +1,2 @@
+AccelName nonexistent_chartreuse_accelerator
+HardwareAccel 1
diff --git a/src/test/conf_examples/crypto_accel/torrc b/src/test/conf_examples/crypto_accel/torrc
new file mode 100644
index 0000000000..9ca18903b7
--- /dev/null
+++ b/src/test/conf_examples/crypto_accel/torrc
@@ -0,0 +1,3 @@
+
+AccelName nonexistent_chartreuse_accelerator
+HardwareAccel 1
diff --git a/src/test/conf_examples/crypto_accel_req/error b/src/test/conf_examples/crypto_accel_req/error
new file mode 100644
index 0000000000..e12e002915
--- /dev/null
+++ b/src/test/conf_examples/crypto_accel_req/error
@@ -0,0 +1 @@
+Unable to load required dynamic OpenSSL engine "nonexistent_chartreuse_accelerator"
diff --git a/src/test/conf_examples/crypto_accel_req/expected_log_nss b/src/test/conf_examples/crypto_accel_req/expected_log_nss
new file mode 100644
index 0000000000..c0fe7b003c
--- /dev/null
+++ b/src/test/conf_examples/crypto_accel_req/expected_log_nss
@@ -0,0 +1 @@
+Tor 0.* running on .* with Libevent .*, NSS .*, Zlib .*, Liblzma .*, and Libzstd .*
diff --git a/src/test/conf_examples/crypto_accel_req/expected_nss b/src/test/conf_examples/crypto_accel_req/expected_nss
new file mode 100644
index 0000000000..f3e172f640
--- /dev/null
+++ b/src/test/conf_examples/crypto_accel_req/expected_nss
@@ -0,0 +1,2 @@
+AccelName !nonexistent_chartreuse_accelerator
+HardwareAccel 1
diff --git a/src/test/conf_examples/crypto_accel_req/torrc b/src/test/conf_examples/crypto_accel_req/torrc
new file mode 100644
index 0000000000..981d9116fc
--- /dev/null
+++ b/src/test/conf_examples/crypto_accel_req/torrc
@@ -0,0 +1,3 @@
+
+AccelName !nonexistent_chartreuse_accelerator
+HardwareAccel 1
diff --git a/src/test/conf_examples/dirauth_1/error_no_dirauth b/src/test/conf_examples/dirauth_1/error_no_dirauth
new file mode 100644
index 0000000000..e6bd5db69c
--- /dev/null
+++ b/src/test/conf_examples/dirauth_1/error_no_dirauth
@@ -0,0 +1 @@
+This tor was built with dirauth mode disabled.
diff --git a/src/test/conf_examples/dirauth_1/error_no_dirauth_relay b/src/test/conf_examples/dirauth_1/error_no_dirauth_relay
new file mode 100644
index 0000000000..e6bd5db69c
--- /dev/null
+++ b/src/test/conf_examples/dirauth_1/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with dirauth mode disabled.
diff --git a/src/test/conf_examples/dirauth_1/expected b/src/test/conf_examples/dirauth_1/expected
new file mode 100644
index 0000000000..901f7d947f
--- /dev/null
+++ b/src/test/conf_examples/dirauth_1/expected
@@ -0,0 +1,8 @@
+Address 192.0.2.1
+AuthoritativeDirectory 1
+ContactInfo tor_parse_test@example.net
+DirPort 9030
+DownloadExtraInfo 1
+Nickname Unnamed
+ORPort 9001
+V3AuthoritativeDirectory 1
diff --git a/src/test/conf_examples/dirauth_1/expected_log b/src/test/conf_examples/dirauth_1/expected_log
new file mode 100644
index 0000000000..b788be2e33
--- /dev/null
+++ b/src/test/conf_examples/dirauth_1/expected_log
@@ -0,0 +1 @@
+Read configuration file .*dirauth_1[./]*torrc
diff --git a/src/test/conf_examples/dirauth_1/torrc b/src/test/conf_examples/dirauth_1/torrc
new file mode 100644
index 0000000000..b870e6e8e0
--- /dev/null
+++ b/src/test/conf_examples/dirauth_1/torrc
@@ -0,0 +1,8 @@
+AuthoritativeDirectory 1
+V3AuthoritativeDirectory 1
+
+ContactInfo tor_parse_test@example.net
+
+Address 192.0.2.1
+ORPort 9001
+DirPort 9030
diff --git a/src/test/conf_examples/dirauth_2/expected b/src/test/conf_examples/dirauth_2/expected
new file mode 100644
index 0000000000..19ab024ed3
--- /dev/null
+++ b/src/test/conf_examples/dirauth_2/expected
@@ -0,0 +1 @@
+AuthDirMaxServersPerAddr 8
diff --git a/src/test/conf_examples/dirauth_2/expected_log b/src/test/conf_examples/dirauth_2/expected_log
new file mode 100644
index 0000000000..88611fee9d
--- /dev/null
+++ b/src/test/conf_examples/dirauth_2/expected_log
@@ -0,0 +1 @@
+Read configuration file
diff --git a/src/test/conf_examples/dirauth_2/expected_log_no_dirauth b/src/test/conf_examples/dirauth_2/expected_log_no_dirauth
new file mode 100644
index 0000000000..01110c5d8c
--- /dev/null
+++ b/src/test/conf_examples/dirauth_2/expected_log_no_dirauth
@@ -0,0 +1 @@
+This copy of Tor was built without support for the option "AuthDirMaxServersPerAddr". Skipping. \ No newline at end of file
diff --git a/src/test/conf_examples/dirauth_2/expected_log_no_dirauth_relay b/src/test/conf_examples/dirauth_2/expected_log_no_dirauth_relay
new file mode 100644
index 0000000000..01110c5d8c
--- /dev/null
+++ b/src/test/conf_examples/dirauth_2/expected_log_no_dirauth_relay
@@ -0,0 +1 @@
+This copy of Tor was built without support for the option "AuthDirMaxServersPerAddr". Skipping. \ No newline at end of file
diff --git a/src/test/conf_examples/dirauth_2/expected_no_dirauth b/src/test/conf_examples/dirauth_2/expected_no_dirauth
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/dirauth_2/expected_no_dirauth
diff --git a/src/test/conf_examples/dirauth_2/expected_no_dirauth_relay b/src/test/conf_examples/dirauth_2/expected_no_dirauth_relay
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/dirauth_2/expected_no_dirauth_relay
diff --git a/src/test/conf_examples/dirauth_2/torrc b/src/test/conf_examples/dirauth_2/torrc
new file mode 100644
index 0000000000..bd1cdbc8b9
--- /dev/null
+++ b/src/test/conf_examples/dirauth_2/torrc
@@ -0,0 +1,5 @@
+#
+# This will get accepted if the module is enabled, and ignored if the module
+# is disabled.
+#
+AuthDirMaxServersPerAddr 8
diff --git a/src/test/conf_examples/empty_1/expected b/src/test/conf_examples/empty_1/expected
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/empty_1/expected
diff --git a/src/test/conf_examples/empty_1/expected_log b/src/test/conf_examples/empty_1/expected_log
new file mode 100644
index 0000000000..4c6b00069f
--- /dev/null
+++ b/src/test/conf_examples/empty_1/expected_log
@@ -0,0 +1 @@
+Read configuration file .*empty_1[./]*torrc
diff --git a/src/test/conf_examples/empty_1/torrc b/src/test/conf_examples/empty_1/torrc
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/empty_1/torrc
diff --git a/src/test/conf_examples/empty_2/cmdline b/src/test/conf_examples/empty_2/cmdline
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/empty_2/cmdline
diff --git a/src/test/conf_examples/empty_2/expected b/src/test/conf_examples/empty_2/expected
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/empty_2/expected
diff --git a/src/test/conf_examples/empty_2/expected_log b/src/test/conf_examples/empty_2/expected_log
new file mode 100644
index 0000000000..9c846a03f3
--- /dev/null
+++ b/src/test/conf_examples/empty_2/expected_log
@@ -0,0 +1 @@
+Read configuration file .*empty_2[./]*torrc\.defaults
diff --git a/src/test/conf_examples/empty_2/torrc b/src/test/conf_examples/empty_2/torrc
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/empty_2/torrc
diff --git a/src/test/conf_examples/empty_2/torrc.defaults b/src/test/conf_examples/empty_2/torrc.defaults
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/empty_2/torrc.defaults
diff --git a/src/test/conf_examples/empty_3/expected b/src/test/conf_examples/empty_3/expected
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/empty_3/expected
diff --git a/src/test/conf_examples/empty_3/expected_log b/src/test/conf_examples/empty_3/expected_log
new file mode 100644
index 0000000000..a42514f37f
--- /dev/null
+++ b/src/test/conf_examples/empty_3/expected_log
@@ -0,0 +1 @@
+Included configuration .*directory at recursion level 1.*included
diff --git a/src/test/conf_examples/empty_3/included/empty b/src/test/conf_examples/empty_3/included/empty
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/empty_3/included/empty
diff --git a/src/test/conf_examples/empty_3/torrc b/src/test/conf_examples/empty_3/torrc
new file mode 100644
index 0000000000..049b438903
--- /dev/null
+++ b/src/test/conf_examples/empty_3/torrc
@@ -0,0 +1 @@
+%include "included"
diff --git a/src/test/conf_examples/empty_4/error b/src/test/conf_examples/empty_4/error
new file mode 100644
index 0000000000..e6c2f7d885
--- /dev/null
+++ b/src/test/conf_examples/empty_4/error
@@ -0,0 +1 @@
+Unable to open configuration file \ No newline at end of file
diff --git a/src/test/conf_examples/example_1/expected_log b/src/test/conf_examples/example_1/expected_log
new file mode 100644
index 0000000000..8f83eec988
--- /dev/null
+++ b/src/test/conf_examples/example_1/expected_log
@@ -0,0 +1 @@
+Read configuration file .*example_1[./]*torrc
diff --git a/src/test/conf_examples/example_3/expected_log b/src/test/conf_examples/example_3/expected_log
new file mode 100644
index 0000000000..807f9c2fc8
--- /dev/null
+++ b/src/test/conf_examples/example_3/expected_log
@@ -0,0 +1 @@
+Read configuration file .*example_3[./]*torrc
diff --git a/src/test/conf_examples/include_1/error_no_dirauth_relay b/src/test/conf_examples/include_1/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/include_1/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/include_1/expected_log b/src/test/conf_examples/include_1/expected_log
new file mode 100644
index 0000000000..f95cad040d
--- /dev/null
+++ b/src/test/conf_examples/include_1/expected_log
@@ -0,0 +1 @@
+Included configuration file .*at recursion level 2.*nested\.inc
diff --git a/src/test/conf_examples/include_bug_31408/error_no_dirauth_relay b/src/test/conf_examples/include_bug_31408/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/include_bug_31408/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/include_bug_31408/expected_log b/src/test/conf_examples/include_bug_31408/expected_log
new file mode 100644
index 0000000000..a42514f37f
--- /dev/null
+++ b/src/test/conf_examples/include_bug_31408/expected_log
@@ -0,0 +1 @@
+Included configuration .*directory at recursion level 1.*included
diff --git a/src/test/conf_examples/large_1/error_no_dirauth_relay b/src/test/conf_examples/large_1/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/large_1/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/large_1/expected_log b/src/test/conf_examples/large_1/expected_log
new file mode 100644
index 0000000000..21248bb5e4
--- /dev/null
+++ b/src/test/conf_examples/large_1/expected_log
@@ -0,0 +1 @@
+Your log may contain sensitive information
diff --git a/src/test/conf_examples/large_1/expected_log_no_dirauth b/src/test/conf_examples/large_1/expected_log_no_dirauth
new file mode 100644
index 0000000000..0b74de4e40
--- /dev/null
+++ b/src/test/conf_examples/large_1/expected_log_no_dirauth
@@ -0,0 +1 @@
+This copy of Tor was built without support for the option "ConsensusParams". Skipping.
diff --git a/src/test/conf_examples/large_1/expected_no_dirauth b/src/test/conf_examples/large_1/expected_no_dirauth
new file mode 100644
index 0000000000..17c11f85fc
--- /dev/null
+++ b/src/test/conf_examples/large_1/expected_no_dirauth
@@ -0,0 +1,158 @@
+AccountingMax 10737418240
+AccountingRule sum
+AccountingStart day 05:15
+Address 128.66.8.8
+AllowNonRFC953Hostnames 1
+AndroidIdentityTag droidy
+AutomapHostsOnResolve 1
+AutomapHostsSuffixes .onions
+AvoidDiskWrites 1
+BandwidthBurst 2147483647
+BandwidthRate 1610612736
+Bridge 128.66.1.10:80
+CacheDirectory /this-is-a-cache
+CellStatistics 1
+CircuitBuildTimeout 200
+CircuitsAvailableTimeout 10
+CircuitStreamTimeout 20
+ClientAutoIPv6ORPort 1
+ClientOnly 1
+ClientPreferIPv6DirPort 1
+ClientPreferIPv6ORPort 1
+ClientRejectInternalAddresses 0
+ClientUseIPv4 0
+ClientUseIPv6 1
+ConnDirectionStatistics 1
+ConnectionPadding 1
+ConnLimit 64
+ConstrainedSockets 1
+ConstrainedSockSize 10240
+ContactInfo long_config@example.com
+ControlPortFileGroupReadable 1
+ControlPort 9058
+CookieAuthentication 1
+CookieAuthFile /control/cookie
+CookieAuthFileGroupReadable 1
+CountPrivateBandwidth 1
+DataDirectory /data/dir
+DirAllowPrivateAddresses 1
+DirPolicy reject 128.66.1.1/32, accept *:*
+DirPortFrontPage /dirport/frontpage
+DirPort 99
+DirReqStatistics 0
+DisableDebuggerAttachment 0
+DisableNetwork 1
+DisableOOSCheck 0
+DNSPort 53535
+DormantCanceledByStartup 1
+DormantClientTimeout 1260
+DormantOnFirstStartup 1
+DormantTimeoutDisabledByIdleStreams 0
+DoSCircuitCreationBurst 1000
+DoSCircuitCreationDefenseTimePeriod 300
+DoSCircuitCreationDefenseType 2
+DoSCircuitCreationEnabled 1
+DoSCircuitCreationMinConnections 10
+DoSCircuitCreationRate 100
+DoSConnectionDefenseType 2
+DoSConnectionEnabled 1
+DoSConnectionMaxConcurrentCount 6
+DoSRefuseSingleHopClientRendezvous 0
+DownloadExtraInfo 1
+EnforceDistinctSubnets 0
+EntryNodes potrzebie,triffid,cromulent
+EntryStatistics 1
+ExcludeExitNodes blaznort,kriffid,zeppelin
+ExcludeNodes 128.66.7.6
+ExitNodes 128.66.7.7,128.66.128.0/17,exitexit
+ExitPolicy accept *:80,reject *:*
+ExitPolicyRejectLocalInterfaces 1
+ExitPolicyRejectPrivate 0
+ExitPortStatistics 1
+ExitRelay 1
+ExtendAllowPrivateAddresses 1
+ExtendByEd25519ID 1
+ExtORPortCookieAuthFile /foobar
+ExtORPort 99
+FascistFirewall 1
+FetchDirInfoEarly 1
+FetchDirInfoExtraEarly 1
+FetchUselessDescriptors 1
+FirewallPorts 80,443,999
+GeoIPExcludeUnknown 1
+GeoIPFile /geoip
+GuardfractionFile /gff
+GuardLifetime 691200
+HeartbeatPeriod 2700
+IPv6Exit 1
+KeepalivePeriod 540
+KeyDirectory /keyz
+KISTSchedRunInterval 1
+Log notice file /logfile
+Log info file /logfile-verbose
+LogTimeGranularity 60000
+LongLivedPorts 9090
+MainloopStats 1
+MapAddress www.example.com:10.0.0.6
+MaxAdvertisedBandwidth 100
+MaxCircuitDirtiness 3600
+MaxClientCircuitsPending 127
+MaxConsensusAgeForDiffs 2629728
+MaxMemInQueues 314572800
+MaxOnionQueueDelay 60000
+MaxUnparseableDescSizeToLog 1048576
+MiddleNodes grommit,truffle,parcheesi
+MyFamily $ffffffffffffffffffffffffffffffffffffffff
+NewCircuitPeriod 7200
+Nickname nickname
+NodeFamily $ffffffffffffffffffffffffffffffffffffffff,$dddddddddddddddddddddddddddddddddddddddd
+NumCPUs 3
+NumDirectoryGuards 4
+NumEntryGuards 5
+NumPrimaryGuards 8
+OfflineMasterKey 1
+OptimisticData 1
+ORPort 2222
+OutboundBindAddress 10.0.0.7
+OutboundBindAddressExit 10.0.0.8
+OutboundBindAddressOR 10.0.0.9
+PerConnBWBurst 10485760
+PerConnBWRate 102400
+PidFile /piddy
+ProtocolWarnings 1
+PublishHidServDescriptors 0
+PublishServerDescriptor 0
+ReachableAddresses 0.0.0.0, *:*
+ReachableDirAddresses 128.0.0.0/1
+ReachableORAddresses 128.0.0.0/8
+RejectPlaintextPorts 23
+RelayBandwidthBurst 10000
+RelayBandwidthRate 1000
+RendPostPeriod 600
+RephistTrackTime 600
+SafeLogging 0
+Schedulers Vanilla,KISTLite,Kist
+ShutdownWaitLength 10
+SigningKeyLifetime 4838400
+Socks5Proxy 128.66.99.99:99
+Socks5ProxyPassword flynn
+Socks5ProxyUsername spaceparanoids
+SocksPolicy accept 127.0.0.0/24, reject *:*
+SocksPort 9099
+SocksTimeout 600
+SSLKeyLifetime 86400
+StrictNodes 1
+SyslogIdentityTag tortor
+TestSocks 1
+TokenBucketRefillInterval 1000
+TrackHostExits www.example.com
+TrackHostExitsExpire 3600
+TruncateLogFile 1
+UnixSocksGroupWritable 1
+UpdateBridgesFromAuthority 1
+UseDefaultFallbackDirs 0
+UseGuardFraction 1
+UseMicrodescriptors 0
+VirtualAddrNetworkIPv4 18.66.0.0/16
+VirtualAddrNetworkIPv6 [ff00::]/16
+WarnPlaintextPorts 7,11,23,1001
diff --git a/src/test/conf_examples/lzma_zstd_1/expected b/src/test/conf_examples/lzma_zstd_1/expected
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/lzma_zstd_1/expected
diff --git a/src/test/conf_examples/lzma_zstd_1/expected_log b/src/test/conf_examples/lzma_zstd_1/expected_log
new file mode 100644
index 0000000000..a5531ca21e
--- /dev/null
+++ b/src/test/conf_examples/lzma_zstd_1/expected_log
@@ -0,0 +1 @@
+Tor 0.* running on .* with Libevent .*, .*, Zlib .*, Liblzma N/A, and Libzstd N/A
diff --git a/src/test/conf_examples/lzma_zstd_1/expected_log_lzma b/src/test/conf_examples/lzma_zstd_1/expected_log_lzma
new file mode 100644
index 0000000000..2947e5991b
--- /dev/null
+++ b/src/test/conf_examples/lzma_zstd_1/expected_log_lzma
@@ -0,0 +1 @@
+Tor 0.* running on .* with Libevent .*, .*, Zlib .*, Liblzma .*, and Libzstd N/A
diff --git a/src/test/conf_examples/lzma_zstd_1/expected_log_lzma_zstd b/src/test/conf_examples/lzma_zstd_1/expected_log_lzma_zstd
new file mode 100644
index 0000000000..e76e4357f8
--- /dev/null
+++ b/src/test/conf_examples/lzma_zstd_1/expected_log_lzma_zstd
@@ -0,0 +1 @@
+Tor 0.* running on .* with Libevent .*, .*, Zlib .*, Liblzma .*, and Libzstd .* \ No newline at end of file
diff --git a/src/test/conf_examples/lzma_zstd_1/expected_log_zstd b/src/test/conf_examples/lzma_zstd_1/expected_log_zstd
new file mode 100644
index 0000000000..c8b174423b
--- /dev/null
+++ b/src/test/conf_examples/lzma_zstd_1/expected_log_zstd
@@ -0,0 +1 @@
+Tor 0.* running on .* with Libevent .*, .*, Zlib .*, Liblzma N/A, and Libzstd .* \ No newline at end of file
diff --git a/src/test/conf_examples/lzma_zstd_1/expected_lzma b/src/test/conf_examples/lzma_zstd_1/expected_lzma
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/lzma_zstd_1/expected_lzma
diff --git a/src/test/conf_examples/lzma_zstd_1/expected_lzma_zstd b/src/test/conf_examples/lzma_zstd_1/expected_lzma_zstd
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/lzma_zstd_1/expected_lzma_zstd
diff --git a/src/test/conf_examples/lzma_zstd_1/expected_zstd b/src/test/conf_examples/lzma_zstd_1/expected_zstd
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/lzma_zstd_1/expected_zstd
diff --git a/src/test/conf_examples/lzma_zstd_1/torrc b/src/test/conf_examples/lzma_zstd_1/torrc
new file mode 100644
index 0000000000..f873d79028
--- /dev/null
+++ b/src/test/conf_examples/lzma_zstd_1/torrc
@@ -0,0 +1 @@
+# This test checks for the optional library list in tor's logs
diff --git a/src/test/conf_examples/missing_cl_arg/cmdline b/src/test/conf_examples/missing_cl_arg/cmdline
new file mode 100644
index 0000000000..7fc4d0a54d
--- /dev/null
+++ b/src/test/conf_examples/missing_cl_arg/cmdline
@@ -0,0 +1 @@
+--hash-password
diff --git a/src/test/conf_examples/missing_cl_arg/error b/src/test/conf_examples/missing_cl_arg/error
new file mode 100644
index 0000000000..61dbeac8aa
--- /dev/null
+++ b/src/test/conf_examples/missing_cl_arg/error
@@ -0,0 +1 @@
+Command-line option '--hash-password' with no value.
diff --git a/src/test/conf_examples/missing_cl_arg/torrc b/src/test/conf_examples/missing_cl_arg/torrc
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/missing_cl_arg/torrc
diff --git a/src/test/conf_examples/nss_1/expected b/src/test/conf_examples/nss_1/expected
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/nss_1/expected
diff --git a/src/test/conf_examples/nss_1/expected_log b/src/test/conf_examples/nss_1/expected_log
new file mode 100644
index 0000000000..32e8cfc2f8
--- /dev/null
+++ b/src/test/conf_examples/nss_1/expected_log
@@ -0,0 +1 @@
+Tor 0.* running on .* with Libevent .*, OpenSSL .*, Zlib .*, Liblzma .*, and Libzstd .*
diff --git a/src/test/conf_examples/nss_1/expected_log_nss b/src/test/conf_examples/nss_1/expected_log_nss
new file mode 100644
index 0000000000..c0fe7b003c
--- /dev/null
+++ b/src/test/conf_examples/nss_1/expected_log_nss
@@ -0,0 +1 @@
+Tor 0.* running on .* with Libevent .*, NSS .*, Zlib .*, Liblzma .*, and Libzstd .*
diff --git a/src/test/conf_examples/nss_1/expected_nss b/src/test/conf_examples/nss_1/expected_nss
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/nss_1/expected_nss
diff --git a/src/test/conf_examples/nss_1/torrc b/src/test/conf_examples/nss_1/torrc
new file mode 100644
index 0000000000..f873d79028
--- /dev/null
+++ b/src/test/conf_examples/nss_1/torrc
@@ -0,0 +1 @@
+# This test checks for the optional library list in tor's logs
diff --git a/src/test/conf_examples/obsolete_1/expected_log b/src/test/conf_examples/obsolete_1/expected_log
new file mode 100644
index 0000000000..52f6f70a2e
--- /dev/null
+++ b/src/test/conf_examples/obsolete_1/expected_log
@@ -0,0 +1 @@
+Skipping obsolete configuration option
diff --git a/src/test/conf_examples/obsolete_1/torrc b/src/test/conf_examples/obsolete_1/torrc
index 3cd9a6d777..e711fe4065 100644
--- a/src/test/conf_examples/obsolete_1/torrc
+++ b/src/test/conf_examples/obsolete_1/torrc
@@ -1,68 +1,70 @@
# These options are obsolete as of 0.4.2
-AllowDotExit
-AllowInvalidNodes
-AllowSingleHopCircuits
-AllowSingleHopExits
-AlternateHSAuthority
-AuthDirBadDir
-AuthDirBadDirCCs
-AuthDirRejectUnlisted
-AuthDirListBadDirs
-AuthDirMaxServersPerAuthAddr
-CircuitIdleTimeout
-ControlListenAddress
-DirListenAddress
-DisableIOCP
-DisableV2DirectoryInfo_
-DynamicDHGroups
-DNSListenAddress
-TestingEnableTbEmptyEvent
-ExcludeSingleHopRelays
-FallbackNetworkstatusFile
-FastFirstHopPK
-FetchV2Networkstatus
-Group
-HidServDirectoryV2
-CloseHSClientCircuitsImmediatelyOnTimeout
-CloseHSServiceRendCircuitsImmediatelyOnTimeout
-MaxOnionsPending
-NamingAuthoritativeDirectory
-NATDListenAddress
-PredictedPortsRelevanceTime
-WarnUnsafeSocks
-ORListenAddress
-PathBiasDisableRate
-PathBiasScaleFactor
-PathBiasMultFactor
-PathBiasUseCloseCounts
-PortForwarding
-PortForwardingHelper
-PreferTunneledDirConns
-RecommendedPackages
-RunTesting
-SchedulerLowWaterMark__
-SchedulerHighWaterMark__
-SchedulerMaxFlushCells__
-SocksListenAddress
-StrictEntryNodes
-StrictExitNodes
-Support022HiddenServices
-Tor2webMode
-Tor2webRendezvousPoints
-TLSECGroup
-TransListenAddress
-TunnelDirConns
-UseEntryGuardsAsDirGuards
-UseNTorHandshake
-UserspaceIOCPBuffers
-V1AuthoritativeDirectory
-V2AuthoritativeDirectory
-VoteOnHidServDirectoriesV2
-UseFilteringSSLBufferevents
-__UseFilteringSSLBufferevents
-TestingConsensusMaxDownloadTries
-ClientBootstrapConsensusMaxDownloadTries
-ClientBootstrapConsensusAuthorityOnlyMaxDownloadTries
-TestingDescriptorMaxDownloadTries
-TestingMicrodescMaxDownloadTries
-TestingCertMaxDownloadTries
+# Obsolete options without arguments, or with an empty argument,
+# are silently ignored. So we give each one of these options an argument.
+AllowDotExit 1
+AllowInvalidNodes 1
+AllowSingleHopCircuits 1
+AllowSingleHopExits 1
+AlternateHSAuthority 1
+AuthDirBadDir 1
+AuthDirBadDirCCs 1
+AuthDirRejectUnlisted 1
+AuthDirListBadDirs 1
+AuthDirMaxServersPerAuthAddr 1
+CircuitIdleTimeout 1
+ControlListenAddress 1
+DirListenAddress 1
+DisableIOCP 1
+DisableV2DirectoryInfo_ 1
+DynamicDHGroups 1
+DNSListenAddress 1
+TestingEnableTbEmptyEvent 1
+ExcludeSingleHopRelays 1
+FallbackNetworkstatusFile 1
+FastFirstHopPK 1
+FetchV2Networkstatus 1
+Group 1
+HidServDirectoryV2 1
+CloseHSClientCircuitsImmediatelyOnTimeout 1
+CloseHSServiceRendCircuitsImmediatelyOnTimeout 1
+MaxOnionsPending 1
+NamingAuthoritativeDirectory 1
+NATDListenAddress 1
+PredictedPortsRelevanceTime 1
+WarnUnsafeSocks 1
+ORListenAddress 1
+PathBiasDisableRate 1
+PathBiasScaleFactor 1
+PathBiasMultFactor 1
+PathBiasUseCloseCounts 1
+PortForwarding 1
+PortForwardingHelper 1
+PreferTunneledDirConns 1
+RecommendedPackages 1
+RunTesting 1
+SchedulerLowWaterMark__ 1
+SchedulerHighWaterMark__ 1
+SchedulerMaxFlushCells__ 1
+SocksListenAddress 1
+StrictEntryNodes 1
+StrictExitNodes 1
+Support022HiddenServices 1
+Tor2webMode 1
+Tor2webRendezvousPoints 1
+TLSECGroup 1
+TransListenAddress 1
+TunnelDirConns 1
+UseEntryGuardsAsDirGuards 1
+UseNTorHandshake 1
+UserspaceIOCPBuffers 1
+V1AuthoritativeDirectory 1
+V2AuthoritativeDirectory 1
+VoteOnHidServDirectoriesV2 1
+UseFilteringSSLBufferevents 1
+__UseFilteringSSLBufferevents 1
+TestingConsensusMaxDownloadTries 1
+ClientBootstrapConsensusMaxDownloadTries 1
+ClientBootstrapConsensusAuthorityOnlyMaxDownloadTries 1
+TestingDescriptorMaxDownloadTries 1
+TestingMicrodescMaxDownloadTries 1
+TestingCertMaxDownloadTries 1
diff --git a/src/test/conf_examples/obsolete_2/expected_log b/src/test/conf_examples/obsolete_2/expected_log
new file mode 100644
index 0000000000..2160355ee9
--- /dev/null
+++ b/src/test/conf_examples/obsolete_2/expected_log
@@ -0,0 +1 @@
+Read configuration file .*obsolete_2[./]*torrc
diff --git a/src/test/conf_examples/obsolete_2/torrc b/src/test/conf_examples/obsolete_2/torrc
index 4f78d47625..b83e7a7369 100644
--- a/src/test/conf_examples/obsolete_2/torrc
+++ b/src/test/conf_examples/obsolete_2/torrc
@@ -1,2 +1,5 @@
# This option has been obsolete for some time
+# Obsolete options without arguments, or with an empty argument,
+# are silently ignored.
AllowDotExit
+AllowInvalidNodes ""
diff --git a/src/test/conf_examples/obsolete_3/expected b/src/test/conf_examples/obsolete_3/expected
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/obsolete_3/expected
diff --git a/src/test/conf_examples/obsolete_3/expected_log b/src/test/conf_examples/obsolete_3/expected_log
new file mode 100644
index 0000000000..82d76ec818
--- /dev/null
+++ b/src/test/conf_examples/obsolete_3/expected_log
@@ -0,0 +1 @@
+Skipping obsolete configuration option "AllowDotExit"
diff --git a/src/test/conf_examples/obsolete_3/torrc b/src/test/conf_examples/obsolete_3/torrc
new file mode 100644
index 0000000000..e0efe752bf
--- /dev/null
+++ b/src/test/conf_examples/obsolete_3/torrc
@@ -0,0 +1,4 @@
+# This option has been obsolete for some time
+# Obsolete options without arguments, or with an empty argument,
+# are silently ignored. So we give this option an argument.
+AllowDotExit 1
diff --git a/src/test/conf_examples/ops_1/error_no_dirauth_relay b/src/test/conf_examples/ops_1/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/ops_1/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/ops_1/expected_log b/src/test/conf_examples/ops_1/expected_log
new file mode 100644
index 0000000000..b785d7fb52
--- /dev/null
+++ b/src/test/conf_examples/ops_1/expected_log
@@ -0,0 +1 @@
+Read configuration file .*ops_1[./]*torrc
diff --git a/src/test/conf_examples/ops_2/expected_log b/src/test/conf_examples/ops_2/expected_log
new file mode 100644
index 0000000000..17fbc3ffbf
--- /dev/null
+++ b/src/test/conf_examples/ops_2/expected_log
@@ -0,0 +1 @@
+Read configuration file .*ops_2[./]*torrc
diff --git a/src/test/conf_examples/ops_3/error_no_dirauth_relay b/src/test/conf_examples/ops_3/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/ops_3/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/ops_3/expected_log b/src/test/conf_examples/ops_3/expected_log
new file mode 100644
index 0000000000..151498f0df
--- /dev/null
+++ b/src/test/conf_examples/ops_3/expected_log
@@ -0,0 +1 @@
+Read configuration file .*ops_3[./]*torrc
diff --git a/src/test/conf_examples/ops_4/error_no_dirauth_relay b/src/test/conf_examples/ops_4/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/ops_4/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/ops_4/expected_log b/src/test/conf_examples/ops_4/expected_log
new file mode 100644
index 0000000000..7632b2290c
--- /dev/null
+++ b/src/test/conf_examples/ops_4/expected_log
@@ -0,0 +1 @@
+Read configuration file .*ops_4[./]*torrc\.defaults
diff --git a/src/test/conf_examples/ops_5/error_no_dirauth_relay b/src/test/conf_examples/ops_5/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/ops_5/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/ops_5/expected_log b/src/test/conf_examples/ops_5/expected_log
new file mode 100644
index 0000000000..ec63cb0638
--- /dev/null
+++ b/src/test/conf_examples/ops_5/expected_log
@@ -0,0 +1 @@
+Read configuration file .*ops_5[./]*torrc\.defaults
diff --git a/src/test/conf_examples/ops_6/expected_log b/src/test/conf_examples/ops_6/expected_log
new file mode 100644
index 0000000000..f9b1ca0412
--- /dev/null
+++ b/src/test/conf_examples/ops_6/expected_log
@@ -0,0 +1 @@
+Read configuration file .*ops_6[./]*torrc\.defaults
diff --git a/src/test/conf_examples/pt_01/expected b/src/test/conf_examples/pt_01/expected
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/pt_01/expected
diff --git a/src/test/conf_examples/pt_01/expected_log b/src/test/conf_examples/pt_01/expected_log
new file mode 100644
index 0000000000..65bfa7a7b7
--- /dev/null
+++ b/src/test/conf_examples/pt_01/expected_log
@@ -0,0 +1 @@
+Linelist option 'ExtORPort' has no value\. Skipping
diff --git a/src/test/conf_examples/pt_01/torrc b/src/test/conf_examples/pt_01/torrc
new file mode 100644
index 0000000000..574bb32a0d
--- /dev/null
+++ b/src/test/conf_examples/pt_01/torrc
@@ -0,0 +1,7 @@
+# Relay PT tests
+# Options from relay/transport_config.c
+# Empty linelist values are ignored with a warning
+ExtORPort
+ServerTransportPlugin
+ServerTransportListenAddr
+ServerTransportOptions
diff --git a/src/test/conf_examples/pt_02/error b/src/test/conf_examples/pt_02/error
new file mode 100644
index 0000000000..ce28eab729
--- /dev/null
+++ b/src/test/conf_examples/pt_02/error
@@ -0,0 +1 @@
+Invalid ExtORPort configuration
diff --git a/src/test/conf_examples/pt_02/expected_log_no_dirauth_relay b/src/test/conf_examples/pt_02/expected_log_no_dirauth_relay
new file mode 100644
index 0000000000..0e48dca7fd
--- /dev/null
+++ b/src/test/conf_examples/pt_02/expected_log_no_dirauth_relay
@@ -0,0 +1 @@
+Read configuration file .*pt_02[./]*torrc
diff --git a/src/test/conf_examples/pt_02/expected_no_dirauth_relay b/src/test/conf_examples/pt_02/expected_no_dirauth_relay
new file mode 100644
index 0000000000..f5cd26e6b7
--- /dev/null
+++ b/src/test/conf_examples/pt_02/expected_no_dirauth_relay
@@ -0,0 +1,8 @@
+ExtORPort illegal_hostname_chars$()^*%(%
+ServerTransportListenAddr bad
+ServerTransportListenAddr bad2 illegal_hostname_chars$()^*%(%
+ServerTransportOptions bad
+ServerTransportOptions bad2 not_kv
+ServerTransportPlugin bad
+ServerTransportPlugin bad2 exec
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_02/torrc b/src/test/conf_examples/pt_02/torrc
new file mode 100644
index 0000000000..825f2c4be4
--- /dev/null
+++ b/src/test/conf_examples/pt_02/torrc
@@ -0,0 +1,13 @@
+# Relay PT tests
+# Options from relay/transport_config.c
+# Bad options are also ignored
+# (Unless the relay module is disabled, because they are relay-only
+# options. We'll ignore all relay-only options in #32395.)
+ExtORPort illegal_hostname_chars$()^*%(%#%)#(%*
+ServerTransportPlugin bad
+ServerTransportPlugin bad2 exec
+ServerTransportPlugin bad3 exec /
+ServerTransportListenAddr bad
+ServerTransportListenAddr bad2 illegal_hostname_chars$()^*%(%#%)#(%*
+ServerTransportOptions bad
+ServerTransportOptions bad2 not_kv
diff --git a/src/test/conf_examples/pt_03/expected b/src/test/conf_examples/pt_03/expected
new file mode 100644
index 0000000000..f849f2a78f
--- /dev/null
+++ b/src/test/conf_examples/pt_03/expected
@@ -0,0 +1 @@
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_03/expected_log b/src/test/conf_examples/pt_03/expected_log
new file mode 100644
index 0000000000..285a189c28
--- /dev/null
+++ b/src/test/conf_examples/pt_03/expected_log
@@ -0,0 +1 @@
+We use pluggable transports but the Extended ORPort is disabled
diff --git a/src/test/conf_examples/pt_03/expected_log_no_dirauth_relay b/src/test/conf_examples/pt_03/expected_log_no_dirauth_relay
new file mode 100644
index 0000000000..88f4e5bdfb
--- /dev/null
+++ b/src/test/conf_examples/pt_03/expected_log_no_dirauth_relay
@@ -0,0 +1 @@
+Read configuration file .*pt_03[./]*torrc
diff --git a/src/test/conf_examples/pt_03/expected_no_dirauth_relay b/src/test/conf_examples/pt_03/expected_no_dirauth_relay
new file mode 100644
index 0000000000..f849f2a78f
--- /dev/null
+++ b/src/test/conf_examples/pt_03/expected_no_dirauth_relay
@@ -0,0 +1 @@
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_03/torrc b/src/test/conf_examples/pt_03/torrc
new file mode 100644
index 0000000000..9868c39b26
--- /dev/null
+++ b/src/test/conf_examples/pt_03/torrc
@@ -0,0 +1,4 @@
+# Relay PT tests
+# Options from relay/transport_config.c
+# Plugin, but no ExtORPort
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_04/expected b/src/test/conf_examples/pt_04/expected
new file mode 100644
index 0000000000..9087f600e0
--- /dev/null
+++ b/src/test/conf_examples/pt_04/expected
@@ -0,0 +1,3 @@
+ExtORPortCookieAuthFile /
+ExtORPort 1
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_04/expected_log b/src/test/conf_examples/pt_04/expected_log
new file mode 100644
index 0000000000..5b3ab51d25
--- /dev/null
+++ b/src/test/conf_examples/pt_04/expected_log
@@ -0,0 +1 @@
+Tor is not configured as a relay but you specified a ServerTransportPlugin line.*The ServerTransportPlugin line will be ignored
diff --git a/src/test/conf_examples/pt_04/expected_log_no_dirauth_relay b/src/test/conf_examples/pt_04/expected_log_no_dirauth_relay
new file mode 100644
index 0000000000..2b989bf320
--- /dev/null
+++ b/src/test/conf_examples/pt_04/expected_log_no_dirauth_relay
@@ -0,0 +1 @@
+Read configuration file .*pt_04[./]*torrc
diff --git a/src/test/conf_examples/pt_04/expected_no_dirauth_relay b/src/test/conf_examples/pt_04/expected_no_dirauth_relay
new file mode 100644
index 0000000000..9087f600e0
--- /dev/null
+++ b/src/test/conf_examples/pt_04/expected_no_dirauth_relay
@@ -0,0 +1,3 @@
+ExtORPortCookieAuthFile /
+ExtORPort 1
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_04/torrc b/src/test/conf_examples/pt_04/torrc
new file mode 100644
index 0000000000..18bb28f9cf
--- /dev/null
+++ b/src/test/conf_examples/pt_04/torrc
@@ -0,0 +1,6 @@
+# Relay PT tests
+# Options from relay/transport_config.c
+# Try a bad cookie auth file
+ExtORPort 1
+ExtORPortCookieAuthFile /
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_05/error_no_dirauth_relay b/src/test/conf_examples/pt_05/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/pt_05/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/pt_05/expected b/src/test/conf_examples/pt_05/expected
new file mode 100644
index 0000000000..61568bb9ac
--- /dev/null
+++ b/src/test/conf_examples/pt_05/expected
@@ -0,0 +1,4 @@
+ExtORPort 1
+Nickname Unnamed
+ORPort 2
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_05/expected_log b/src/test/conf_examples/pt_05/expected_log
new file mode 100644
index 0000000000..c05a0931d6
--- /dev/null
+++ b/src/test/conf_examples/pt_05/expected_log
@@ -0,0 +1 @@
+Your ContactInfo config option is not set
diff --git a/src/test/conf_examples/pt_05/torrc b/src/test/conf_examples/pt_05/torrc
new file mode 100644
index 0000000000..55c569bb1b
--- /dev/null
+++ b/src/test/conf_examples/pt_05/torrc
@@ -0,0 +1,6 @@
+# Relay PT tests
+# Options from relay/transport_config.c
+# Try a valid minimal config
+ORPort 2
+ExtORPort 1
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_06/expected b/src/test/conf_examples/pt_06/expected
new file mode 100644
index 0000000000..d5788b92c9
--- /dev/null
+++ b/src/test/conf_examples/pt_06/expected
@@ -0,0 +1,6 @@
+ExtORPortCookieAuthFile /
+ExtORPortCookieAuthFileGroupReadable 1
+ExtORPort 1
+ServerTransportListenAddr bad3 127.0.0.1:2
+ServerTransportOptions bad3 a=b
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_06/expected_log b/src/test/conf_examples/pt_06/expected_log
new file mode 100644
index 0000000000..5b3ab51d25
--- /dev/null
+++ b/src/test/conf_examples/pt_06/expected_log
@@ -0,0 +1 @@
+Tor is not configured as a relay but you specified a ServerTransportPlugin line.*The ServerTransportPlugin line will be ignored
diff --git a/src/test/conf_examples/pt_06/expected_log_no_dirauth_relay b/src/test/conf_examples/pt_06/expected_log_no_dirauth_relay
new file mode 100644
index 0000000000..f35a380c9f
--- /dev/null
+++ b/src/test/conf_examples/pt_06/expected_log_no_dirauth_relay
@@ -0,0 +1 @@
+Read configuration file .*pt_06[./]*torrc
diff --git a/src/test/conf_examples/pt_06/expected_no_dirauth_relay b/src/test/conf_examples/pt_06/expected_no_dirauth_relay
new file mode 100644
index 0000000000..d5788b92c9
--- /dev/null
+++ b/src/test/conf_examples/pt_06/expected_no_dirauth_relay
@@ -0,0 +1,6 @@
+ExtORPortCookieAuthFile /
+ExtORPortCookieAuthFileGroupReadable 1
+ExtORPort 1
+ServerTransportListenAddr bad3 127.0.0.1:2
+ServerTransportOptions bad3 a=b
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_06/torrc b/src/test/conf_examples/pt_06/torrc
new file mode 100644
index 0000000000..20cfc329a7
--- /dev/null
+++ b/src/test/conf_examples/pt_06/torrc
@@ -0,0 +1,9 @@
+# Relay PT tests
+# Options from relay/transport_config.c
+# Try a config with all the options
+ExtORPort 1
+ExtORPortCookieAuthFile /
+ExtORPortCookieAuthFileGroupReadable 1
+ServerTransportPlugin bad3 exec /
+ServerTransportListenAddr bad3 127.0.0.1:2
+ServerTransportOptions bad3 a=b
diff --git a/src/test/conf_examples/pt_07/error_no_dirauth_relay b/src/test/conf_examples/pt_07/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/pt_07/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/pt_07/expected b/src/test/conf_examples/pt_07/expected
new file mode 100644
index 0000000000..c3a75dc407
--- /dev/null
+++ b/src/test/conf_examples/pt_07/expected
@@ -0,0 +1,4 @@
+ExtORPort 2.2.2.2:1
+Nickname Unnamed
+ORPort 2
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_07/expected_log b/src/test/conf_examples/pt_07/expected_log
new file mode 100644
index 0000000000..5afaf02ba9
--- /dev/null
+++ b/src/test/conf_examples/pt_07/expected_log
@@ -0,0 +1 @@
+You specified a public address .* for ExtORPort
diff --git a/src/test/conf_examples/pt_07/torrc b/src/test/conf_examples/pt_07/torrc
new file mode 100644
index 0000000000..40eaf50e64
--- /dev/null
+++ b/src/test/conf_examples/pt_07/torrc
@@ -0,0 +1,6 @@
+# Relay PT tests
+# Options from relay/transport_config.c
+# Try a valid config with a risky ExtORPort address
+ORPort 2
+ExtORPort 2.2.2.2:1
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_08/error b/src/test/conf_examples/pt_08/error
new file mode 100644
index 0000000000..7931bbb4b9
--- /dev/null
+++ b/src/test/conf_examples/pt_08/error
@@ -0,0 +1 @@
+ExtORPort does not support unix sockets \ No newline at end of file
diff --git a/src/test/conf_examples/pt_08/expected_log_no_dirauth_relay b/src/test/conf_examples/pt_08/expected_log_no_dirauth_relay
new file mode 100644
index 0000000000..79dcbc10ca
--- /dev/null
+++ b/src/test/conf_examples/pt_08/expected_log_no_dirauth_relay
@@ -0,0 +1 @@
+Read configuration file .*pt_08[./]*torrc
diff --git a/src/test/conf_examples/pt_08/expected_no_dirauth_relay b/src/test/conf_examples/pt_08/expected_no_dirauth_relay
new file mode 100644
index 0000000000..9a1a9bd1e4
--- /dev/null
+++ b/src/test/conf_examples/pt_08/expected_no_dirauth_relay
@@ -0,0 +1,2 @@
+ExtORPort unix:/
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_08/torrc b/src/test/conf_examples/pt_08/torrc
new file mode 100644
index 0000000000..6f1d79d706
--- /dev/null
+++ b/src/test/conf_examples/pt_08/torrc
@@ -0,0 +1,7 @@
+# Relay PT tests
+# Options from relay/transport_config.c
+# Try an invalid config with a unix socket for ExtORPort
+# (Unless the relay module is disabled, because they are relay-only
+# options. We'll ignore all relay-only options in #32395.)
+ExtORPort unix:/
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_09/error b/src/test/conf_examples/pt_09/error
new file mode 100644
index 0000000000..882b50a7bc
--- /dev/null
+++ b/src/test/conf_examples/pt_09/error
@@ -0,0 +1 @@
+Error parsing ServerTransportListenAddr address \ No newline at end of file
diff --git a/src/test/conf_examples/pt_09/error_no_dirauth_relay b/src/test/conf_examples/pt_09/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/pt_09/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/pt_09/torrc b/src/test/conf_examples/pt_09/torrc
new file mode 100644
index 0000000000..50a8e95b95
--- /dev/null
+++ b/src/test/conf_examples/pt_09/torrc
@@ -0,0 +1,7 @@
+# Relay PT tests
+# Options from relay/transport_config.c
+# Try a valid minimal config, with a bad ServerTransportListenAddr
+ORPort 2
+ExtORPort 1
+ServerTransportPlugin bad3 exec /
+ServerTransportListenAddr bad3 [aaaa::bbbb:ccccc]
diff --git a/src/test/conf_examples/relay_01/expected b/src/test/conf_examples/relay_01/expected
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/relay_01/expected
diff --git a/src/test/conf_examples/relay_01/expected_log b/src/test/conf_examples/relay_01/expected_log
new file mode 100644
index 0000000000..32e8c99d27
--- /dev/null
+++ b/src/test/conf_examples/relay_01/expected_log
@@ -0,0 +1 @@
+Linelist option 'ORPort' has no value\. Skipping
diff --git a/src/test/conf_examples/relay_01/torrc b/src/test/conf_examples/relay_01/torrc
new file mode 100644
index 0000000000..da3e85b427
--- /dev/null
+++ b/src/test/conf_examples/relay_01/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Empty linelist values are ignored with a warning
+ORPort
+DirPort
diff --git a/src/test/conf_examples/relay_02/error b/src/test/conf_examples/relay_02/error
new file mode 100644
index 0000000000..dd87d9f7e2
--- /dev/null
+++ b/src/test/conf_examples/relay_02/error
@@ -0,0 +1 @@
+Unrecognized value bad
diff --git a/src/test/conf_examples/relay_02/error_no_dirauth_relay b/src/test/conf_examples/relay_02/error_no_dirauth_relay
new file mode 100644
index 0000000000..dd87d9f7e2
--- /dev/null
+++ b/src/test/conf_examples/relay_02/error_no_dirauth_relay
@@ -0,0 +1 @@
+Unrecognized value bad
diff --git a/src/test/conf_examples/relay_02/torrc b/src/test/conf_examples/relay_02/torrc
new file mode 100644
index 0000000000..3eaa4403a9
--- /dev/null
+++ b/src/test/conf_examples/relay_02/torrc
@@ -0,0 +1,7 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Bad options are also ignored
+ORPort illegal_hostname_chars$()^*%(%#%)#(%*
+DirPort illegal_hostname_chars$()^*%(%#%)#(%*
+DirCache bad
+BridgeRelay bad
diff --git a/src/test/conf_examples/relay_03/error_no_dirauth_relay b/src/test/conf_examples/relay_03/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_03/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_03/expected b/src/test/conf_examples/relay_03/expected
new file mode 100644
index 0000000000..15056a8d1f
--- /dev/null
+++ b/src/test/conf_examples/relay_03/expected
@@ -0,0 +1,2 @@
+DirPort 1
+ORPort 0
diff --git a/src/test/conf_examples/relay_03/expected_log b/src/test/conf_examples/relay_03/expected_log
new file mode 100644
index 0000000000..46ab723e4a
--- /dev/null
+++ b/src/test/conf_examples/relay_03/expected_log
@@ -0,0 +1 @@
+Read configuration file .*relay_03[./]*torrc
diff --git a/src/test/conf_examples/relay_03/torrc b/src/test/conf_examples/relay_03/torrc
new file mode 100644
index 0000000000..fd7da7bb95
--- /dev/null
+++ b/src/test/conf_examples/relay_03/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# DirPort, but no ORPort
+ORPort 0
+DirPort 1
diff --git a/src/test/conf_examples/relay_04/error_no_dirauth_relay b/src/test/conf_examples/relay_04/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_04/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_04/expected b/src/test/conf_examples/relay_04/expected
new file mode 100644
index 0000000000..1d25374ed1
--- /dev/null
+++ b/src/test/conf_examples/relay_04/expected
@@ -0,0 +1,2 @@
+Nickname Unnamed
+ORPort 1
diff --git a/src/test/conf_examples/relay_04/expected_log b/src/test/conf_examples/relay_04/expected_log
new file mode 100644
index 0000000000..c05a0931d6
--- /dev/null
+++ b/src/test/conf_examples/relay_04/expected_log
@@ -0,0 +1 @@
+Your ContactInfo config option is not set
diff --git a/src/test/conf_examples/relay_04/torrc b/src/test/conf_examples/relay_04/torrc
new file mode 100644
index 0000000000..ff08b2376b
--- /dev/null
+++ b/src/test/conf_examples/relay_04/torrc
@@ -0,0 +1,4 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Try a valid minimal config
+ORPort 1
diff --git a/src/test/conf_examples/relay_05/error_no_dirauth_relay b/src/test/conf_examples/relay_05/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_05/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_05/expected b/src/test/conf_examples/relay_05/expected
new file mode 100644
index 0000000000..ae58cee1af
--- /dev/null
+++ b/src/test/conf_examples/relay_05/expected
@@ -0,0 +1,3 @@
+DirPort 2
+Nickname Unnamed
+ORPort 1
diff --git a/src/test/conf_examples/relay_05/expected_log b/src/test/conf_examples/relay_05/expected_log
new file mode 100644
index 0000000000..483c2e2aae
--- /dev/null
+++ b/src/test/conf_examples/relay_05/expected_log
@@ -0,0 +1 @@
+Read configuration file .*relay_05[./]*torrc
diff --git a/src/test/conf_examples/relay_05/torrc b/src/test/conf_examples/relay_05/torrc
new file mode 100644
index 0000000000..faeaad32a0
--- /dev/null
+++ b/src/test/conf_examples/relay_05/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Try a valid minimal directory mirror config
+ORPort 1
+DirPort 2
diff --git a/src/test/conf_examples/relay_06/error_no_dirauth_relay b/src/test/conf_examples/relay_06/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_06/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_06/expected b/src/test/conf_examples/relay_06/expected
new file mode 100644
index 0000000000..904c7339e0
--- /dev/null
+++ b/src/test/conf_examples/relay_06/expected
@@ -0,0 +1,3 @@
+BridgeRelay 1
+Nickname Unnamed
+ORPort 1
diff --git a/src/test/conf_examples/relay_06/expected_log b/src/test/conf_examples/relay_06/expected_log
new file mode 100644
index 0000000000..70eb18df19
--- /dev/null
+++ b/src/test/conf_examples/relay_06/expected_log
@@ -0,0 +1 @@
+Read configuration file .*relay_06[./]*torrc
diff --git a/src/test/conf_examples/relay_06/torrc b/src/test/conf_examples/relay_06/torrc
new file mode 100644
index 0000000000..baeae8df5d
--- /dev/null
+++ b/src/test/conf_examples/relay_06/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Try a valid minimal bridge config
+ORPort 1
+BridgeRelay 1
diff --git a/src/test/conf_examples/relay_07/error_no_dirauth_relay b/src/test/conf_examples/relay_07/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_07/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_07/expected b/src/test/conf_examples/relay_07/expected
new file mode 100644
index 0000000000..79fa3e5a47
--- /dev/null
+++ b/src/test/conf_examples/relay_07/expected
@@ -0,0 +1,3 @@
+DirCache 0
+Nickname Unnamed
+ORPort 1
diff --git a/src/test/conf_examples/relay_07/expected_log b/src/test/conf_examples/relay_07/expected_log
new file mode 100644
index 0000000000..14729a7ab1
--- /dev/null
+++ b/src/test/conf_examples/relay_07/expected_log
@@ -0,0 +1 @@
+DirCache is disabled and we are configured as a relay
diff --git a/src/test/conf_examples/relay_07/torrc b/src/test/conf_examples/relay_07/torrc
new file mode 100644
index 0000000000..01ac138597
--- /dev/null
+++ b/src/test/conf_examples/relay_07/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Try a valid minimal non-directory cache config
+ORPort 1
+DirCache 0
diff --git a/src/test/conf_examples/relay_08/error_no_dirauth_relay b/src/test/conf_examples/relay_08/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_08/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_08/expected b/src/test/conf_examples/relay_08/expected
new file mode 100644
index 0000000000..904c7339e0
--- /dev/null
+++ b/src/test/conf_examples/relay_08/expected
@@ -0,0 +1,3 @@
+BridgeRelay 1
+Nickname Unnamed
+ORPort 1
diff --git a/src/test/conf_examples/relay_08/expected_log b/src/test/conf_examples/relay_08/expected_log
new file mode 100644
index 0000000000..b0168c803d
--- /dev/null
+++ b/src/test/conf_examples/relay_08/expected_log
@@ -0,0 +1 @@
+Read configuration file .*relay_08[./]*torrc
diff --git a/src/test/conf_examples/relay_08/torrc b/src/test/conf_examples/relay_08/torrc
new file mode 100644
index 0000000000..9e2ff9465c
--- /dev/null
+++ b/src/test/conf_examples/relay_08/torrc
@@ -0,0 +1,6 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Try a valid config with all the bridge options
+ORPort 1
+BridgeRelay 1
+DirCache 1
diff --git a/src/test/conf_examples/relay_09/error_no_dirauth_relay b/src/test/conf_examples/relay_09/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_09/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_09/expected b/src/test/conf_examples/relay_09/expected
new file mode 100644
index 0000000000..ae58cee1af
--- /dev/null
+++ b/src/test/conf_examples/relay_09/expected
@@ -0,0 +1,3 @@
+DirPort 2
+Nickname Unnamed
+ORPort 1
diff --git a/src/test/conf_examples/relay_09/expected_log b/src/test/conf_examples/relay_09/expected_log
new file mode 100644
index 0000000000..d3ab4f6593
--- /dev/null
+++ b/src/test/conf_examples/relay_09/expected_log
@@ -0,0 +1 @@
+By default, Tor does not run as an exit relay
diff --git a/src/test/conf_examples/relay_09/torrc b/src/test/conf_examples/relay_09/torrc
new file mode 100644
index 0000000000..014eeca34b
--- /dev/null
+++ b/src/test/conf_examples/relay_09/torrc
@@ -0,0 +1,6 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Try a valid config with all the non-bridge options
+ORPort 1
+DirPort 2
+DirCache 1
diff --git a/src/test/conf_examples/relay_10/error_no_dirauth_relay b/src/test/conf_examples/relay_10/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_10/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_10/expected b/src/test/conf_examples/relay_10/expected
new file mode 100644
index 0000000000..904c7339e0
--- /dev/null
+++ b/src/test/conf_examples/relay_10/expected
@@ -0,0 +1,3 @@
+BridgeRelay 1
+Nickname Unnamed
+ORPort 1
diff --git a/src/test/conf_examples/relay_10/expected_log b/src/test/conf_examples/relay_10/expected_log
new file mode 100644
index 0000000000..5b81a904e5
--- /dev/null
+++ b/src/test/conf_examples/relay_10/expected_log
@@ -0,0 +1 @@
+Can't set a DirPort on a bridge relay
diff --git a/src/test/conf_examples/relay_10/torrc b/src/test/conf_examples/relay_10/torrc
new file mode 100644
index 0000000000..4318ebb45b
--- /dev/null
+++ b/src/test/conf_examples/relay_10/torrc
@@ -0,0 +1,7 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Try a valid config, that has a warning: Bridge, warn and disable DirPort
+ORPort 1
+DirPort 2
+DirCache 1
+BridgeRelay 1
diff --git a/src/test/conf_examples/relay_11/error b/src/test/conf_examples/relay_11/error
new file mode 100644
index 0000000000..8ed5c31bc7
--- /dev/null
+++ b/src/test/conf_examples/relay_11/error
@@ -0,0 +1 @@
+We are advertising an ORPort, but not actually listening on one
diff --git a/src/test/conf_examples/relay_11/error_no_dirauth_relay b/src/test/conf_examples/relay_11/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_11/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_11/torrc b/src/test/conf_examples/relay_11/torrc
new file mode 100644
index 0000000000..a1e13eb3ce
--- /dev/null
+++ b/src/test/conf_examples/relay_11/torrc
@@ -0,0 +1,4 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Advertising but not listening: ORPort
+ORPort 1 NoListen
diff --git a/src/test/conf_examples/relay_12/error b/src/test/conf_examples/relay_12/error
new file mode 100644
index 0000000000..57706d6a7a
--- /dev/null
+++ b/src/test/conf_examples/relay_12/error
@@ -0,0 +1 @@
+We are advertising a DirPort, but not actually listening on one
diff --git a/src/test/conf_examples/relay_12/error_no_dirauth_relay b/src/test/conf_examples/relay_12/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_12/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_12/torrc b/src/test/conf_examples/relay_12/torrc
new file mode 100644
index 0000000000..4a7d398112
--- /dev/null
+++ b/src/test/conf_examples/relay_12/torrc
@@ -0,0 +1,4 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Advertising but not listening: DirPort
+DirPort 1 NoListen
diff --git a/src/test/conf_examples/relay_13/error b/src/test/conf_examples/relay_13/error
new file mode 100644
index 0000000000..cd74247ea8
--- /dev/null
+++ b/src/test/conf_examples/relay_13/error
@@ -0,0 +1 @@
+We are listening on an ORPort, but not advertising any ORPorts
diff --git a/src/test/conf_examples/relay_13/error_no_dirauth_relay b/src/test/conf_examples/relay_13/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_13/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_13/torrc b/src/test/conf_examples/relay_13/torrc
new file mode 100644
index 0000000000..b76b72c0cc
--- /dev/null
+++ b/src/test/conf_examples/relay_13/torrc
@@ -0,0 +1,4 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Listening but not advertising: ORPort
+ORPort 1 NoAdvertise
diff --git a/src/test/conf_examples/relay_14/error_no_dirauth_relay b/src/test/conf_examples/relay_14/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_14/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_14/expected b/src/test/conf_examples/relay_14/expected
new file mode 100644
index 0000000000..31bb1c2507
--- /dev/null
+++ b/src/test/conf_examples/relay_14/expected
@@ -0,0 +1 @@
+DirPort 1 NoAdvertise
diff --git a/src/test/conf_examples/relay_14/expected_log b/src/test/conf_examples/relay_14/expected_log
new file mode 100644
index 0000000000..9b0c820211
--- /dev/null
+++ b/src/test/conf_examples/relay_14/expected_log
@@ -0,0 +1 @@
+Read configuration file .*relay_14[./]*torrc
diff --git a/src/test/conf_examples/relay_14/torrc b/src/test/conf_examples/relay_14/torrc
new file mode 100644
index 0000000000..15c6496c7e
--- /dev/null
+++ b/src/test/conf_examples/relay_14/torrc
@@ -0,0 +1,4 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Listening but not advertising: DirPort
+DirPort 1 NoAdvertise
diff --git a/src/test/conf_examples/relay_15/error b/src/test/conf_examples/relay_15/error
new file mode 100644
index 0000000000..da30f0cd14
--- /dev/null
+++ b/src/test/conf_examples/relay_15/error
@@ -0,0 +1 @@
+Can't advertise more than one DirPort
diff --git a/src/test/conf_examples/relay_15/error_no_dirauth_relay b/src/test/conf_examples/relay_15/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_15/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_15/torrc b/src/test/conf_examples/relay_15/torrc
new file mode 100644
index 0000000000..e1f78ee6a0
--- /dev/null
+++ b/src/test/conf_examples/relay_15/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Advertising more than one DirPort
+DirPort 1
+DirPort 2
diff --git a/src/test/conf_examples/relay_16/error b/src/test/conf_examples/relay_16/error
new file mode 100644
index 0000000000..37b89ee572
--- /dev/null
+++ b/src/test/conf_examples/relay_16/error
@@ -0,0 +1 @@
+Configured public relay to listen only on an IPv6 address. Tor needs to listen on an IPv4 address
diff --git a/src/test/conf_examples/relay_16/error_no_dirauth_relay b/src/test/conf_examples/relay_16/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_16/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_16/torrc b/src/test/conf_examples/relay_16/torrc
new file mode 100644
index 0000000000..e544cd87a4
--- /dev/null
+++ b/src/test/conf_examples/relay_16/torrc
@@ -0,0 +1,4 @@
+# Relay tests
+# Options from relay/relay_config.c
+# IPv6 ORPort only
+ORPort [::1]:2
diff --git a/src/test/conf_examples/relay_17/error_no_dirauth_relay b/src/test/conf_examples/relay_17/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_17/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_17/expected b/src/test/conf_examples/relay_17/expected
new file mode 100644
index 0000000000..3fb0c9db92
--- /dev/null
+++ b/src/test/conf_examples/relay_17/expected
@@ -0,0 +1,4 @@
+AccountingMax 1
+KeepBindCapabilities 0
+Nickname Unnamed
+ORPort 1
diff --git a/src/test/conf_examples/relay_17/expected_log b/src/test/conf_examples/relay_17/expected_log
new file mode 100644
index 0000000000..7711f90178
--- /dev/null
+++ b/src/test/conf_examples/relay_17/expected_log
@@ -0,0 +1 @@
+You have set AccountingMax to use hibernation
diff --git a/src/test/conf_examples/relay_17/torrc b/src/test/conf_examples/relay_17/torrc
new file mode 100644
index 0000000000..f63f36815e
--- /dev/null
+++ b/src/test/conf_examples/relay_17/torrc
@@ -0,0 +1,6 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Rebind warning
+ORPort 1
+AccountingMax 1
+KeepBindCapabilities 0
diff --git a/src/test/conf_examples/relay_18/error b/src/test/conf_examples/relay_18/error
new file mode 100644
index 0000000000..5b28d311b0
--- /dev/null
+++ b/src/test/conf_examples/relay_18/error
@@ -0,0 +1 @@
+Invalid DirPort configuration
diff --git a/src/test/conf_examples/relay_18/error_no_dirauth_relay b/src/test/conf_examples/relay_18/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_18/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_18/torrc b/src/test/conf_examples/relay_18/torrc
new file mode 100644
index 0000000000..67a0fd0dfb
--- /dev/null
+++ b/src/test/conf_examples/relay_18/torrc
@@ -0,0 +1,4 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Bad DirPort
+DirPort illegal_hostname_chars$()^*%(%#%)#(%*
diff --git a/src/test/conf_examples/relay_19/error_no_dirauth_relay b/src/test/conf_examples/relay_19/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_19/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_19/expected b/src/test/conf_examples/relay_19/expected
new file mode 100644
index 0000000000..f077169c88
--- /dev/null
+++ b/src/test/conf_examples/relay_19/expected
@@ -0,0 +1,3 @@
+Nickname Unnamed
+ORPort 1
+PublishServerDescriptor
diff --git a/src/test/conf_examples/relay_19/expected_log b/src/test/conf_examples/relay_19/expected_log
new file mode 100644
index 0000000000..17656ba2cf
--- /dev/null
+++ b/src/test/conf_examples/relay_19/expected_log
@@ -0,0 +1 @@
+Read configuration file .*relay_19[./]*torrc
diff --git a/src/test/conf_examples/relay_19/torrc b/src/test/conf_examples/relay_19/torrc
new file mode 100644
index 0000000000..fd2cd91fa5
--- /dev/null
+++ b/src/test/conf_examples/relay_19/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Minimal PublishServerDescriptor
+ORPort 1
+PublishServerDescriptor
diff --git a/src/test/conf_examples/relay_20/error b/src/test/conf_examples/relay_20/error
new file mode 100644
index 0000000000..e5a81637f8
--- /dev/null
+++ b/src/test/conf_examples/relay_20/error
@@ -0,0 +1 @@
+Unrecognized value in PublishServerDescriptor
diff --git a/src/test/conf_examples/relay_20/error_no_dirauth_relay b/src/test/conf_examples/relay_20/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_20/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_20/torrc b/src/test/conf_examples/relay_20/torrc
new file mode 100644
index 0000000000..87dd74fdc1
--- /dev/null
+++ b/src/test/conf_examples/relay_20/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Invalid PublishServerDescriptor
+ORPort 1
+PublishServerDescriptor bad
diff --git a/src/test/conf_examples/relay_21/error_no_dirauth_relay b/src/test/conf_examples/relay_21/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_21/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_21/expected b/src/test/conf_examples/relay_21/expected
new file mode 100644
index 0000000000..9bcead1402
--- /dev/null
+++ b/src/test/conf_examples/relay_21/expected
@@ -0,0 +1,3 @@
+Nickname Unnamed
+ORPort 1
+PublishServerDescriptor v1,v2,hidserv
diff --git a/src/test/conf_examples/relay_21/expected_log b/src/test/conf_examples/relay_21/expected_log
new file mode 100644
index 0000000000..ba0d56fb1c
--- /dev/null
+++ b/src/test/conf_examples/relay_21/expected_log
@@ -0,0 +1 @@
+PublishServerDescriptor v1 has no effect
diff --git a/src/test/conf_examples/relay_21/torrc b/src/test/conf_examples/relay_21/torrc
new file mode 100644
index 0000000000..97f032f626
--- /dev/null
+++ b/src/test/conf_examples/relay_21/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Ignored PublishServerDescriptor values
+ORPort 1
+PublishServerDescriptor v1,v2,hidserv
diff --git a/src/test/conf_examples/relay_22/error b/src/test/conf_examples/relay_22/error
new file mode 100644
index 0000000000..c47dd8c4c6
--- /dev/null
+++ b/src/test/conf_examples/relay_22/error
@@ -0,0 +1 @@
+Invalid BridgeDistribution value
diff --git a/src/test/conf_examples/relay_22/error_no_dirauth_relay b/src/test/conf_examples/relay_22/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_22/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_22/torrc b/src/test/conf_examples/relay_22/torrc
new file mode 100644
index 0000000000..e83c83260e
--- /dev/null
+++ b/src/test/conf_examples/relay_22/torrc
@@ -0,0 +1,6 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Bad BridgeDistribution characters
+ORPort 1
+BridgeRelay 1
+BridgeDistribution *$%()@!
diff --git a/src/test/conf_examples/relay_23/error b/src/test/conf_examples/relay_23/error
new file mode 100644
index 0000000000..f76bbe77c4
--- /dev/null
+++ b/src/test/conf_examples/relay_23/error
@@ -0,0 +1 @@
+Relays must use 'auto' for the ConnectionPadding setting
diff --git a/src/test/conf_examples/relay_23/error_no_dirauth_relay b/src/test/conf_examples/relay_23/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_23/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_23/torrc b/src/test/conf_examples/relay_23/torrc
new file mode 100644
index 0000000000..3d28a1e27c
--- /dev/null
+++ b/src/test/conf_examples/relay_23/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Relays can't set ConnectionPadding
+ORPort 1
+ConnectionPadding 1
diff --git a/src/test/conf_examples/relay_24/error b/src/test/conf_examples/relay_24/error
new file mode 100644
index 0000000000..f76bbe77c4
--- /dev/null
+++ b/src/test/conf_examples/relay_24/error
@@ -0,0 +1 @@
+Relays must use 'auto' for the ConnectionPadding setting
diff --git a/src/test/conf_examples/relay_24/error_no_dirauth_relay b/src/test/conf_examples/relay_24/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_24/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_24/torrc b/src/test/conf_examples/relay_24/torrc
new file mode 100644
index 0000000000..1206e59e09
--- /dev/null
+++ b/src/test/conf_examples/relay_24/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Relays can't set ConnectionPadding
+ORPort 1
+ConnectionPadding 0
diff --git a/src/test/conf_examples/relay_25/error b/src/test/conf_examples/relay_25/error
new file mode 100644
index 0000000000..bac681e6cc
--- /dev/null
+++ b/src/test/conf_examples/relay_25/error
@@ -0,0 +1 @@
+Relays cannot set ReducedConnectionPadding
diff --git a/src/test/conf_examples/relay_25/error_no_dirauth_relay b/src/test/conf_examples/relay_25/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_25/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_25/torrc b/src/test/conf_examples/relay_25/torrc
new file mode 100644
index 0000000000..ab862a16f3
--- /dev/null
+++ b/src/test/conf_examples/relay_25/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Relays can't set ReducedConnectionPadding 1
+ORPort 1
+ReducedConnectionPadding 1
diff --git a/src/test/conf_examples/relay_26/error b/src/test/conf_examples/relay_26/error
new file mode 100644
index 0000000000..94334935e3
--- /dev/null
+++ b/src/test/conf_examples/relay_26/error
@@ -0,0 +1 @@
+Relays cannot set CircuitPadding to 0
diff --git a/src/test/conf_examples/relay_26/error_no_dirauth_relay b/src/test/conf_examples/relay_26/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_26/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_26/torrc b/src/test/conf_examples/relay_26/torrc
new file mode 100644
index 0000000000..5dd6d68dc4
--- /dev/null
+++ b/src/test/conf_examples/relay_26/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Relays can't set CircuitPadding to 0
+ORPort 1
+CircuitPadding 0
diff --git a/src/test/conf_examples/relay_27/error b/src/test/conf_examples/relay_27/error
new file mode 100644
index 0000000000..e26ce46914
--- /dev/null
+++ b/src/test/conf_examples/relay_27/error
@@ -0,0 +1 @@
+Relays cannot set ReducedCircuitPadding
diff --git a/src/test/conf_examples/relay_27/error_no_dirauth_relay b/src/test/conf_examples/relay_27/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_27/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_27/torrc b/src/test/conf_examples/relay_27/torrc
new file mode 100644
index 0000000000..8556b2f351
--- /dev/null
+++ b/src/test/conf_examples/relay_27/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Relays can't set ReducedCircuitPadding 1
+ORPort 1
+ReducedCircuitPadding 1
diff --git a/src/test/conf_examples/relay_28/error b/src/test/conf_examples/relay_28/error
new file mode 100644
index 0000000000..3f14df975b
--- /dev/null
+++ b/src/test/conf_examples/relay_28/error
@@ -0,0 +1 @@
+SigningKeyLifetime is too short
diff --git a/src/test/conf_examples/relay_28/error_no_dirauth_relay b/src/test/conf_examples/relay_28/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_28/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_28/torrc b/src/test/conf_examples/relay_28/torrc
new file mode 100644
index 0000000000..3e2c895bb7
--- /dev/null
+++ b/src/test/conf_examples/relay_28/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Short key lifetimes
+ORPort 1
+SigningKeyLifetime 1
diff --git a/src/test/conf_examples/relay_29/error_no_dirauth_relay b/src/test/conf_examples/relay_29/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_29/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_29/expected b/src/test/conf_examples/relay_29/expected
new file mode 100644
index 0000000000..1d25374ed1
--- /dev/null
+++ b/src/test/conf_examples/relay_29/expected
@@ -0,0 +1,2 @@
+Nickname Unnamed
+ORPort 1
diff --git a/src/test/conf_examples/relay_29/expected_log b/src/test/conf_examples/relay_29/expected_log
new file mode 100644
index 0000000000..f46c609c0c
--- /dev/null
+++ b/src/test/conf_examples/relay_29/expected_log
@@ -0,0 +1 @@
+Linelist option 'MyFamily' has no value\. Skipping
diff --git a/src/test/conf_examples/relay_29/torrc b/src/test/conf_examples/relay_29/torrc
new file mode 100644
index 0000000000..4181d5acc2
--- /dev/null
+++ b/src/test/conf_examples/relay_29/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# MyFamily normalisation: empty MyFamily
+ORPort 1
+MyFamily
diff --git a/src/test/conf_failures/README b/src/test/conf_failures/README
new file mode 100644
index 0000000000..0da470eeb4
--- /dev/null
+++ b/src/test/conf_failures/README
@@ -0,0 +1,5 @@
+This directory contains typical test_parseconf.sh failure cases.
+
+If these directories are copied into conf_examples, test_parseconf.sh will
+fail. Use these failure cases to make sure test_parseconf.sh handles failures
+correctly, and produces useful output.
diff --git a/src/test/conf_failures/fail-error-success/error b/src/test/conf_failures/fail-error-success/error
new file mode 100644
index 0000000000..569a631e86
--- /dev/null
+++ b/src/test/conf_failures/fail-error-success/error
@@ -0,0 +1 @@
+Tor
diff --git a/src/test/conf_failures/fail-error-success/torrc b/src/test/conf_failures/fail-error-success/torrc
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_failures/fail-error-success/torrc
diff --git a/src/test/conf_failures/fail-error/error b/src/test/conf_failures/fail-error/error
new file mode 100644
index 0000000000..4c0be97832
--- /dev/null
+++ b/src/test/conf_failures/fail-error/error
@@ -0,0 +1 @@
+no match
diff --git a/src/test/conf_failures/fail-error/torrc b/src/test/conf_failures/fail-error/torrc
new file mode 100644
index 0000000000..bb6fe186a4
--- /dev/null
+++ b/src/test/conf_failures/fail-error/torrc
@@ -0,0 +1 @@
+bad bad bad
diff --git a/src/test/conf_failures/fail-expected-error/expected b/src/test/conf_failures/fail-expected-error/expected
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_failures/fail-expected-error/expected
diff --git a/src/test/conf_failures/fail-expected-error/torrc b/src/test/conf_failures/fail-expected-error/torrc
new file mode 100644
index 0000000000..bb6fe186a4
--- /dev/null
+++ b/src/test/conf_failures/fail-expected-error/torrc
@@ -0,0 +1 @@
+bad bad bad
diff --git a/src/test/conf_failures/fail-expected-log/expected b/src/test/conf_failures/fail-expected-log/expected
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_failures/fail-expected-log/expected
diff --git a/src/test/conf_failures/fail-expected-log/expected_log b/src/test/conf_failures/fail-expected-log/expected_log
new file mode 100644
index 0000000000..bb6fe186a4
--- /dev/null
+++ b/src/test/conf_failures/fail-expected-log/expected_log
@@ -0,0 +1 @@
+bad bad bad
diff --git a/src/test/conf_failures/fail-expected-log/torrc b/src/test/conf_failures/fail-expected-log/torrc
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_failures/fail-expected-log/torrc
diff --git a/src/test/conf_failures/fail-expected/expected b/src/test/conf_failures/fail-expected/expected
new file mode 100644
index 0000000000..67be85f127
--- /dev/null
+++ b/src/test/conf_failures/fail-expected/expected
@@ -0,0 +1 @@
+bad
diff --git a/src/test/conf_failures/fail-expected/torrc b/src/test/conf_failures/fail-expected/torrc
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_failures/fail-expected/torrc
diff --git a/src/test/ed25519_exts_ref.py b/src/test/ed25519_exts_ref.py
index 75562184b5..ae537ff15b 100644
--- a/src/test/ed25519_exts_ref.py
+++ b/src/test/ed25519_exts_ref.py
@@ -8,6 +8,11 @@
Includes self-tester and test vector generator.
"""
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import slow_ed25519
from slow_ed25519 import *
@@ -147,7 +152,7 @@ class SelfTest(unittest.TestCase):
# Check that identities match
assert(identity == identity2)
# Check that identity is the point (0,1)
- assert(identity == [0L,1L])
+ assert(identity == [0,1])
# Check identity element: a*E = E, where a is a random scalar
scalar = random_scalar(os.urandom)
@@ -181,22 +186,22 @@ BLINDING_PARAMS = [
PREFIX = "ED25519_"
def writeArray(name, array):
- print "static const char *{prefix}{name}[] = {{".format(
- prefix=PREFIX,name=name)
+ print("static const char *{prefix}{name}[] = {{".format(
+ prefix=PREFIX,name=name))
for a in array:
h = binascii.b2a_hex(a)
if len(h) > 70:
h1 = h[:70]
h2 = h[70:]
- print ' "{0}"\n "{1}",'.format(h1,h2)
+ print(' "{0}"\n "{1}",'.format(h1,h2))
else:
- print ' "{0}",'.format(h)
- print "};\n"
+ print(' "{0}",'.format(h))
+ print("};\n")
def comment(text, initial="/**"):
- print initial
- print textwrap.fill(text,initial_indent=" * ",subsequent_indent=" * ")
- print " */"
+ print(initial)
+ print(textwrap.fill(text,initial_indent=" * ",subsequent_indent=" * "))
+ print(" */")
def makeTestVectors():
comment("""Test vectors for our ed25519 implementation and related
@@ -252,7 +257,7 @@ def makeTestVectors():
if __name__ == '__main__':
import sys
if len(sys.argv) == 1 or sys.argv[1] not in ("SelfTest", "MakeVectors"):
- print "You should specify one of 'SelfTest' or 'MakeVectors'"
+ print("You should specify one of 'SelfTest' or 'MakeVectors'")
sys.exit(1)
if sys.argv[1] == 'SelfTest':
unittest.main()
diff --git a/src/test/fakechans.h b/src/test/fakechans.h
index 4006e1bec4..c3accb1637 100644
--- a/src/test/fakechans.h
+++ b/src/test/fakechans.h
@@ -1,4 +1,4 @@
- /* Copyright (c) 2014-2019, The Tor Project, Inc. */
+ /* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_FAKECHANS_H
diff --git a/src/test/fakecircs.c b/src/test/fakecircs.c
new file mode 100644
index 0000000000..4d5b97197e
--- /dev/null
+++ b/src/test/fakecircs.c
@@ -0,0 +1,91 @@
+/* Copyright (c) 2019-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file fakecircs.c
+ * \brief Fake circuits API for unit test.
+ **/
+
+#define CIRCUITBUILD_PRIVATE
+#define CIRCUITLIST_PRIVATE
+#define CRYPT_PATH_PRIVATE
+
+#include "core/or/or.h"
+
+#include "core/crypto/relay_crypto.h"
+#include "core/or/channel.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuitpadding.h"
+#include "core/or/crypt_path.h"
+#include "core/or/relay.h"
+#include "core/or/relay_crypto_st.h"
+
+#include "test/fakecircs.h"
+
+/** Return newly allocated OR circuit using the given nchan and pchan. It must
+ * be freed with the free_fake_orcirc(). */
+or_circuit_t *
+new_fake_orcirc(channel_t *nchan, channel_t *pchan)
+{
+ or_circuit_t *orcirc = NULL;
+ circuit_t *circ = NULL;
+ crypt_path_t tmp_cpath;
+ char whatevs_key[CPATH_KEY_MATERIAL_LEN];
+
+ orcirc = tor_malloc_zero(sizeof(*orcirc));
+ circ = &(orcirc->base_);
+ circ->magic = OR_CIRCUIT_MAGIC;
+
+ circuit_set_n_circid_chan(circ, get_unique_circ_id_by_chan(nchan), nchan);
+ cell_queue_init(&(circ->n_chan_cells));
+
+ circ->n_hop = NULL;
+ circ->streams_blocked_on_n_chan = 0;
+ circ->streams_blocked_on_p_chan = 0;
+ circ->n_delete_pending = 0;
+ circ->p_delete_pending = 0;
+ circ->received_destroy = 0;
+ circ->state = CIRCUIT_STATE_OPEN;
+ circ->purpose = CIRCUIT_PURPOSE_OR;
+ circ->package_window = CIRCWINDOW_START_MAX;
+ circ->deliver_window = CIRCWINDOW_START_MAX;
+ circ->n_chan_create_cell = NULL;
+
+ circuit_set_p_circid_chan(orcirc, get_unique_circ_id_by_chan(pchan), pchan);
+ cell_queue_init(&(orcirc->p_chan_cells));
+
+ memset(&tmp_cpath, 0, sizeof(tmp_cpath));
+ if (cpath_init_circuit_crypto(&tmp_cpath, whatevs_key,
+ sizeof(whatevs_key), 0, 0)<0) {
+ log_warn(LD_BUG,"Circuit initialization failed");
+ return NULL;
+ }
+ orcirc->crypto = tmp_cpath.pvt_crypto;
+
+ return orcirc;
+}
+
+/** Free fake OR circuit which MUST be created by new_fake_orcirc(). */
+void
+free_fake_orcirc(or_circuit_t *orcirc)
+{
+ if (!orcirc) {
+ return;
+ }
+
+ circuit_t *circ = TO_CIRCUIT(orcirc);
+
+ relay_crypto_clear(&orcirc->crypto);
+
+ circpad_circuit_free_all_machineinfos(circ);
+
+ if (orcirc->p_chan && orcirc->p_chan->cmux) {
+ circuitmux_detach_circuit(orcirc->p_chan->cmux, circ);
+ }
+ if (circ->n_chan && circ->n_chan->cmux) {
+ circuitmux_detach_circuit(circ->n_chan->cmux, circ);
+ }
+
+ tor_free_(circ);
+}
diff --git a/src/test/fakecircs.h b/src/test/fakecircs.h
new file mode 100644
index 0000000000..ed8a150a3f
--- /dev/null
+++ b/src/test/fakecircs.h
@@ -0,0 +1,17 @@
+/* Copyright (c) 2019-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file fakecircs.h
+ * \brief Declarations for fake circuits for test suite use.
+ **/
+
+#ifndef TOR_FAKECIRCS_H
+#define TOR_FAKECIRCS_H
+
+#include "core/or/or_circuit_st.h"
+
+or_circuit_t *new_fake_orcirc(channel_t *nchan, channel_t *pchan);
+void free_fake_orcirc(or_circuit_t *orcirc);
+
+#endif /* !defined(TOR_FAKECIRCS_H) */
diff --git a/src/test/fuzz/.may_include b/src/test/fuzz/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/test/fuzz/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/test/fuzz/fuzz_consensus.c b/src/test/fuzz/fuzz_consensus.c
index 656ef0bdb2..f2bf29ea78 100644
--- a/src/test/fuzz/fuzz_consensus.c
+++ b/src/test/fuzz/fuzz_consensus.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define SIGCOMMON_PRIVATE
#include "core/or/or.h"
diff --git a/src/test/fuzz/fuzz_descriptor.c b/src/test/fuzz/fuzz_descriptor.c
index 58ee3dbc35..eb4d4d507f 100644
--- a/src/test/fuzz/fuzz_descriptor.c
+++ b/src/test/fuzz/fuzz_descriptor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define SIGCOMMON_PRIVATE
#include "core/or/or.h"
diff --git a/src/test/fuzz/fuzz_diff.c b/src/test/fuzz/fuzz_diff.c
index a31445666c..9cd2116245 100644
--- a/src/test/fuzz/fuzz_diff.c
+++ b/src/test/fuzz/fuzz_diff.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONSDIFF_PRIVATE
diff --git a/src/test/fuzz/fuzz_diff_apply.c b/src/test/fuzz/fuzz_diff_apply.c
index d8a0f9e590..a819c73338 100644
--- a/src/test/fuzz/fuzz_diff_apply.c
+++ b/src/test/fuzz/fuzz_diff_apply.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONSDIFF_PRIVATE
diff --git a/src/test/fuzz/fuzz_extrainfo.c b/src/test/fuzz/fuzz_extrainfo.c
index f18bd68d65..ad21254e3e 100644
--- a/src/test/fuzz/fuzz_extrainfo.c
+++ b/src/test/fuzz/fuzz_extrainfo.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define SIGCOMMON_PRIVATE
#include "core/or/or.h"
diff --git a/src/test/fuzz/fuzz_hsdescv2.c b/src/test/fuzz/fuzz_hsdescv2.c
index 34639b237c..81d9e5f00e 100644
--- a/src/test/fuzz/fuzz_hsdescv2.c
+++ b/src/test/fuzz/fuzz_hsdescv2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
#include "feature/dirparse/unparseable.h"
diff --git a/src/test/fuzz/fuzz_hsdescv3.c b/src/test/fuzz/fuzz_hsdescv3.c
index 9d4a6dbb55..3955241389 100644
--- a/src/test/fuzz/fuzz_hsdescv3.c
+++ b/src/test/fuzz/fuzz_hsdescv3.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define HS_DESCRIPTOR_PRIVATE
diff --git a/src/test/fuzz/fuzz_http.c b/src/test/fuzz/fuzz_http.c
index 44393b3a10..a4fd182f1e 100644
--- a/src/test/fuzz/fuzz_http.c
+++ b/src/test/fuzz/fuzz_http.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/fuzz/fuzz_http_connect.c b/src/test/fuzz/fuzz_http_connect.c
index 2a597cae74..9e5a48ba4d 100644
--- a/src/test/fuzz/fuzz_http_connect.c
+++ b/src/test/fuzz/fuzz_http_connect.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/fuzz/fuzz_iptsv2.c b/src/test/fuzz/fuzz_iptsv2.c
index 76fa3c164e..bc51ffcdb8 100644
--- a/src/test/fuzz/fuzz_iptsv2.c
+++ b/src/test/fuzz/fuzz_iptsv2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
diff --git a/src/test/fuzz/fuzz_microdesc.c b/src/test/fuzz/fuzz_microdesc.c
index 28fdc5e24d..3fc709183b 100644
--- a/src/test/fuzz/fuzz_microdesc.c
+++ b/src/test/fuzz/fuzz_microdesc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
diff --git a/src/test/fuzz/fuzz_socks.c b/src/test/fuzz/fuzz_socks.c
index d6c416a0f9..4e7cb4d48d 100644
--- a/src/test/fuzz/fuzz_socks.c
+++ b/src/test/fuzz/fuzz_socks.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/fuzz/fuzz_strops.c b/src/test/fuzz/fuzz_strops.c
index 459b4e21aa..05d9101e72 100644
--- a/src/test/fuzz/fuzz_strops.c
+++ b/src/test/fuzz/fuzz_strops.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/fuzz/fuzz_vrs.c b/src/test/fuzz/fuzz_vrs.c
index 7b61b8df2d..d6e88e59e7 100644
--- a/src/test/fuzz/fuzz_vrs.c
+++ b/src/test/fuzz/fuzz_vrs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define NS_PARSE_PRIVATE
#define NETWORKSTATUS_PRIVATE
diff --git a/src/test/fuzz/fuzzing.h b/src/test/fuzz/fuzzing.h
index 2d278825ec..6cbcdc41ad 100644
--- a/src/test/fuzz/fuzzing.h
+++ b/src/test/fuzz/fuzzing.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef FUZZING_H
#define FUZZING_H
diff --git a/src/test/fuzz/fuzzing_common.c b/src/test/fuzz/fuzzing_common.c
index 604aba7a7f..d9719074ad 100644
--- a/src/test/fuzz/fuzzing_common.c
+++ b/src/test/fuzz/fuzzing_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CRYPTO_ED25519_PRIVATE
#define CONFIG_PRIVATE
diff --git a/src/test/hs_build_address.py b/src/test/hs_build_address.py
index 7ff22c3a9a..91864eabcb 100644
--- a/src/test/hs_build_address.py
+++ b/src/test/hs_build_address.py
@@ -1,3 +1,8 @@
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import sys
import hashlib
import struct
diff --git a/src/test/hs_indexes.py b/src/test/hs_indexes.py
index af0b81f8de..5c6d893a66 100644
--- a/src/test/hs_indexes.py
+++ b/src/test/hs_indexes.py
@@ -7,6 +7,11 @@
# store/fetch the descriptor on the hashring. (hs_build_hs_index()).
#
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import sys
import hashlib
import struct
diff --git a/src/test/hs_ntor_ref.py b/src/test/hs_ntor_ref.py
index 1b9772a5d6..f107cc36ca 100644
--- a/src/test/hs_ntor_ref.py
+++ b/src/test/hs_ntor_ref.py
@@ -41,6 +41,11 @@ The whole logic and concept for this test suite was taken from ntor_ref.py.
*** DO NOT USE THIS IN PRODUCTION. ***
"""
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import struct
import os, sys
import binascii
diff --git a/src/test/hs_test_helpers.c b/src/test/hs_test_helpers.c
index 0a21fe576b..e8b99aaac8 100644
--- a/src/test/hs_test_helpers.c
+++ b/src/test/hs_test_helpers.c
@@ -1,12 +1,16 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+#define HS_CLIENT_PRIVATE
+
#include "core/or/or.h"
#include "lib/crypt_ops/crypto_ed25519.h"
#include "test/test.h"
#include "feature/nodelist/torcert.h"
+#include "feature/hs/hs_client.h"
#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_service.h"
#include "test/hs_test_helpers.h"
hs_desc_intro_point_t *
@@ -53,7 +57,7 @@ hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now,
}
ret = ed25519_keypair_generate(&auth_kp, 0);
- tt_int_op(ret, ==, 0);
+ tt_int_op(ret, OP_EQ, 0);
ip->auth_key_cert = tor_cert_create(signing_kp, CERT_TYPE_AUTH_HS_IP_KEY,
&auth_kp.pubkey, now,
HS_DESC_CERT_LIFETIME,
@@ -64,7 +68,7 @@ hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now,
ip->legacy.key = crypto_pk_new();
tt_assert(ip->legacy.key);
ret = crypto_pk_generate_key(ip->legacy.key);
- tt_int_op(ret, ==, 0);
+ tt_int_op(ret, OP_EQ, 0);
ssize_t cert_len = tor_make_rsa_ed25519_crosscert(
&signing_kp->pubkey, ip->legacy.key,
now + HS_DESC_CERT_LIFETIME,
@@ -82,7 +86,7 @@ hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now,
tor_cert_t *cross_cert;
ret = curve25519_keypair_generate(&curve25519_kp, 0);
- tt_int_op(ret, ==, 0);
+ tt_int_op(ret, OP_EQ, 0);
ed25519_keypair_from_curve25519_keypair(&ed25519_kp, &signbit,
&curve25519_kp);
cross_cert = tor_cert_create(signing_kp, CERT_TYPE_CROSS_HS_IP_KEYS,
@@ -140,7 +144,7 @@ hs_helper_build_hs_desc_impl(unsigned int no_ip,
/* Setup superencrypted data section. */
ret = curve25519_keypair_generate(&auth_ephemeral_kp, 0);
- tt_int_op(ret, ==, 0);
+ tt_int_op(ret, OP_EQ, 0);
memcpy(&desc->superencrypted_data.auth_ephemeral_pubkey,
&auth_ephemeral_kp.pubkey,
sizeof(curve25519_public_key_t));
@@ -207,6 +211,35 @@ hs_helper_build_hs_desc_no_ip(const ed25519_keypair_t *signing_kp)
return hs_helper_build_hs_desc_impl(1, signing_kp);
}
+hs_descriptor_t *
+hs_helper_build_hs_desc_with_client_auth(
+ const uint8_t *descriptor_cookie,
+ const curve25519_public_key_t *client_pk,
+ const ed25519_keypair_t *signing_kp)
+{
+ curve25519_keypair_t auth_ephemeral_kp;
+ hs_descriptor_t *desc = hs_helper_build_hs_desc_impl(0, signing_kp);
+ hs_desc_authorized_client_t *desc_client;
+
+ /* The number of client authorized auth has tobe a multiple of
+ * HS_DESC_AUTH_CLIENT_MULTIPLE so remove one that we'll replace. */
+ desc_client = smartlist_get(desc->superencrypted_data.clients, 0);
+ smartlist_remove(desc->superencrypted_data.clients, desc_client);
+ hs_desc_authorized_client_free(desc_client);
+
+ desc_client = tor_malloc_zero(sizeof(hs_desc_authorized_client_t));
+
+ curve25519_keypair_generate(&auth_ephemeral_kp, 0);
+ memcpy(&desc->superencrypted_data.auth_ephemeral_pubkey,
+ &auth_ephemeral_kp.pubkey, sizeof(curve25519_public_key_t));
+
+ hs_desc_build_authorized_client(desc->subcredential, client_pk,
+ &auth_ephemeral_kp.seckey,
+ descriptor_cookie, desc_client);
+ smartlist_add(desc->superencrypted_data.clients, desc_client);
+ return desc;
+}
+
void
hs_helper_desc_equal(const hs_descriptor_t *desc1,
const hs_descriptor_t *desc2)
@@ -224,7 +257,7 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1,
tt_mem_op(desc1->plaintext_data.blinded_pubkey.pubkey, OP_EQ,
desc2->plaintext_data.blinded_pubkey.pubkey,
ED25519_PUBKEY_LEN);
- tt_u64_op(desc1->plaintext_data.revision_counter, ==,
+ tt_u64_op(desc1->plaintext_data.revision_counter, OP_EQ,
desc2->plaintext_data.revision_counter);
/* NOTE: We can't compare the encrypted blob because when encoding the
@@ -241,7 +274,7 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1,
{
tt_assert(desc1->superencrypted_data.clients);
tt_assert(desc2->superencrypted_data.clients);
- tt_int_op(smartlist_len(desc1->superencrypted_data.clients), ==,
+ tt_int_op(smartlist_len(desc1->superencrypted_data.clients), OP_EQ,
smartlist_len(desc2->superencrypted_data.clients));
for (int i=0;
i < smartlist_len(desc1->superencrypted_data.clients);
@@ -259,15 +292,15 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1,
}
/* Encrypted data section. */
- tt_uint_op(desc1->encrypted_data.create2_ntor, ==,
+ tt_uint_op(desc1->encrypted_data.create2_ntor, OP_EQ,
desc2->encrypted_data.create2_ntor);
/* Authentication type. */
- tt_int_op(!!desc1->encrypted_data.intro_auth_types, ==,
+ tt_int_op(!!desc1->encrypted_data.intro_auth_types, OP_EQ,
!!desc2->encrypted_data.intro_auth_types);
if (desc1->encrypted_data.intro_auth_types &&
desc2->encrypted_data.intro_auth_types) {
- tt_int_op(smartlist_len(desc1->encrypted_data.intro_auth_types), ==,
+ tt_int_op(smartlist_len(desc1->encrypted_data.intro_auth_types), OP_EQ,
smartlist_len(desc2->encrypted_data.intro_auth_types));
for (int i = 0;
i < smartlist_len(desc1->encrypted_data.intro_auth_types);
@@ -281,7 +314,7 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1,
{
tt_assert(desc1->encrypted_data.intro_points);
tt_assert(desc2->encrypted_data.intro_points);
- tt_int_op(smartlist_len(desc1->encrypted_data.intro_points), ==,
+ tt_int_op(smartlist_len(desc1->encrypted_data.intro_points), OP_EQ,
smartlist_len(desc2->encrypted_data.intro_points));
for (int i=0; i < smartlist_len(desc1->encrypted_data.intro_points); i++) {
hs_desc_intro_point_t *ip1 = smartlist_get(desc1->encrypted_data
@@ -296,12 +329,12 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1,
tt_mem_op(&ip1->enc_key, OP_EQ, &ip2->enc_key, CURVE25519_PUBKEY_LEN);
}
- tt_int_op(smartlist_len(ip1->link_specifiers), ==,
+ tt_int_op(smartlist_len(ip1->link_specifiers), OP_EQ,
smartlist_len(ip2->link_specifiers));
for (int j = 0; j < smartlist_len(ip1->link_specifiers); j++) {
link_specifier_t *ls1 = smartlist_get(ip1->link_specifiers, j),
*ls2 = smartlist_get(ip2->link_specifiers, j);
- tt_int_op(link_specifier_get_ls_type(ls1), ==,
+ tt_int_op(link_specifier_get_ls_type(ls1), OP_EQ,
link_specifier_get_ls_type(ls2));
switch (link_specifier_get_ls_type(ls1)) {
case LS_IPV4:
@@ -311,7 +344,7 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1,
tt_int_op(addr1, OP_EQ, addr2);
uint16_t port1 = link_specifier_get_un_ipv4_port(ls1);
uint16_t port2 = link_specifier_get_un_ipv4_port(ls2);
- tt_int_op(port1, ==, port2);
+ tt_int_op(port1, OP_EQ, port2);
}
break;
case LS_IPV6:
@@ -326,7 +359,7 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1,
link_specifier_getlen_un_ipv6_addr(ls1));
uint16_t port1 = link_specifier_get_un_ipv6_port(ls1);
uint16_t port2 = link_specifier_get_un_ipv6_port(ls2);
- tt_int_op(port1, ==, port2);
+ tt_int_op(port1, OP_EQ, port2);
}
break;
case LS_LEGACY_ID:
@@ -353,3 +386,19 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1,
;
}
+void
+hs_helper_add_client_auth(const ed25519_public_key_t *service_pk,
+ const curve25519_secret_key_t *client_sk)
+{
+ digest256map_t *client_auths = get_hs_client_auths_map();
+ if (client_auths == NULL) {
+ client_auths = digest256map_new();
+ set_hs_client_auths_map(client_auths);
+ }
+
+ hs_client_service_authorization_t *auth =
+ tor_malloc_zero(sizeof(hs_client_service_authorization_t));
+ memcpy(&auth->enc_seckey, client_sk, sizeof(curve25519_secret_key_t));
+ hs_build_address(service_pk, HS_VERSION_THREE, auth->onion_address);
+ digest256map_set(client_auths, service_pk->pubkey, auth);
+}
diff --git a/src/test/hs_test_helpers.h b/src/test/hs_test_helpers.h
index 9662a83ba8..a01fd45d63 100644
--- a/src/test/hs_test_helpers.h
+++ b/src/test/hs_test_helpers.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_HS_TEST_HELPERS_H
@@ -15,11 +15,18 @@ hs_descriptor_t *hs_helper_build_hs_desc_no_ip(
const ed25519_keypair_t *signing_kp);
hs_descriptor_t *hs_helper_build_hs_desc_with_ip(
const ed25519_keypair_t *signing_kp);
+hs_descriptor_t *hs_helper_build_hs_desc_with_client_auth(
+ const uint8_t *descriptor_cookie,
+ const curve25519_public_key_t *client_pk,
+ const ed25519_keypair_t *signing_kp);
void hs_helper_desc_equal(const hs_descriptor_t *desc1,
const hs_descriptor_t *desc2);
void
hs_helper_get_subcred_from_identity_keypair(ed25519_keypair_t *signing_kp,
uint8_t *subcred_out);
+void hs_helper_add_client_auth(const ed25519_public_key_t *service_pk,
+ const curve25519_secret_key_t *client_sk);
+
#endif /* !defined(TOR_HS_TEST_HELPERS_H) */
diff --git a/src/test/include.am b/src/test/include.am
index d8e25dea9f..90e50752ce 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -48,6 +48,11 @@ TESTSCRIPTS += src/test/test_rebind.sh
endif
endif
+if USE_PERL
+TESTSCRIPTS += \
+ scripts/maint/checkSpaceTest.sh
+endif
+
TESTS += src/test/test src/test/test-slow src/test/test-memwipe \
src/test/test_workqueue \
src/test/test_keygen.sh \
@@ -99,8 +104,10 @@ if UNITTESTS_ENABLED
# ADD_C_FILE: INSERT SOURCES HERE.
src_test_test_SOURCES += \
+ src/test/fakecircs.c \
src/test/log_test_helpers.c \
src/test/hs_test_helpers.c \
+ src/test/opts_test_helpers.c \
src/test/rend_test_helpers.c \
src/test/resolve_test_helpers.c \
src/test/rng_test_helpers.c \
@@ -122,6 +129,7 @@ src_test_test_SOURCES += \
src/test/test_checkdir.c \
src/test/test_circuitlist.c \
src/test/test_circuitmux.c \
+ src/test/test_circuitmux_ewma.c \
src/test/test_circuitbuild.c \
src/test/test_circuituse.c \
src/test/test_circuitstats.c \
@@ -175,6 +183,7 @@ src_test_test_SOURCES += \
src/test/test_oom.c \
src/test/test_oos.c \
src/test/test_options.c \
+ src/test/test_options_act.c \
src/test/test_pem.c \
src/test/test_periodic_event.c \
src/test/test_policy.c \
@@ -182,6 +191,7 @@ src_test_test_SOURCES += \
src/test/test_process_descs.c \
src/test/test_prob_distr.c \
src/test/test_procmon.c \
+ src/test/test_proto_haproxy.c \
src/test/test_proto_http.c \
src/test/test_proto_misc.c \
src/test/test_protover.c \
@@ -201,6 +211,7 @@ src_test_test_SOURCES += \
src/test/test_sendme.c \
src/test/test_shared_random.c \
src/test/test_socks.c \
+ src/test/test_stats.c \
src/test/test_status.c \
src/test/test_storagedir.c \
src/test/test_threads.c \
@@ -339,8 +350,10 @@ src_test_test_timers_LDFLAGS = $(src_test_test_LDFLAGS)
# ADD_C_FILE: INSERT HEADERS HERE.
noinst_HEADERS+= \
src/test/fakechans.h \
+ src/test/fakecircs.h \
src/test/hs_test_helpers.h \
src/test/log_test_helpers.h \
+ src/test/opts_test_helpers.h \
src/test/rend_test_helpers.h \
src/test/resolve_test_helpers.h \
src/test/rng_test_helpers.h \
diff --git a/src/test/log_test_helpers.c b/src/test/log_test_helpers.c
index 03c52dd6bd..5e60d6b282 100644
--- a/src/test/log_test_helpers.c
+++ b/src/test/log_test_helpers.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2019, The Tor Project, Inc. */
+/* Copyright (c) 2015-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define LOG_PRIVATE
#include "lib/log/log.h"
diff --git a/src/test/log_test_helpers.h b/src/test/log_test_helpers.h
index 5d1c3c1914..e2ddf09466 100644
--- a/src/test/log_test_helpers.h
+++ b/src/test/log_test_helpers.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
diff --git a/src/test/ntor_ref.py b/src/test/ntor_ref.py
index 204f05e2ad..e3307430e1 100755
--- a/src/test/ntor_ref.py
+++ b/src/test/ntor_ref.py
@@ -27,6 +27,11 @@ commands:
"""
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import binascii
try:
import curve25519
@@ -99,7 +104,7 @@ else:
def int2byte(i):
return bytes([i])
-def kdf_rfc5869(key, salt, info, n):
+def kdf_rfc5869(key, salt, info, n):
prk = HMAC(key=salt, msg=key)
diff --git a/src/test/ope_ref.py b/src/test/ope_ref.py
index b2f7012563..61a86b57bb 100644
--- a/src/test/ope_ref.py
+++ b/src/test/ope_ref.py
@@ -4,6 +4,11 @@
# Reference implementation for our rudimentary OPE code, used to
# generate test vectors. See crypto_ope.c for more details.
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives.ciphers.algorithms import AES
from cryptography.hazmat.backends import default_backend
diff --git a/src/test/opts_test_helpers.c b/src/test/opts_test_helpers.c
new file mode 100644
index 0000000000..619ca40733
--- /dev/null
+++ b/src/test/opts_test_helpers.c
@@ -0,0 +1,38 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file opts_testing_helpers.c
+ * @brief Helper functions to access module-specific config options.
+ **/
+
+#include "orconfig.h"
+#include "test/opts_test_helpers.h"
+
+#define CONFIG_PRIVATE
+#include "core/or/or.h"
+#include "lib/confmgt/confmgt.h"
+#include "app/main/subsysmgr.h"
+#include "app/config/config.h"
+
+#include "lib/crypt_ops/crypto_sys.h"
+#include "feature/dirauth/dirauth_sys.h"
+
+struct dirauth_options_t *
+get_dirauth_options(struct or_options_t *opt)
+{
+ int idx = subsystems_get_options_idx(&sys_dirauth);
+ tor_assert(idx >= 0);
+ return config_mgr_get_obj_mutable(get_options_mgr(), opt, idx);
+}
+
+struct crypto_options_t *
+get_crypto_options(struct or_options_t *opt)
+{
+ int idx = subsystems_get_options_idx(&sys_crypto);
+ tor_assert(idx >= 0);
+ return config_mgr_get_obj_mutable(get_options_mgr(), opt, idx);
+}
diff --git a/src/test/opts_test_helpers.h b/src/test/opts_test_helpers.h
new file mode 100644
index 0000000000..f925194e63
--- /dev/null
+++ b/src/test/opts_test_helpers.h
@@ -0,0 +1,22 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file opts_testing_helpers.h
+ * @brief Header for test/opts_test_helpers.c
+ **/
+
+#ifndef TOR_TEST_OPTS_TESTING_HELPERS_H
+#define TOR_TEST_OPTS_TESTING_HELPERS_H
+
+struct crypto_options_t;
+struct dirauth_options_t;
+struct or_options_t;
+
+struct crypto_options_t *get_crypto_options(struct or_options_t *opt);
+struct dirauth_options_t *get_dirauth_options(struct or_options_t *opt);
+
+#endif /* !defined(TOR_TEST_OPTS_TESTING_HELPERS_H) */
diff --git a/src/test/prob_distr_mpfr_ref.c b/src/test/prob_distr_mpfr_ref.c
index 425733dc1b..de4179c4e0 100644
--- a/src/test/prob_distr_mpfr_ref.c
+++ b/src/test/prob_distr_mpfr_ref.c
@@ -1,4 +1,4 @@
-/* Copyright 2012-2019, The Tor Project, Inc
+/* Copyright 2012-2020, The Tor Project, Inc
* See LICENSE for licensing information */
/** prob_distr_mpfr_ref.c
diff --git a/src/test/ptr_helpers.c b/src/test/ptr_helpers.c
index a55ab437fa..0e0995df7c 100644
--- a/src/test/ptr_helpers.c
+++ b/src/test/ptr_helpers.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "test/ptr_helpers.h"
diff --git a/src/test/ptr_helpers.h b/src/test/ptr_helpers.h
index 7349bddd51..0999fdf5d2 100644
--- a/src/test/ptr_helpers.h
+++ b/src/test/ptr_helpers.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_PTR_HELPERS_H
diff --git a/src/test/rend_test_helpers.c b/src/test/rend_test_helpers.c
index f12d193cc5..61bacb4d2e 100644
--- a/src/test/rend_test_helpers.c
+++ b/src/test/rend_test_helpers.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
diff --git a/src/test/rend_test_helpers.h b/src/test/rend_test_helpers.h
index c10da52cd7..b1078ce866 100644
--- a/src/test/rend_test_helpers.h
+++ b/src/test/rend_test_helpers.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
diff --git a/src/test/resolve_test_helpers.c b/src/test/resolve_test_helpers.c
index 73ea730149..ed5853c359 100644
--- a/src/test/resolve_test_helpers.c
+++ b/src/test/resolve_test_helpers.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/resolve_test_helpers.h b/src/test/resolve_test_helpers.h
index e7d2e29373..ca642d6c63 100644
--- a/src/test/resolve_test_helpers.h
+++ b/src/test/resolve_test_helpers.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/rng_test_helpers.c b/src/test/rng_test_helpers.c
index 7024fb5793..b7d7cb0dfa 100644
--- a/src/test/rng_test_helpers.c
+++ b/src/test/rng_test_helpers.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/rng_test_helpers.h b/src/test/rng_test_helpers.h
index d7925148ae..6fcdaa2653 100644
--- a/src/test/rng_test_helpers.h
+++ b/src/test/rng_test_helpers.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_RNG_TEST_HELPERS_H
diff --git a/src/test/slow_ed25519.py b/src/test/slow_ed25519.py
index f44708b200..afad678000 100644
--- a/src/test/slow_ed25519.py
+++ b/src/test/slow_ed25519.py
@@ -8,6 +8,11 @@
#
# Don't edit this file. Mess with ed25519_ref.py
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import hashlib
b = 256
diff --git a/src/test/slownacl_curve25519.py b/src/test/slownacl_curve25519.py
index 4dabab61b6..0cafe0e71f 100644
--- a/src/test/slownacl_curve25519.py
+++ b/src/test/slownacl_curve25519.py
@@ -6,10 +6,15 @@
# Nick got the slownacl source from:
# https://github.com/mdempsky/dnscurve/tree/master/slownacl
-__all__ = ['smult_curve25519_base', 'smult_curve25519']
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
import sys
+__all__ = ['smult_curve25519_base', 'smult_curve25519']
+
P = 2 ** 255 - 19
A = 486662
diff --git a/src/test/sr_commit_calc_ref.py b/src/test/sr_commit_calc_ref.py
index 45e629cfb0..c4cb72d87f 100644
--- a/src/test/sr_commit_calc_ref.py
+++ b/src/test/sr_commit_calc_ref.py
@@ -12,6 +12,11 @@
# COMMIT = base64-encode( TIMESTAMP || H(REVEAL) )
#
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import sys
import hashlib
import struct
diff --git a/src/test/sr_srv_calc_ref.py b/src/test/sr_srv_calc_ref.py
index 492ca62b15..a3752b15cc 100644
--- a/src/test/sr_srv_calc_ref.py
+++ b/src/test/sr_srv_calc_ref.py
@@ -10,6 +10,11 @@
# HASHED_REVEALS | previous_SRV)
#
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import sys
import hashlib
import struct
diff --git a/src/test/test-memwipe.c b/src/test/test-memwipe.c
index 3f952e484f..4faf7bc5a1 100644
--- a/src/test/test-memwipe.c
+++ b/src/test/test-memwipe.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2019, The Tor Project, Inc. */
+/* Copyright (c) 2015-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test-process.c b/src/test/test-process.c
index eb28ad90e9..f5a1f1a54e 100644
--- a/src/test/test-process.c
+++ b/src/test/test-process.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2019, The Tor Project, Inc. */
+/* Copyright (c) 2011-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test-timers.c b/src/test/test-timers.c
index c80fb1e305..18e2191a09 100644
--- a/src/test/test-timers.c
+++ b/src/test/test-timers.c
@@ -1,4 +1,4 @@
-/* Copyright 2016-2019, The Tor Project, Inc. */
+/* Copyright 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -59,7 +59,7 @@ main(int argc, char **argv)
{
(void)argc;
(void)argv;
- tor_libevent_cfg cfg;
+ tor_libevent_cfg_t cfg;
memset(&cfg, 0, sizeof(cfg));
tor_libevent_initialize(&cfg);
timers_initialize();
diff --git a/src/test/test.c b/src/test/test.c
index 6dbec26fa8..1742f1d952 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -55,7 +55,6 @@
#include "core/crypto/onion_fast.h"
#include "core/crypto/onion_tap.h"
#include "core/or/policies.h"
-#include "feature/stats/rephist.h"
#include "app/config/statefile.h"
#include "lib/crypt_ops/crypto_curve25519.h"
@@ -639,166 +638,6 @@ test_rend_fns(void *arg)
tor_free(intro_points_encrypted);
}
-/** Run unit tests for stats code. */
-static void
-test_stats(void *arg)
-{
- time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
- char *s = NULL;
- int i;
-
- /* Start with testing exit port statistics; we shouldn't collect exit
- * stats without initializing them. */
- (void)arg;
- rep_hist_note_exit_stream_opened(80);
- rep_hist_note_exit_bytes(80, 100, 10000);
- s = rep_hist_format_exit_stats(now + 86400);
- tt_ptr_op(s, OP_EQ, NULL);
-
- /* Initialize stats, note some streams and bytes, and generate history
- * string. */
- rep_hist_exit_stats_init(now);
- rep_hist_note_exit_stream_opened(80);
- rep_hist_note_exit_bytes(80, 100, 10000);
- rep_hist_note_exit_stream_opened(443);
- rep_hist_note_exit_bytes(443, 100, 10000);
- rep_hist_note_exit_bytes(443, 100, 10000);
- s = rep_hist_format_exit_stats(now + 86400);
- tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n"
- "exit-kibibytes-written 80=1,443=1,other=0\n"
- "exit-kibibytes-read 80=10,443=20,other=0\n"
- "exit-streams-opened 80=4,443=4,other=0\n",OP_EQ, s);
- tor_free(s);
-
- /* Add a few bytes on 10 more ports and ensure that only the top 10
- * ports are contained in the history string. */
- for (i = 50; i < 60; i++) {
- rep_hist_note_exit_bytes(i, i, i);
- rep_hist_note_exit_stream_opened(i);
- }
- s = rep_hist_format_exit_stats(now + 86400);
- tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n"
- "exit-kibibytes-written 52=1,53=1,54=1,55=1,56=1,57=1,58=1,"
- "59=1,80=1,443=1,other=1\n"
- "exit-kibibytes-read 52=1,53=1,54=1,55=1,56=1,57=1,58=1,"
- "59=1,80=10,443=20,other=1\n"
- "exit-streams-opened 52=4,53=4,54=4,55=4,56=4,57=4,58=4,"
- "59=4,80=4,443=4,other=4\n",OP_EQ, s);
- tor_free(s);
-
- /* Stop collecting stats, add some bytes, and ensure we don't generate
- * a history string. */
- rep_hist_exit_stats_term();
- rep_hist_note_exit_bytes(80, 100, 10000);
- s = rep_hist_format_exit_stats(now + 86400);
- tt_ptr_op(s, OP_EQ, NULL);
-
- /* Re-start stats, add some bytes, reset stats, and see what history we
- * get when observing no streams or bytes at all. */
- rep_hist_exit_stats_init(now);
- rep_hist_note_exit_stream_opened(80);
- rep_hist_note_exit_bytes(80, 100, 10000);
- rep_hist_reset_exit_stats(now);
- s = rep_hist_format_exit_stats(now + 86400);
- tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n"
- "exit-kibibytes-written other=0\n"
- "exit-kibibytes-read other=0\n"
- "exit-streams-opened other=0\n",OP_EQ, s);
- tor_free(s);
-
- /* Continue with testing connection statistics; we shouldn't collect
- * conn stats without initializing them. */
- rep_hist_note_or_conn_bytes(1, 20, 400, now);
- s = rep_hist_format_conn_stats(now + 86400);
- tt_ptr_op(s, OP_EQ, NULL);
-
- /* Initialize stats, note bytes, and generate history string. */
- rep_hist_conn_stats_init(now);
- rep_hist_note_or_conn_bytes(1, 30000, 400000, now);
- rep_hist_note_or_conn_bytes(1, 30000, 400000, now + 5);
- rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10);
- rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
- s = rep_hist_format_conn_stats(now + 86400);
- tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,1,0\n",OP_EQ, s);
- tor_free(s);
-
- /* Stop collecting stats, add some bytes, and ensure we don't generate
- * a history string. */
- rep_hist_conn_stats_term();
- rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
- s = rep_hist_format_conn_stats(now + 86400);
- tt_ptr_op(s, OP_EQ, NULL);
-
- /* Re-start stats, add some bytes, reset stats, and see what history we
- * get when observing no bytes at all. */
- rep_hist_conn_stats_init(now);
- rep_hist_note_or_conn_bytes(1, 30000, 400000, now);
- rep_hist_note_or_conn_bytes(1, 30000, 400000, now + 5);
- rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10);
- rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
- rep_hist_reset_conn_stats(now);
- s = rep_hist_format_conn_stats(now + 86400);
- tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n",OP_EQ, s);
- tor_free(s);
-
- /* Continue with testing buffer statistics; we shouldn't collect buffer
- * stats without initializing them. */
- rep_hist_add_buffer_stats(2.0, 2.0, 20);
- s = rep_hist_format_buffer_stats(now + 86400);
- tt_ptr_op(s, OP_EQ, NULL);
-
- /* Initialize stats, add statistics for a single circuit, and generate
- * the history string. */
- rep_hist_buffer_stats_init(now);
- rep_hist_add_buffer_stats(2.0, 2.0, 20);
- s = rep_hist_format_buffer_stats(now + 86400);
- tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
- "cell-processed-cells 20,0,0,0,0,0,0,0,0,0\n"
- "cell-queued-cells 2.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,"
- "0.00,0.00\n"
- "cell-time-in-queue 2,0,0,0,0,0,0,0,0,0\n"
- "cell-circuits-per-decile 1\n",OP_EQ, s);
- tor_free(s);
-
- /* Add nineteen more circuit statistics to the one that's already in the
- * history to see that the math works correctly. */
- for (i = 21; i < 30; i++)
- rep_hist_add_buffer_stats(2.0, 2.0, i);
- for (i = 20; i < 30; i++)
- rep_hist_add_buffer_stats(3.5, 3.5, i);
- s = rep_hist_format_buffer_stats(now + 86400);
- tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
- "cell-processed-cells 29,28,27,26,25,24,23,22,21,20\n"
- "cell-queued-cells 2.75,2.75,2.75,2.75,2.75,2.75,2.75,2.75,"
- "2.75,2.75\n"
- "cell-time-in-queue 3,3,3,3,3,3,3,3,3,3\n"
- "cell-circuits-per-decile 2\n",OP_EQ, s);
- tor_free(s);
-
- /* Stop collecting stats, add statistics for one circuit, and ensure we
- * don't generate a history string. */
- rep_hist_buffer_stats_term();
- rep_hist_add_buffer_stats(2.0, 2.0, 20);
- s = rep_hist_format_buffer_stats(now + 86400);
- tt_ptr_op(s, OP_EQ, NULL);
-
- /* Re-start stats, add statistics for one circuit, reset stats, and make
- * sure that the history has all zeros. */
- rep_hist_buffer_stats_init(now);
- rep_hist_add_buffer_stats(2.0, 2.0, 20);
- rep_hist_reset_buffer_stats(now);
- s = rep_hist_format_buffer_stats(now + 86400);
- tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
- "cell-processed-cells 0,0,0,0,0,0,0,0,0,0\n"
- "cell-queued-cells 0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,"
- "0.00,0.00\n"
- "cell-time-in-queue 0,0,0,0,0,0,0,0,0,0\n"
- "cell-circuits-per-decile 0\n",OP_EQ, s);
-
- done:
- tor_free(s);
-}
-
#define ENT(name) \
{ #name, test_ ## name , 0, NULL, NULL }
#define FORK(name) \
@@ -812,7 +651,6 @@ static struct testcase_t test_array[] = {
{ "fast_handshake", test_fast_handshake, 0, NULL, NULL },
FORK(circuit_timeout),
FORK(rend_fns),
- FORK(stats),
END_OF_TESTCASES
};
@@ -836,6 +674,7 @@ struct testgroup_t testgroups[] = {
{ "circuitpadding/", circuitpadding_tests },
{ "circuitlist/", circuitlist_tests },
{ "circuitmux/", circuitmux_tests },
+ { "circuitmux_ewma/", circuitmux_ewma_tests },
{ "circuitstats/", circuitstats_tests },
{ "circuituse/", circuituse_tests },
{ "compat/libevent/", compat_libevent_tests },
@@ -893,12 +732,14 @@ struct testgroup_t testgroups[] = {
{ "oom/", oom_tests },
{ "oos/", oos_tests },
{ "options/", options_tests },
+ { "options/act/", options_act_tests },
{ "parsecommon/", parsecommon_tests },
{ "periodic-event/" , periodic_event_tests },
{ "policy/" , policy_tests },
{ "prob_distr/", prob_distr_tests },
{ "procmon/", procmon_tests },
{ "process/", process_tests },
+ { "proto/haproxy/", proto_haproxy_tests },
{ "proto/http/", proto_http_tests },
{ "proto/misc/", proto_misc_tests },
{ "protover/", protover_tests },
@@ -918,6 +759,7 @@ struct testgroup_t testgroups[] = {
{ "sendme/", sendme_tests },
{ "shared-random/", sr_tests },
{ "socks/", socks_tests },
+ { "stats/", stats_tests },
{ "status/" , status_tests },
{ "storagedir/", storagedir_tests },
{ "token_bucket/", token_bucket_tests },
diff --git a/src/test/test.h b/src/test/test.h
index 76c4c0ec75..63e2faff95 100644
--- a/src/test/test.h
+++ b/src/test/test.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2003, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_TEST_H
@@ -37,6 +37,7 @@
#define test_memeq_hex(expr1, hex) test_mem_op_hex(expr1, OP_EQ, hex)
+#ifndef COCCI
#define tt_double_op(a,op,b) \
tt_assert_test_type(a,b,#a" "#op" "#b,double,(val1_ op val2_),"%g", \
TT_EXIT_TEST_FUNCTION)
@@ -64,6 +65,7 @@
tt_assert_test_fmt_type(a,b,#a" "#op" "#b,int64_t,(val1_ op val2_), \
int64_t, "%"PRId64, \
{print_ = (int64_t) value_;}, {}, TT_EXIT_TEST_FUNCTION)
+#endif /* !defined(COCCI) */
/**
* Declare that the test is done, even though no tt___op() calls were made.
@@ -79,99 +81,6 @@ struct crypto_pk_t *pk_generate(int idx);
void init_pregenerated_keys(void);
void free_pregenerated_keys(void);
-#define US2_CONCAT_2__(a, b) a ## __ ## b
-#define US_CONCAT_2__(a, b) a ## _ ## b
-#define US_CONCAT_3__(a, b, c) a ## _ ## b ## _ ## c
-#define US_CONCAT_2_(a, b) US_CONCAT_2__(a, b)
-#define US_CONCAT_3_(a, b, c) US_CONCAT_3__(a, b, c)
-
-/*
- * These macros are helpful for streamlining the authorship of several test
- * cases that use mocks.
- *
- * The pattern is as follows.
- * * Declare a top level namespace:
- * #define NS_MODULE foo
- *
- * * For each test case you want to write, create a new submodule in the
- * namespace. All mocks and other information should belong to a single
- * submodule to avoid interference with other test cases.
- * You can simply name the submodule after the function in the module you
- * are testing:
- * #define NS_SUBMODULE some_function
- * or, if you're wanting to write several tests against the same function,
- * ie., you are testing an aspect of that function, you can use:
- * #define NS_SUBMODULE ASPECT(some_function, behavior)
- *
- * * Declare all the mocks you will use. The NS_DECL macro serves to declare
- * the mock in the current namespace (defined by NS_MODULE and NS_SUBMODULE).
- * It behaves like MOCK_DECL:
- * NS_DECL(int, dependent_function, (void *));
- * Here, dependent_function must be declared and implemented with the
- * MOCK_DECL and MOCK_IMPL macros. The NS_DECL macro also defines an integer
- * global for use for tracking how many times a mock was called, and can be
- * accessed by CALLED(mock_name). For example, you might put
- * CALLED(dependent_function)++;
- * in your mock body.
- *
- * * Define a function called NS(main) that will contain the body of the
- * test case. The NS macro can be used to reference a name in the current
- * namespace.
- *
- * * In NS(main), indicate that a mock function in the current namespace,
- * declared with NS_DECL is to override that in the global namespace,
- * with the NS_MOCK macro:
- * NS_MOCK(dependent_function)
- * Unmock with:
- * NS_UNMOCK(dependent_function)
- *
- * * Define the mocks with the NS macro, eg.,
- * int
- * NS(dependent_function)(void *)
- * {
- * CALLED(dependent_function)++;
- * }
- *
- * * In the struct testcase_t array, you can use the TEST_CASE and
- * TEST_CASE_ASPECT macros to define the cases without having to do so
- * explicitly nor without having to reset NS_SUBMODULE, eg.,
- * struct testcase_t foo_tests[] = {
- * TEST_CASE_ASPECT(some_function, behavior),
- * ...
- * END_OF_TESTCASES
- * which will define a test case named "some_function__behavior".
- */
-
-#define NAME_TEST_(name) #name
-#define NAME_TEST(name) NAME_TEST_(name)
-#define ASPECT(test_module, test_name) US2_CONCAT_2__(test_module, test_name)
-#define TEST_CASE(function) \
- { \
- NAME_TEST(function), \
- NS_FULL(NS_MODULE, function, test_main), \
- TT_FORK, \
- NULL, \
- NULL, \
- }
-#define TEST_CASE_ASPECT(function, aspect) \
- { \
- NAME_TEST(ASPECT(function, aspect)), \
- NS_FULL(NS_MODULE, ASPECT(function, aspect), test_main), \
- TT_FORK, \
- NULL, \
- NULL, \
- }
-
-#define NS(name) US_CONCAT_3_(NS_MODULE, NS_SUBMODULE, name)
-#define NS_FULL(module, submodule, name) US_CONCAT_3_(module, submodule, name)
-
-#define CALLED(mock_name) US_CONCAT_2_(NS(mock_name), called)
-#define NS_DECL(retval, mock_fn, args) \
- extern int CALLED(mock_fn); \
- static retval NS(mock_fn) args; int CALLED(mock_fn) = 0
-#define NS_MOCK(name) MOCK(name, NS(name))
-#define NS_UNMOCK(name) UNMOCK(name)
-
extern const struct testcase_setup_t passthrough_setup;
extern const struct testcase_setup_t ed25519_test_setup;
@@ -193,6 +102,7 @@ extern struct testcase_t checkdir_tests[];
extern struct testcase_t circuitbuild_tests[];
extern struct testcase_t circuitlist_tests[];
extern struct testcase_t circuitmux_tests[];
+extern struct testcase_t circuitmux_ewma_tests[];
extern struct testcase_t circuitstats_tests[];
extern struct testcase_t circuituse_tests[];
extern struct testcase_t compat_libevent_tests[];
@@ -245,6 +155,7 @@ extern struct testcase_t nodelist_tests[];
extern struct testcase_t oom_tests[];
extern struct testcase_t oos_tests[];
extern struct testcase_t options_tests[];
+extern struct testcase_t options_act_tests[];
extern struct testcase_t parsecommon_tests[];
extern struct testcase_t pem_tests[];
extern struct testcase_t periodic_event_tests[];
@@ -254,6 +165,7 @@ extern struct testcase_t slow_stochastic_prob_distr_tests[];
extern struct testcase_t procmon_tests[];
extern struct testcase_t process_tests[];
extern struct testcase_t process_descs_tests[];
+extern struct testcase_t proto_haproxy_tests[];
extern struct testcase_t proto_http_tests[];
extern struct testcase_t proto_misc_tests[];
extern struct testcase_t protover_tests[];
@@ -273,6 +185,7 @@ extern struct testcase_t scheduler_tests[];
extern struct testcase_t sendme_tests[];
extern struct testcase_t socks_tests[];
extern struct testcase_t sr_tests[];
+extern struct testcase_t stats_tests[];
extern struct testcase_t status_tests[];
extern struct testcase_t storagedir_tests[];
extern struct testcase_t thread_tests[];
diff --git a/src/test/test_accounting.c b/src/test/test_accounting.c
index 8ae8fe4343..7933df5e35 100644
--- a/src/test/test_accounting.c
+++ b/src/test/test_accounting.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
@@ -11,19 +11,16 @@
#include "app/config/or_state_st.h"
-#define NS_MODULE accounting
-
-#define NS_SUBMODULE limits
-
/*
* Test to make sure accounting triggers hibernation
* correctly with both sum or max rules set
*/
static or_state_t *or_state;
-NS_DECL(or_state_t *, get_or_state, (void));
+static or_state_t * acct_limits_get_or_state(void);
+ATTR_UNUSED static int acct_limits_get_or_state_called = 0;
static or_state_t *
-NS(get_or_state)(void)
+acct_limits_get_or_state(void)
{
return or_state;
}
@@ -35,7 +32,8 @@ test_accounting_limits(void *arg)
time_t fake_time = time(NULL);
(void) arg;
- NS_MOCK(get_or_state);
+ MOCK(get_or_state,
+ acct_limits_get_or_state);
or_state = or_state_new();
options->AccountingMax = 100;
@@ -94,12 +92,10 @@ test_accounting_limits(void *arg)
goto done;
done:
- NS_UNMOCK(get_or_state);
+ UNMOCK(get_or_state);
or_state_free(or_state);
}
-#undef NS_SUBMODULE
-
struct testcase_t accounting_tests[] = {
{ "bwlimits", test_accounting_limits, TT_FORK, NULL, NULL },
END_OF_TESTCASES
diff --git a/src/test/test_addr.c b/src/test/test_addr.c
index c89c6e78d4..42232e467a 100644
--- a/src/test/test_addr.c
+++ b/src/test/test_addr.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ADDRESSMAP_PRIVATE
@@ -52,6 +52,7 @@ test_addr_basic(void *arg)
;
}
+#ifndef COCCI
#define test_op_ip6_(a,op,b,e1,e2) \
STMT_BEGIN \
tt_assert_test_fmt_type(a,b,e1" "#op" "e2,struct in6_addr*, \
@@ -69,6 +70,7 @@ test_addr_basic(void *arg)
TT_EXIT_TEST_FUNCTION \
); \
STMT_END
+#endif /* !defined(COCCI) */
/** Helper: Assert that two strings both decode as IPv6 addresses with
* tor_inet_pton(), and both decode to the same address. */
@@ -108,9 +110,10 @@ test_addr_basic(void *arg)
tt_int_op(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), OP_EQ, 1); \
t1.family = AF_INET6; \
if (tor_addr_is_internal(&t1, for_listening)) \
- TT_DIE(("%s was not internal", a)); \
+ TT_DIE(("%s was internal", a)); \
STMT_END
+#ifndef COCCI
/** Helper: Assert that <b>a</b> and <b>b</b>, when parsed by
* tor_inet_pton(), give addresses that compare in the order defined by
* <b>op</b> with tor_addr_compare(). */
@@ -135,6 +138,7 @@ test_addr_basic(void *arg)
TT_DIE(("Failed: tor_addr_compare_masked(%s,%s,%d) %s 0", \
a, b, m, #op)); \
STMT_END
+#endif /* !defined(COCCI) */
/** Helper: assert that <b>xx</b> is parseable as a masked IPv6 address with
* ports by tor_parse_mask_addr_ports(), with family <b>f</b>, IP address
@@ -1649,8 +1653,10 @@ test_addr_rfc6598(void *arg)
;
}
+#ifndef COCCI
#define ADDR_LEGACY(name) \
{ #name, test_addr_ ## name , 0, NULL, NULL }
+#endif
struct testcase_t addr_tests[] = {
ADDR_LEGACY(basic),
diff --git a/src/test/test_address.c b/src/test/test_address.c
index 32fb4aa232..e068c99d97 100644
--- a/src/test/test_address.c
+++ b/src/test/test_address.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ADDRESS_PRIVATE
diff --git a/src/test/test_address_set.c b/src/test/test_address_set.c
index 6e299d779e..829ecd79e8 100644
--- a/src/test/test_address_set.c
+++ b/src/test/test_address_set.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
diff --git a/src/test/test_bridges.c b/src/test/test_bridges.c
index 879ae6636b..f1624a529d 100644
--- a/src/test/test_bridges.c
+++ b/src/test/test_bridges.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -550,8 +550,6 @@ test_bridges_get_transport_by_bridge_addrport_no_ptlist(void *arg)
sweep_bridge_list();
}
-#define PT_PRIVATE
-
/**
* Calling get_transport_by_bridge_addrport() with the address and port of a
* configured bridge which uses a pluggable transport should return 0 and set
diff --git a/src/test/test_bt_cl.c b/src/test/test_bt_cl.c
index b29c2c6cbc..5f9a88705c 100644
--- a/src/test/test_bt_cl.c
+++ b/src/test/test_bt_cl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -33,7 +33,7 @@ int a_tangled_web(int x) NOINLINE;
int we_weave(int x) NOINLINE;
#ifdef HAVE_CFLAG_WNULL_DEREFERENCE
-DISABLE_GCC_WARNING(null-dereference)
+DISABLE_GCC_WARNING("-Wnull-dereference")
#endif
int
crash(int x)
@@ -55,7 +55,7 @@ crash(int x)
return crashtype;
}
#ifdef HAVE_CFLAG_WNULL_DEREFERENCE
-ENABLE_GCC_WARNING(null-dereference)
+ENABLE_GCC_WARNING("-Wnull-dereference")
#endif
int
diff --git a/src/test/test_btrack.c b/src/test/test_btrack.c
index 80da7829ae..2b2f34fc23 100644
--- a/src/test/test_btrack.c
+++ b/src/test/test_btrack.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
diff --git a/src/test/test_buffers.c b/src/test/test_buffers.c
index 3084c19d74..fbaa628fd7 100644
--- a/src/test/test_buffers.c
+++ b/src/test/test_buffers.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define BUFFERS_PRIVATE
diff --git a/src/test/test_bwmgt.c b/src/test/test_bwmgt.c
index e6f028ed74..117783cafc 100644
--- a/src/test/test_bwmgt.c
+++ b/src/test/test_bwmgt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -8,12 +8,14 @@
#define CONFIG_PRIVATE
#define CONNECTION_PRIVATE
+#define DIRAUTH_SYS_PRIVATE
#define TOKEN_BUCKET_PRIVATE
#include "core/or/or.h"
#include "app/config/config.h"
#include "core/mainloop/connection.h"
+#include "feature/dirauth/dirauth_sys.h"
#include "feature/dircommon/directory.h"
#include "feature/nodelist/microdesc.h"
#include "feature/nodelist/networkstatus.h"
@@ -26,6 +28,7 @@
#include "app/config/or_options_st.h"
#include "core/or/connection_st.h"
+#include "feature/dirauth/dirauth_options_st.h"
#include "feature/nodelist/microdesc_st.h"
#include "feature/nodelist/networkstatus_st.h"
#include "feature/nodelist/routerinfo_st.h"
@@ -277,6 +280,7 @@ test_bwmgt_dir_conn_global_write_low(void *arg)
connection_t *conn = NULL;
routerstatus_t *rs = NULL; microdesc_t *md = NULL; routerinfo_t *ri = NULL;
tor_addr_t relay_addr;
+ dirauth_options_t *dirauth_opts = NULL;
(void) arg;
@@ -329,6 +333,10 @@ test_bwmgt_dir_conn_global_write_low(void *arg)
nodelist_set_consensus(dummy_ns);
+ dirauth_opts = tor_malloc_zero(sizeof(dirauth_options_t));
+ dirauth_opts->AuthDirRejectRequestsUnderLoad = 0;
+ dirauth_set_options(dirauth_opts);
+
/* Ok, now time to control which options we use. */
MOCK(get_options, mock_get_options);
@@ -365,7 +373,7 @@ test_bwmgt_dir_conn_global_write_low(void *arg)
/* Now, we will reject requests under load so try again a non authority non
* relay IP thus a client. We should get a warning that our limit is too
* low. */
- mock_options.AuthDirRejectRequestsUnderLoad = 1;
+ dirauth_opts->AuthDirRejectRequestsUnderLoad = 1;
addr_family = tor_addr_parse(&conn->addr, "1.1.1.1");
tt_int_op(addr_family, OP_EQ, AF_INET);
diff --git a/src/test/test_cell_formats.c b/src/test/test_cell_formats.c
index fc5367557d..8d6d1940fd 100644
--- a/src/test/test_cell_formats.c
+++ b/src/test/test_cell_formats.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_cell_queue.c b/src/test/test_cell_queue.c
index 8fc1da031e..b778c07802 100644
--- a/src/test/test_cell_queue.c
+++ b/src/test/test_cell_queue.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CIRCUITLIST_PRIVATE
diff --git a/src/test/test_channel.c b/src/test/test_channel.c
index 6a6bc9d810..5b13f1f979 100644
--- a/src/test/test_channel.c
+++ b/src/test/test_channel.c
@@ -1,8 +1,8 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#define TOR_CHANNEL_INTERNAL_
-#define CHANNEL_PRIVATE_
+#define CHANNEL_OBJECT_PRIVATE
+#define CHANNEL_FILE_PRIVATE
#include "core/or/or.h"
#include "core/or/channel.h"
/* For channel_note_destroy_not_pending */
@@ -34,8 +34,6 @@
static int test_chan_accept_cells = 0;
static int test_chan_fixed_cells_recved = 0;
static cell_t * test_chan_last_seen_fixed_cell_ptr = NULL;
-static int test_chan_var_cells_recved = 0;
-static var_cell_t * test_chan_last_seen_var_cell_ptr = NULL;
static int test_cells_written = 0;
static int test_doesnt_want_writes_count = 0;
static int test_dumpstats_calls = 0;
@@ -113,24 +111,6 @@ chan_test_dumpstats(channel_t *ch, int severity)
return;
}
-/*
- * Handle an incoming variable-size cell for unit tests
- */
-
-static void
-chan_test_var_cell_handler(channel_t *ch,
- var_cell_t *var_cell)
-{
- tt_assert(ch);
- tt_assert(var_cell);
-
- test_chan_last_seen_var_cell_ptr = var_cell;
- ++test_chan_var_cells_recved;
-
- done:
- return;
-}
-
static void
chan_test_close(channel_t *ch)
{
@@ -492,11 +472,8 @@ test_channel_dumpstats(void *arg)
/* Receive path */
channel_set_cell_handlers(ch,
- chan_test_cell_handler,
- chan_test_var_cell_handler);
+ chan_test_cell_handler);
tt_ptr_op(channel_get_cell_handler(ch), OP_EQ, chan_test_cell_handler);
- tt_ptr_op(channel_get_var_cell_handler(ch), OP_EQ,
- chan_test_var_cell_handler);
cell = tor_malloc_zero(sizeof(*cell));
old_count = test_chan_fixed_cells_recved;
channel_process_cell(ch, cell);
@@ -722,7 +699,7 @@ test_channel_inbound_cell(void *arg)
/* Setup incoming cell handlers. We don't care about var cell, the channel
* layers is not handling those. */
- channel_set_cell_handlers(chan, chan_test_cell_handler, NULL);
+ channel_set_cell_handlers(chan, chan_test_cell_handler);
tt_ptr_op(chan->cell_handler, OP_EQ, chan_test_cell_handler);
/* Now process the cell, we should see it. */
old_count = test_chan_fixed_cells_recved;
diff --git a/src/test/test_channelpadding.c b/src/test/test_channelpadding.c
index 885246628e..63a591583d 100644
--- a/src/test/test_channelpadding.c
+++ b/src/test/test_channelpadding.c
@@ -1,7 +1,7 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define MAINLOOP_PRIVATE
#define NETWORKSTATUS_PRIVATE
#define TOR_TIMERS_PRIVATE
diff --git a/src/test/test_channeltls.c b/src/test/test_channeltls.c
index 054d3910e4..94ce56f2be 100644
--- a/src/test/test_channeltls.c
+++ b/src/test/test_channeltls.c
@@ -1,11 +1,11 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#include <math.h>
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#include "core/or/or.h"
#include "lib/net/address.h"
#include "lib/buf/buffers.h"
diff --git a/src/test/test_checkdir.c b/src/test/test_checkdir.c
index 1df74c390a..186a55cc8c 100644
--- a/src/test/test_checkdir.c
+++ b/src/test/test_checkdir.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_circuitbuild.c b/src/test/test_circuitbuild.c
index 7291e04d6a..70920c0c52 100644
--- a/src/test/test_circuitbuild.c
+++ b/src/test/test_circuitbuild.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CIRCUITBUILD_PRIVATE
diff --git a/src/test/test_circuitlist.c b/src/test/test_circuitlist.c
index 5cebdbeda0..63c4418f29 100644
--- a/src/test/test_circuitlist.c
+++ b/src/test/test_circuitlist.c
@@ -1,7 +1,7 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define CIRCUITBUILD_PRIVATE
#define CIRCUITLIST_PRIVATE
#define HS_CIRCUITMAP_PRIVATE
@@ -136,7 +136,7 @@ test_clist_maps(void *arg)
channel_note_destroy_pending(ch2, 200);
channel_note_destroy_pending(ch2, 205);
channel_note_destroy_pending(ch1, 100);
- tt_assert(circuit_id_in_use_on_channel(205, ch2))
+ tt_assert(circuit_id_in_use_on_channel(205, ch2));
tt_assert(circuit_id_in_use_on_channel(200, ch2));
tt_assert(circuit_id_in_use_on_channel(100, ch1));
diff --git a/src/test/test_circuitmux.c b/src/test/test_circuitmux.c
index a2b3e62fe8..2c11d107d0 100644
--- a/src/test/test_circuitmux.c
+++ b/src/test/test_circuitmux.c
@@ -1,33 +1,27 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define CIRCUITMUX_PRIVATE
#define CIRCUITMUX_EWMA_PRIVATE
#define RELAY_PRIVATE
+
#include "core/or/or.h"
#include "core/or/channel.h"
#include "core/or/circuitmux.h"
#include "core/or/circuitmux_ewma.h"
+#include "core/or/destroy_cell_queue_st.h"
#include "core/or/relay.h"
#include "core/or/scheduler.h"
-#include "test/test.h"
-#include "core/or/destroy_cell_queue_st.h"
+#include "test/fakechans.h"
+#include "test/fakecircs.h"
+#include "test/test.h"
#include <math.h>
-/* XXXX duplicated function from test_circuitlist.c */
-static channel_t *
-new_fake_channel(void)
-{
- channel_t *chan = tor_malloc_zero(sizeof(channel_t));
- channel_init(chan);
- return chan;
-}
-
static int
-has_queued_writes(channel_t *c)
+mock_has_queued_writes_true(channel_t *c)
{
(void) c;
return 1;
@@ -44,16 +38,14 @@ test_cmux_destroy_cell_queue(void *arg)
packed_cell_t *pc = NULL;
destroy_cell_t *dc = NULL;
- scheduler_init();
+ MOCK(scheduler_release_channel, scheduler_release_channel_mock);
(void) arg;
- cmux = circuitmux_alloc();
- tt_assert(cmux);
ch = new_fake_channel();
- circuitmux_set_policy(cmux, &ewma_policy);
- ch->has_queued_writes = has_queued_writes;
+ ch->has_queued_writes = mock_has_queued_writes_true;
ch->wide_circ_ids = 1;
+ cmux = ch->cmux;
circ = circuitmux_get_first_active_circuit(cmux, &cq);
tt_ptr_op(circ, OP_EQ, NULL);
@@ -78,10 +70,11 @@ test_cmux_destroy_cell_queue(void *arg)
tt_int_op(circuitmux_num_cells(cmux), OP_EQ, 2);
done:
- circuitmux_free(cmux);
- channel_free(ch);
+ free_fake_channel(ch);
packed_cell_free(pc);
tor_free(dc);
+
+ UNMOCK(scheduler_release_channel);
}
static void
@@ -125,9 +118,363 @@ test_cmux_compute_ticks(void *arg)
;
}
+static void
+test_cmux_allocate(void *arg)
+{
+ circuitmux_t *cmux = NULL;
+
+ (void) arg;
+
+ cmux = circuitmux_alloc();
+ tt_assert(cmux);
+ tt_assert(cmux->chanid_circid_map);
+ tt_int_op(HT_SIZE(cmux->chanid_circid_map), OP_EQ, 0);
+ tt_uint_op(cmux->n_circuits, OP_EQ, 0);
+ tt_uint_op(cmux->n_active_circuits, OP_EQ, 0);
+ tt_uint_op(cmux->n_cells, OP_EQ, 0);
+ tt_uint_op(cmux->last_cell_was_destroy, OP_EQ, 0);
+ tt_i64_op(cmux->destroy_ctr, OP_EQ, 0);
+ tt_ptr_op(cmux->policy, OP_EQ, NULL);
+ tt_ptr_op(cmux->policy_data, OP_EQ, NULL);
+
+ tt_assert(TOR_SIMPLEQ_EMPTY(&cmux->destroy_cell_queue.head));
+
+ done:
+ circuitmux_free(cmux);
+}
+
+static void
+test_cmux_attach_circuit(void *arg)
+{
+ circuit_t *circ = NULL;
+ or_circuit_t *orcirc = NULL;
+ channel_t *pchan = NULL, *nchan = NULL;
+ cell_direction_t cdir;
+ unsigned int n_cells;
+
+ (void) arg;
+
+ pchan = new_fake_channel();
+ tt_assert(pchan);
+ nchan = new_fake_channel();
+ tt_assert(nchan);
+
+ orcirc = new_fake_orcirc(nchan, pchan);
+ tt_assert(orcirc);
+ circ = TO_CIRCUIT(orcirc);
+
+ /* While assigning a new circuit IDs, the circuitmux_attach_circuit() is
+ * called for a new channel on the circuit. This means, we should now have
+ * the created circuit attached on both the pchan and nchan cmux. */
+ tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 1);
+ tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 1);
+
+ /* There should be _no_ active circuit due to no queued cells. */
+ tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 0);
+ tt_uint_op(circuitmux_num_active_circuits(nchan->cmux), OP_EQ, 0);
+
+ /* Circuit should not be active on the cmux. */
+ tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0);
+ tt_int_op(circuitmux_is_circuit_active(nchan->cmux, circ), OP_EQ, 0);
+
+ /* Not active so no cells. */
+ n_cells = circuitmux_num_cells_for_circuit(pchan->cmux, circ);
+ tt_uint_op(n_cells, OP_EQ, 0);
+ n_cells = circuitmux_num_cells(pchan->cmux);
+ tt_uint_op(n_cells, OP_EQ, 0);
+ n_cells = circuitmux_num_cells_for_circuit(nchan->cmux, circ);
+ tt_uint_op(n_cells, OP_EQ, 0);
+ n_cells = circuitmux_num_cells(nchan->cmux);
+ tt_uint_op(n_cells, OP_EQ, 0);
+
+ /* So it should be attached :) */
+ tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 1);
+ tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 1);
+
+ /* Query the chanid<->circid map in the cmux subsytem with what we just
+ * created and validate the cell direction. */
+ cdir = circuitmux_attached_circuit_direction(pchan->cmux, circ);
+ tt_int_op(cdir, OP_EQ, CELL_DIRECTION_IN);
+ cdir = circuitmux_attached_circuit_direction(nchan->cmux, circ);
+ tt_int_op(cdir, OP_EQ, CELL_DIRECTION_OUT);
+
+ /*
+ * We'll activate->deactivate->activate to test all code paths of
+ * circuitmux_set_num_cells().
+ */
+
+ /* Activate circuit. */
+ circuitmux_set_num_cells(pchan->cmux, circ, 4);
+ tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1);
+
+ /* Deactivate. */
+ circuitmux_clear_num_cells(pchan->cmux, circ);
+ tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0);
+ tt_uint_op(circuitmux_num_cells_for_circuit(pchan->cmux, circ), OP_EQ, 0);
+
+ /* Re-activate. */
+ circuitmux_set_num_cells(pchan->cmux, circ, 4);
+ tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1);
+
+ /* Once re-attached, it should become inactive because the circuit has no
+ * cells while the chanid<->circid object has some. The attach code will
+ * reset the count on the cmux for that circuit:
+ *
+ * if (chanid_circid_muxinfo_t->muxinfo.cell_count > 0 && cell_count == 0) {
+ */
+ circuitmux_attach_circuit(pchan->cmux, circ, CELL_DIRECTION_IN);
+ n_cells = circuitmux_num_cells_for_circuit(pchan->cmux, circ);
+ tt_uint_op(n_cells, OP_EQ, 0);
+ tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0);
+ tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 0);
+
+ /* Lets queue a cell on the circuit now so it becomes active when
+ * re-attaching:
+ *
+ * else if (chanid_circid_muxinfo_t->muxinfo.cell_count == 0 &&
+ * cell_count > 0) {
+ */
+ orcirc->p_chan_cells.n = 1;
+ circuitmux_attach_circuit(pchan->cmux, circ, CELL_DIRECTION_IN);
+ tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1);
+
+ done:
+ free_fake_orcirc(orcirc);
+ free_fake_channel(pchan);
+ free_fake_channel(nchan);
+}
+
+static void
+test_cmux_detach_circuit(void *arg)
+{
+ circuit_t *circ = NULL;
+ or_circuit_t *orcirc = NULL;
+ channel_t *pchan = NULL, *nchan = NULL;
+
+ (void) arg;
+
+ pchan = new_fake_channel();
+ tt_assert(pchan);
+ nchan = new_fake_channel();
+ tt_assert(nchan);
+
+ orcirc = new_fake_orcirc(nchan, pchan);
+ tt_assert(orcirc);
+ circ = TO_CIRCUIT(orcirc);
+
+ /* While assigning a new circuit IDs, the circuitmux_attach_circuit() is
+ * called for a new channel on the circuit. This means, we should now have
+ * the created circuit attached on both the pchan and nchan cmux. */
+ tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 1);
+ tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 1);
+ tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 1);
+ tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 1);
+
+ /* Now, detach the circuit from pchan and then nchan. */
+ circuitmux_detach_circuit(pchan->cmux, circ);
+ tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 0);
+ tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 0);
+ circuitmux_detach_circuit(nchan->cmux, circ);
+ tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 0);
+ tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 0);
+
+ done:
+ free_fake_orcirc(orcirc);
+ free_fake_channel(pchan);
+ free_fake_channel(nchan);
+}
+
+static void
+test_cmux_detach_all_circuits(void *arg)
+{
+ circuit_t *circ = NULL;
+ or_circuit_t *orcirc = NULL;
+ channel_t *pchan = NULL, *nchan = NULL;
+ smartlist_t *detached_out = smartlist_new();
+
+ (void) arg;
+
+ /* Channels need to be registered in order for the detach all circuit
+ * function to find them. */
+ pchan = new_fake_channel();
+ tt_assert(pchan);
+ channel_register(pchan);
+ nchan = new_fake_channel();
+ tt_assert(nchan);
+ channel_register(nchan);
+
+ orcirc = new_fake_orcirc(nchan, pchan);
+ tt_assert(orcirc);
+ circ = TO_CIRCUIT(orcirc);
+
+ /* Just make sure it is attached. */
+ tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 1);
+ tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 1);
+ tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 1);
+ tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 1);
+
+ /* Queue some cells so we can test if the circuit becomes inactive on the
+ * cmux after the mass detach. */
+ circuitmux_set_num_cells(pchan->cmux, circ, 4);
+ circuitmux_set_num_cells(nchan->cmux, circ, 4);
+
+ /* Detach all on pchan and then nchan. */
+ circuitmux_detach_all_circuits(pchan->cmux, detached_out);
+ tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 0);
+ tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 0);
+ tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0);
+ tt_int_op(smartlist_len(detached_out), OP_EQ, 1);
+ circuitmux_detach_all_circuits(nchan->cmux, NULL);
+ tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 0);
+ tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 0);
+ tt_int_op(circuitmux_is_circuit_active(nchan->cmux, circ), OP_EQ, 0);
+
+ done:
+ smartlist_free(detached_out);
+ free_fake_orcirc(orcirc);
+ free_fake_channel(pchan);
+ free_fake_channel(nchan);
+}
+
+static void
+test_cmux_policy(void *arg)
+{
+ circuit_t *circ = NULL;
+ or_circuit_t *orcirc = NULL;
+ channel_t *pchan = NULL, *nchan = NULL;
+
+ (void) arg;
+
+ pchan = new_fake_channel();
+ tt_assert(pchan);
+ channel_register(pchan);
+ nchan = new_fake_channel();
+ tt_assert(nchan);
+ channel_register(nchan);
+
+ orcirc = new_fake_orcirc(nchan, pchan);
+ tt_assert(orcirc);
+ circ = TO_CIRCUIT(orcirc);
+
+ /* Confirm we have the EWMA policy by default for new channels. */
+ tt_ptr_op(circuitmux_get_policy(pchan->cmux), OP_EQ, &ewma_policy);
+ tt_ptr_op(circuitmux_get_policy(nchan->cmux), OP_EQ, &ewma_policy);
+
+ /* Putting cell on the cmux means will make the notify policy code path to
+ * trigger. */
+ circuitmux_set_num_cells(pchan->cmux, circ, 4);
+
+ /* Clear it out. */
+ circuitmux_clear_policy(pchan->cmux);
+
+ /* Set back the EWMA policy. */
+ circuitmux_set_policy(pchan->cmux, &ewma_policy);
+
+ done:
+ free_fake_orcirc(orcirc);
+ free_fake_channel(pchan);
+ free_fake_channel(nchan);
+}
+
+static void
+test_cmux_xmit_cell(void *arg)
+{
+ circuit_t *circ = NULL;
+ or_circuit_t *orcirc = NULL;
+ channel_t *pchan = NULL, *nchan = NULL;
+
+ (void) arg;
+
+ pchan = new_fake_channel();
+ tt_assert(pchan);
+ nchan = new_fake_channel();
+ tt_assert(nchan);
+
+ orcirc = new_fake_orcirc(nchan, pchan);
+ tt_assert(orcirc);
+ circ = TO_CIRCUIT(orcirc);
+
+ /* Queue 4 cells on the circuit. */
+ circuitmux_set_num_cells(pchan->cmux, circ, 4);
+ tt_uint_op(circuitmux_num_cells_for_circuit(pchan->cmux, circ), OP_EQ, 4);
+ tt_uint_op(circuitmux_num_cells(pchan->cmux), OP_EQ, 4);
+ tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1);
+ tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 1);
+
+ /* Emit the first cell. Circuit should still be active. */
+ circuitmux_notify_xmit_cells(pchan->cmux, circ, 1);
+ tt_uint_op(circuitmux_num_cells(pchan->cmux), OP_EQ, 3);
+ tt_uint_op(circuitmux_num_cells_for_circuit(pchan->cmux, circ), OP_EQ, 3);
+ tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1);
+ tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 1);
+
+ /* Emit the last 3 cells. Circuit should become inactive. */
+ circuitmux_notify_xmit_cells(pchan->cmux, circ, 3);
+ tt_uint_op(circuitmux_num_cells(pchan->cmux), OP_EQ, 0);
+ tt_uint_op(circuitmux_num_cells_for_circuit(pchan->cmux, circ), OP_EQ, 0);
+ tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0);
+ tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 0);
+
+ /* Queue a DESTROY cell. */
+ pchan->has_queued_writes = mock_has_queued_writes_true;
+ circuitmux_append_destroy_cell(pchan, pchan->cmux, orcirc->p_circ_id, 0);
+ tt_i64_op(pchan->cmux->destroy_ctr, OP_EQ, 1);
+ tt_int_op(pchan->cmux->destroy_cell_queue.n, OP_EQ, 1);
+ tt_i64_op(circuitmux_count_queued_destroy_cells(pchan, pchan->cmux),
+ OP_EQ, 1);
+
+ /* Emit the DESTROY cell. */
+ circuitmux_notify_xmit_destroy(pchan->cmux);
+ tt_i64_op(pchan->cmux->destroy_ctr, OP_EQ, 0);
+
+ done:
+ free_fake_orcirc(orcirc);
+ free_fake_channel(pchan);
+ free_fake_channel(nchan);
+}
+
+static void *
+cmux_setup_test(const struct testcase_t *tc)
+{
+ static int whatever;
+
+ (void) tc;
+
+ cell_ewma_initialize_ticks();
+ return &whatever;
+}
+
+static int
+cmux_cleanup_test(const struct testcase_t *tc, void *ptr)
+{
+ (void) tc;
+ (void) ptr;
+
+ circuitmux_ewma_free_all();
+
+ return 1;
+}
+
+static struct testcase_setup_t cmux_test_setup = {
+ .setup_fn = cmux_setup_test,
+ .cleanup_fn = cmux_cleanup_test,
+};
+
+#define TEST_CMUX(name) \
+ { #name, test_cmux_##name, TT_FORK, &cmux_test_setup, NULL }
+
struct testcase_t circuitmux_tests[] = {
- { "destroy_cell_queue", test_cmux_destroy_cell_queue, TT_FORK, NULL, NULL },
- { "compute_ticks", test_cmux_compute_ticks, TT_FORK, NULL, NULL },
+ /* Test circuitmux_t object */
+ TEST_CMUX(allocate),
+ TEST_CMUX(attach_circuit),
+ TEST_CMUX(detach_circuit),
+ TEST_CMUX(detach_all_circuits),
+ TEST_CMUX(policy),
+ TEST_CMUX(xmit_cell),
+
+ /* Misc. */
+ TEST_CMUX(compute_ticks),
+ TEST_CMUX(destroy_cell_queue),
+
END_OF_TESTCASES
};
-
diff --git a/src/test/test_circuitmux_ewma.c b/src/test/test_circuitmux_ewma.c
new file mode 100644
index 0000000000..27601e0c7d
--- /dev/null
+++ b/src/test/test_circuitmux_ewma.c
@@ -0,0 +1,228 @@
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define CIRCUITMUX_PRIVATE
+#define CIRCUITMUX_EWMA_PRIVATE
+
+#include "core/or/or.h"
+#include "core/or/circuitmux.h"
+#include "core/or/circuitmux_ewma.h"
+
+#include "test/fakechans.h"
+#include "test/fakecircs.h"
+#include "test/test.h"
+
+static void
+test_cmux_ewma_active_circuit(void *arg)
+{
+ circuitmux_t cmux; /* garbage */
+ circuitmux_policy_data_t *pol_data = NULL;
+ circuit_t circ; /* garbage */
+ circuitmux_policy_circ_data_t *circ_data = NULL;
+
+ (void) arg;
+
+ pol_data = ewma_policy.alloc_cmux_data(&cmux);
+ tt_assert(pol_data);
+ circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ,
+ CELL_DIRECTION_OUT, 42);
+ tt_assert(circ_data);
+
+ /* Get EWMA specific objects. */
+
+ /* Make circuit active. */
+ ewma_policy.notify_circ_active(&cmux, pol_data, &circ, circ_data);
+
+ circuit_t *entry = ewma_policy.pick_active_circuit(&cmux, pol_data);
+ tt_mem_op(entry, OP_EQ, &circ, sizeof(circ));
+
+ done:
+ ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data);
+ ewma_policy.free_cmux_data(&cmux, pol_data);
+}
+
+static void
+test_cmux_ewma_xmit_cell(void *arg)
+{
+ circuitmux_t cmux; /* garbage */
+ circuitmux_policy_data_t *pol_data = NULL;
+ circuit_t circ; /* garbage */
+ circuitmux_policy_circ_data_t *circ_data = NULL;
+ ewma_policy_data_t *ewma_pol_data;
+ ewma_policy_circ_data_t *ewma_data;
+ double old_cell_count;
+
+ (void) arg;
+
+ pol_data = ewma_policy.alloc_cmux_data(&cmux);
+ tt_assert(pol_data);
+ circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ,
+ CELL_DIRECTION_OUT, 42);
+ tt_assert(circ_data);
+ ewma_pol_data = TO_EWMA_POL_DATA(pol_data);
+ ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data);
+
+ /* Make circuit active. */
+ ewma_policy.notify_circ_active(&cmux, pol_data, &circ, circ_data);
+
+ /* Move back in time the last time we calibrated so we scale the active
+ * circuit when emitting a cell. */
+ ewma_pol_data->active_circuit_pqueue_last_recalibrated -= 100;
+ ewma_data->cell_ewma.last_adjusted_tick =
+ ewma_pol_data->active_circuit_pqueue_last_recalibrated;
+
+ /* Grab old cell count. */
+ old_cell_count = ewma_data->cell_ewma.cell_count;
+
+ ewma_policy.notify_xmit_cells(&cmux, pol_data, &circ, circ_data, 1);
+
+ /* Our old cell count should be lower to what we have since we just emitted
+ * a cell and thus we scale. */
+ tt_double_op(old_cell_count, OP_LT, ewma_data->cell_ewma.cell_count);
+
+ done:
+ ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data);
+ ewma_policy.free_cmux_data(&cmux, pol_data);
+}
+
+static void
+test_cmux_ewma_notify_circ(void *arg)
+{
+ circuitmux_t cmux; /* garbage */
+ circuitmux_policy_data_t *pol_data = NULL;
+ circuit_t circ; /* garbage */
+ circuitmux_policy_circ_data_t *circ_data = NULL;
+ const ewma_policy_data_t *ewma_pol_data;
+
+ (void) arg;
+
+ pol_data = ewma_policy.alloc_cmux_data(&cmux);
+ tt_assert(pol_data);
+ circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ,
+ CELL_DIRECTION_OUT, 42);
+ tt_assert(circ_data);
+
+ /* Currently, notify_circ_active() ignores cmux and circ. They can not be
+ * NULL so it is fine to pass garbage. */
+ ewma_policy.notify_circ_active(&cmux, pol_data, &circ, circ_data);
+
+ /* We should have an active circuit in the queue so its EWMA value can be
+ * tracked. */
+ ewma_pol_data = TO_EWMA_POL_DATA(pol_data);
+ tt_int_op(smartlist_len(ewma_pol_data->active_circuit_pqueue), OP_EQ, 1);
+ tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0);
+
+ ewma_policy.notify_circ_inactive(&cmux, pol_data, &circ, circ_data);
+ /* Should be removed from the active queue. */
+ ewma_pol_data = TO_EWMA_POL_DATA(pol_data);
+ tt_int_op(smartlist_len(ewma_pol_data->active_circuit_pqueue), OP_EQ, 0);
+ tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0);
+
+ done:
+ ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data);
+ ewma_policy.free_cmux_data(&cmux, pol_data);
+}
+
+static void
+test_cmux_ewma_policy_circ_data(void *arg)
+{
+ circuitmux_t cmux; /* garbage */
+ circuitmux_policy_data_t pol_data; /* garbage */
+ circuit_t circ; /* garbage */
+ circuitmux_policy_circ_data_t *circ_data = NULL;
+ const ewma_policy_circ_data_t *ewma_data;
+
+ (void) arg;
+
+ /* Currently, alloc_circ_data() ignores every parameter _except_ the cell
+ * direction so it is OK to pass garbage. They can not be NULL. */
+ circ_data = ewma_policy.alloc_circ_data(&cmux, &pol_data, &circ,
+ CELL_DIRECTION_OUT, 42);
+ tt_assert(circ_data);
+ tt_uint_op(circ_data->magic, OP_EQ, EWMA_POL_CIRC_DATA_MAGIC);
+
+ ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data);
+ tt_mem_op(ewma_data->circ, OP_EQ, &circ, sizeof(circuit_t));
+ tt_double_op(ewma_data->cell_ewma.cell_count, OP_LE, 0.0);
+ tt_int_op(ewma_data->cell_ewma.heap_index, OP_EQ, -1);
+ tt_uint_op(ewma_data->cell_ewma.is_for_p_chan, OP_EQ, 0);
+ ewma_policy.free_circ_data(&cmux, &pol_data, &circ, circ_data);
+
+ circ_data = ewma_policy.alloc_circ_data(&cmux, &pol_data, &circ,
+ CELL_DIRECTION_IN, 42);
+ tt_assert(circ_data);
+ tt_uint_op(circ_data->magic, OP_EQ, EWMA_POL_CIRC_DATA_MAGIC);
+
+ ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data);
+ tt_mem_op(ewma_data->circ, OP_EQ, &circ, sizeof(circuit_t));
+ tt_double_op(ewma_data->cell_ewma.cell_count, OP_LE, 0.0);
+ tt_int_op(ewma_data->cell_ewma.heap_index, OP_EQ, -1);
+ tt_uint_op(ewma_data->cell_ewma.is_for_p_chan, OP_EQ, 1);
+
+ done:
+ ewma_policy.free_circ_data(&cmux, &pol_data, &circ, circ_data);
+}
+
+static void
+test_cmux_ewma_policy_data(void *arg)
+{
+ circuitmux_t cmux; /* garbage. */
+ circuitmux_policy_data_t *pol_data = NULL;
+ const ewma_policy_data_t *ewma_pol_data;
+
+ (void) arg;
+
+ pol_data = ewma_policy.alloc_cmux_data(&cmux);
+ tt_assert(pol_data);
+ tt_uint_op(pol_data->magic, OP_EQ, EWMA_POL_DATA_MAGIC);
+
+ /* Test EWMA object. */
+ ewma_pol_data = TO_EWMA_POL_DATA(pol_data);
+ tt_assert(ewma_pol_data->active_circuit_pqueue);
+ tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0);
+
+ done:
+ ewma_policy.free_cmux_data(&cmux, pol_data);
+}
+
+static void *
+cmux_ewma_setup_test(const struct testcase_t *tc)
+{
+ static int whatever;
+
+ (void) tc;
+
+ cell_ewma_initialize_ticks();
+ cmux_ewma_set_options(NULL, NULL);
+
+ return &whatever;
+}
+
+static int
+cmux_ewma_cleanup_test(const struct testcase_t *tc, void *ptr)
+{
+ (void) tc;
+ (void) ptr;
+
+ circuitmux_ewma_free_all();
+
+ return 1;
+}
+
+static struct testcase_setup_t cmux_ewma_test_setup = {
+ .setup_fn = cmux_ewma_setup_test,
+ .cleanup_fn = cmux_ewma_cleanup_test,
+};
+
+#define TEST_CMUX_EWMA(name) \
+ { #name, test_cmux_ewma_##name, TT_FORK, &cmux_ewma_test_setup, NULL }
+
+struct testcase_t circuitmux_ewma_tests[] = {
+ TEST_CMUX_EWMA(active_circuit),
+ TEST_CMUX_EWMA(policy_data),
+ TEST_CMUX_EWMA(policy_circ_data),
+ TEST_CMUX_EWMA(notify_circ),
+ TEST_CMUX_EWMA(xmit_cell),
+
+ END_OF_TESTCASES
+};
diff --git a/src/test/test_circuitpadding.c b/src/test/test_circuitpadding.c
index 934ddb0208..cfb24c032c 100644
--- a/src/test/test_circuitpadding.c
+++ b/src/test/test_circuitpadding.c
@@ -1,4 +1,4 @@
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define TOR_TIMERS_PRIVATE
#define CIRCUITPADDING_PRIVATE
#define CIRCUITPADDING_MACHINES_PRIVATE
@@ -27,7 +27,6 @@
#include "core/crypto/relay_crypto.h"
#include "core/or/protover.h"
#include "feature/nodelist/nodelist.h"
-#include "lib/evloop/compat_libevent.h"
#include "app/config/config.h"
#include "feature/nodelist/routerstatus_st.h"
@@ -38,6 +37,7 @@
#include "core/or/or_circuit_st.h"
#include "core/or/origin_circuit_st.h"
+#include "test/fakecircs.h"
#include "test/rng_test_helpers.h"
/* Start our monotime mocking at 1 second past whatever monotime_init()
@@ -53,7 +53,6 @@ circid_t get_unique_circ_id_by_chan(channel_t *chan);
void helper_create_basic_machine(void);
static void helper_create_conditional_machines(void);
-static or_circuit_t * new_fake_orcirc(channel_t *nchan, channel_t *pchan);
channel_t *new_fake_channel(void);
void test_circuitpadding_negotiation(void *arg);
void test_circuitpadding_wronghop(void *arg);
@@ -67,7 +66,6 @@ void test_circuitpadding_state_length(void *arg);
static void
simulate_single_hop_extend(circuit_t *client, circuit_t *mid_relay,
int padding);
-void free_fake_orcirc(circuit_t *circ);
void free_fake_origin_circuit(origin_circuit_t *circ);
static int deliver_negotiated = 1;
@@ -127,62 +125,6 @@ circuit_get_nth_node_mock(origin_circuit_t *circ, int hop)
return &padding_node;
}
-static or_circuit_t *
-new_fake_orcirc(channel_t *nchan, channel_t *pchan)
-{
- or_circuit_t *orcirc = NULL;
- circuit_t *circ = NULL;
- crypt_path_t tmp_cpath;
- char whatevs_key[CPATH_KEY_MATERIAL_LEN];
-
- orcirc = tor_malloc_zero(sizeof(*orcirc));
- circ = &(orcirc->base_);
- circ->magic = OR_CIRCUIT_MAGIC;
-
- //circ->n_chan = nchan;
- circ->n_circ_id = get_unique_circ_id_by_chan(nchan);
- cell_queue_init(&(circ->n_chan_cells));
- circ->n_hop = NULL;
- circ->streams_blocked_on_n_chan = 0;
- circ->streams_blocked_on_p_chan = 0;
- circ->n_delete_pending = 0;
- circ->p_delete_pending = 0;
- circ->received_destroy = 0;
- circ->state = CIRCUIT_STATE_OPEN;
- circ->purpose = CIRCUIT_PURPOSE_OR;
- circ->package_window = CIRCWINDOW_START_MAX;
- circ->deliver_window = CIRCWINDOW_START_MAX;
- circ->n_chan_create_cell = NULL;
-
- //orcirc->p_chan = pchan;
- orcirc->p_circ_id = get_unique_circ_id_by_chan(pchan);
- cell_queue_init(&(orcirc->p_chan_cells));
-
- circuit_set_p_circid_chan(orcirc, orcirc->p_circ_id, pchan);
- circuit_set_n_circid_chan(circ, circ->n_circ_id, nchan);
-
- memset(&tmp_cpath, 0, sizeof(tmp_cpath));
- if (cpath_init_circuit_crypto(&tmp_cpath, whatevs_key,
- sizeof(whatevs_key), 0, 0)<0) {
- log_warn(LD_BUG,"Circuit initialization failed");
- return NULL;
- }
- orcirc->crypto = tmp_cpath.pvt_crypto;
-
- return orcirc;
-}
-
-void
-free_fake_orcirc(circuit_t *circ)
-{
- or_circuit_t *orcirc = TO_OR_CIRCUIT(circ);
-
- relay_crypto_clear(&orcirc->crypto);
-
- circpad_circuit_free_all_machineinfos(circ);
- tor_free(circ);
-}
-
void
free_fake_origin_circuit(origin_circuit_t *circ)
{
@@ -413,7 +355,7 @@ test_circuitpadding_rtt(void *arg)
circpad_machine_current_state(
client_side->padding_info[0])->histogram_edges[0]);
done:
- free_fake_orcirc(relay_side);
+ free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
circuitmux_free(dummy_channel.cmux);
timers_shutdown();
@@ -1439,7 +1381,7 @@ test_circuitpadding_wronghop(void *arg)
/* Test 2: Test no padding */
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
- free_fake_orcirc(relay_side);
+ free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
client_side = TO_CIRCUIT(origin_circuit_new());
relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel,
@@ -1484,7 +1426,7 @@ test_circuitpadding_wronghop(void *arg)
done:
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
- free_fake_orcirc(relay_side);
+ free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
circuitmux_free(dummy_channel.cmux);
monotime_disable_test_mocking();
@@ -1553,7 +1495,7 @@ test_circuitpadding_negotiation(void *arg)
/* Test 2: Test no padding */
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
- free_fake_orcirc(relay_side);
+ free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
client_side = TO_CIRCUIT(origin_circuit_new());
relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, &dummy_channel));
@@ -1591,7 +1533,7 @@ test_circuitpadding_negotiation(void *arg)
/* 3. Test failure to negotiate a machine due to desync */
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
- free_fake_orcirc(relay_side);
+ free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
client_side = TO_CIRCUIT(origin_circuit_new());
relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, &dummy_channel));
@@ -1619,7 +1561,7 @@ test_circuitpadding_negotiation(void *arg)
done:
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
- free_fake_orcirc(relay_side);
+ free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
circuitmux_free(dummy_channel.cmux);
monotime_disable_test_mocking();
@@ -1939,7 +1881,7 @@ test_circuitpadding_state_length(void *arg)
tor_free(client_machine);
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
- free_fake_orcirc(relay_side);
+ free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
circuitmux_free(dummy_channel.cmux);
@@ -2312,7 +2254,7 @@ test_circuitpadding_circuitsetup_machine(void *arg)
tt_u64_op(relay_side->padding_info[0]->padding_scheduled_at_usec,
OP_NE, 0);
circuit_mark_for_close(client_side, END_CIRC_REASON_FLAG_REMOTE);
- free_fake_orcirc(relay_side);
+ free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
timers_advance_and_run(5000);
/* No cells sent */
@@ -2616,7 +2558,7 @@ test_circuitpadding_global_rate_limiting(void *arg)
tt_int_op(retval, OP_EQ, 0);
done:
- free_fake_orcirc(relay_side);
+ free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
circuitmux_free(dummy_channel.cmux);
SMARTLIST_FOREACH(vote1.net_params, char *, cp, tor_free(cp));
@@ -2769,7 +2711,7 @@ test_circuitpadding_reduce_disable(void *arg)
tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL);
done:
- free_fake_orcirc(relay_side);
+ free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
circuitmux_free(dummy_channel.cmux);
testing_disable_reproducible_rng();
@@ -3075,7 +3017,7 @@ helper_test_hs_machines(bool test_intro_circs)
}
done:
- free_fake_orcirc(relay_side);
+ free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
circuitmux_free(dummy_channel.cmux);
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
diff --git a/src/test/test_circuitstats.c b/src/test/test_circuitstats.c
index 9bfaabeb2f..e15dec5a01 100644
--- a/src/test/test_circuitstats.c
+++ b/src/test/test_circuitstats.c
@@ -1,10 +1,10 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CIRCUITBUILD_PRIVATE
#define CIRCUITSTATS_PRIVATE
#define CIRCUITLIST_PRIVATE
-#define CHANNEL_PRIVATE_
+#define CHANNEL_FILE_PRIVATE
#include "core/or/or.h"
#include "test/test.h"
diff --git a/src/test/test_circuituse.c b/src/test/test_circuituse.c
index 3acfc12044..49438d9d3b 100644
--- a/src/test/test_circuituse.c
+++ b/src/test/test_circuituse.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CIRCUITLIST_PRIVATE
diff --git a/src/test/test_cmdline.sh b/src/test/test_cmdline.sh
index cf758c3851..ded58af63d 100755
--- a/src/test/test_cmdline.sh
+++ b/src/test/test_cmdline.sh
@@ -3,6 +3,21 @@
umask 077
set -e
+# emulate realpath(), in case coreutils or equivalent is not installed.
+abspath() {
+ f="$*"
+ if [ -d "$f" ]; then
+ dir="$f"
+ base=""
+ else
+ dir="$(dirname "$f")"
+ base="/$(basename "$f")"
+ fi
+ dir="$(cd "$dir" && pwd)"
+ echo "$dir$base"
+}
+
+# find the tor binary
if [ $# -ge 1 ]; then
TOR_BINARY="${1}"
shift
@@ -10,6 +25,8 @@ else
TOR_BINARY="${TESTING_TOR_BINARY:-./src/app/tor}"
fi
+TOR_BINARY="$(abspath "$TOR_BINARY")"
+
echo "TOR BINARY IS ${TOR_BINARY}"
die() { echo "$1" >&2 ; exit 5; }
diff --git a/src/test/test_compat_libevent.c b/src/test/test_compat_libevent.c
index ecd97e3474..5376e08fb3 100644
--- a/src/test/test_compat_libevent.c
+++ b/src/test/test_compat_libevent.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define COMPAT_LIBEVENT_PRIVATE
@@ -13,8 +13,6 @@
#include "test/log_test_helpers.h"
-#define NS_MODULE compat_libevent
-
static void
test_compat_libevent_logging_callback(void *ignored)
{
diff --git a/src/test/test_config.c b/src/test/test_config.c
index ebc0624fb2..ae3f04de11 100644
--- a/src/test/test_config.c
+++ b/src/test/test_config.c
@@ -1,11 +1,13 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#define CONFIG_PRIVATE
+#define RELAY_CONFIG_PRIVATE
+#define RELAY_TRANSPORT_CONFIG_PRIVATE
#define PT_PRIVATE
#define ROUTERSET_PRIVATE
#include "core/or/or.h"
@@ -16,7 +18,9 @@
#include "core/or/circuitmux_ewma.h"
#include "core/or/circuitbuild.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "feature/relay/relay_config.h"
+#include "feature/relay/transport_config.h"
+#include "lib/confmgt/confmgt.h"
#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
#include "test/test.h"
@@ -24,6 +28,7 @@
#include "feature/control/control.h"
#include "core/mainloop/cpuworker.h"
#include "feature/dircache/dirserv.h"
+#include "feature/dirclient/dirclient_modes.h"
#include "feature/dirauth/dirvote.h"
#include "feature/relay/dns.h"
#include "feature/client/entrynodes.h"
@@ -672,6 +677,52 @@ transport_is_needed_mock(const char *transport_name)
return transport_is_needed_mock_return;
}
+static void
+test_config_parse_tcp_proxy_line(void *arg)
+{
+ (void)arg;
+
+ int ret;
+ char *msg = NULL;
+ or_options_t *options = get_options_mutable();
+
+ /* Bad TCPProxy line - too short. */
+ ret = parse_tcp_proxy_line("haproxy", options, &msg);
+ /* Return error. */
+ tt_int_op(ret, OP_EQ, -1);
+ /* Correct error message. */
+ tt_str_op(msg, OP_EQ, "TCPProxy has no address/port. Please fix.");
+ /* Free error message. */
+ tor_free(msg);
+
+ /* Bad TCPProxy line - unsupported protocol. */
+ ret = parse_tcp_proxy_line("unsupported 95.216.163.36:443", options, &msg);
+ tt_int_op(ret, OP_EQ, -1);
+ tt_str_op(msg, OP_EQ, "TCPProxy protocol is not supported. Currently the "
+ "only supported protocol is 'haproxy'. Please fix.");
+ tor_free(msg);
+
+ /* Bad TCPProxy line - unparsable address/port. */
+ ret = parse_tcp_proxy_line("haproxy 95.216.163.36/443", options, &msg);
+ tt_int_op(ret, OP_EQ, -1);
+ tt_str_op(msg, OP_EQ, "TCPProxy address/port failed to parse or resolve. "
+ "Please fix.");
+ tor_free(msg);
+
+ /* Good TCPProxy line - ipv4. */
+ ret = parse_tcp_proxy_line("haproxy 95.216.163.36:443", options, &msg);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_ptr_op(msg, OP_EQ, NULL);
+ tt_int_op(options->TCPProxyProtocol, OP_EQ, TCP_PROXY_PROTOCOL_HAPROXY);
+ /* Correct the address. */
+ tt_assert(tor_addr_eq_ipv4h(&options->TCPProxyAddr, 0x5fd8a324));
+ tt_int_op(options->TCPProxyPort, OP_EQ, 443);
+ tor_free(msg);
+
+ done:
+ ;
+}
+
/**
* Test parsing for the ClientTransportPlugin and ServerTransportPlugin config
* options.
@@ -689,84 +740,84 @@ test_config_parse_transport_plugin_line(void *arg)
int old_transport_is_needed_mock_call_count;
/* Bad transport lines - too short */
- r = parse_transport_line(options, "bad", 1, 0);
+ r = pt_parse_transport_line(options, "bad", 1, 0);
tt_int_op(r, OP_LT, 0);
- r = parse_transport_line(options, "bad", 1, 1);
+ r = pt_parse_transport_line(options, "bad", 1, 1);
tt_int_op(r, OP_LT, 0);
- r = parse_transport_line(options, "bad bad", 1, 0);
+ r = pt_parse_transport_line(options, "bad bad", 1, 0);
tt_int_op(r, OP_LT, 0);
- r = parse_transport_line(options, "bad bad", 1, 1);
+ r = pt_parse_transport_line(options, "bad bad", 1, 1);
tt_int_op(r, OP_LT, 0);
/* Test transport list parsing */
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 exec /usr/bin/fake-transport", 1, 0);
tt_int_op(r, OP_EQ, 0);
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 exec /usr/bin/fake-transport", 1, 1);
tt_int_op(r, OP_EQ, 0);
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1,transport_2 exec /usr/bin/fake-transport", 1, 0);
tt_int_op(r, OP_EQ, 0);
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1,transport_2 exec /usr/bin/fake-transport", 1, 1);
tt_int_op(r, OP_EQ, 0);
/* Bad transport identifiers */
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_* exec /usr/bin/fake-transport", 1, 0);
tt_int_op(r, OP_LT, 0);
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_* exec /usr/bin/fake-transport", 1, 1);
tt_int_op(r, OP_LT, 0);
/* Check SOCKS cases for client transport */
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 socks4 1.2.3.4:567", 1, 0);
tt_int_op(r, OP_EQ, 0);
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 socks5 1.2.3.4:567", 1, 0);
tt_int_op(r, OP_EQ, 0);
/* Proxy case for server transport */
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 proxy 1.2.3.4:567", 1, 1);
tt_int_op(r, OP_EQ, 0);
/* Multiple-transport error exit */
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1,transport_2 socks5 1.2.3.4:567", 1, 0);
tt_int_op(r, OP_LT, 0);
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1,transport_2 proxy 1.2.3.4:567", 1, 1);
tt_int_op(r, OP_LT, 0);
/* No port error exit */
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 socks5 1.2.3.4", 1, 0);
tt_int_op(r, OP_LT, 0);
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 proxy 1.2.3.4", 1, 1);
tt_int_op(r, OP_LT, 0);
/* Unparsable address error exit */
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 socks5 1.2.3:6x7", 1, 0);
tt_int_op(r, OP_LT, 0);
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 proxy 1.2.3:6x7", 1, 1);
tt_int_op(r, OP_LT, 0);
/* "Strange {Client|Server}TransportPlugin field" error exit */
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 foo bar", 1, 0);
tt_int_op(r, OP_LT, 0);
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 foo bar", 1, 1);
tt_int_op(r, OP_LT, 0);
/* No sandbox mode error exit */
tmp = options->Sandbox;
options->Sandbox = 1;
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 exec /usr/bin/fake-transport", 1, 0);
tt_int_op(r, OP_LT, 0);
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 exec /usr/bin/fake-transport", 1, 1);
tt_int_op(r, OP_LT, 0);
options->Sandbox = tmp;
@@ -778,7 +829,7 @@ test_config_parse_transport_plugin_line(void *arg)
MOCK(pt_kickstart_proxy, pt_kickstart_proxy_mock);
old_pt_kickstart_proxy_mock_call_count =
pt_kickstart_proxy_mock_call_count;
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 exec /usr/bin/fake-transport", 0, 1);
tt_int_op(r, OP_EQ, 0);
tt_assert(pt_kickstart_proxy_mock_call_count ==
@@ -786,7 +837,7 @@ test_config_parse_transport_plugin_line(void *arg)
UNMOCK(pt_kickstart_proxy);
/* This one hits a log line in the !validate_only case only */
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 proxy 1.2.3.4:567", 0, 1);
tt_int_op(r, OP_EQ, 0);
@@ -803,7 +854,7 @@ test_config_parse_transport_plugin_line(void *arg)
transport_add_from_config_mock_call_count;
old_transport_is_needed_mock_call_count =
transport_is_needed_mock_call_count;
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 exec /usr/bin/fake-transport", 0, 0);
/* Should have succeeded */
tt_int_op(r, OP_EQ, 0);
@@ -827,7 +878,7 @@ test_config_parse_transport_plugin_line(void *arg)
transport_add_from_config_mock_call_count;
old_transport_is_needed_mock_call_count =
transport_is_needed_mock_call_count;
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 exec /usr/bin/fake-transport", 0, 0);
/* Should have succeeded */
tt_int_op(r, OP_EQ, 0);
@@ -851,7 +902,7 @@ test_config_parse_transport_plugin_line(void *arg)
transport_add_from_config_mock_call_count;
old_transport_is_needed_mock_call_count =
transport_is_needed_mock_call_count;
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 socks5 1.2.3.4:567", 0, 0);
/* Should have succeeded */
tt_int_op(r, OP_EQ, 0);
@@ -906,14 +957,12 @@ test_config_fix_my_family(void *arg)
family3->next = NULL;
or_options_t* options = options_new();
- or_options_t* defaults = options_new();
(void) arg;
options_init(options);
- options_init(defaults);
options->MyFamily_lines = family;
- options_validate(NULL, options, defaults, 0, &err) ;
+ options_validate(NULL, options, &err) ;
if (err != NULL) {
TT_FAIL(("options_validate failed: %s", err));
@@ -935,7 +984,6 @@ test_config_fix_my_family(void *arg)
done:
tor_free(err);
or_options_free(options);
- or_options_free(defaults);
}
static int n_hostname_01010101 = 0;
@@ -3658,7 +3706,7 @@ test_config_directory_fetch(void *arg)
options->ClientOnly = 1;
tt_assert(server_mode(options) == 0);
tt_assert(public_server_mode(options) == 0);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 1);
@@ -3668,7 +3716,7 @@ test_config_directory_fetch(void *arg)
options->UseBridges = 1;
tt_assert(server_mode(options) == 0);
tt_assert(public_server_mode(options) == 0);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 1);
@@ -3680,7 +3728,7 @@ test_config_directory_fetch(void *arg)
options->ORPort_set = 1;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 0);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 1);
@@ -3691,7 +3739,7 @@ test_config_directory_fetch(void *arg)
options->FetchDirInfoEarly = 1;
tt_assert(server_mode(options) == 0);
tt_assert(public_server_mode(options) == 0);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 1);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 1);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 1);
@@ -3705,14 +3753,14 @@ test_config_directory_fetch(void *arg)
mock_router_pick_published_address_result = -1;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 1);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 1);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 0);
mock_router_pick_published_address_result = 0;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 0);
@@ -3733,7 +3781,7 @@ test_config_directory_fetch(void *arg)
options->RefuseUnknownExits = 1;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 1);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 1);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 0);
@@ -3741,7 +3789,7 @@ test_config_directory_fetch(void *arg)
mock_router_pick_published_address_result = 0;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 0);
@@ -3763,7 +3811,7 @@ test_config_directory_fetch(void *arg)
mock_router_get_my_routerinfo_result = &routerinfo;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 1);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 1);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 0);
@@ -3772,7 +3820,7 @@ test_config_directory_fetch(void *arg)
mock_router_get_my_routerinfo_result = &routerinfo;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 0);
@@ -3780,7 +3828,7 @@ test_config_directory_fetch(void *arg)
mock_router_get_my_routerinfo_result = NULL;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 0);
@@ -3790,7 +3838,7 @@ test_config_directory_fetch(void *arg)
mock_router_get_my_routerinfo_result = &routerinfo;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 0);
@@ -3800,7 +3848,7 @@ test_config_directory_fetch(void *arg)
mock_router_get_my_routerinfo_result = &routerinfo;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 1);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 1);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 0);
@@ -3816,7 +3864,9 @@ static void
test_config_default_fallback_dirs(void *arg)
{
const char *fallback[] = {
+#ifndef COCCI
#include "app/config/fallback_dirs.inc"
+#endif
NULL
};
@@ -3998,40 +4048,40 @@ test_config_parse_port_config__ports__no_ports_given(void *data)
slout = smartlist_new();
// Test no defaultport, no defaultaddress and no out
- ret = parse_port_config(NULL, NULL, "DNS", 0, NULL, 0, 0);
+ ret = port_parse_config(NULL, NULL, "DNS", 0, NULL, 0, 0);
tt_int_op(ret, OP_EQ, 0);
// Test with defaultport, no defaultaddress and no out
- ret = parse_port_config(NULL, NULL, "DNS", 0, NULL, 42, 0);
+ ret = port_parse_config(NULL, NULL, "DNS", 0, NULL, 42, 0);
tt_int_op(ret, OP_EQ, 0);
// Test no defaultport, with defaultaddress and no out
- ret = parse_port_config(NULL, NULL, "DNS", 0, "127.0.0.2", 0, 0);
+ ret = port_parse_config(NULL, NULL, "DNS", 0, "127.0.0.2", 0, 0);
tt_int_op(ret, OP_EQ, 0);
// Test with defaultport, with defaultaddress and no out
- ret = parse_port_config(NULL, NULL, "DNS", 0, "127.0.0.2", 42, 0);
+ ret = port_parse_config(NULL, NULL, "DNS", 0, "127.0.0.2", 42, 0);
tt_int_op(ret, OP_EQ, 0);
// Test no defaultport, no defaultaddress and with out
- ret = parse_port_config(slout, NULL, "DNS", 0, NULL, 0, 0);
+ ret = port_parse_config(slout, NULL, "DNS", 0, NULL, 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 0);
// Test with defaultport, no defaultaddress and with out
- ret = parse_port_config(slout, NULL, "DNS", 0, NULL, 42, 0);
+ ret = port_parse_config(slout, NULL, "DNS", 0, NULL, 42, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 0);
// Test no defaultport, with defaultaddress and with out
- ret = parse_port_config(slout, NULL, "DNS", 0, "127.0.0.2", 0, 0);
+ ret = port_parse_config(slout, NULL, "DNS", 0, "127.0.0.2", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 0);
// Test with defaultport, with defaultaddress and out, adds a new port cfg
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
- ret = parse_port_config(slout, NULL, "DNS", 0, "127.0.0.2", 42, 0);
+ ret = port_parse_config(slout, NULL, "DNS", 0, "127.0.0.2", 42, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
port_cfg = (port_cfg_t *)smartlist_get(slout, 0);
@@ -4042,7 +4092,7 @@ test_config_parse_port_config__ports__no_ports_given(void *data)
// for a unix address
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
- ret = parse_port_config(slout, NULL, "DNS", 0, "/foo/bar/unixdomain",
+ ret = port_parse_config(slout, NULL, "DNS", 0, "/foo/bar/unixdomain",
42, CL_PORT_IS_UNIXSOCKET);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4073,28 +4123,28 @@ test_config_parse_port_config__ports__ports_given(void *data)
// Test error when encounters an invalid Port specification
config_port_invalid = mock_config_line("DNSPort", "");
- ret = parse_port_config(NULL, config_port_invalid, "DNS", 0, NULL,
+ ret = port_parse_config(NULL, config_port_invalid, "DNS", 0, NULL,
0, 0);
tt_int_op(ret, OP_EQ, -1);
// Test error when encounters an empty unix domain specification
config_free_lines(config_port_invalid); config_port_invalid = NULL;
config_port_invalid = mock_config_line("DNSPort", "unix:");
- ret = parse_port_config(NULL, config_port_invalid, "DNS", 0, NULL,
+ ret = port_parse_config(NULL, config_port_invalid, "DNS", 0, NULL,
0, 0);
tt_int_op(ret, OP_EQ, -1);
// Test error when encounters a unix domain specification but the listener
// doesn't support domain sockets
config_port_valid = mock_config_line("DNSPort", "unix:/tmp/foo/bar");
- ret = parse_port_config(NULL, config_port_valid, "DNS",
+ ret = port_parse_config(NULL, config_port_valid, "DNS",
CONN_TYPE_AP_DNS_LISTENER, NULL, 0, 0);
tt_int_op(ret, OP_EQ, -1);
// Test valid unix domain
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
- ret = parse_port_config(slout, config_port_valid, "SOCKS",
+ ret = port_parse_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0, 0);
#ifdef _WIN32
tt_int_op(ret, OP_EQ, -1);
@@ -4105,9 +4155,11 @@ test_config_parse_port_config__ports__ports_given(void *data)
tt_int_op(port_cfg->port, OP_EQ, 0);
tt_int_op(port_cfg->is_unix_addr, OP_EQ, 1);
tt_str_op(port_cfg->unix_addr, OP_EQ, "/tmp/foo/bar");
- /* Test entry port defaults as initialised in parse_port_config */
+ /* Test entry port defaults as initialised in port_parse_config */
tt_int_op(port_cfg->entry_cfg.dns_request, OP_EQ, 1);
tt_int_op(port_cfg->entry_cfg.ipv4_traffic, OP_EQ, 1);
+ tt_int_op(port_cfg->entry_cfg.ipv6_traffic, OP_EQ, 1);
+ tt_int_op(port_cfg->entry_cfg.prefer_ipv6, OP_EQ, 0);
tt_int_op(port_cfg->entry_cfg.onion_traffic, OP_EQ, 1);
tt_int_op(port_cfg->entry_cfg.cache_ipv4_answers, OP_EQ, 0);
tt_int_op(port_cfg->entry_cfg.prefer_ipv6_virtaddr, OP_EQ, 1);
@@ -4119,7 +4171,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
"unix:/tmp/foo/bar NoIPv4Traffic "
"NoIPv6Traffic "
"NoOnionTraffic");
- ret = parse_port_config(NULL, config_port_invalid, "SOCKS",
+ ret = port_parse_config(NULL, config_port_invalid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, -1);
@@ -4128,7 +4180,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_free_lines(config_port_invalid); config_port_invalid = NULL;
config_port_invalid = mock_config_line("DNSPort",
"127.0.0.1:80 NoDNSRequest");
- ret = parse_port_config(NULL, config_port_invalid, "DNS",
+ ret = port_parse_config(NULL, config_port_invalid, "DNS",
CONN_TYPE_AP_DNS_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, -1);
@@ -4141,7 +4193,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_port_valid = mock_config_line("DNSPort", "127.0.0.1:80 "
"NoIPv6Traffic "
"NoIPv4Traffic NoOnionTraffic");
- ret = parse_port_config(slout, config_port_valid, "DNS",
+ ret = port_parse_config(slout, config_port_valid, "DNS",
CONN_TYPE_AP_DNS_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, 0);
@@ -4157,7 +4209,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_port_invalid = mock_config_line("SOCKSPort",
"NoIPv6Traffic "
"unix:/tmp/foo/bar NoIPv4Traffic");
- ret = parse_port_config(NULL, config_port_invalid, "SOCKS",
+ ret = port_parse_config(NULL, config_port_invalid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, -1);
@@ -4170,7 +4222,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_port_valid = mock_config_line("SOCKSPort", "unix:/tmp/foo/bar "
"NoIPv6Traffic "
"NoDNSRequest NoIPv4Traffic");
- ret = parse_port_config(slout, config_port_valid, "SOCKS",
+ ret = port_parse_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
#ifdef _WIN32
@@ -4192,7 +4244,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_port_valid = mock_config_line("SOCKSPort", "unix:\"/tmp/foo/ bar\" "
"NoIPv6Traffic "
"NoDNSRequest NoIPv4Traffic");
- ret = parse_port_config(slout, config_port_valid, "SOCKS",
+ ret = port_parse_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
#ifdef _WIN32
@@ -4214,7 +4266,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_port_valid = mock_config_line("SOCKSPort", "unix:\"/tmp/foo/ bar "
"NoIPv6Traffic "
"NoDNSRequest NoIPv4Traffic");
- ret = parse_port_config(slout, config_port_valid, "SOCKS",
+ ret = port_parse_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, -1);
@@ -4226,7 +4278,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_port_valid = mock_config_line("SOCKSPort", "unix:\"\" "
"NoIPv6Traffic "
"NoDNSRequest NoIPv4Traffic");
- ret = parse_port_config(slout, config_port_valid, "SOCKS",
+ ret = port_parse_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, -1);
@@ -4237,7 +4289,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
smartlist_clear(slout);
config_port_valid = mock_config_line("SOCKSPort", "unix:/tmp/foo/bar "
"OnionTrafficOnly");
- ret = parse_port_config(slout, config_port_valid, "SOCKS",
+ ret = port_parse_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
#ifdef _WIN32
@@ -4258,7 +4310,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
smartlist_clear(slout);
config_port_valid = mock_config_line("SOCKSPort", "unix:/tmp/foo/bar "
"NoIPv4Traffic IPv6Traffic");
- ret = parse_port_config(slout, config_port_valid, "SOCKS",
+ ret = port_parse_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
#ifdef _WIN32
@@ -4277,7 +4329,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
smartlist_clear(slout);
config_port_valid = mock_config_line("SOCKSPort", "unix:/tmp/foo/bar "
"IPv4Traffic IPv6Traffic");
- ret = parse_port_config(slout, config_port_valid, "SOCKS",
+ ret = port_parse_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
#ifdef _WIN32
@@ -4293,28 +4345,28 @@ test_config_parse_port_config__ports__ports_given(void *data)
// Test failure if we specify world writable for an IP Port
config_free_lines(config_port_invalid); config_port_invalid = NULL;
config_port_invalid = mock_config_line("DNSPort", "42 WorldWritable");
- ret = parse_port_config(NULL, config_port_invalid, "DNS", 0,
+ ret = port_parse_config(NULL, config_port_invalid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, -1);
// Test failure if we specify group writable for an IP Port
config_free_lines(config_port_invalid); config_port_invalid = NULL;
config_port_invalid = mock_config_line("DNSPort", "42 GroupWritable");
- ret = parse_port_config(NULL, config_port_invalid, "DNS", 0,
+ ret = port_parse_config(NULL, config_port_invalid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, -1);
// Test failure if we specify group writable for an IP Port
config_free_lines(config_port_invalid); config_port_invalid = NULL;
config_port_invalid = mock_config_line("DNSPort", "42 RelaxDirModeCheck");
- ret = parse_port_config(NULL, config_port_invalid, "DNS", 0,
+ ret = port_parse_config(NULL, config_port_invalid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, -1);
// Test success with only a port (this will fail without a default address)
config_free_lines(config_port_valid); config_port_valid = NULL;
config_port_valid = mock_config_line("DNSPort", "42");
- ret = parse_port_config(NULL, config_port_valid, "DNS", 0,
+ ret = port_parse_config(NULL, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
@@ -4323,7 +4375,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 IsolateDestPort");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4336,7 +4388,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 NoIsolateDestPorts");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4349,7 +4401,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 IsolateDestAddr");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4362,7 +4414,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 IsolateSOCKSAuth");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4375,7 +4427,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 IsolateClientProtocol");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4388,7 +4440,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 IsolateClientAddr");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4399,7 +4451,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
// Test success with ignored unknown options
config_free_lines(config_port_valid); config_port_valid = NULL;
config_port_valid = mock_config_line("DNSPort", "42 ThisOptionDoesntExist");
- ret = parse_port_config(NULL, config_port_valid, "DNS", 0,
+ ret = port_parse_config(NULL, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
@@ -4408,7 +4460,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 NoIsolateSOCKSAuth");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4421,7 +4473,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
smartlist_clear(slout);
config_port_valid = mock_config_line("SOCKSPort",
"42 IPv6Traffic PreferIPv6");
- ret = parse_port_config(slout, config_port_valid, "SOCKS",
+ ret = port_parse_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, "127.0.0.42", 0,
CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, 0);
@@ -4434,7 +4486,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 CacheIPv4DNS");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4447,7 +4499,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 CacheIPv6DNS");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4460,7 +4512,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 NoCacheIPv4DNS");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4473,7 +4525,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 CacheDNS");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4486,7 +4538,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 UseIPv4Cache");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4499,7 +4551,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 UseIPv6Cache");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4512,7 +4564,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 UseDNSCache");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4525,7 +4577,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 NoPreferIPv6Automap");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4537,7 +4589,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 PreferSOCKSNoAuth");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4552,14 +4604,14 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_port_invalid = mock_config_line("DNSPort", "0");
config_port_valid = mock_config_line("DNSPort", "42");
config_port_invalid->next = config_port_valid;
- ret = parse_port_config(slout, config_port_invalid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_invalid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, -1);
// Test success with warn non-local control
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
- ret = parse_port_config(slout, config_port_valid, "Control",
+ ret = port_parse_config(slout, config_port_valid, "Control",
CONN_TYPE_CONTROL_LISTENER, "127.0.0.42", 0,
CL_PORT_WARN_NONLOCAL);
tt_int_op(ret, OP_EQ, 0);
@@ -4567,7 +4619,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
// Test success with warn non-local listener
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
- ret = parse_port_config(slout, config_port_valid, "ExtOR",
+ ret = port_parse_config(slout, config_port_valid, "ExtOR",
CONN_TYPE_EXT_OR_LISTENER, "127.0.0.42", 0,
CL_PORT_WARN_NONLOCAL);
tt_int_op(ret, OP_EQ, 0);
@@ -4575,12 +4627,12 @@ test_config_parse_port_config__ports__ports_given(void *data)
// Test success with warn non-local other
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, CL_PORT_WARN_NONLOCAL);
tt_int_op(ret, OP_EQ, 0);
// Test success with warn non-local other without out
- ret = parse_port_config(NULL, config_port_valid, "DNS", 0,
+ ret = port_parse_config(NULL, config_port_valid, "DNS", 0,
"127.0.0.42", 0, CL_PORT_WARN_NONLOCAL);
tt_int_op(ret, OP_EQ, 0);
@@ -4591,7 +4643,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 IPv4Traffic "
"IPv6Traffic");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.44", 0,
CL_PORT_TAKES_HOSTNAMES |
CL_PORT_NO_STREAM_OPTIONS);
@@ -4606,7 +4658,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "42 SessionGroup=invalid");
- ret = parse_port_config(slout, config_port_invalid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_invalid, "DNS", 0,
"127.0.0.44", 0, CL_PORT_NO_STREAM_OPTIONS);
tt_int_op(ret, OP_EQ, -1);
@@ -4616,7 +4668,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "42 SessionGroup=123");
- ret = parse_port_config(slout, config_port_invalid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_invalid, "DNS", 0,
"127.0.0.44", 0, CL_PORT_NO_STREAM_OPTIONS);
tt_int_op(ret, OP_EQ, -1);
@@ -4626,7 +4678,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "42 SessionGroup=123 "
"SessionGroup=321");
- ret = parse_port_config(slout, config_port_invalid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_invalid, "DNS", 0,
"127.0.0.44", 0, 0);
tt_int_op(ret, OP_EQ, -1);
@@ -4635,7 +4687,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 SessionGroup=1111122");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.44", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4647,7 +4699,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "0");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.45", 0, CL_PORT_IS_UNIXSOCKET);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 0);
@@ -4657,7 +4709,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "something");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.45", 0, CL_PORT_IS_UNIXSOCKET);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4670,48 +4722,48 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "auto");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.46", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
port_cfg = (port_cfg_t *)smartlist_get(slout, 0);
tt_int_op(port_cfg->port, OP_EQ, CFG_AUTO_PORT);
tor_addr_parse(&addr, "127.0.0.46");
- tt_assert(tor_addr_eq(&port_cfg->addr, &addr))
+ tt_assert(tor_addr_eq(&port_cfg->addr, &addr));
// Test success with a port of auto in mixed case
config_free_lines(config_port_valid); config_port_valid = NULL;
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "AuTo");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.46", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
port_cfg = (port_cfg_t *)smartlist_get(slout, 0);
tt_int_op(port_cfg->port, OP_EQ, CFG_AUTO_PORT);
tor_addr_parse(&addr, "127.0.0.46");
- tt_assert(tor_addr_eq(&port_cfg->addr, &addr))
+ tt_assert(tor_addr_eq(&port_cfg->addr, &addr));
// Test success with parsing both an address and an auto port
config_free_lines(config_port_valid); config_port_valid = NULL;
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "127.0.0.122:auto");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.46", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
port_cfg = (port_cfg_t *)smartlist_get(slout, 0);
tt_int_op(port_cfg->port, OP_EQ, CFG_AUTO_PORT);
tor_addr_parse(&addr, "127.0.0.122");
- tt_assert(tor_addr_eq(&port_cfg->addr, &addr))
+ tt_assert(tor_addr_eq(&port_cfg->addr, &addr));
// Test failure when asked to parse an invalid address followed by auto
config_free_lines(config_port_invalid); config_port_invalid = NULL;
config_port_invalid = mock_config_line("DNSPort", "invalidstuff!!:auto");
MOCK(tor_addr_lookup, mock_tor_addr_lookup__fail_on_bad_addrs);
- ret = parse_port_config(NULL, config_port_invalid, "DNS", 0,
+ ret = port_parse_config(NULL, config_port_invalid, "DNS", 0,
"127.0.0.46", 0, 0);
UNMOCK(tor_addr_lookup);
tt_int_op(ret, OP_EQ, -1);
@@ -4721,21 +4773,21 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "127.0.0.123:656");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.46", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
port_cfg = (port_cfg_t *)smartlist_get(slout, 0);
tt_int_op(port_cfg->port, OP_EQ, 656);
tor_addr_parse(&addr, "127.0.0.123");
- tt_assert(tor_addr_eq(&port_cfg->addr, &addr))
+ tt_assert(tor_addr_eq(&port_cfg->addr, &addr));
// Test failure if we can't parse anything at all
config_free_lines(config_port_invalid); config_port_invalid = NULL;
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "something wrong");
- ret = parse_port_config(slout, config_port_invalid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_invalid, "DNS", 0,
"127.0.0.46", 0, 0);
tt_int_op(ret, OP_EQ, -1);
@@ -4744,7 +4796,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "127.0.1.0:123:auto");
- ret = parse_port_config(slout, config_port_invalid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_invalid, "DNS", 0,
"127.0.0.46", 0, 0);
tt_int_op(ret, OP_EQ, -1);
@@ -4754,7 +4806,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("SOCKSPort", "unix:/tmp/somewhere");
- ret = parse_port_config(slout, config_port_valid, "SOCKS",
+ ret = port_parse_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, "127.0.0.46", 0,
CL_PORT_DFLT_GROUP_WRITABLE);
#ifdef _WIN32
@@ -4790,7 +4842,7 @@ test_config_parse_port_config__ports__server_options(void *data)
config_free_lines(config_port_valid); config_port_valid = NULL;
config_port_valid = mock_config_line("DNSPort",
"127.0.0.124:656 NoAdvertise");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0, NULL, 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0, NULL, 0,
CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4803,7 +4855,7 @@ test_config_parse_port_config__ports__server_options(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "127.0.0.124:656 NoListen");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0, NULL, 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0, NULL, 0,
CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4817,7 +4869,7 @@ test_config_parse_port_config__ports__server_options(void *data)
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "127.0.0.124:656 NoListen "
"NoAdvertise");
- ret = parse_port_config(slout, config_port_invalid, "DNS", 0, NULL,
+ ret = port_parse_config(slout, config_port_invalid, "DNS", 0, NULL,
0, CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, -1);
@@ -4826,7 +4878,7 @@ test_config_parse_port_config__ports__server_options(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "127.0.0.124:656 IPv4Only");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0, NULL, 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0, NULL, 0,
CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4839,7 +4891,7 @@ test_config_parse_port_config__ports__server_options(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "[::1]:656 IPv6Only");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0, NULL, 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0, NULL, 0,
CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4853,7 +4905,7 @@ test_config_parse_port_config__ports__server_options(void *data)
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "127.0.0.124:656 IPv6Only "
"IPv4Only");
- ret = parse_port_config(slout, config_port_invalid, "DNS", 0, NULL,
+ ret = port_parse_config(slout, config_port_invalid, "DNS", 0, NULL,
0, CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, -1);
@@ -4862,7 +4914,7 @@ test_config_parse_port_config__ports__server_options(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "127.0.0.124:656 unknown");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0, NULL, 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0, NULL, 0,
CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4873,7 +4925,7 @@ test_config_parse_port_config__ports__server_options(void *data)
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort",
"127.0.0.124:656 IPv6Only");
- ret = parse_port_config(slout, config_port_invalid, "DNS", 0, NULL,
+ ret = port_parse_config(slout, config_port_invalid, "DNS", 0, NULL,
0, CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, -1);
@@ -4882,7 +4934,7 @@ test_config_parse_port_config__ports__server_options(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "[::1]:656 IPv4Only");
- ret = parse_port_config(slout, config_port_invalid, "DNS", 0, NULL,
+ ret = port_parse_config(slout, config_port_invalid, "DNS", 0, NULL,
0, CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, -1);
@@ -4891,7 +4943,7 @@ test_config_parse_port_config__ports__server_options(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_invalid = mock_config_line("ORPort", "unix:\"\"");
- ret = parse_port_config(slout, config_port_invalid, "ORPort", 0, NULL,
+ ret = port_parse_config(slout, config_port_invalid, "ORPort", 0, NULL,
0, CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, -1);
@@ -4904,6 +4956,71 @@ test_config_parse_port_config__ports__server_options(void *data)
}
static void
+test_config_get_first_advertised(void *data)
+{
+ (void)data;
+ int r, w=0, n=0;
+ char *msg=NULL;
+ or_options_t *opts = options_new();
+ int port;
+ const tor_addr_t *addr;
+
+ // no ports are configured? We get NULL.
+ port = get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER,
+ AF_INET);
+ tt_int_op(port, OP_EQ, 0);
+ addr = get_first_advertised_addr_by_type_af(CONN_TYPE_OR_LISTENER,
+ AF_INET);
+ tt_ptr_op(addr, OP_EQ, NULL);
+
+ port = get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER,
+ AF_INET6);
+ tt_int_op(port, OP_EQ, 0);
+ addr = get_first_advertised_addr_by_type_af(CONN_TYPE_OR_LISTENER,
+ AF_INET6);
+ tt_ptr_op(addr, OP_EQ, NULL);
+
+ config_line_append(&opts->ORPort_lines, "ORPort", "[1234::5678]:8080");
+ config_line_append(&opts->ORPort_lines, "ORPort",
+ "1.2.3.4:9999 noadvertise");
+ config_line_append(&opts->ORPort_lines, "ORPort",
+ "5.6.7.8:9911 nolisten");
+
+ r = parse_ports(opts, 0, &msg, &n, &w);
+ tt_assert(r == 0);
+
+ // UNSPEC gets us nothing.
+ port = get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER,
+ AF_UNSPEC);
+ tt_int_op(port, OP_EQ, 0);
+ addr = get_first_advertised_addr_by_type_af(CONN_TYPE_OR_LISTENER,
+ AF_UNSPEC);
+ tt_ptr_op(addr, OP_EQ, NULL);
+
+ // Try AF_INET.
+ port = get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER,
+ AF_INET);
+ tt_int_op(port, OP_EQ, 9911);
+ addr = get_first_advertised_addr_by_type_af(CONN_TYPE_OR_LISTENER,
+ AF_INET);
+ tt_ptr_op(addr, OP_NE, NULL);
+ tt_str_op(fmt_addrport(addr,port), OP_EQ, "5.6.7.8:9911");
+
+ // Try AF_INET6
+ port = get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER,
+ AF_INET6);
+ tt_int_op(port, OP_EQ, 8080);
+ addr = get_first_advertised_addr_by_type_af(CONN_TYPE_OR_LISTENER,
+ AF_INET6);
+ tt_ptr_op(addr, OP_NE, NULL);
+ tt_str_op(fmt_addrport(addr,port), OP_EQ, "[1234::5678]:8080");
+
+ done:
+ or_options_free(opts);
+ config_free_all();
+}
+
+static void
test_config_parse_log_severity(void *data)
{
int ret;
@@ -5640,7 +5757,6 @@ test_config_check_bridge_distribution_setting_not_a_bridge(void *arg)
{
or_options_t* options = get_options_mutable();
or_options_t* old_options = options;
- or_options_t* default_options = options;
char* message = NULL;
int ret;
@@ -5649,7 +5765,7 @@ test_config_check_bridge_distribution_setting_not_a_bridge(void *arg)
options->BridgeRelay = 0;
options->BridgeDistribution = (char*)("https");
- ret = options_validate(old_options, options, default_options, 0, &message);
+ ret = options_validate(old_options, options, &message);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(message, OP_EQ, "You set BridgeDistribution, but you "
@@ -6064,6 +6180,36 @@ test_config_kvline_parse(void *arg)
tt_str_op(lines->next->next->value, OP_EQ, "I");
enc = kvline_encode(lines, KV_OMIT_VALS|KV_QUOTED);
tt_str_op(enc, OP_EQ, "AB=\"CD E\" DE FGH=I");
+ tor_free(enc);
+ config_free_lines(lines);
+
+ lines = kvline_parse("AB=CD \"EF=GH\"", KV_OMIT_KEYS|KV_QUOTED);
+ tt_assert(lines);
+ tt_str_op(lines->key, OP_EQ, "AB");
+ tt_str_op(lines->value, OP_EQ, "CD");
+ tt_str_op(lines->next->key, OP_EQ, "");
+ tt_str_op(lines->next->value, OP_EQ, "EF=GH");
+ enc = kvline_encode(lines, KV_OMIT_KEYS);
+ tt_assert(!enc);
+ enc = kvline_encode(lines, KV_OMIT_KEYS|KV_QUOTED);
+ tt_assert(enc);
+ tt_str_op(enc, OP_EQ, "AB=CD \"EF=GH\"");
+ tor_free(enc);
+ config_free_lines(lines);
+
+ lines = tor_malloc_zero(sizeof(*lines));
+ lines->key = tor_strdup("A=B");
+ lines->value = tor_strdup("CD");
+ enc = kvline_encode(lines, 0);
+ tt_assert(!enc);
+ config_free_lines(lines);
+
+ config_line_append(&lines, "A", "B C");
+ enc = kvline_encode(lines, 0);
+ tt_assert(!enc);
+ enc = kvline_encode(lines, KV_RAW);
+ tt_assert(enc);
+ tt_str_op(enc, OP_EQ, "A=B C");
done:
config_free_lines(lines);
@@ -6113,6 +6259,7 @@ struct testcase_t config_tests[] = {
CONFIG_TEST(parse_bridge_line, 0),
CONFIG_TEST(parse_transport_options_line, 0),
CONFIG_TEST(parse_transport_plugin_line, TT_FORK),
+ CONFIG_TEST(parse_tcp_proxy_line, TT_FORK),
CONFIG_TEST(check_or_create_data_subdir, TT_FORK),
CONFIG_TEST(write_to_data_subdir, TT_FORK),
CONFIG_TEST(fix_my_family, 0),
@@ -6121,6 +6268,7 @@ struct testcase_t config_tests[] = {
CONFIG_TEST(parse_port_config__ports__no_ports_given, 0),
CONFIG_TEST(parse_port_config__ports__server_options, 0),
CONFIG_TEST(parse_port_config__ports__ports_given, 0),
+ CONFIG_TEST(get_first_advertised, TT_FORK),
CONFIG_TEST(parse_log_severity, 0),
CONFIG_TEST(include_limit, 0),
CONFIG_TEST(include_does_not_exist, 0),
diff --git a/src/test/test_confmgr.c b/src/test/test_confmgr.c
index d5c73b48e4..a647b92e0a 100644
--- a/src/test/test_confmgr.c
+++ b/src/test/test_confmgr.c
@@ -1,19 +1,19 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/*
- * Tests for confparse.c's features that support multiple configuration
+ * Tests for confmgt.c's features that support multiple configuration
* formats and configuration objects.
*/
-#define CONFPARSE_PRIVATE
+#define CONFMGT_PRIVATE
#include "orconfig.h"
#include "core/or/or.h"
#include "lib/encoding/confline.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "test/test.h"
#include "test/log_test_helpers.h"
@@ -43,6 +43,8 @@ typedef struct {
int fuzziness;
char *alpacaname;
int n_wings; /* deprecated; alpacas don't have wings. */
+
+ int square_fuzziness; /* Derived from fuzziness. */
} alpaca_cfg_t;
/*
@@ -105,6 +107,84 @@ static config_abbrev_t llama_abbrevs[] = {
{ NULL, NULL, 0, 0 },
};
+static int
+legacy_validate_pasture(const void *old_, void *obj, char **msg_out)
+{
+ const pasture_cfg_t *old = old_;
+ pasture_cfg_t *p = obj;
+
+ // llamas can't find their way home if the letters are lowercase.
+ if (p->address)
+ tor_strupper(p->address);
+
+ if (old && old->address &&
+ (!p->address || strcmp(old->address, p->address))) {
+ *msg_out = tor_strdup("You can't move a pasture.");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+validate_llama(const void *obj, char **msg_out)
+{
+ const llama_cfg_t *llama = obj;
+ tor_assert(llama->magic == 0x11aa11);
+
+ if (! llama->llamaname || strlen(llama->llamaname) == 0) {
+ *msg_out = tor_strdup("A llama has no name!?");
+ return -1;
+ }
+
+ if (strspn(llama->llamaname, "0123456789") == strlen(llama->llamaname)) {
+ *msg_out = tor_strdup("It is not a number; it is a free llama!");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+check_transition_alpaca(const void *old_, const void *new_, char **msg_out)
+{
+ const alpaca_cfg_t *old_alpaca = old_;
+ const alpaca_cfg_t *new_alpaca = new_;
+
+ tor_assert(old_alpaca && new_alpaca);
+ tor_assert(old_alpaca->magic == 0xa15aca);
+ tor_assert(new_alpaca->magic == 0xa15aca);
+
+ if (old_alpaca->fuzziness > new_alpaca->fuzziness) {
+ *msg_out = tor_strdup("An alpaca only becomes more fuzzy over time.");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+post_normalize_llama(void *obj, char **msg_out)
+{
+ (void)msg_out;
+ llama_cfg_t *llama = obj;
+ tor_assert(llama->magic == 0x11aa11);
+ tor_assert(llama->llamaname); // we have already checked for a NULL name.
+ tor_free(llama->description);
+ tor_asprintf(&llama->description, "A llama called %s.", llama->llamaname);
+ return 0;
+}
+
+static int
+pre_normalize_alpaca(void *obj, char **msg_out)
+{
+ (void)msg_out;
+ alpaca_cfg_t *alpaca = obj;
+ tor_assert(alpaca->magic == 0xa15aca);
+ alpaca->square_fuzziness = alpaca->fuzziness * alpaca->fuzziness;
+ return 0;
+}
+
static const config_format_t pasture_fmt = {
sizeof(pasture_cfg_t),
{
@@ -113,7 +193,9 @@ static const config_format_t pasture_fmt = {
offsetof(pasture_cfg_t, magic)
},
.vars = pasture_vars,
+ .has_config_suite = true,
.config_suite_offset = offsetof(pasture_cfg_t, subobjs),
+ .legacy_validate_fn = legacy_validate_pasture,
};
static const config_format_t llama_fmt = {
@@ -124,10 +206,11 @@ static const config_format_t llama_fmt = {
offsetof(llama_cfg_t, magic)
},
.vars = llama_vars,
- .config_suite_offset = -1,
.deprecations = llama_deprecations,
.abbrevs = llama_abbrevs,
.clear_fn = clear_llama_cfg,
+ .validate_fn = validate_llama,
+ .post_normalize_fn = post_normalize_llama,
};
static const config_format_t alpaca_fmt = {
@@ -138,8 +221,9 @@ static const config_format_t alpaca_fmt = {
offsetof(alpaca_cfg_t, magic)
},
.vars = alpaca_vars,
- .config_suite_offset = -1,
.deprecations = alpaca_deprecations,
+ .pre_normalize_fn = pre_normalize_alpaca,
+ .check_transition_fn = check_transition_alpaca,
};
#define LLAMA_IDX 0
@@ -313,6 +397,95 @@ test_confmgr_dump(void *arg)
tor_free(s);
}
+static pasture_cfg_t *
+parse_and_validate(config_mgr_t *mgr,
+ const char *inp, const pasture_cfg_t *old, char **msg_out)
+{
+ pasture_cfg_t *p = config_new(mgr);
+ pasture_cfg_t *result = NULL;
+ config_line_t *lines = NULL;
+
+ config_init(mgr, p); // set defaults.
+ int r = config_get_lines(inp, &lines, 0);
+ tt_int_op(r, OP_EQ, 0);
+ r = config_assign(mgr, p, lines, 0, msg_out);
+ tt_int_op(r, OP_EQ, 0);
+ tor_free(*msg_out); // sets it to NULL
+ r = config_validate(mgr, old, p, msg_out);
+ if (r < 0)
+ goto done;
+
+ tt_ptr_op(*msg_out, OP_EQ, NULL);
+ result = p;
+ p = NULL; // prevent free
+ done:
+ config_free(mgr, p);
+ config_free_lines(lines);
+ return result;
+}
+
+static void
+test_confmgr_validate(void *arg)
+{
+ (void)arg;
+ char *msg = NULL;
+ config_mgr_t *mgr = get_mgr(true);
+ pasture_cfg_t *p_orig, *p=NULL;
+
+ p_orig = parse_and_validate(mgr, "Llamaname Quest\n"
+ "Address 99 camelid way\n"
+ "Fuzziness 8\n", NULL, &msg);
+ tt_assert(p_orig);
+
+ // Make sure normalization code was run.
+ const alpaca_cfg_t *ac0 = config_mgr_get_obj(mgr, p_orig, ALPACA_IDX);
+ const llama_cfg_t *lc0 = config_mgr_get_obj(mgr, p_orig, LLAMA_IDX);
+ tt_int_op(ac0->fuzziness, OP_EQ, 8);
+ tt_int_op(ac0->square_fuzziness, OP_EQ, 64);
+ tt_str_op(lc0->description, OP_EQ, "A llama called Quest.");
+ tt_str_op(p_orig->address, OP_EQ, "99 CAMELID WAY");
+
+ // try a bad llamaname.
+ p = parse_and_validate(mgr, "llamaname 123", p_orig, &msg);
+ tt_assert(!p);
+ tt_str_op(msg, OP_EQ, "It is not a number; it is a free llama!");
+ tor_free(msg);
+
+ // try a llamaname that would crash the post_normalize step, if it ran.
+ p = parse_and_validate(mgr, "", p_orig, &msg);
+ tt_assert(!p);
+ tt_str_op(msg, OP_EQ, "A llama has no name!?");
+ tor_free(msg);
+
+ // Verify that a transition to a less fuzzy alpaca fails.
+ p = parse_and_validate(mgr, "Llamaname Quest\n"
+ "Address 99 camelid way\n"
+ "Fuzziness 4\n", p_orig, &msg);
+ tt_assert(!p);
+ tt_str_op(msg, OP_EQ, "An alpaca only becomes more fuzzy over time.");
+ tor_free(msg);
+
+ // Try a transition to a more fuzzy alpaca; it should work fine.
+ p = parse_and_validate(mgr, "Llamaname Mercutio\n"
+ // the default fuzziness is 50
+ "Address 99 camelid way\n", p_orig, &msg);
+ tt_assert(p);
+ config_free(mgr, p);
+
+ // Verify that we can't move the pasture.
+ p = parse_and_validate(mgr, "Llamaname Montague\n"
+ // the default fuzziness is 50
+ "Address 99 ungulate st\n", p_orig, &msg);
+ tt_assert(!p);
+ tt_str_op(msg, OP_EQ, "You can't move a pasture.");
+
+ done:
+ config_free(mgr, p);
+ config_free(mgr, p_orig);
+ config_mgr_free(mgr);
+ tor_free(msg);
+}
+
#define CONFMGR_TEST(name, flags) \
{ #name, test_confmgr_ ## name, flags, NULL, NULL }
@@ -321,5 +494,6 @@ struct testcase_t confmgr_tests[] = {
CONFMGR_TEST(magic, 0),
CONFMGR_TEST(parse, 0),
CONFMGR_TEST(dump, 0),
+ CONFMGR_TEST(validate, 0),
END_OF_TESTCASES
};
diff --git a/src/test/test_confparse.c b/src/test/test_confparse.c
index 5f29a22c10..21301ce75e 100644
--- a/src/test/test_confparse.c
+++ b/src/test/test_confparse.c
@@ -1,20 +1,20 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/*
- * Tests for confparse.c module that we use to parse various
+ * Tests for confmgt.c module that we use to parse various
* configuration/state file types.
*/
-#define CONFPARSE_PRIVATE
+#define CONFMGT_PRIVATE
#include "orconfig.h"
#include "core/or/or.h"
#include "lib/encoding/confline.h"
#include "feature/nodelist/routerset.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "test/test.h"
#include "test/log_test_helpers.h"
@@ -103,12 +103,9 @@ static config_deprecation_t test_deprecation_notes[] = {
};
static int
-test_validate_cb(void *old_options, void *options, void *default_options,
- int from_setconf, char **msg)
+test_validate_cb(const void *old_options, void *options, char **msg)
{
(void)old_options;
- (void)default_options;
- (void)from_setconf;
(void)msg;
test_struct_t *ts = options;
@@ -122,19 +119,16 @@ test_validate_cb(void *old_options, void *options, void *default_options,
#define TEST_MAGIC 0x1337
static const config_format_t test_fmt = {
- sizeof(test_struct_t),
- {
+ .size = sizeof(test_struct_t),
+ .magic = {
"test_struct_t",
TEST_MAGIC,
offsetof(test_struct_t, magic),
},
- test_abbrevs,
- test_deprecation_notes,
- test_vars,
- test_validate_cb,
- NULL,
- NULL,
- -1,
+ .abbrevs = test_abbrevs,
+ .deprecations = test_deprecation_notes,
+ .vars = test_vars,
+ .legacy_validate_fn = test_validate_cb,
};
/* Make sure that config_init sets everything to the right defaults. */
@@ -818,19 +812,17 @@ static struct_member_t extra = {
};
static config_format_t etest_fmt = {
- sizeof(test_struct_t),
- {
+ .size = sizeof(test_struct_t),
+ .magic = {
"test_struct_t (with extra lines)",
ETEST_MAGIC,
offsetof(test_struct_t, magic),
},
- test_abbrevs,
- test_deprecation_notes,
- test_vars,
- test_validate_cb,
- NULL,
- &extra,
- -1,
+ .abbrevs = test_abbrevs,
+ .deprecations = test_deprecation_notes,
+ .vars = test_vars,
+ .legacy_validate_fn = test_validate_cb,
+ .extra = &extra,
};
/* Try out the feature where we can store unrecognized lines and dump them
@@ -906,11 +898,22 @@ test_confparse_unitparse(void *args)
tt_assert(ok);
/* u64 overflow */
- /* XXXX our implementation does not currently detect this. See bug 30920. */
- /*
tt_u64_op(config_parse_memunit("20000000 TB", &ok), OP_EQ, 0);
tt_assert(!ok);
- */
+ // This test fails the double check as the float representing 15000000.5 TB
+ // is greater than (double) INT64_MAX
+ tt_u64_op(config_parse_memunit("15000000.5 TB", &ok), OP_EQ, 0);
+ tt_assert(!ok);
+ // 8388608.1 TB passes double check because it falls in the same float
+ // value as (double)INT64_MAX (which is 2^63) due to precision.
+ // But will fail the int check because the unsigned representation of
+ // the float, which is 2^63, is strictly greater than INT64_MAX (2^63-1)
+ tt_u64_op(config_parse_memunit("8388608.1 TB", &ok), OP_EQ, 0);
+ tt_assert(!ok);
+
+ /* negative float */
+ tt_u64_op(config_parse_memunit("-1.5 GB", &ok), OP_EQ, 0);
+ tt_assert(!ok);
/* i32 overflow */
tt_int_op(config_parse_interval("1000 months", &ok), OP_EQ, -1);
@@ -1037,12 +1040,14 @@ test_confparse_find_option_name(void *arg)
config_mgr_free(mgr);
}
+#ifndef COCCI
#define CONFPARSE_TEST(name, flags) \
{ #name, test_confparse_ ## name, flags, NULL, NULL }
#define BADVAL_TEST(name) \
{ "badval_" #name, test_confparse_assign_badval, 0, \
&passthrough_setup, (void*)&bv_ ## name }
+#endif /* !defined(COCCI) */
struct testcase_t confparse_tests[] = {
CONFPARSE_TEST(init, 0),
diff --git a/src/test/test_connection.c b/src/test/test_connection.c
index ebe7c6d36f..7ed831f7d8 100644
--- a/src/test/test_connection.c
+++ b/src/test/test_connection.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2019, The Tor Project, Inc. */
+/* Copyright (c) 2015-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -10,6 +10,7 @@
#include "core/or/or.h"
#include "test/test.h"
+#include "app/config/or_options_st.h"
#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
#include "feature/hs/hs_common.h"
@@ -312,6 +313,25 @@ test_conn_download_status_teardown(const struct testcase_t *tc, void *arg)
return rv;
}
+static void *
+test_conn_proxy_connect_setup(const struct testcase_t *tc)
+{
+ return test_conn_get_proxy_or_connection(*(unsigned int *)tc->setup_data);
+}
+
+static int
+test_conn_proxy_connect_teardown(const struct testcase_t *tc, void *arg)
+{
+ (void)tc;
+ or_connection_t *conn = arg;
+
+ tt_assert(conn);
+ assert_connection_ok(&conn->base_, time(NULL));
+
+ done:
+ return 1;
+}
+
/* Like connection_ap_make_link(), but does much less */
static connection_t *
test_conn_get_linked_connection(connection_t *l_conn, uint8_t state)
@@ -360,6 +380,10 @@ static struct testcase_setup_t test_conn_download_status_st = {
test_conn_download_status_setup, test_conn_download_status_teardown
};
+static struct testcase_setup_t test_conn_proxy_connect_st = {
+ test_conn_proxy_connect_setup, test_conn_proxy_connect_teardown
+};
+
static void
test_conn_get_basic(void *arg)
{
@@ -788,6 +812,64 @@ test_conn_download_status(void *arg)
/* the teardown function removes all the connections in the global list*/;
}
+static void
+test_conn_https_proxy_connect(void *arg)
+{
+ size_t sz;
+ char *buf = NULL;
+ or_connection_t *conn = arg;
+
+ MOCK(connection_or_change_state, mock_connection_or_change_state);
+
+ tt_int_op(conn->base_.proxy_state, OP_EQ, PROXY_HTTPS_WANT_CONNECT_OK);
+
+ buf = buf_get_contents(conn->base_.outbuf, &sz);
+ tt_str_op(buf, OP_EQ, "CONNECT 127.0.0.1:12345 HTTP/1.0\r\n\r\n");
+
+ done:
+ UNMOCK(connection_or_change_state);
+ tor_free(buf);
+}
+
+static int handshake_start_called = 0;
+
+static int
+handshake_start(or_connection_t *conn, int receiving)
+{
+ (void)receiving;
+
+ tor_assert(conn);
+
+ handshake_start_called = 1;
+ return 0;
+}
+
+static void
+test_conn_haproxy_proxy_connect(void *arg)
+{
+ size_t sz;
+ char *buf = NULL;
+ or_connection_t *conn = arg;
+
+ MOCK(connection_or_change_state, mock_connection_or_change_state);
+ MOCK(connection_tls_start_handshake, handshake_start);
+
+ tt_int_op(conn->base_.proxy_state, OP_EQ, PROXY_HAPROXY_WAIT_FOR_FLUSH);
+
+ buf = buf_get_contents(conn->base_.outbuf, &sz);
+ tt_str_op(buf, OP_EQ, "PROXY TCP4 0.0.0.0 127.0.0.1 0 12345\r\n");
+
+ connection_or_finished_flushing(conn);
+
+ tt_int_op(conn->base_.proxy_state, OP_EQ, PROXY_CONNECTED);
+ tt_int_op(handshake_start_called, OP_EQ, 1);
+
+ done:
+ UNMOCK(connection_or_change_state);
+ UNMOCK(connection_tls_start_handshake);
+ tor_free(buf);
+}
+
static node_t test_node;
static node_t *
@@ -881,21 +963,33 @@ test_failed_orconn_tracker(void *arg)
;
}
+#ifndef COCCI
#define CONNECTION_TESTCASE(name, fork, setup) \
{ #name, test_conn_##name, fork, &setup, NULL }
/* where arg is an expression (constant, variable, compound expression) */
#define CONNECTION_TESTCASE_ARG(name, fork, setup, arg) \
{ #name "_" #arg, test_conn_##name, fork, &setup, (void *)arg }
+#endif /* !defined(COCCI) */
+
+static const unsigned int PROXY_CONNECT_ARG = PROXY_CONNECT;
+static const unsigned int PROXY_HAPROXY_ARG = PROXY_HAPROXY;
struct testcase_t connection_tests[] = {
CONNECTION_TESTCASE(get_basic, TT_FORK, test_conn_get_basic_st),
CONNECTION_TESTCASE(get_rend, TT_FORK, test_conn_get_rend_st),
CONNECTION_TESTCASE(get_rsrc, TT_FORK, test_conn_get_rsrc_st),
- CONNECTION_TESTCASE_ARG(download_status, TT_FORK,
+
+ CONNECTION_TESTCASE_ARG(download_status, TT_FORK,
test_conn_download_status_st, FLAV_MICRODESC),
- CONNECTION_TESTCASE_ARG(download_status, TT_FORK,
+ CONNECTION_TESTCASE_ARG(download_status, TT_FORK,
test_conn_download_status_st, FLAV_NS),
+
+ CONNECTION_TESTCASE_ARG(https_proxy_connect, TT_FORK,
+ test_conn_proxy_connect_st, &PROXY_CONNECT_ARG),
+ CONNECTION_TESTCASE_ARG(haproxy_proxy_connect, TT_FORK,
+ test_conn_proxy_connect_st, &PROXY_HAPROXY_ARG),
+
//CONNECTION_TESTCASE(func_suffix, TT_FORK, setup_func_pair),
{ "failed_orconn_tracker", test_failed_orconn_tracker, TT_FORK, NULL, NULL },
END_OF_TESTCASES
diff --git a/src/test/test_connection.h b/src/test/test_connection.h
index 40121e6d38..bf327c0a3d 100644
--- a/src/test/test_connection.h
+++ b/src/test/test_connection.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_TEST_CONNECTION_H
@@ -7,9 +7,10 @@
/** Some constants used by test_connection and helpers */
#define TEST_CONN_FAMILY (AF_INET)
#define TEST_CONN_ADDRESS "127.0.0.1"
+#define TEST_CONN_ADDRESS_2 "127.0.0.2"
#define TEST_CONN_PORT (12345)
#define TEST_CONN_ADDRESS_PORT "127.0.0.1:12345"
-#define TEST_CONN_FD_INIT 50
+#define TEST_CONN_FD_INIT 0x10000
void test_conn_lookup_addr_helper(const char *address,
int family, tor_addr_t *addr);
diff --git a/src/test/test_conscache.c b/src/test/test_conscache.c
index 095ff09350..c805774fa3 100644
--- a/src/test/test_conscache.c
+++ b/src/test/test_conscache.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
diff --git a/src/test/test_consdiff.c b/src/test/test_consdiff.c
index 7c4c92ea42..e4cfece9c3 100644
--- a/src/test/test_consdiff.c
+++ b/src/test/test_consdiff.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2014, Daniel Martí
- * Copyright (c) 2014-2019, The Tor Project, Inc. */
+ * Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONSDIFF_PRIVATE
diff --git a/src/test/test_consdiffmgr.c b/src/test/test_consdiffmgr.c
index 74226b8c52..4bec6baeb0 100644
--- a/src/test/test_consdiffmgr.c
+++ b/src/test/test_consdiffmgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONSDIFFMGR_PRIVATE
@@ -119,7 +119,7 @@ typedef struct fake_work_queue_ent_t {
void (*reply_fn)(void *);
void *arg;
} fake_work_queue_ent_t;
-static struct workqueue_entry_s *
+static struct workqueue_entry_t *
mock_cpuworker_queue_work(workqueue_priority_t prio,
enum workqueue_reply_t (*fn)(void *, void *),
void (*reply_fn)(void *),
@@ -135,7 +135,7 @@ mock_cpuworker_queue_work(workqueue_priority_t prio,
ent->reply_fn = reply_fn;
ent->arg = arg;
smartlist_add(fake_cpuworker_queue, ent);
- return (struct workqueue_entry_s *)ent;
+ return (struct workqueue_entry_t *)ent;
}
static int
mock_cpuworker_run_work(void)
diff --git a/src/test/test_containers.c b/src/test/test_containers.c
index 67ba457975..6072148d1b 100644
--- a/src/test/test_containers.c
+++ b/src/test/test_containers.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_controller.c b/src/test/test_controller.c
index 55eb79e448..a69ec17db8 100644
--- a/src/test/test_controller.c
+++ b/src/test/test_controller.c
@@ -1,9 +1,10 @@
-/* Copyright (c) 2015-2019, The Tor Project, Inc. */
+/* Copyright (c) 2015-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONTROL_CMD_PRIVATE
#define CONTROL_GETINFO_PRIVATE
#include "core/or/or.h"
+#include "app/config/config.h"
#include "lib/crypt_ops/crypto_ed25519.h"
#include "feature/client/bridges.h"
#include "feature/control/control.h"
@@ -11,6 +12,8 @@
#include "feature/control/control_getinfo.h"
#include "feature/control/control_proto.h"
#include "feature/client/entrynodes.h"
+#include "feature/dircache/cached_dir_st.h"
+#include "feature/dircache/dirserv.h"
#include "feature/hs/hs_common.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/rend/rendservice.h"
@@ -119,6 +122,7 @@ test_controller_parse_cmd(void *arg)
control_cmd_args_free(result);
}
+#ifndef COCCI
#define OK(inp, out) \
{ inp "\r\n", out, NULL }
#define ERR(inp, err) \
@@ -128,6 +132,7 @@ test_controller_parse_cmd(void *arg)
{ &syntax, \
ARRAY_LENGTH(array), \
array }
+#endif /* !defined(COCCI) */
static const parser_testcase_t one_to_three_tests[] = {
ERR("", "Need at least 1 argument(s)"),
@@ -1691,6 +1696,138 @@ test_download_status_bridge(void *arg)
return;
}
+/** Mock cached consensus */
+static cached_dir_t *mock_ns_consensus_cache;
+static cached_dir_t *mock_microdesc_consensus_cache;
+
+/** Mock the function that retrieves consensus from cache. These use a
+ * global variable so that they can be cleared from within the test.
+ * The actual code retains the pointer to the consensus data, but
+ * we are doing this here, to prevent memory leaks
+ * from within the tests */
+static cached_dir_t *
+mock_dirserv_get_consensus(const char *flavor_name)
+{
+ if (!strcmp(flavor_name, "ns")) {
+ mock_ns_consensus_cache = tor_malloc_zero(sizeof(cached_dir_t));
+ mock_ns_consensus_cache->dir = tor_strdup("mock_ns_consensus");
+ return mock_ns_consensus_cache;
+ } else {
+ mock_microdesc_consensus_cache = tor_malloc_zero(sizeof(cached_dir_t));
+ mock_microdesc_consensus_cache->dir = tor_strdup(
+ "mock_microdesc_consensus");
+ return mock_microdesc_consensus_cache;
+ }
+}
+
+/** Mock the function that retrieves consensuses
+ * from a files in the directory. */
+static tor_mmap_t *
+mock_tor_mmap_file(const char* filename)
+{
+ tor_mmap_t *res;
+ res = tor_malloc_zero(sizeof(tor_mmap_t));
+ if (strstr(filename, "cached-consensus") != NULL) {
+ res->data = "mock_ns_consensus";
+ } else if (strstr(filename, "cached-microdesc-consensus") != NULL) {
+ res->data = "mock_microdesc_consensus";
+ } else {
+ res->data = ".";
+ }
+ res->size = strlen(res->data);
+ return res;
+}
+
+/** Mock the function that clears file data
+ * loaded into the memory */
+static int
+mock_tor_munmap_file(tor_mmap_t *handle)
+{
+ tor_free(handle);
+ return 0;
+}
+
+static void
+test_getinfo_helper_current_consensus_from_file(void *arg)
+{
+ /* We just need one of these to pass, it doesn't matter what's in it */
+ control_connection_t dummy;
+ /* Get results out */
+ char *answer = NULL;
+ const char *errmsg = NULL;
+
+ (void)arg;
+
+ MOCK(tor_mmap_file, mock_tor_mmap_file);
+ MOCK(tor_munmap_file, mock_tor_munmap_file);
+
+ getinfo_helper_dir(&dummy,
+ "dir/status-vote/current/consensus",
+ &answer,
+ &errmsg);
+ tt_str_op(answer, OP_EQ, "mock_ns_consensus");
+ tt_ptr_op(errmsg, OP_EQ, NULL);
+ tor_free(answer);
+ errmsg = NULL;
+
+ getinfo_helper_dir(&dummy,
+ "dir/status-vote/current/consensus-microdesc",
+ &answer,
+ &errmsg);
+ tt_str_op(answer, OP_EQ, "mock_microdesc_consensus");
+ tt_ptr_op(errmsg, OP_EQ, NULL);
+ errmsg = NULL;
+
+ done:
+ tor_free(answer);
+ UNMOCK(tor_mmap_file);
+ UNMOCK(tor_munmap_file);
+ return;
+}
+
+static void
+test_getinfo_helper_current_consensus_from_cache(void *arg)
+{
+ /* We just need one of these to pass, it doesn't matter what's in it */
+ control_connection_t dummy;
+ /* Get results out */
+ char *answer = NULL;
+ const char *errmsg = NULL;
+
+ (void)arg;
+ or_options_t *options = get_options_mutable();
+ options->FetchUselessDescriptors = 1;
+ MOCK(dirserv_get_consensus, mock_dirserv_get_consensus);
+
+ getinfo_helper_dir(&dummy,
+ "dir/status-vote/current/consensus",
+ &answer,
+ &errmsg);
+ tt_str_op(answer, OP_EQ, "mock_ns_consensus");
+ tt_ptr_op(errmsg, OP_EQ, NULL);
+ tor_free(answer);
+ tor_free(mock_ns_consensus_cache->dir);
+ tor_free(mock_ns_consensus_cache);
+ errmsg = NULL;
+
+ getinfo_helper_dir(&dummy,
+ "dir/status-vote/current/consensus-microdesc",
+ &answer,
+ &errmsg);
+ tt_str_op(answer, OP_EQ, "mock_microdesc_consensus");
+ tt_ptr_op(errmsg, OP_EQ, NULL);
+ tor_free(mock_microdesc_consensus_cache->dir);
+ tor_free(answer);
+ errmsg = NULL;
+
+ done:
+ options->FetchUselessDescriptors = 0;
+ tor_free(answer);
+ tor_free(mock_microdesc_consensus_cache);
+ UNMOCK(dirserv_get_consensus);
+ return;
+}
+
/** Set timeval to a mock date and time. This is necessary
* to make tor_gettimeofday() mockable. */
static void
@@ -1820,9 +1957,166 @@ test_getinfo_md_all(void *arg)
return;
}
+static smartlist_t *reply_strs;
+
+static void
+mock_control_write_reply_list(control_connection_t *conn, int code, int c,
+ const char *s)
+{
+ (void)conn;
+ /* To make matching easier, don't append "\r\n" */
+ smartlist_add_asprintf(reply_strs, "%03d%c%s", code, c, s);
+}
+
+static void
+test_control_reply(void *arg)
+{
+ (void)arg;
+ smartlist_t *lines = smartlist_new();
+
+ MOCK(control_write_reply, mock_control_write_reply);
+
+ tor_free(reply_str);
+ control_reply_clear(lines);
+ control_reply_add_str(lines, 250, "FOO");
+ control_write_reply_lines(NULL, lines);
+ tt_str_op(reply_str, OP_EQ, "FOO");
+
+ tor_free(reply_str);
+ control_reply_clear(lines);
+ control_reply_add_done(lines);
+ control_write_reply_lines(NULL, lines);
+ tt_str_op(reply_str, OP_EQ, "OK");
+
+ tor_free(reply_str);
+ control_reply_clear(lines);
+ UNMOCK(control_write_reply);
+ MOCK(control_write_reply, mock_control_write_reply_list);
+ reply_strs = smartlist_new();
+ control_reply_add_one_kv(lines, 250, 0, "A", "B");
+ control_reply_add_one_kv(lines, 250, 0, "C", "D");
+ control_write_reply_lines(NULL, lines);
+ tt_int_op(smartlist_len(reply_strs), OP_EQ, 2);
+ tt_str_op((char *)smartlist_get(reply_strs, 0), OP_EQ, "250-A=B");
+ tt_str_op((char *)smartlist_get(reply_strs, 1), OP_EQ, "250 C=D");
+
+ control_reply_clear(lines);
+ SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
+ smartlist_clear(reply_strs);
+ control_reply_add_printf(lines, 250, "PROTOCOLINFO %d", 1);
+ control_reply_add_one_kv(lines, 250, KV_OMIT_VALS|KV_RAW, "AUTH", "");
+ control_reply_append_kv(lines, "METHODS", "COOKIE");
+ control_reply_append_kv(lines, "COOKIEFILE", escaped("/tmp/cookie"));
+ control_reply_add_done(lines);
+ control_write_reply_lines(NULL, lines);
+ tt_int_op(smartlist_len(reply_strs), OP_EQ, 3);
+ tt_str_op((char *)smartlist_get(reply_strs, 0),
+ OP_EQ, "250-PROTOCOLINFO 1");
+ tt_str_op((char *)smartlist_get(reply_strs, 1),
+ OP_EQ, "250-AUTH METHODS=COOKIE COOKIEFILE=\"/tmp/cookie\"");
+ tt_str_op((char *)smartlist_get(reply_strs, 2),
+ OP_EQ, "250 OK");
+
+ done:
+ UNMOCK(control_write_reply);
+ tor_free(reply_str);
+ control_reply_free(lines);
+ if (reply_strs)
+ SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
+ smartlist_free(reply_strs);
+ return;
+}
+
+static void
+test_control_getconf(void *arg)
+{
+ (void)arg;
+ control_connection_t conn;
+ char *args = NULL;
+ int r = -1;
+
+ memset(&conn, 0, sizeof(conn));
+ conn.current_cmd = tor_strdup("GETCONF");
+
+ MOCK(control_write_reply, mock_control_write_reply_list);
+ reply_strs = smartlist_new();
+
+ args = tor_strdup("");
+ r = handle_control_command(&conn, (uint32_t)strlen(args), args);
+ tt_int_op(r, OP_EQ, 0);
+ tt_int_op(smartlist_len(reply_strs), OP_EQ, 1);
+ tt_str_op((char *)smartlist_get(reply_strs, 0), OP_EQ, "250 OK");
+ SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
+ smartlist_clear(reply_strs);
+ tor_free(args);
+
+ args = tor_strdup("NoSuch");
+ r = handle_control_command(&conn, (uint32_t)strlen(args), args);
+ tt_int_op(r, OP_EQ, 0);
+ tt_int_op(smartlist_len(reply_strs), OP_EQ, 1);
+ tt_str_op((char *)smartlist_get(reply_strs, 0), OP_EQ,
+ "552 Unrecognized configuration key \"NoSuch\"");
+ tor_free(args);
+ SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
+ smartlist_clear(reply_strs);
+
+ args = tor_strdup("NoSuch1 NoSuch2");
+ r = handle_control_command(&conn, (uint32_t)strlen(args), args);
+ tt_int_op(r, OP_EQ, 0);
+ tt_int_op(smartlist_len(reply_strs), OP_EQ, 2);
+ tt_str_op((char *)smartlist_get(reply_strs, 0), OP_EQ,
+ "552-Unrecognized configuration key \"NoSuch1\"");
+ tt_str_op((char *)smartlist_get(reply_strs, 1), OP_EQ,
+ "552 Unrecognized configuration key \"NoSuch2\"");
+ tor_free(args);
+ SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
+ smartlist_clear(reply_strs);
+
+ args = tor_strdup("ControlPort NoSuch");
+ r = handle_control_command(&conn, (uint32_t)strlen(args), args);
+ tt_int_op(r, OP_EQ, 0);
+ /* Valid keys ignored if there are any invalid ones */
+ tt_int_op(smartlist_len(reply_strs), OP_EQ, 1);
+ tt_str_op((char *)smartlist_get(reply_strs, 0), OP_EQ,
+ "552 Unrecognized configuration key \"NoSuch\"");
+ tor_free(args);
+ SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
+ smartlist_clear(reply_strs);
+
+ args = tor_strdup("ClientOnly");
+ r = handle_control_command(&conn, (uint32_t)strlen(args), args);
+ tt_int_op(r, OP_EQ, 0);
+ tt_int_op(smartlist_len(reply_strs), OP_EQ, 1);
+ /* According to config.c, this is an exception for the unit tests */
+ tt_str_op((char *)smartlist_get(reply_strs, 0), OP_EQ, "250 ClientOnly=0");
+ tor_free(args);
+ SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
+ smartlist_clear(reply_strs);
+
+ args = tor_strdup("BridgeRelay ClientOnly");
+ r = handle_control_command(&conn, (uint32_t)strlen(args), args);
+ tt_int_op(r, OP_EQ, 0);
+ tt_int_op(smartlist_len(reply_strs), OP_EQ, 2);
+ /* Change if config.c changes BridgeRelay default (unlikely) */
+ tt_str_op((char *)smartlist_get(reply_strs, 0), OP_EQ, "250-BridgeRelay=0");
+ tt_str_op((char *)smartlist_get(reply_strs, 1), OP_EQ, "250 ClientOnly=0");
+ tor_free(args);
+ SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
+ smartlist_clear(reply_strs);
+
+ done:
+ tor_free(conn.current_cmd);
+ tor_free(args);
+ UNMOCK(control_write_reply);
+ SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
+ smartlist_free(reply_strs);
+}
+
+#ifndef COCCI
#define PARSER_TEST(type) \
{ "parse/" #type, test_controller_parse_cmd, 0, &passthrough_setup, \
(void*)&parse_ ## type ## _params }
+#endif
struct testcase_t controller_tests[] = {
PARSER_TEST(one_to_three),
@@ -1840,11 +2134,17 @@ struct testcase_t controller_tests[] = {
NULL },
{ "download_status_consensus", test_download_status_consensus, 0, NULL,
NULL },
+ {"getinfo_helper_current_consensus_from_cache",
+ test_getinfo_helper_current_consensus_from_cache, 0, NULL, NULL },
+ {"getinfo_helper_current_consensus_from_file",
+ test_getinfo_helper_current_consensus_from_file, 0, NULL, NULL },
{ "download_status_cert", test_download_status_cert, 0, NULL,
NULL },
{ "download_status_desc", test_download_status_desc, 0, NULL, NULL },
{ "download_status_bridge", test_download_status_bridge, 0, NULL, NULL },
{ "current_time", test_current_time, 0, NULL, NULL },
{ "getinfo_md_all", test_getinfo_md_all, 0, NULL, NULL },
+ { "control_reply", test_control_reply, 0, NULL, NULL },
+ { "control_getconf", test_control_getconf, 0, NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_controller_events.c b/src/test/test_controller_events.c
index 0d276ef8a6..60dfbd630a 100644
--- a/src/test/test_controller_events.c
+++ b/src/test/test_controller_events.c
@@ -1,8 +1,8 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONNECTION_PRIVATE
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define CONTROL_PRIVATE
#define CONTROL_EVENTS_PRIVATE
#define OCIRC_EVENT_PRIVATE
@@ -16,12 +16,15 @@
#include "core/or/orconn_event.h"
#include "core/mainloop/connection.h"
#include "feature/control/control_events.h"
+#include "feature/control/control_fmt.h"
#include "test/test.h"
#include "test/test_helpers.h"
#include "test/log_test_helpers.h"
+#include "core/or/entry_connection_st.h"
#include "core/or/or_circuit_st.h"
#include "core/or/origin_circuit_st.h"
+#include "core/or/socks_request_st.h"
static void
add_testing_cell_stats_entry(circuit_t *circ, uint8_t command,
@@ -575,6 +578,133 @@ test_cntev_orconn_state_proxy(void *arg)
UNMOCK(queue_control_event_string);
}
+static void
+test_cntev_format_stream(void *arg)
+{
+ entry_connection_t *ec = NULL;
+ char *conndesc = NULL;
+ (void)arg;
+
+ ec = entry_connection_new(CONN_TYPE_AP, AF_INET);
+
+ char *username = tor_strdup("jeremy");
+ char *password = tor_strdup("letmein");
+ ec->socks_request->username = username; // steal reference
+ ec->socks_request->usernamelen = strlen(username);
+ ec->socks_request->password = password; // steal reference
+ ec->socks_request->passwordlen = strlen(password);
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "SOCKS_USERNAME=\"jeremy\""));
+ tt_assert(strstr(conndesc, "SOCKS_PASSWORD=\"letmein\""));
+ tor_free(conndesc);
+
+ ec->socks_request->listener_type = CONN_TYPE_AP_LISTENER;
+ ec->socks_request->socks_version = 4;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=SOCKS4"));
+ tor_free(conndesc);
+
+ ec->socks_request->listener_type = CONN_TYPE_AP_LISTENER;
+ ec->socks_request->socks_version = 5;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=SOCKS5"));
+ tor_free(conndesc);
+
+ ec->socks_request->listener_type = CONN_TYPE_AP_LISTENER;
+ ec->socks_request->socks_version = 6;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=UNKNOWN"));
+ tor_free(conndesc);
+
+ ec->socks_request->listener_type = CONN_TYPE_AP_TRANS_LISTENER;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=TRANS"));
+ tor_free(conndesc);
+
+ ec->socks_request->listener_type = CONN_TYPE_AP_NATD_LISTENER;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=NATD"));
+ tor_free(conndesc);
+
+ ec->socks_request->listener_type = CONN_TYPE_AP_DNS_LISTENER;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=DNS"));
+ tor_free(conndesc);
+
+ ec->socks_request->listener_type = CONN_TYPE_AP_HTTP_CONNECT_LISTENER;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=HTTPCONNECT"));
+ tor_free(conndesc);
+
+ ec->socks_request->listener_type = CONN_TYPE_OR;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=UNKNOWN"));
+ tor_free(conndesc);
+
+ ec->nym_epoch = 1337;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "NYM_EPOCH=1337"));
+ tor_free(conndesc);
+
+ ec->entry_cfg.session_group = 4321;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "SESSION_GROUP=4321"));
+ tor_free(conndesc);
+
+ ec->entry_cfg.isolation_flags = ISO_DESTPORT;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "ISO_FIELDS=DESTPORT"));
+ tt_assert(!strstr(conndesc, "ISO_FIELDS=DESTPORT,"));
+ tor_free(conndesc);
+
+ ec->entry_cfg.isolation_flags = ISO_DESTADDR;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "ISO_FIELDS=DESTADDR"));
+ tt_assert(!strstr(conndesc, "ISO_FIELDS=DESTADDR,"));
+ tor_free(conndesc);
+
+ ec->entry_cfg.isolation_flags = ISO_SOCKSAUTH;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "ISO_FIELDS=SOCKS_USERNAME,SOCKS_PASSWORD"));
+ tt_assert(!strstr(conndesc, "ISO_FIELDS=SOCKS_USERNAME,SOCKS_PASSWORD,"));
+ tor_free(conndesc);
+
+ ec->entry_cfg.isolation_flags = ISO_CLIENTPROTO;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "ISO_FIELDS=CLIENT_PROTOCOL"));
+ tt_assert(!strstr(conndesc, "ISO_FIELDS=CLIENT_PROTOCOL,"));
+ tor_free(conndesc);
+
+ ec->entry_cfg.isolation_flags = ISO_CLIENTADDR;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "ISO_FIELDS=CLIENTADDR"));
+ tt_assert(!strstr(conndesc, "ISO_FIELDS=CLIENTADDR,"));
+ tor_free(conndesc);
+
+ ec->entry_cfg.isolation_flags = ISO_SESSIONGRP;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "ISO_FIELDS=SESSION_GROUP"));
+ tt_assert(!strstr(conndesc, "ISO_FIELDS=SESSION_GROUP,"));
+ tor_free(conndesc);
+
+ ec->entry_cfg.isolation_flags = ISO_NYM_EPOCH;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "ISO_FIELDS=NYM_EPOCH"));
+ tt_assert(!strstr(conndesc, "ISO_FIELDS=NYM_EPOCH,"));
+ tor_free(conndesc);
+
+ ec->entry_cfg.isolation_flags = ISO_DESTPORT | ISO_SOCKSAUTH | ISO_NYM_EPOCH;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc,
+ "ISO_FIELDS=DESTPORT,SOCKS_USERNAME,SOCKS_PASSWORD,NYM_EPOCH"));
+ tt_assert(!strstr(conndesc,
+ "ISO_FIELDS=DESTPORT,SOCKS_USERNAME,SOCKS_PASSWORD,NYM_EPOCH,"));
+
+ done:
+ tor_free(conndesc);
+ connection_free_minimal(ENTRY_TO_CONN(ec));
+}
+
#define TEST(name, flags) \
{ #name, test_cntev_ ## name, flags, 0, NULL }
@@ -586,9 +716,10 @@ struct testcase_t controller_event_tests[] = {
TEST(append_cell_stats, TT_FORK),
TEST(format_cell_stats, TT_FORK),
TEST(event_mask, TT_FORK),
+ TEST(format_stream, TT_FORK),
+ TEST(signal, TT_FORK),
T_PUBSUB(dirboot_defer_desc, TT_FORK),
T_PUBSUB(dirboot_defer_orconn, TT_FORK),
- T_PUBSUB(signal, TT_FORK),
T_PUBSUB(orconn_state, TT_FORK),
T_PUBSUB(orconn_state_pt, TT_FORK),
T_PUBSUB(orconn_state_proxy, TT_FORK),
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c
index ed39f41560..0d75a212e9 100644
--- a/src/test/test_crypto.c
+++ b/src/test/test_crypto.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -29,9 +29,9 @@
#if defined(ENABLE_OPENSSL)
#include "lib/crypt_ops/compat_openssl.h"
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/dh.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
#endif /* defined(ENABLE_OPENSSL) */
/** Run unit tests for Diffie-Hellman functionality. */
@@ -3009,6 +3009,7 @@ test_crypto_failure_modes(void *arg)
;
}
+#ifndef COCCI
#define CRYPTO_LEGACY(name) \
{ #name, test_crypto_ ## name , 0, NULL, NULL }
@@ -3019,6 +3020,7 @@ test_crypto_failure_modes(void *arg)
#define ED25519_TEST(name, fl) \
ED25519_TEST_ONE(name, (fl), "donna"), \
ED25519_TEST_ONE(name, (fl), "ref10")
+#endif /* !defined(COCCI) */
struct testcase_t crypto_tests[] = {
CRYPTO_LEGACY(formats),
diff --git a/src/test/test_crypto_ope.c b/src/test/test_crypto_ope.c
index dc67c02676..119ebc114a 100644
--- a/src/test/test_crypto_ope.c
+++ b/src/test/test_crypto_ope.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_crypto_openssl.c b/src/test/test_crypto_openssl.c
index 42dc3f6be2..989f4a56ca 100644
--- a/src/test/test_crypto_openssl.c
+++ b/src/test/test_crypto_openssl.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_crypto_rng.c b/src/test/test_crypto_rng.c
index 6b7749a889..b0dc4c117c 100644
--- a/src/test/test_crypto_rng.c
+++ b/src/test/test_crypto_rng.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_crypto_slow.c b/src/test/test_crypto_slow.c
index 3b20dfa587..56319f2c72 100644
--- a/src/test/test_crypto_slow.c
+++ b/src/test/test_crypto_slow.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -584,6 +584,7 @@ test_crypto_ed25519_fuzz_donna(void *arg)
;
}
+#ifndef COCCI
#define CRYPTO_LEGACY(name) \
{ #name, test_crypto_ ## name , 0, NULL, NULL }
@@ -594,6 +595,7 @@ test_crypto_ed25519_fuzz_donna(void *arg)
#define ED25519_TEST(name, fl) \
ED25519_TEST_ONE(name, (fl), "donna"), \
ED25519_TEST_ONE(name, (fl), "ref10")
+#endif /* !defined(COCCI) */
struct testcase_t slow_crypto_tests[] = {
CRYPTO_LEGACY(s2k_rfc2440),
diff --git a/src/test/test_data.c b/src/test/test_data.c
index fe1190ea77..30c14fcfff 100644
--- a/src/test/test_data.c
+++ b/src/test/test_data.c
@@ -1,6 +1,6 @@
/* Copyright 2001-2004 Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "test/test.h"
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index 6329ff7750..3b2ba64d2c 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -9,9 +9,9 @@
#define BWAUTH_PRIVATE
#define CONFIG_PRIVATE
#define CONTROL_GETINFO_PRIVATE
+#define DIRAUTH_SYS_PRIVATE
#define DIRCACHE_PRIVATE
#define DIRCLIENT_PRIVATE
-#define DIRSERV_PRIVATE
#define DIRVOTE_PRIVATE
#define DLSTATUS_PRIVATE
#define HIBERNATE_PRIVATE
@@ -26,7 +26,7 @@
#include "core/or/or.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "core/mainloop/connection.h"
#include "core/or/relay.h"
#include "core/or/versions.h"
@@ -34,6 +34,7 @@
#include "feature/client/entrynodes.h"
#include "feature/control/control_getinfo.h"
#include "feature/dirauth/bwauth.h"
+#include "feature/dirauth/dirauth_sys.h"
#include "feature/dirauth/dirvote.h"
#include "feature/dirauth/dsigs_parse.h"
#include "feature/dirauth/process_descs.h"
@@ -50,6 +51,7 @@
#include "feature/hibernate/hibernate.h"
#include "feature/nodelist/authcert.h"
#include "feature/nodelist/dirlist.h"
+#include "feature/nodelist/microdesc.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nickname.h"
#include "feature/nodelist/node_select.h"
@@ -71,13 +73,16 @@
#include "lib/memarea/memarea.h"
#include "lib/osinfo/uname.h"
#include "test/log_test_helpers.h"
+#include "test/opts_test_helpers.h"
#include "test/test.h"
#include "test/test_dir_common.h"
#include "core/or/addr_policy_st.h"
+#include "feature/dirauth/dirauth_options_st.h"
#include "feature/nodelist/authority_cert_st.h"
#include "feature/nodelist/document_signature_st.h"
#include "feature/nodelist/extrainfo_st.h"
+#include "feature/nodelist/microdesc_st.h"
#include "feature/nodelist/networkstatus_st.h"
#include "feature/nodelist/networkstatus_voter_info_st.h"
#include "feature/dirauth/ns_detached_signatures_st.h"
@@ -95,8 +100,6 @@
#include <unistd.h>
#endif
-#define NS_MODULE dir
-
static networkstatus_t *
networkstatus_parse_vote_from_string_(const char *s,
const char **eos_out,
@@ -635,7 +638,6 @@ setup_dir_formats_options(const char *arg, or_options_t *options)
STMT_BEGIN \
tt_assert(r1); \
tt_assert(rp1); \
-\
tt_int_op(rp1->addr,OP_EQ, r1->addr); \
tt_int_op(rp1->or_port,OP_EQ, r1->or_port); \
tt_int_op(rp1->dir_port,OP_EQ, r1->dir_port); \
@@ -4691,10 +4693,13 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
(void)arg;
/* Init options */
+ dirauth_options_t *dirauth_options =
+ tor_malloc_zero(sizeof(dirauth_options_t));
+
mock_options = tor_malloc(sizeof(or_options_t));
reset_options(mock_options, &mock_get_options_calls);
-
MOCK(get_options, mock_get_options);
+ dirauth_set_options(dirauth_options);
/* Init routersets */
routerset_t *routerset_all = routerset_new();
@@ -4734,16 +4739,15 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
/* Check that "*" sets flags on all routers: Exit
* Check the flags aren't being confused with each other */
reset_options(mock_options, &mock_get_options_calls);
+ memset(dirauth_options, 0, sizeof(*dirauth_options));
reset_routerstatus(rs_a, ROUTER_A_ID_STR, ROUTER_A_IPV4);
reset_routerstatus(rs_b, ROUTER_B_ID_STR, ROUTER_B_IPV4);
- mock_options->TestingDirAuthVoteExit = routerset_all;
- mock_options->TestingDirAuthVoteExitIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteExit = routerset_all;
+ dirauth_options->TestingDirAuthVoteExitIsStrict = 0;
dirserv_set_routerstatus_testing(rs_a);
- tt_int_op(mock_get_options_calls, OP_EQ, 1);
dirserv_set_routerstatus_testing(rs_b);
- tt_int_op(mock_get_options_calls, OP_EQ, 2);
tt_uint_op(rs_a->is_exit, OP_EQ, 1);
tt_uint_op(rs_b->is_exit, OP_EQ, 1);
@@ -4756,18 +4760,17 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
/* Check that "*" sets flags on all routers: Guard & HSDir
* Cover the remaining flags in one test */
reset_options(mock_options, &mock_get_options_calls);
+ memset(dirauth_options, 0, sizeof(*dirauth_options));
reset_routerstatus(rs_a, ROUTER_A_ID_STR, ROUTER_A_IPV4);
reset_routerstatus(rs_b, ROUTER_B_ID_STR, ROUTER_B_IPV4);
- mock_options->TestingDirAuthVoteGuard = routerset_all;
- mock_options->TestingDirAuthVoteGuardIsStrict = 0;
- mock_options->TestingDirAuthVoteHSDir = routerset_all;
- mock_options->TestingDirAuthVoteHSDirIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteGuard = routerset_all;
+ dirauth_options->TestingDirAuthVoteGuardIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteHSDir = routerset_all;
+ dirauth_options->TestingDirAuthVoteHSDirIsStrict = 0;
dirserv_set_routerstatus_testing(rs_a);
- tt_int_op(mock_get_options_calls, OP_EQ, 1);
dirserv_set_routerstatus_testing(rs_b);
- tt_int_op(mock_get_options_calls, OP_EQ, 2);
tt_uint_op(rs_a->is_possible_guard, OP_EQ, 1);
tt_uint_op(rs_b->is_possible_guard, OP_EQ, 1);
@@ -4780,20 +4783,19 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
/* Check routerset A sets all flags on router A,
* but leaves router B unmodified */
reset_options(mock_options, &mock_get_options_calls);
+ memset(dirauth_options, 0, sizeof(*dirauth_options));
reset_routerstatus(rs_a, ROUTER_A_ID_STR, ROUTER_A_IPV4);
reset_routerstatus(rs_b, ROUTER_B_ID_STR, ROUTER_B_IPV4);
- mock_options->TestingDirAuthVoteExit = routerset_a;
- mock_options->TestingDirAuthVoteExitIsStrict = 0;
- mock_options->TestingDirAuthVoteGuard = routerset_a;
- mock_options->TestingDirAuthVoteGuardIsStrict = 0;
- mock_options->TestingDirAuthVoteHSDir = routerset_a;
- mock_options->TestingDirAuthVoteHSDirIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteExit = routerset_a;
+ dirauth_options->TestingDirAuthVoteExitIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteGuard = routerset_a;
+ dirauth_options->TestingDirAuthVoteGuardIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteHSDir = routerset_a;
+ dirauth_options->TestingDirAuthVoteHSDirIsStrict = 0;
dirserv_set_routerstatus_testing(rs_a);
- tt_int_op(mock_get_options_calls, OP_EQ, 1);
dirserv_set_routerstatus_testing(rs_b);
- tt_int_op(mock_get_options_calls, OP_EQ, 2);
tt_uint_op(rs_a->is_exit, OP_EQ, 1);
tt_uint_op(rs_b->is_exit, OP_EQ, 0);
@@ -4804,21 +4806,21 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
/* Check routerset A unsets all flags on router B when Strict is set */
reset_options(mock_options, &mock_get_options_calls);
+ memset(dirauth_options, 0, sizeof(*dirauth_options));
reset_routerstatus(rs_b, ROUTER_B_ID_STR, ROUTER_B_IPV4);
- mock_options->TestingDirAuthVoteExit = routerset_a;
- mock_options->TestingDirAuthVoteExitIsStrict = 1;
- mock_options->TestingDirAuthVoteGuard = routerset_a;
- mock_options->TestingDirAuthVoteGuardIsStrict = 1;
- mock_options->TestingDirAuthVoteHSDir = routerset_a;
- mock_options->TestingDirAuthVoteHSDirIsStrict = 1;
+ dirauth_options->TestingDirAuthVoteExit = routerset_a;
+ dirauth_options->TestingDirAuthVoteExitIsStrict = 1;
+ dirauth_options->TestingDirAuthVoteGuard = routerset_a;
+ dirauth_options->TestingDirAuthVoteGuardIsStrict = 1;
+ dirauth_options->TestingDirAuthVoteHSDir = routerset_a;
+ dirauth_options->TestingDirAuthVoteHSDirIsStrict = 1;
rs_b->is_exit = 1;
rs_b->is_possible_guard = 1;
rs_b->is_hs_dir = 1;
dirserv_set_routerstatus_testing(rs_b);
- tt_int_op(mock_get_options_calls, OP_EQ, 1);
tt_uint_op(rs_b->is_exit, OP_EQ, 0);
tt_uint_op(rs_b->is_possible_guard, OP_EQ, 0);
@@ -4826,21 +4828,21 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
/* Check routerset A doesn't modify flags on router B without Strict set */
reset_options(mock_options, &mock_get_options_calls);
+ memset(dirauth_options, 0, sizeof(*dirauth_options));
reset_routerstatus(rs_b, ROUTER_B_ID_STR, ROUTER_B_IPV4);
- mock_options->TestingDirAuthVoteExit = routerset_a;
- mock_options->TestingDirAuthVoteExitIsStrict = 0;
- mock_options->TestingDirAuthVoteGuard = routerset_a;
- mock_options->TestingDirAuthVoteGuardIsStrict = 0;
- mock_options->TestingDirAuthVoteHSDir = routerset_a;
- mock_options->TestingDirAuthVoteHSDirIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteExit = routerset_a;
+ dirauth_options->TestingDirAuthVoteExitIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteGuard = routerset_a;
+ dirauth_options->TestingDirAuthVoteGuardIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteHSDir = routerset_a;
+ dirauth_options->TestingDirAuthVoteHSDirIsStrict = 0;
rs_b->is_exit = 1;
rs_b->is_possible_guard = 1;
rs_b->is_hs_dir = 1;
dirserv_set_routerstatus_testing(rs_b);
- tt_int_op(mock_get_options_calls, OP_EQ, 1);
tt_uint_op(rs_b->is_exit, OP_EQ, 1);
tt_uint_op(rs_b->is_possible_guard, OP_EQ, 1);
@@ -4849,21 +4851,21 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
/* Check the empty routerset zeroes all flags
* on routers A & B with Strict set */
reset_options(mock_options, &mock_get_options_calls);
+ memset(dirauth_options, 0, sizeof(*dirauth_options));
reset_routerstatus(rs_b, ROUTER_B_ID_STR, ROUTER_B_IPV4);
- mock_options->TestingDirAuthVoteExit = routerset_none;
- mock_options->TestingDirAuthVoteExitIsStrict = 1;
- mock_options->TestingDirAuthVoteGuard = routerset_none;
- mock_options->TestingDirAuthVoteGuardIsStrict = 1;
- mock_options->TestingDirAuthVoteHSDir = routerset_none;
- mock_options->TestingDirAuthVoteHSDirIsStrict = 1;
+ dirauth_options->TestingDirAuthVoteExit = routerset_none;
+ dirauth_options->TestingDirAuthVoteExitIsStrict = 1;
+ dirauth_options->TestingDirAuthVoteGuard = routerset_none;
+ dirauth_options->TestingDirAuthVoteGuardIsStrict = 1;
+ dirauth_options->TestingDirAuthVoteHSDir = routerset_none;
+ dirauth_options->TestingDirAuthVoteHSDirIsStrict = 1;
rs_b->is_exit = 1;
rs_b->is_possible_guard = 1;
rs_b->is_hs_dir = 1;
dirserv_set_routerstatus_testing(rs_b);
- tt_int_op(mock_get_options_calls, OP_EQ, 1);
tt_uint_op(rs_b->is_exit, OP_EQ, 0);
tt_uint_op(rs_b->is_possible_guard, OP_EQ, 0);
@@ -4872,24 +4874,23 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
/* Check the empty routerset doesn't modify any flags
* on A or B without Strict set */
reset_options(mock_options, &mock_get_options_calls);
+ memset(dirauth_options, 0, sizeof(*dirauth_options));
reset_routerstatus(rs_a, ROUTER_A_ID_STR, ROUTER_A_IPV4);
reset_routerstatus(rs_b, ROUTER_B_ID_STR, ROUTER_B_IPV4);
- mock_options->TestingDirAuthVoteExit = routerset_none;
- mock_options->TestingDirAuthVoteExitIsStrict = 0;
- mock_options->TestingDirAuthVoteGuard = routerset_none;
- mock_options->TestingDirAuthVoteGuardIsStrict = 0;
- mock_options->TestingDirAuthVoteHSDir = routerset_none;
- mock_options->TestingDirAuthVoteHSDirIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteExit = routerset_none;
+ dirauth_options->TestingDirAuthVoteExitIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteGuard = routerset_none;
+ dirauth_options->TestingDirAuthVoteGuardIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteHSDir = routerset_none;
+ dirauth_options->TestingDirAuthVoteHSDirIsStrict = 0;
rs_b->is_exit = 1;
rs_b->is_possible_guard = 1;
rs_b->is_hs_dir = 1;
dirserv_set_routerstatus_testing(rs_a);
- tt_int_op(mock_get_options_calls, OP_EQ, 1);
dirserv_set_routerstatus_testing(rs_b);
- tt_int_op(mock_get_options_calls, OP_EQ, 2);
tt_uint_op(rs_a->is_exit, OP_EQ, 0);
tt_uint_op(rs_a->is_possible_guard, OP_EQ, 0);
@@ -4900,6 +4901,7 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
done:
tor_free(mock_options);
+ tor_free(dirauth_options);
mock_options = NULL;
UNMOCK(get_options);
@@ -5474,15 +5476,15 @@ test_dir_conn_purpose_to_string(void *data)
teardown_capture_of_logs();
}
-NS_DECL(int,
-public_server_mode, (const or_options_t *options));
+static int dir_tests_public_server_mode(const or_options_t *options);
+ATTR_UNUSED static int dir_tests_public_server_mode_called = 0;
static int
-NS(public_server_mode)(const or_options_t *options)
+dir_tests_public_server_mode(const or_options_t *options)
{
(void)options;
- if (CALLED(public_server_mode)++ == 0) {
+ if (dir_tests_public_server_mode_called++ == 0) {
return 1;
}
@@ -5496,13 +5498,14 @@ test_dir_should_use_directory_guards(void *data)
char *errmsg = NULL;
(void)data;
- NS_MOCK(public_server_mode);
+ MOCK(public_server_mode,
+ dir_tests_public_server_mode);
options = options_new();
options_init(options);
tt_int_op(should_use_directory_guards(options), OP_EQ, 0);
- tt_int_op(CALLED(public_server_mode), OP_EQ, 1);
+ tt_int_op(dir_tests_public_server_mode_called, OP_EQ, 1);
options->UseEntryGuards = 1;
options->DownloadExtraInfo = 0;
@@ -5510,41 +5513,41 @@ test_dir_should_use_directory_guards(void *data)
options->FetchDirInfoExtraEarly = 0;
options->FetchUselessDescriptors = 0;
tt_int_op(should_use_directory_guards(options), OP_EQ, 1);
- tt_int_op(CALLED(public_server_mode), OP_EQ, 2);
+ tt_int_op(dir_tests_public_server_mode_called, OP_EQ, 2);
options->UseEntryGuards = 0;
tt_int_op(should_use_directory_guards(options), OP_EQ, 0);
- tt_int_op(CALLED(public_server_mode), OP_EQ, 3);
+ tt_int_op(dir_tests_public_server_mode_called, OP_EQ, 3);
options->UseEntryGuards = 1;
options->DownloadExtraInfo = 1;
tt_int_op(should_use_directory_guards(options), OP_EQ, 0);
- tt_int_op(CALLED(public_server_mode), OP_EQ, 4);
+ tt_int_op(dir_tests_public_server_mode_called, OP_EQ, 4);
options->DownloadExtraInfo = 0;
options->FetchDirInfoEarly = 1;
tt_int_op(should_use_directory_guards(options), OP_EQ, 0);
- tt_int_op(CALLED(public_server_mode), OP_EQ, 5);
+ tt_int_op(dir_tests_public_server_mode_called, OP_EQ, 5);
options->FetchDirInfoEarly = 0;
options->FetchDirInfoExtraEarly = 1;
tt_int_op(should_use_directory_guards(options), OP_EQ, 0);
- tt_int_op(CALLED(public_server_mode), OP_EQ, 6);
+ tt_int_op(dir_tests_public_server_mode_called, OP_EQ, 6);
options->FetchDirInfoExtraEarly = 0;
options->FetchUselessDescriptors = 1;
tt_int_op(should_use_directory_guards(options), OP_EQ, 0);
- tt_int_op(CALLED(public_server_mode), OP_EQ, 7);
+ tt_int_op(dir_tests_public_server_mode_called, OP_EQ, 7);
options->FetchUselessDescriptors = 0;
done:
- NS_UNMOCK(public_server_mode);
+ UNMOCK(public_server_mode);
or_options_free(options);
tor_free(errmsg);
}
-NS_DECL(void,
-directory_initiate_request, (directory_request_t *req));
+static void dir_tests_directory_initiate_request(directory_request_t *req);
+ATTR_UNUSED static int dir_tests_directory_initiate_request_called = 0;
static void
test_dir_should_not_init_request_to_ourselves(void *data)
@@ -5554,7 +5557,8 @@ test_dir_should_not_init_request_to_ourselves(void *data)
crypto_pk_t *key = pk_generate(2);
(void) data;
- NS_MOCK(directory_initiate_request);
+ MOCK(directory_initiate_request,
+ dir_tests_directory_initiate_request);
clear_dir_servers();
routerlist_free_all();
@@ -5569,15 +5573,15 @@ test_dir_should_not_init_request_to_ourselves(void *data)
dir_server_add(ourself);
directory_get_from_all_authorities(DIR_PURPOSE_FETCH_STATUS_VOTE, 0, NULL);
- tt_int_op(CALLED(directory_initiate_request), OP_EQ, 0);
+ tt_int_op(dir_tests_directory_initiate_request_called, OP_EQ, 0);
directory_get_from_all_authorities(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, 0,
NULL);
- tt_int_op(CALLED(directory_initiate_request), OP_EQ, 0);
+ tt_int_op(dir_tests_directory_initiate_request_called, OP_EQ, 0);
done:
- NS_UNMOCK(directory_initiate_request);
+ UNMOCK(directory_initiate_request);
clear_dir_servers();
routerlist_free_all();
crypto_pk_free(key);
@@ -5591,7 +5595,8 @@ test_dir_should_not_init_request_to_dir_auths_without_v3_info(void *data)
| MICRODESC_DIRINFO;
(void) data;
- NS_MOCK(directory_initiate_request);
+ MOCK(directory_initiate_request,
+ dir_tests_directory_initiate_request);
clear_dir_servers();
routerlist_free_all();
@@ -5602,14 +5607,14 @@ test_dir_should_not_init_request_to_dir_auths_without_v3_info(void *data)
dir_server_add(ds);
directory_get_from_all_authorities(DIR_PURPOSE_FETCH_STATUS_VOTE, 0, NULL);
- tt_int_op(CALLED(directory_initiate_request), OP_EQ, 0);
+ tt_int_op(dir_tests_directory_initiate_request_called, OP_EQ, 0);
directory_get_from_all_authorities(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, 0,
NULL);
- tt_int_op(CALLED(directory_initiate_request), OP_EQ, 0);
+ tt_int_op(dir_tests_directory_initiate_request_called, OP_EQ, 0);
done:
- NS_UNMOCK(directory_initiate_request);
+ UNMOCK(directory_initiate_request);
clear_dir_servers();
routerlist_free_all();
}
@@ -5620,7 +5625,8 @@ test_dir_should_init_request_to_dir_auths(void *data)
dir_server_t *ds = NULL;
(void) data;
- NS_MOCK(directory_initiate_request);
+ MOCK(directory_initiate_request,
+ dir_tests_directory_initiate_request);
clear_dir_servers();
routerlist_free_all();
@@ -5631,23 +5637,23 @@ test_dir_should_init_request_to_dir_auths(void *data)
dir_server_add(ds);
directory_get_from_all_authorities(DIR_PURPOSE_FETCH_STATUS_VOTE, 0, NULL);
- tt_int_op(CALLED(directory_initiate_request), OP_EQ, 1);
+ tt_int_op(dir_tests_directory_initiate_request_called, OP_EQ, 1);
directory_get_from_all_authorities(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, 0,
NULL);
- tt_int_op(CALLED(directory_initiate_request), OP_EQ, 2);
+ tt_int_op(dir_tests_directory_initiate_request_called, OP_EQ, 2);
done:
- NS_UNMOCK(directory_initiate_request);
+ UNMOCK(directory_initiate_request);
clear_dir_servers();
routerlist_free_all();
}
void
-NS(directory_initiate_request)(directory_request_t *req)
+dir_tests_directory_initiate_request(directory_request_t *req)
{
(void)req;
- CALLED(directory_initiate_request)++;
+ dir_tests_directory_initiate_request_called++;
}
static void
@@ -7067,98 +7073,6 @@ test_dir_platform_str(void *arg)
;
}
-static networkstatus_t *mock_networkstatus;
-
-static networkstatus_t *
-mock_networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f)
-{
- (void)f;
- return mock_networkstatus;
-}
-
-static void
-test_dir_networkstatus_consensus_has_ipv6(void *arg)
-{
- (void)arg;
-
- int has_ipv6 = 0;
-
- /* Init options and networkstatus */
- or_options_t our_options;
- mock_options = &our_options;
- reset_options(mock_options, &mock_get_options_calls);
- MOCK(get_options, mock_get_options);
-
- networkstatus_t our_networkstatus;
- mock_networkstatus = &our_networkstatus;
- memset(mock_networkstatus, 0, sizeof(*mock_networkstatus));
- MOCK(networkstatus_get_latest_consensus_by_flavor,
- mock_networkstatus_get_latest_consensus_by_flavor);
-
- /* A live consensus */
- mock_networkstatus->valid_after = time(NULL) - 3600;
- mock_networkstatus->valid_until = time(NULL) + 3600;
-
- /* Test the bounds for A lines in the NS consensus */
- mock_options->UseMicrodescriptors = 0;
-
- mock_networkstatus->consensus_method = MIN_SUPPORTED_CONSENSUS_METHOD;
- has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
- tt_assert(has_ipv6);
-
- /* Test the bounds for A lines in the microdesc consensus */
- mock_options->UseMicrodescriptors = 1;
-
- mock_networkstatus->consensus_method =
- MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS;
- has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
- tt_assert(has_ipv6);
-
- mock_networkstatus->consensus_method = MAX_SUPPORTED_CONSENSUS_METHOD + 20;
- has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
- tt_assert(has_ipv6);
-
- mock_networkstatus->consensus_method =
- MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS + 1;
- has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
- tt_assert(has_ipv6);
-
- mock_networkstatus->consensus_method =
- MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS + 20;
- has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
- tt_assert(has_ipv6);
-
- mock_networkstatus->consensus_method =
- MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS - 1;
- has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
- tt_assert(!has_ipv6);
-
- /* Test the edge cases */
- mock_options->UseMicrodescriptors = 1;
- mock_networkstatus->consensus_method =
- MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS;
-
- /* Reasonably live */
- mock_networkstatus->valid_until = approx_time() - 60;
- has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
- tt_assert(has_ipv6);
-
- /* Not reasonably live */
- mock_networkstatus->valid_after = approx_time() - 24*60*60 - 3600;
- mock_networkstatus->valid_until = approx_time() - 24*60*60 - 60;
- has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
- tt_assert(!has_ipv6);
-
- /* NULL consensus */
- mock_networkstatus = NULL;
- has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
- tt_assert(!has_ipv6);
-
- done:
- UNMOCK(get_options);
- UNMOCK(networkstatus_get_latest_consensus_by_flavor);
-}
-
static void
test_dir_format_versions_list(void *arg)
{
@@ -7210,6 +7124,301 @@ test_dir_format_versions_list(void *arg)
teardown_capture_of_logs();
}
+static void
+test_dir_add_fingerprint(void *arg)
+{
+ (void)arg;
+ authdir_config_t *list;
+ int ret;
+ ed25519_secret_key_t seckey;
+ ed25519_public_key_t pubkey_good, pubkey_bad;
+
+ authdir_init_fingerprint_list();
+ list = authdir_return_fingerprint_list();
+
+ setup_capture_of_logs(LOG_WARN);
+
+ /* RSA test - successful */
+ ret = add_rsa_fingerprint_to_dir("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ list, 0);
+ tt_int_op(ret, OP_EQ, 0);
+
+ /* RSA test - failure */
+ ret = add_rsa_fingerprint_to_dir("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ",
+ list, 0);
+ tt_int_op(ret, OP_EQ, -1);
+
+ /* ed25519 test - successful */
+ ed25519_secret_key_generate(&seckey, 0);
+ ed25519_public_key_generate(&pubkey_good, &seckey);
+
+ ret = add_ed25519_to_dir(&pubkey_good, list, 0);
+ tt_int_op(ret, OP_EQ, 0);
+
+ /* ed25519 test - failure */
+ digest256_from_base64((char *) pubkey_bad.pubkey, "gibberish");
+
+ ret = add_ed25519_to_dir(&pubkey_bad, list, 0);
+ tt_int_op(ret, OP_EQ, -1);
+
+ done:
+ teardown_capture_of_logs();
+ dirserv_free_fingerprint_list();
+}
+
+static void
+test_dir_dirserv_load_fingerprint_file(void *arg)
+{
+ (void)arg;
+ char *fname = tor_strdup(get_fname("approved-routers"));
+
+ // Neither RSA nor ed25519
+ const char *router_lines_invalid =
+ "!badexit notafingerprint";
+ const char *router_lines_too_long =
+ "!badexit thisisareallylongstringthatislongerthanafingerprint\n";
+ const char *router_lines_bad_fmt_str =
+ "!badexit ABCDEFGH|%1$p|%2$p|%3$p|%4$p|%5$p|%6$p\n";
+ const char *router_lines_valid_rsa =
+ "!badexit AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n";
+ const char *router_lines_invalid_rsa =
+ "!badexit ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ\n";
+ const char *router_lines_valid_ed25519 =
+ "!badexit wqfLzgfCtRfYNg88LsL1QpzxS0itapJ1aj6TbnByx/Q\n";
+ const char *router_lines_invalid_ed25519 =
+ "!badexit --fLzgfCtRfYNg88LsL1QpzxS0itapJ1aj6TbnByx--\n";
+
+ // Test: Invalid Fingerprint (not RSA or ed25519)
+ setup_capture_of_logs(LOG_NOTICE);
+ write_str_to_file(fname, router_lines_invalid, 0);
+ tt_int_op(dirserv_load_fingerprint_file(), OP_EQ, 0);
+ expect_log_msg_containing("Invalid fingerprint");
+ teardown_capture_of_logs();
+
+ // Test: Very long string (longer than RSA or ed25519 key)
+ setup_capture_of_logs(LOG_NOTICE);
+ write_str_to_file(fname, router_lines_too_long, 0);
+ tt_int_op(dirserv_load_fingerprint_file(), OP_EQ, 0);
+ expect_log_msg_containing("Invalid fingerprint");
+ teardown_capture_of_logs();
+
+ // Test: Formt string exploit
+ setup_capture_of_logs(LOG_NOTICE);
+ write_str_to_file(fname, router_lines_bad_fmt_str, 0);
+ tt_int_op(dirserv_load_fingerprint_file(), OP_EQ, 0);
+ expect_log_msg_containing("Invalid fingerprint");
+ teardown_capture_of_logs();
+
+ // Test: Valid RSA
+ setup_capture_of_logs(LOG_NOTICE);
+ write_str_to_file(fname, router_lines_valid_rsa, 0);
+ tt_int_op(dirserv_load_fingerprint_file(), OP_EQ, 0);
+ teardown_capture_of_logs();
+
+ // Test: Invalid RSA
+ setup_capture_of_logs(LOG_NOTICE);
+ write_str_to_file(fname, router_lines_invalid_rsa, 0);
+ tt_int_op(dirserv_load_fingerprint_file(), OP_EQ, 0);
+ expect_log_msg_containing("Invalid fingerprint");
+ teardown_capture_of_logs();
+
+ // Test: Valid ed25519
+ setup_capture_of_logs(LOG_NOTICE);
+ write_str_to_file(fname, router_lines_valid_ed25519, 0);
+ tt_int_op(dirserv_load_fingerprint_file(), OP_EQ, 0);
+ teardown_capture_of_logs();
+
+ // Test: Invalid ed25519
+ setup_capture_of_logs(LOG_NOTICE);
+ write_str_to_file(fname, router_lines_invalid_ed25519, 0);
+ tt_int_op(dirserv_load_fingerprint_file(), OP_EQ, 0);
+ expect_log_msg_containing("Invalid fingerprint");
+ teardown_capture_of_logs();
+
+ done:
+ tor_free(fname);
+ dirserv_free_fingerprint_list();
+}
+
+#define RESET_FP_LIST(list) STMT_BEGIN \
+ dirserv_free_fingerprint_list(); \
+ authdir_init_fingerprint_list(); \
+ list = authdir_return_fingerprint_list(); \
+ STMT_END
+
+static void
+test_dir_dirserv_router_get_status(void *arg)
+{
+ authdir_config_t *list;
+ routerinfo_t *ri = NULL;
+ ed25519_keypair_t kp1, kp2;
+ char d[DIGEST_LEN];
+ char fp[HEX_DIGEST_LEN+1];
+ int ret;
+ const char *msg;
+ time_t now = time(NULL);
+
+ (void)arg;
+
+ crypto_pk_t *pk = pk_generate(0);
+
+ authdir_init_fingerprint_list();
+ list = authdir_return_fingerprint_list();
+
+ /* Set up the routerinfo */
+ ri = tor_malloc_zero(sizeof(routerinfo_t));
+ ri->addr = 0xc0a80001u;
+ ri->or_port = 9001;
+ ri->platform = tor_strdup("0.4.0.1-alpha");
+ ri->nickname = tor_strdup("Jessica");
+ ri->identity_pkey = crypto_pk_dup_key(pk);
+
+ curve25519_keypair_t ri_onion_keypair;
+ curve25519_keypair_generate(&ri_onion_keypair, 0);
+ ri->onion_curve25519_pkey = tor_memdup(&ri_onion_keypair.pubkey,
+ sizeof(curve25519_public_key_t));
+
+ ed25519_secret_key_from_seed(&kp1.seckey,
+ (const uint8_t*)"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY");
+ ed25519_public_key_generate(&kp1.pubkey, &kp1.seckey);
+ ed25519_secret_key_from_seed(&kp2.seckey,
+ (const uint8_t*)"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
+ ed25519_public_key_generate(&kp2.pubkey, &kp2.seckey);
+ ri->cache_info.signing_key_cert = tor_cert_create(&kp1,
+ CERT_TYPE_ID_SIGNING,
+ &kp2.pubkey,
+ now, 86400,
+ CERT_FLAG_INCLUDE_SIGNING_KEY);
+
+ crypto_pk_get_digest(ri->identity_pkey, d);
+ base16_encode(fp, HEX_DIGEST_LEN + 1, d, DIGEST_LEN);
+
+ /* Try on an empty fingerprint list */
+ ret = dirserv_router_get_status(ri, &msg, LOG_INFO);
+ tt_int_op(ret, OP_EQ, 0);
+ RESET_FP_LIST(list);
+
+ ret = dirserv_router_get_status(ri, &msg, LOG_INFO);
+ tt_int_op(ret, OP_EQ, 0);
+ RESET_FP_LIST(list);
+
+ /* Try an accepted router */
+ add_rsa_fingerprint_to_dir(fp, list, 0);
+ ret = dirserv_router_get_status(ri, &msg, LOG_INFO);
+ tt_int_op(ret, OP_EQ, 0);
+ RESET_FP_LIST(list);
+
+ add_ed25519_to_dir(&kp1.pubkey, list, 0);
+ ret = dirserv_router_get_status(ri, &msg, LOG_INFO);
+ tt_int_op(ret, OP_EQ, 0);
+ RESET_FP_LIST(list);
+
+ /* Try a rejected router */
+ add_rsa_fingerprint_to_dir(fp, list, RTR_REJECT);
+ ret = dirserv_router_get_status(ri, &msg, LOG_INFO);
+ tt_int_op(ret, OP_EQ, RTR_REJECT);
+ RESET_FP_LIST(list);
+
+ add_ed25519_to_dir(&kp1.pubkey, list, RTR_REJECT);
+ ret = dirserv_router_get_status(ri, &msg, LOG_INFO);
+ tt_int_op(ret, OP_EQ, RTR_REJECT);
+ RESET_FP_LIST(list);
+
+ done:
+ dirserv_free_fingerprint_list();
+ routerinfo_free(ri);
+ crypto_pk_free(pk);
+}
+
+static void
+test_dir_dirserv_would_reject_router(void *arg)
+{
+ authdir_config_t *list;
+ routerstatus_t rs;
+ vote_routerstatus_t vrs;
+ ed25519_keypair_t kp;
+ char fp[HEX_DIGEST_LEN+1];
+
+ (void)arg;
+
+ authdir_init_fingerprint_list();
+ list = authdir_return_fingerprint_list();
+
+ /* Set up the routerstatus */
+ memset(&rs, 0, sizeof(rs));
+ rs.addr = 0xc0a80001u;
+ rs.or_port = 9001;
+ strlcpy(rs.nickname, "Nicole", sizeof(rs.nickname));
+ memcpy(rs.identity_digest, "Cloud nine is great ", DIGEST_LEN);
+
+ ed25519_secret_key_from_seed(&kp.seckey,
+ (const uint8_t*)"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY");
+ ed25519_public_key_generate(&kp.pubkey, &kp.seckey);
+
+ base16_encode(fp, HEX_DIGEST_LEN + 1, rs.identity_digest, DIGEST_LEN);
+
+ /* Setup the vote_routerstatus_t. */
+ memcpy(vrs.ed25519_id, &kp.pubkey, ED25519_PUBKEY_LEN);
+
+ /* Try an empty fingerprint list */
+ tt_assert(!dirserv_would_reject_router(&rs, &vrs));
+ RESET_FP_LIST(list);
+
+ tt_assert(!dirserv_would_reject_router(&rs, &vrs));
+ RESET_FP_LIST(list);
+
+ /* Try an accepted router */
+ add_rsa_fingerprint_to_dir(fp, list, 0);
+ tt_assert(!dirserv_would_reject_router(&rs, &vrs));
+ RESET_FP_LIST(list);
+
+ add_ed25519_to_dir(&kp.pubkey, list, 0);
+ tt_assert(!dirserv_would_reject_router(&rs, &vrs));
+ RESET_FP_LIST(list);
+
+ /* Try a rejected router */
+ add_rsa_fingerprint_to_dir(fp, list, RTR_REJECT);
+ tt_assert(dirserv_would_reject_router(&rs, &vrs));
+ RESET_FP_LIST(list);
+
+ add_ed25519_to_dir(&kp.pubkey, list, RTR_REJECT);
+ tt_assert(dirserv_would_reject_router(&rs, &vrs));
+ RESET_FP_LIST(list);
+
+ done:
+ dirserv_free_fingerprint_list();
+}
+
+static void
+test_dir_dirserv_add_own_fingerprint(void *arg)
+{
+ authdir_config_t *list;
+ char digest[DIGEST_LEN];
+ crypto_pk_t *pk = pk_generate(0);
+
+ (void)arg;
+
+ init_mock_ed_keys(pk);
+ authdir_init_fingerprint_list();
+ list = authdir_return_fingerprint_list();
+ dirserv_add_own_fingerprint(pk, get_master_identity_key());
+
+ /* Check if we have a RSA key. */
+ crypto_pk_get_digest(pk, digest);
+ tt_assert(digestmap_get(list->status_by_digest, digest));
+
+ /* Check if we have a ed25519 key. */
+ tt_assert(digest256map_get(list->status_by_digest256,
+ get_master_identity_key()->pubkey));
+
+ RESET_FP_LIST(list);
+
+ done:
+ dirserv_free_fingerprint_list();
+ crypto_pk_free(pk);
+}
+
+#ifndef COCCI
#define DIR_LEGACY(name) \
{ #name, test_dir_ ## name , TT_FORK, NULL, NULL }
@@ -7219,6 +7428,7 @@ test_dir_format_versions_list(void *arg)
/* where arg is a string constant */
#define DIR_ARG(name,flags,arg) \
{ #name "_" arg, test_dir_##name, (flags), &passthrough_setup, (void*) arg }
+#endif /* !defined(COCCI) */
struct testcase_t dir_tests[] = {
DIR_LEGACY(nicknames),
@@ -7260,7 +7470,7 @@ struct testcase_t dir_tests[] = {
DIR_LEGACY(clip_unmeasured_bw_kb),
DIR_LEGACY(clip_unmeasured_bw_kb_alt),
DIR(fmt_control_ns, 0),
- DIR(dirserv_set_routerstatus_testing, 0),
+ DIR(dirserv_set_routerstatus_testing, TT_FORK),
DIR(http_handling, 0),
DIR(purpose_needs_anonymity_returns_true_for_bridges, 0),
DIR(purpose_needs_anonymity_returns_false_for_own_bridge_desc, 0),
@@ -7295,7 +7505,11 @@ struct testcase_t dir_tests[] = {
DIR(matching_flags, 0),
DIR(networkstatus_compute_bw_weights_v10, 0),
DIR(platform_str, 0),
- DIR(networkstatus_consensus_has_ipv6, TT_FORK),
DIR(format_versions_list, TT_FORK),
+ DIR(add_fingerprint, TT_FORK),
+ DIR(dirserv_load_fingerprint_file, TT_FORK),
+ DIR(dirserv_router_get_status, TT_FORK),
+ DIR(dirserv_would_reject_router, TT_FORK),
+ DIR(dirserv_add_own_fingerprint, TT_FORK),
END_OF_TESTCASES
};
diff --git a/src/test/test_dir_common.c b/src/test/test_dir_common.c
index 0b87e29873..4533ad5c03 100644
--- a/src/test/test_dir_common.c
+++ b/src/test/test_dir_common.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_dir_common.h b/src/test/test_dir_common.h
index 619dc83eb9..d37496465c 100644
--- a/src/test/test_dir_common.h
+++ b/src/test/test_dir_common.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_TEST_DIR_COMMON_H
diff --git a/src/test/test_dir_handle_get.c b/src/test/test_dir_handle_get.c
index edfd0c74e1..6293839b0d 100644
--- a/src/test/test_dir_handle_get.c
+++ b/src/test/test_dir_handle_get.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define RENDCOMMON_PRIVATE
@@ -20,6 +20,7 @@
#include "lib/compress/compress.h"
#include "feature/rend/rendcommon.h"
#include "feature/rend/rendcache.h"
+#include "feature/relay/relay_config.h"
#include "feature/relay/router.h"
#include "feature/nodelist/authcert.h"
#include "feature/nodelist/dirlist.h"
@@ -54,17 +55,15 @@
#endif /* defined(_WIN32) */
#ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
-DISABLE_GCC_WARNING(overlength-strings)
+DISABLE_GCC_WARNING("-Woverlength-strings")
/* We allow huge string constants in the unit tests, but not in the code
* at large. */
#endif
#include "vote_descriptors.inc"
#ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
-ENABLE_GCC_WARNING(overlength-strings)
+ENABLE_GCC_WARNING("-Woverlength-strings")
#endif
-#define NS_MODULE dir_handle_get
-
#define NOT_FOUND "HTTP/1.0 404 Not found\r\n\r\n"
#define BAD_REQUEST "HTTP/1.0 400 Bad request\r\n\r\n"
#define SERVER_BUSY "HTTP/1.0 503 Directory busy, try again later\r\n\r\n"
@@ -118,7 +117,7 @@ test_dir_handle_get_v1_command_not_found(void *data)
conn = new_dir_conn();
// no frontpage configured
- tt_ptr_op(get_dirportfrontpage(), OP_EQ, NULL);
+ tt_ptr_op(relay_get_dirportfrontpage(), OP_EQ, NULL);
/* V1 path */
tt_int_op(directory_handle_command_get(conn, GET("/tor/"), NULL, 0),
@@ -152,9 +151,9 @@ test_dir_handle_get_v1_command(void *data)
(void) data;
MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
- MOCK(get_dirportfrontpage, mock_get_dirportfrontpage);
+ MOCK(relay_get_dirportfrontpage, mock_get_dirportfrontpage);
- exp_body = get_dirportfrontpage();
+ exp_body = relay_get_dirportfrontpage();
body_len = strlen(exp_body);
conn = new_dir_conn();
@@ -177,7 +176,7 @@ test_dir_handle_get_v1_command(void *data)
done:
UNMOCK(connection_write_to_buf_impl_);
- UNMOCK(get_dirportfrontpage);
+ UNMOCK(relay_get_dirportfrontpage);
connection_free_minimal(TO_CONN(conn));
tor_free(header);
tor_free(body);
@@ -257,7 +256,7 @@ test_dir_handle_get_rendezvous2_not_found_if_not_encrypted(void *data)
conn = new_dir_conn();
// connection is not encrypted
- tt_assert(!connection_dir_is_encrypted(conn))
+ tt_assert(!connection_dir_is_encrypted(conn));
tt_int_op(directory_handle_command_get(conn, RENDEZVOUS2_GET(), NULL, 0),
OP_EQ, 0);
@@ -363,12 +362,13 @@ test_dir_handle_get_rendezvous2_not_found(void *data)
rend_cache_free_all();
}
-NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void));
+static const routerinfo_t * dhg_tests_router_get_my_routerinfo(void);
+ATTR_UNUSED static int dhg_tests_router_get_my_routerinfo_called = 0;
static routerinfo_t *mock_routerinfo;
static const routerinfo_t *
-NS(router_get_my_routerinfo)(void)
+dhg_tests_router_get_my_routerinfo(void)
{
if (!mock_routerinfo) {
mock_routerinfo = tor_malloc_zero(sizeof(routerinfo_t));
@@ -393,7 +393,8 @@ test_dir_handle_get_rendezvous2_on_encrypted_conn_success(void *data)
(void) data;
MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
- NS_MOCK(router_get_my_routerinfo);
+ MOCK(router_get_my_routerinfo,
+ dhg_tests_router_get_my_routerinfo);
rend_cache_init();
@@ -436,7 +437,7 @@ test_dir_handle_get_rendezvous2_on_encrypted_conn_success(void *data)
done:
UNMOCK(connection_write_to_buf_impl_);
- NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(router_get_my_routerinfo);
connection_free_minimal(TO_CONN(conn));
tor_free(header);
@@ -768,7 +769,8 @@ test_dir_handle_get_server_descriptors_all(void* data)
helper_setup_fake_routerlist();
//TODO: change to router_get_my_extrainfo when testing "extra" path
- NS_MOCK(router_get_my_routerinfo);
+ MOCK(router_get_my_routerinfo,
+ dhg_tests_router_get_my_routerinfo);
MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
// We are one of the routers
@@ -810,7 +812,7 @@ test_dir_handle_get_server_descriptors_all(void* data)
tt_ptr_op(conn->spool, OP_EQ, NULL);
done:
- NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(router_get_my_routerinfo);
UNMOCK(connection_write_to_buf_impl_);
connection_free_minimal(TO_CONN(conn));
tor_free(header);
@@ -867,7 +869,8 @@ test_dir_handle_get_server_descriptors_authority(void* data)
crypto_pk_t *identity_pkey = pk_generate(0);
(void) data;
- NS_MOCK(router_get_my_routerinfo);
+ MOCK(router_get_my_routerinfo,
+ dhg_tests_router_get_my_routerinfo);
MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
/* init mock */
@@ -912,7 +915,7 @@ test_dir_handle_get_server_descriptors_authority(void* data)
tt_ptr_op(conn->spool, OP_EQ, NULL);
done:
- NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(router_get_my_routerinfo);
UNMOCK(connection_write_to_buf_impl_);
tor_free(mock_routerinfo->cache_info.signed_descriptor_body);
tor_free(mock_routerinfo);
@@ -932,7 +935,8 @@ test_dir_handle_get_server_descriptors_fp(void* data)
crypto_pk_t *identity_pkey = pk_generate(0);
(void) data;
- NS_MOCK(router_get_my_routerinfo);
+ MOCK(router_get_my_routerinfo,
+ dhg_tests_router_get_my_routerinfo);
MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
/* init mock */
@@ -984,7 +988,7 @@ test_dir_handle_get_server_descriptors_fp(void* data)
tt_ptr_op(conn->spool, OP_EQ, NULL);
done:
- NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(router_get_my_routerinfo);
UNMOCK(connection_write_to_buf_impl_);
tor_free(mock_routerinfo->cache_info.signed_descriptor_body);
tor_free(mock_routerinfo);
@@ -1788,13 +1792,14 @@ test_dir_handle_get_status_vote_current_consensus_too_old(void *data)
or_options_free(mock_options); mock_options = NULL;
}
-NS_DECL(int, geoip_get_country_by_addr, (const tor_addr_t *addr));
+static int dhg_tests_geoip_get_country_by_addr(const tor_addr_t *addr);
+ATTR_UNUSED static int dhg_tests_geoip_get_country_by_addr_called = 0;
int
-NS(geoip_get_country_by_addr)(const tor_addr_t *addr)
+dhg_tests_geoip_get_country_by_addr(const tor_addr_t *addr)
{
(void)addr;
- CALLED(geoip_get_country_by_addr)++;
+ dhg_tests_geoip_get_country_by_addr_called++;
return 1;
}
@@ -1858,7 +1863,8 @@ test_dir_handle_get_status_vote_current_consensus_ns(void* data)
dirserv_free_all();
clear_geoip_db();
- NS_MOCK(geoip_get_country_by_addr);
+ MOCK(geoip_get_country_by_addr,
+ dhg_tests_geoip_get_country_by_addr);
MOCK(get_options, mock_get_options);
init_mock_options();
@@ -1895,7 +1901,7 @@ test_dir_handle_get_status_vote_current_consensus_ns(void* data)
tt_str_op("ab=8", OP_EQ, hist);
done:
- NS_UNMOCK(geoip_get_country_by_addr);
+ UNMOCK(geoip_get_country_by_addr);
UNMOCK(get_options);
tor_free(header);
tor_free(comp_body);
@@ -2247,11 +2253,11 @@ test_dir_handle_get_status_vote_next_bandwidth_not_found(void* data)
tor_free(header);
}
-NS_DECL(const char*,
-dirvote_get_pending_consensus, (consensus_flavor_t flav));
+static const char* dhg_tests_dirvote_get_pending_consensus(
+ consensus_flavor_t flav);
const char*
-NS(dirvote_get_pending_consensus)(consensus_flavor_t flav)
+dhg_tests_dirvote_get_pending_consensus(consensus_flavor_t flav)
{
(void)flav;
return "pending consensus";
@@ -2264,7 +2270,8 @@ test_dir_handle_get_status_vote_next_consensus(void* data)
size_t body_used = 0;
(void) data;
- NS_MOCK(dirvote_get_pending_consensus);
+ MOCK(dirvote_get_pending_consensus,
+ dhg_tests_dirvote_get_pending_consensus);
status_vote_next_consensus_test(&header, &body, &body_used);
tt_assert(header);
@@ -2277,7 +2284,7 @@ test_dir_handle_get_status_vote_next_consensus(void* data)
tt_str_op("pending consensus", OP_EQ, body);
done:
- NS_UNMOCK(dirvote_get_pending_consensus);
+ UNMOCK(dirvote_get_pending_consensus);
tor_free(header);
tor_free(body);
}
@@ -2290,7 +2297,8 @@ test_dir_handle_get_status_vote_next_consensus_busy(void* data)
(void) data;
MOCK(get_options, mock_get_options);
- NS_MOCK(dirvote_get_pending_consensus);
+ MOCK(dirvote_get_pending_consensus,
+ dhg_tests_dirvote_get_pending_consensus);
//Make it busy
init_mock_options();
@@ -2302,7 +2310,7 @@ test_dir_handle_get_status_vote_next_consensus_busy(void* data)
tt_str_op(SERVER_BUSY, OP_EQ, header);
done:
- NS_UNMOCK(dirvote_get_pending_consensus);
+ UNMOCK(dirvote_get_pending_consensus);
UNMOCK(get_options);
tor_free(header);
tor_free(body);
@@ -2346,11 +2354,10 @@ test_dir_handle_get_status_vote_next_consensus_signatures_not_found(void* data)
tor_free(body);
}
-NS_DECL(const char*,
-dirvote_get_pending_detached_signatures, (void));
+static const char* dhg_tests_dirvote_get_pending_detached_signatures(void);
const char*
-NS(dirvote_get_pending_detached_signatures)(void)
+dhg_tests_dirvote_get_pending_detached_signatures(void)
{
return "pending detached sigs";
}
@@ -2362,7 +2369,8 @@ test_dir_handle_get_status_vote_next_consensus_signatures(void* data)
size_t body_used = 0;
(void) data;
- NS_MOCK(dirvote_get_pending_detached_signatures);
+ MOCK(dirvote_get_pending_detached_signatures,
+ dhg_tests_dirvote_get_pending_detached_signatures);
status_vote_next_consensus_signatures_test(&header, &body, &body_used);
tt_assert(header);
@@ -2375,7 +2383,7 @@ test_dir_handle_get_status_vote_next_consensus_signatures(void* data)
tt_str_op("pending detached sigs", OP_EQ, body);
done:
- NS_UNMOCK(dirvote_get_pending_detached_signatures);
+ UNMOCK(dirvote_get_pending_detached_signatures);
tor_free(header);
tor_free(body);
}
@@ -2387,7 +2395,8 @@ test_dir_handle_get_status_vote_next_consensus_signatures_busy(void* data)
size_t body_used;
(void) data;
- NS_MOCK(dirvote_get_pending_detached_signatures);
+ MOCK(dirvote_get_pending_detached_signatures,
+ dhg_tests_dirvote_get_pending_detached_signatures);
MOCK(get_options, mock_get_options);
//Make it busy
@@ -2401,7 +2410,7 @@ test_dir_handle_get_status_vote_next_consensus_signatures_busy(void* data)
done:
UNMOCK(get_options);
- NS_UNMOCK(dirvote_get_pending_detached_signatures);
+ UNMOCK(dirvote_get_pending_detached_signatures);
tor_free(header);
tor_free(body);
or_options_free(mock_options); mock_options = NULL;
diff --git a/src/test/test_dispatch.c b/src/test/test_dispatch.c
index a62c18e0c9..77f33e4b15 100644
--- a/src/test/test_dispatch.c
+++ b/src/test/test_dispatch.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define DISPATCH_NEW_PRIVATE
@@ -167,7 +167,7 @@ test_dispatch_no_recipient(void *arg)
dcfg_free(cfg);
}
-struct coord { int x; int y; };
+struct coord_t { int x; int y; };
static void
free_coord(msg_aux_data_t d)
{
@@ -177,7 +177,7 @@ static char *
fmt_coord(msg_aux_data_t d)
{
char *v;
- struct coord *c = d.ptr;
+ struct coord_t *c = d.ptr;
tor_asprintf(&v, "[%d, %d]", c->x, c->y);
return v;
}
@@ -225,7 +225,7 @@ test_dispatch_with_types(void *arg)
r = dispatch_set_alert_fn(d, 2, alert_run_immediate, NULL);
tt_int_op(r, OP_EQ, 0);
- struct coord *xy = tor_malloc(sizeof(*xy));
+ struct coord_t *xy = tor_malloc(sizeof(*xy));
xy->x = 13;
xy->y = 37;
msg_aux_data_t data = {.ptr = xy};
diff --git a/src/test/test_dns.c b/src/test/test_dns.c
index 51ff8729d0..ec17e9e91e 100644
--- a/src/test/test_dns.c
+++ b/src/test/test_dns.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2019, The Tor Project, Inc. */
+/* Copyright (c) 2015-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -20,10 +20,7 @@
#include <event2/event.h>
#include <event2/dns.h>
-#define NS_MODULE dns
-
#ifdef HAVE_EVDNS_BASE_GET_NAMESERVER_ADDR
-#define NS_SUBMODULE configure_nameservers_fallback
static or_options_t options = {
.ORPort_set = 1,
@@ -36,7 +33,7 @@ mock_get_options(void)
}
static void
-NS(test_main)(void *arg)
+test_dns_configure_ns_fallback(void *arg)
{
(void)arg;
tor_addr_t *nameserver_addr = NULL;
@@ -76,13 +73,10 @@ NS(test_main)(void *arg)
return;
}
-#undef NS_SUBMODULE
#endif /* defined(HAVE_EVDNS_BASE_GET_NAMESERVER_ADDR) */
-#define NS_SUBMODULE clip_ttl
-
static void
-NS(test_main)(void *arg)
+test_dns_clip_ttl(void *arg)
{
(void)arg;
@@ -96,10 +90,6 @@ NS(test_main)(void *arg)
return;
}
-#undef NS_SUBMODULE
-
-#define NS_SUBMODULE resolve
-
static int resolve_retval = 0;
static int resolve_made_conn_pending = 0;
static char *resolved_name = NULL;
@@ -107,10 +97,11 @@ static cached_resolve_t *cache_entry_mock = NULL;
static int n_fake_impl = 0;
-NS_DECL(int, dns_resolve_impl, (edge_connection_t *exitconn, int is_resolve,
- or_circuit_t *oncirc, char **hostname_out,
- int *made_connection_pending_out,
- cached_resolve_t **resolve_out));
+static int dns_resolve_dns_resolve_impl(edge_connection_t *exitconn,
+ int is_resolve, or_circuit_t *oncirc,
+ char **hostname_out, int *made_connection_pending_out,
+ cached_resolve_t **resolve_out);
+ATTR_UNUSED static int dns_resolve_dns_resolve_impl_called = 0;
/** This will be our configurable substitute for <b>dns_resolve_impl</b> in
* dns.c. It will return <b>resolve_retval</b>,
@@ -121,7 +112,7 @@ NS_DECL(int, dns_resolve_impl, (edge_connection_t *exitconn, int is_resolve,
* 1.
*/
static int
-NS(dns_resolve_impl)(edge_connection_t *exitconn, int is_resolve,
+dns_resolve_dns_resolve_impl(edge_connection_t *exitconn, int is_resolve,
or_circuit_t *oncirc, char **hostname_out,
int *made_connection_pending_out,
cached_resolve_t **resolve_out)
@@ -151,7 +142,7 @@ static uint8_t last_answer_type = 0;
static cached_resolve_t *last_resolved;
static void
-NS(send_resolved_cell)(edge_connection_t *conn, uint8_t answer_type,
+dns_resolve_send_resolved_cell(edge_connection_t *conn, uint8_t answer_type,
const cached_resolve_t *resolved)
{
conn_for_resolved_cell = conn;
@@ -167,7 +158,7 @@ static int n_send_resolved_hostname_cell_replacement = 0;
static char *last_resolved_hostname = NULL;
static void
-NS(send_resolved_hostname_cell)(edge_connection_t *conn,
+dns_resolve_send_resolved_hostname_cell(edge_connection_t *conn,
const char *hostname)
{
conn_for_resolved_cell = conn;
@@ -181,7 +172,7 @@ NS(send_resolved_hostname_cell)(edge_connection_t *conn,
static int n_dns_cancel_pending_resolve_replacement = 0;
static void
-NS(dns_cancel_pending_resolve)(const char *address)
+dns_resolve_dns_cancel_pending_resolve(const char *address)
{
(void) address;
n_dns_cancel_pending_resolve_replacement++;
@@ -191,7 +182,7 @@ static int n_connection_free = 0;
static connection_t *last_freed_conn = NULL;
static void
-NS(connection_free_)(connection_t *conn)
+dns_resolve_connection_free_(connection_t *conn)
{
n_connection_free++;
@@ -199,7 +190,7 @@ NS(connection_free_)(connection_t *conn)
}
static void
-NS(test_main)(void *arg)
+test_dns_resolve(void *arg)
{
(void) arg;
int retval;
@@ -218,9 +209,12 @@ NS(test_main)(void *arg)
memset(exitconn,0,sizeof(edge_connection_t));
memset(nextconn,0,sizeof(edge_connection_t));
- NS_MOCK(dns_resolve_impl);
- NS_MOCK(send_resolved_cell);
- NS_MOCK(send_resolved_hostname_cell);
+ MOCK(dns_resolve_impl,
+ dns_resolve_dns_resolve_impl);
+ MOCK(send_resolved_cell,
+ dns_resolve_send_resolved_cell);
+ MOCK(send_resolved_hostname_cell,
+ dns_resolve_send_resolved_hostname_cell);
/*
* CASE 1: dns_resolve_impl returns 1 and sets a hostname. purpose is
@@ -333,8 +327,10 @@ NS(test_main)(void *arg)
* on exitconn with type being RESOLVED_TYPE_ERROR.
*/
- NS_MOCK(dns_cancel_pending_resolve);
- NS_MOCK(connection_free_);
+ MOCK(dns_cancel_pending_resolve,
+ dns_resolve_dns_cancel_pending_resolve);
+ MOCK(connection_free_,
+ dns_resolve_connection_free_);
exitconn->on_circuit = &(on_circuit->base_);
exitconn->base_.purpose = EXIT_PURPOSE_RESOLVE;
@@ -357,11 +353,11 @@ NS(test_main)(void *arg)
tt_assert(last_freed_conn == TO_CONN(exitconn));
done:
- NS_UNMOCK(dns_resolve_impl);
- NS_UNMOCK(send_resolved_cell);
- NS_UNMOCK(send_resolved_hostname_cell);
- NS_UNMOCK(dns_cancel_pending_resolve);
- NS_UNMOCK(connection_free_);
+ UNMOCK(dns_resolve_impl);
+ UNMOCK(send_resolved_cell);
+ UNMOCK(send_resolved_hostname_cell);
+ UNMOCK(dns_cancel_pending_resolve);
+ UNMOCK(connection_free_);
tor_free(on_circuit);
tor_free(exitconn);
tor_free(nextconn);
@@ -371,8 +367,6 @@ NS(test_main)(void *arg)
return;
}
-#undef NS_SUBMODULE
-
/** Create an <b>edge_connection_t</b> instance that is considered a
* valid exit connection by asserts in dns_resolve_impl.
*/
@@ -389,8 +383,6 @@ create_valid_exitconn(void)
return exitconn;
}
-#define NS_SUBMODULE ASPECT(resolve_impl, addr_is_ip_no_need_to_resolve)
-
/*
* Given that <b>exitconn->base_.address</b> is IP address string, we
* want dns_resolve_impl() to parse it and store in
@@ -399,7 +391,7 @@ create_valid_exitconn(void)
*/
static void
-NS(test_main)(void *arg)
+test_dns_impl_addr_is_ip(void *arg)
{
int retval;
int made_pending;
@@ -432,21 +424,17 @@ NS(test_main)(void *arg)
return;
}
-#undef NS_SUBMODULE
-
-#define NS_SUBMODULE ASPECT(resolve_impl, non_exit)
-
/** Given that Tor instance is not configured as an exit node, we want
* dns_resolve_impl() to fail with return value -1.
*/
static int
-NS(router_my_exit_policy_is_reject_star)(void)
+dns_impl_non_exit_router_my_exit_policy_is_reject_star(void)
{
return 1;
}
static void
-NS(test_main)(void *arg)
+test_dns_impl_non_exit(void *arg)
{
int retval;
int made_pending;
@@ -458,7 +446,8 @@ NS(test_main)(void *arg)
TO_CONN(exitconn)->address = tor_strdup("torproject.org");
- NS_MOCK(router_my_exit_policy_is_reject_star);
+ MOCK(router_my_exit_policy_is_reject_star,
+ dns_impl_non_exit_router_my_exit_policy_is_reject_star);
retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
NULL);
@@ -469,27 +458,23 @@ NS(test_main)(void *arg)
tor_free(TO_CONN(exitconn)->address);
tor_free(exitconn);
tor_free(on_circ);
- NS_UNMOCK(router_my_exit_policy_is_reject_star);
+ UNMOCK(router_my_exit_policy_is_reject_star);
return;
}
-#undef NS_SUBMODULE
-
-#define NS_SUBMODULE ASPECT(resolve_impl, addr_is_invalid_dest)
-
/** Given that address is not a valid destination (as judged by
* address_is_invalid_destination() function), we want dns_resolve_impl()
* function to fail with return value -1.
*/
static int
-NS(router_my_exit_policy_is_reject_star)(void)
+dns_impl_addr_is_invalid_dest_router_my_exit_policy_is_reject_star(void)
{
return 0;
}
static void
-NS(test_main)(void *arg)
+test_dns_impl_addr_is_invalid_dest(void *arg)
{
int retval;
int made_pending;
@@ -499,7 +484,8 @@ NS(test_main)(void *arg)
(void)arg;
- NS_MOCK(router_my_exit_policy_is_reject_star);
+ MOCK(router_my_exit_policy_is_reject_star,
+ dns_impl_addr_is_invalid_dest_router_my_exit_policy_is_reject_star);
TO_CONN(exitconn)->address = tor_strdup("invalid#@!.org");
@@ -509,29 +495,25 @@ NS(test_main)(void *arg)
tt_int_op(retval,OP_EQ,-1);
done:
- NS_UNMOCK(router_my_exit_policy_is_reject_star);
+ UNMOCK(router_my_exit_policy_is_reject_star);
tor_free(TO_CONN(exitconn)->address);
tor_free(exitconn);
tor_free(on_circ);
return;
}
-#undef NS_SUBMODULE
-
-#define NS_SUBMODULE ASPECT(resolve_impl, malformed_ptr)
-
/** Given that address is a malformed PTR name, we want dns_resolve_impl to
* fail.
*/
static int
-NS(router_my_exit_policy_is_reject_star)(void)
+dns_impl_malformed_ptr_router_my_exit_policy_is_reject_star(void)
{
return 0;
}
static void
-NS(test_main)(void *arg)
+test_dns_impl_malformed_ptr(void *arg)
{
int retval;
int made_pending;
@@ -543,7 +525,8 @@ NS(test_main)(void *arg)
TO_CONN(exitconn)->address = tor_strdup("1.0.0.127.in-addr.arpa");
- NS_MOCK(router_my_exit_policy_is_reject_star);
+ MOCK(router_my_exit_policy_is_reject_star,
+ dns_impl_malformed_ptr_router_my_exit_policy_is_reject_star);
retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
NULL);
@@ -561,30 +544,26 @@ NS(test_main)(void *arg)
tt_int_op(retval,OP_EQ,-1);
done:
- NS_UNMOCK(router_my_exit_policy_is_reject_star);
+ UNMOCK(router_my_exit_policy_is_reject_star);
tor_free(TO_CONN(exitconn)->address);
tor_free(exitconn);
tor_free(on_circ);
return;
}
-#undef NS_SUBMODULE
-
-#define NS_SUBMODULE ASPECT(resolve_impl, cache_hit_pending)
-
/* Given that there is already a pending resolve for the given address,
* we want dns_resolve_impl to append our exit connection to list
* of pending connections for the pending DNS request and return 0.
*/
static int
-NS(router_my_exit_policy_is_reject_star)(void)
+dns_impl_cache_hit_pending_router_my_exit_policy_is_reject_star(void)
{
return 0;
}
static void
-NS(test_main)(void *arg)
+test_dns_impl_cache_hit_pending(void *arg)
{
int retval;
int made_pending = 0;
@@ -607,7 +586,8 @@ NS(test_main)(void *arg)
strlcpy(cache_entry->address, TO_CONN(exitconn)->address,
sizeof(cache_entry->address));
- NS_MOCK(router_my_exit_policy_is_reject_star);
+ MOCK(router_my_exit_policy_is_reject_star,
+ dns_impl_cache_hit_pending_router_my_exit_policy_is_reject_star);
dns_init();
@@ -625,7 +605,7 @@ NS(test_main)(void *arg)
tt_assert(pending_conn->conn == exitconn);
done:
- NS_UNMOCK(router_my_exit_policy_is_reject_star);
+ UNMOCK(router_my_exit_policy_is_reject_star);
tor_free(on_circ);
tor_free(TO_CONN(exitconn)->address);
tor_free(cache_entry->pending_connections);
@@ -634,16 +614,12 @@ NS(test_main)(void *arg)
return;
}
-#undef NS_SUBMODULE
-
-#define NS_SUBMODULE ASPECT(resolve_impl, cache_hit_cached)
-
/* Given that a finished DNS resolve is available in our cache, we want
* dns_resolve_impl() return it to called via resolve_out and pass the
* handling to set_exitconn_info_from_resolve function.
*/
static int
-NS(router_my_exit_policy_is_reject_star)(void)
+dns_impl_cache_hit_cached_router_my_exit_policy_is_reject_star(void)
{
return 0;
}
@@ -652,7 +628,8 @@ static edge_connection_t *last_exitconn = NULL;
static cached_resolve_t *last_resolve = NULL;
static int
-NS(set_exitconn_info_from_resolve)(edge_connection_t *exitconn,
+dns_impl_cache_hit_cached_set_exitconn_info_from_resolve(
+ edge_connection_t *exitconn,
const cached_resolve_t *resolve,
char **hostname_out)
{
@@ -665,7 +642,7 @@ NS(set_exitconn_info_from_resolve)(edge_connection_t *exitconn,
}
static void
-NS(test_main)(void *arg)
+test_dns_impl_cache_hit_cached(void *arg)
{
int retval;
int made_pending = 0;
@@ -688,8 +665,10 @@ NS(test_main)(void *arg)
strlcpy(cache_entry->address, TO_CONN(exitconn)->address,
sizeof(cache_entry->address));
- NS_MOCK(router_my_exit_policy_is_reject_star);
- NS_MOCK(set_exitconn_info_from_resolve);
+ MOCK(router_my_exit_policy_is_reject_star,
+ dns_impl_cache_hit_cached_router_my_exit_policy_is_reject_star);
+ MOCK(set_exitconn_info_from_resolve,
+ dns_impl_cache_hit_cached_set_exitconn_info_from_resolve);
dns_init();
@@ -706,8 +685,8 @@ NS(test_main)(void *arg)
tt_assert(last_resolve == cache_entry);
done:
- NS_UNMOCK(router_my_exit_policy_is_reject_star);
- NS_UNMOCK(set_exitconn_info_from_resolve);
+ UNMOCK(router_my_exit_policy_is_reject_star);
+ UNMOCK(set_exitconn_info_from_resolve);
tor_free(on_circ);
tor_free(TO_CONN(exitconn)->address);
tor_free(cache_entry->pending_connections);
@@ -715,10 +694,6 @@ NS(test_main)(void *arg)
return;
}
-#undef NS_SUBMODULE
-
-#define NS_SUBMODULE ASPECT(resolve_impl, cache_miss)
-
/* Given that there are neither pending nor pre-cached resolve for a given
* address, we want dns_resolve_impl() to create a new cached_resolve_t
* object, mark it as pending, insert it into the cache, attach the exit
@@ -726,7 +701,7 @@ NS(test_main)(void *arg)
* with the cached_resolve_t object it created.
*/
static int
-NS(router_my_exit_policy_is_reject_star)(void)
+dns_impl_cache_miss_router_my_exit_policy_is_reject_star(void)
{
return 0;
}
@@ -734,7 +709,7 @@ NS(router_my_exit_policy_is_reject_star)(void)
static cached_resolve_t *last_launched_resolve = NULL;
static int
-NS(launch_resolve)(cached_resolve_t *resolve)
+dns_impl_cache_miss_launch_resolve(cached_resolve_t *resolve)
{
last_launched_resolve = resolve;
@@ -742,7 +717,7 @@ NS(launch_resolve)(cached_resolve_t *resolve)
}
static void
-NS(test_main)(void *arg)
+test_dns_impl_cache_miss(void *arg)
{
int retval;
int made_pending = 0;
@@ -761,8 +736,10 @@ NS(test_main)(void *arg)
strlcpy(query.address, TO_CONN(exitconn)->address, sizeof(query.address));
- NS_MOCK(router_my_exit_policy_is_reject_star);
- NS_MOCK(launch_resolve);
+ MOCK(router_my_exit_policy_is_reject_star,
+ dns_impl_cache_miss_router_my_exit_policy_is_reject_star);
+ MOCK(launch_resolve,
+ dns_impl_cache_miss_launch_resolve);
dns_init();
@@ -785,8 +762,8 @@ NS(test_main)(void *arg)
tt_str_op(cache_entry->address,OP_EQ,TO_CONN(exitconn)->address);
done:
- NS_UNMOCK(router_my_exit_policy_is_reject_star);
- NS_UNMOCK(launch_resolve);
+ UNMOCK(router_my_exit_policy_is_reject_star);
+ UNMOCK(launch_resolve);
tor_free(on_circ);
tor_free(TO_CONN(exitconn)->address);
if (cache_entry)
@@ -796,22 +773,22 @@ NS(test_main)(void *arg)
return;
}
-#undef NS_SUBMODULE
-
struct testcase_t dns_tests[] = {
#ifdef HAVE_EVDNS_BASE_GET_NAMESERVER_ADDR
- TEST_CASE(configure_nameservers_fallback),
+ { "configure_ns_fallback", test_dns_configure_ns_fallback,
+ TT_FORK, NULL, NULL },
#endif
- TEST_CASE(clip_ttl),
- TEST_CASE(resolve),
- TEST_CASE_ASPECT(resolve_impl, addr_is_ip_no_need_to_resolve),
- TEST_CASE_ASPECT(resolve_impl, non_exit),
- TEST_CASE_ASPECT(resolve_impl, addr_is_invalid_dest),
- TEST_CASE_ASPECT(resolve_impl, malformed_ptr),
- TEST_CASE_ASPECT(resolve_impl, cache_hit_pending),
- TEST_CASE_ASPECT(resolve_impl, cache_hit_cached),
- TEST_CASE_ASPECT(resolve_impl, cache_miss),
+ { "clip_ttl", test_dns_clip_ttl, TT_FORK, NULL, NULL },
+ { "resolve", test_dns_resolve, TT_FORK, NULL, NULL },
+ { "impl_addr_is_ip", test_dns_impl_addr_is_ip, TT_FORK, NULL, NULL },
+ { "impl_non_exit", test_dns_impl_non_exit, TT_FORK, NULL, NULL },
+ { "impl_addr_is_invalid_dest", test_dns_impl_addr_is_invalid_dest,
+ TT_FORK, NULL, NULL },
+ { "impl_malformed_ptr", test_dns_impl_malformed_ptr, TT_FORK, NULL, NULL },
+ { "impl_cache_hit_pending", test_dns_impl_cache_hit_pending,
+ TT_FORK, NULL, NULL },
+ { "impl_cache_hit_cached", test_dns_impl_cache_hit_cached,
+ TT_FORK, NULL, NULL },
+ { "impl_cache_miss", test_dns_impl_cache_miss, TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
-
-#undef NS_MODULE
diff --git a/src/test/test_dos.c b/src/test/test_dos.c
index c17cfedbf6..527e5bbe7f 100644
--- a/src/test/test_dos.c
+++ b/src/test/test_dos.c
@@ -1,8 +1,8 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define DOS_PRIVATE
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define CIRCUITLIST_PRIVATE
#include "core/or/or.h"
diff --git a/src/test/test_entryconn.c b/src/test/test_entryconn.c
index 8f2d507743..9cdd7f6d0e 100644
--- a/src/test/test_entryconn.c
+++ b/src/test/test_entryconn.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -11,7 +11,7 @@
#include "feature/client/addressmap.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
#include "feature/nodelist/nodelist.h"
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index d59b1c7153..12b4fcde3c 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -18,7 +18,7 @@
#include "core/or/circuitlist.h"
#include "core/or/circuitbuild.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "feature/dircommon/directory.h"
#include "feature/dirclient/dirclient.h"
@@ -3039,6 +3039,7 @@ static const struct testcase_setup_t upgrade_circuits = {
upgrade_circuits_setup, upgrade_circuits_cleanup
};
+#ifndef COCCI
#define NO_PREFIX_TEST(name) \
{ #name, test_ ## name, 0, NULL, NULL }
@@ -3061,6 +3062,7 @@ static const struct testcase_setup_t upgrade_circuits = {
&upgrade_circuits, (void*)(arg REASONABLY_FUTURE) }, \
{ #name "_reasonably_past", test_entry_guard_ ## name, TT_FORK, \
&upgrade_circuits, (void*)(arg REASONABLY_PAST) }
+#endif /* !defined(COCCI) */
struct testcase_t entrynodes_tests[] = {
NO_PREFIX_TEST(node_preferred_orport),
diff --git a/src/test/test_extorport.c b/src/test/test_extorport.c
index cb53a4e662..7935530653 100644
--- a/src/test/test_extorport.c
+++ b/src/test/test_extorport.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONNECTION_PRIVATE
diff --git a/src/test/test_geoip.c b/src/test/test_geoip.c
index 16c566bdbc..bf9932c169 100644
--- a/src/test/test_geoip.c
+++ b/src/test/test_geoip.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_guardfraction.c b/src/test/test_guardfraction.c
index ac8bfbfded..00c200e0fd 100644
--- a/src/test/test_guardfraction.c
+++ b/src/test/test_guardfraction.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define GUARDFRACTION_PRIVATE
diff --git a/src/test/test_handles.c b/src/test/test_handles.c
index 7f1d6e1898..dbb5b1a18e 100644
--- a/src/test/test_handles.c
+++ b/src/test/test_handles.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_helpers.c b/src/test/test_helpers.c
index 8eb3c2c928..f31c28b24d 100644
--- a/src/test/test_helpers.c
+++ b/src/test/test_helpers.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,6 +9,7 @@
#define ROUTERLIST_PRIVATE
#define CONFIG_PRIVATE
#define CONNECTION_PRIVATE
+#define CONNECTION_OR_PRIVATE
#define MAINLOOP_PRIVATE
#include "orconfig.h"
@@ -16,9 +17,10 @@
#include "lib/buf/buffers.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "app/main/subsysmgr.h"
#include "core/mainloop/connection.h"
+#include "core/or/connection_or.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "core/mainloop/mainloop.h"
#include "feature/nodelist/nodelist.h"
@@ -33,6 +35,7 @@
#include "core/or/cell_st.h"
#include "core/or/connection_st.h"
+#include "core/or/or_connection_st.h"
#include "feature/nodelist/node_st.h"
#include "core/or/origin_circuit_st.h"
#include "feature/nodelist/routerlist_st.h"
@@ -42,14 +45,14 @@
#include "test/test_connection.h"
#ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
-DISABLE_GCC_WARNING(overlength-strings)
+DISABLE_GCC_WARNING("-Woverlength-strings")
/* We allow huge string constants in the unit tests, but not in the code
* at large. */
#endif
#include "test_descriptors.inc"
#include "core/or/circuitlist.h"
#ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
-ENABLE_GCC_WARNING(overlength-strings)
+ENABLE_GCC_WARNING("-Woverlength-strings")
#endif
/* Return a statically allocated string representing yesterday's date
@@ -194,6 +197,14 @@ fake_close_socket(tor_socket_t sock)
return 0;
}
+/* Helper for test_conn_get_proxy_or_connection() */
+void
+mock_connection_or_change_state(or_connection_t *conn, uint8_t state)
+{
+ tor_assert(conn);
+ conn->base_.state = state;
+}
+
static int mock_connection_connect_sockaddr_called = 0;
static int fake_socket_number = TEST_CONN_FD_INIT;
@@ -228,6 +239,77 @@ mock_connection_connect_sockaddr(connection_t *conn,
return 1;
}
+or_connection_t *
+test_conn_get_proxy_or_connection(unsigned int proxy_type)
+{
+ or_connection_t *conn = NULL;
+ tor_addr_t dst_addr;
+ tor_addr_t proxy_addr;
+ int socket_err = 0;
+ int in_progress = 0;
+
+ MOCK(connection_connect_sockaddr,
+ mock_connection_connect_sockaddr);
+ MOCK(connection_write_to_buf_impl_,
+ connection_write_to_buf_mock);
+ MOCK(connection_or_change_state,
+ mock_connection_or_change_state);
+ MOCK(tor_close_socket, fake_close_socket);
+
+ tor_init_connection_lists();
+
+ conn = or_connection_new(CONN_TYPE_OR, TEST_CONN_FAMILY);
+ tt_assert(conn);
+
+ /* Set up a destination address. */
+ test_conn_lookup_addr_helper(TEST_CONN_ADDRESS, TEST_CONN_FAMILY,
+ &dst_addr);
+ tt_assert(!tor_addr_is_null(&dst_addr));
+
+ conn->proxy_type = proxy_type;
+ conn->base_.proxy_state = PROXY_INFANT;
+
+ tor_addr_copy_tight(&conn->base_.addr, &dst_addr);
+ conn->base_.address = tor_addr_to_str_dup(&dst_addr);
+ conn->base_.port = TEST_CONN_PORT;
+
+ /* Set up a proxy address. */
+ test_conn_lookup_addr_helper(TEST_CONN_ADDRESS_2, TEST_CONN_FAMILY,
+ &proxy_addr);
+ tt_assert(!tor_addr_is_null(&proxy_addr));
+
+ conn->base_.state = OR_CONN_STATE_CONNECTING;
+
+ mock_connection_connect_sockaddr_called = 0;
+ in_progress = connection_connect(TO_CONN(conn), TEST_CONN_ADDRESS_PORT,
+ &proxy_addr, TEST_CONN_PORT, &socket_err);
+ tt_int_op(mock_connection_connect_sockaddr_called, OP_EQ, 1);
+ tt_assert(!socket_err);
+ tt_assert(in_progress == 0 || in_progress == 1);
+
+ assert_connection_ok(TO_CONN(conn), time(NULL));
+
+ in_progress = connection_or_finished_connecting(conn);
+ tt_int_op(in_progress, OP_EQ, 0);
+
+ assert_connection_ok(TO_CONN(conn), time(NULL));
+
+ UNMOCK(connection_connect_sockaddr);
+ UNMOCK(connection_write_to_buf_impl_);
+ UNMOCK(connection_or_change_state);
+ UNMOCK(tor_close_socket);
+ return conn;
+
+ /* On failure */
+ done:
+ UNMOCK(connection_connect_sockaddr);
+ UNMOCK(connection_write_to_buf_impl_);
+ UNMOCK(connection_or_change_state);
+ UNMOCK(tor_close_socket);
+ connection_free_(TO_CONN(conn));
+ return NULL;
+}
+
/** Create and return a new connection/stream */
connection_t *
test_conn_get_connection(uint8_t state, uint8_t type, uint8_t purpose)
diff --git a/src/test/test_helpers.h b/src/test/test_helpers.h
index d82072bb34..eaf18e19e2 100644
--- a/src/test/test_helpers.h
+++ b/src/test/test_helpers.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_TEST_HELPERS_H
@@ -26,6 +26,9 @@ char *buf_get_contents(buf_t *buf, size_t *sz_out);
int mock_tor_addr_lookup__fail_on_bad_addrs(const char *name,
uint16_t family, tor_addr_t *out);
+void mock_connection_or_change_state(or_connection_t *conn, uint8_t state);
+
+or_connection_t *test_conn_get_proxy_or_connection(unsigned int proxy_type);
connection_t *test_conn_get_connection(uint8_t state,
uint8_t type, uint8_t purpose);
or_options_t *helper_parse_options(const char *conf);
diff --git a/src/test/test_hs.c b/src/test/test_hs.c
index 2b69aae547..46b4493a3d 100644
--- a/src/test/test_hs.c
+++ b/src/test/test_hs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_hs_cache.c b/src/test/test_hs_cache.c
index 86ac7e7fb1..8ea550b65f 100644
--- a/src/test/test_hs_cache.c
+++ b/src/test/test_hs_cache.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -10,7 +10,7 @@
#define DIRCACHE_PRIVATE
#define DIRCLIENT_PRIVATE
#define HS_CACHE_PRIVATE
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#include "trunnel/ed25519_cert.h"
#include "feature/hs/hs_cache.h"
@@ -20,9 +20,10 @@
#include "feature/nodelist/networkstatus.h"
#include "core/mainloop/connection.h"
#include "core/proto/proto_http.h"
-#include "lib/crypt_ops/crypto_format.h"
#include "core/or/circuitlist.h"
#include "core/or/channel.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/crypt_ops/crypto_rand.h"
#include "core/or/edge_connection_st.h"
#include "core/or/or_circuit_st.h"
@@ -411,7 +412,7 @@ test_hsdir_revision_counter_check(void *arg)
retval = hs_desc_decode_descriptor(received_desc_str,
subcredential, NULL, &received_desc);
- tt_int_op(retval, OP_EQ, 0);
+ tt_int_op(retval, OP_EQ, HS_DESC_DECODE_OK);
tt_assert(received_desc);
/* Check that the revision counter is correct */
@@ -444,7 +445,7 @@ test_hsdir_revision_counter_check(void *arg)
retval = hs_desc_decode_descriptor(received_desc_str,
subcredential, NULL, &received_desc);
- tt_int_op(retval, OP_EQ, 0);
+ tt_int_op(retval, OP_EQ, HS_DESC_DECODE_OK);
tt_assert(received_desc);
/* Check that the revision counter is the latest */
@@ -567,6 +568,136 @@ test_client_cache(void *arg)
}
}
+/** Test that we can store HS descriptors in the client HS cache. */
+static void
+test_client_cache_decrypt(void *arg)
+{
+ int ret;
+ char *desc_encoded = NULL;
+ uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN];
+ curve25519_keypair_t client_kp;
+ ed25519_keypair_t service_kp;
+ hs_descriptor_t *desc = NULL;
+ const hs_descriptor_t *search_desc;
+ const char *search_desc_encoded;
+
+ (void) arg;
+
+ /* Initialize HSDir cache subsystem */
+ hs_init();
+
+ MOCK(networkstatus_get_live_consensus,
+ mock_networkstatus_get_live_consensus);
+
+ /* Set consensus time */
+ parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
+ &mock_ns.valid_after);
+ parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
+ &mock_ns.fresh_until);
+ parse_rfc1123_time("Sat, 26 Oct 1985 16:00:00 UTC",
+ &mock_ns.valid_until);
+
+ /* Generate a valid descriptor with normal values. */
+ {
+ ret = ed25519_keypair_generate(&service_kp, 0);
+ tt_int_op(ret, OP_EQ, 0);
+ ret = curve25519_keypair_generate(&client_kp, 0);
+ tt_int_op(ret, OP_EQ, 0);
+ crypto_rand((char *) descriptor_cookie, sizeof(descriptor_cookie));
+
+ desc = hs_helper_build_hs_desc_with_client_auth(descriptor_cookie,
+ &client_kp.pubkey,
+ &service_kp);
+ tt_assert(desc);
+ ret = hs_desc_encode_descriptor(desc, &service_kp, descriptor_cookie,
+ &desc_encoded);
+ tt_int_op(ret, OP_EQ, 0);
+ }
+
+ /* Put it in the cache. Should not be decrypted since the client
+ * authorization creds were not added to the global map. */
+ ret = hs_cache_store_as_client(desc_encoded, &service_kp.pubkey);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_NEED_CLIENT_AUTH);
+
+ /* We should not be able to decrypt anything. */
+ ret = hs_cache_client_new_auth_parse(&service_kp.pubkey);
+ tt_int_op(ret, OP_EQ, false);
+
+ /* Add client auth to global map. */
+ hs_helper_add_client_auth(&service_kp.pubkey, &client_kp.seckey);
+
+ /* We should not be able to decrypt anything. */
+ ret = hs_cache_client_new_auth_parse(&service_kp.pubkey);
+ tt_int_op(ret, OP_EQ, true);
+
+ /* Lookup the cache to make sure it is usable and there. */
+ search_desc = hs_cache_lookup_as_client(&service_kp.pubkey);
+ tt_assert(search_desc);
+ search_desc_encoded = hs_cache_lookup_encoded_as_client(&service_kp.pubkey);
+ tt_mem_op(search_desc_encoded, OP_EQ, desc_encoded, strlen(desc_encoded));
+
+ done:
+ hs_descriptor_free(desc);
+ tor_free(desc_encoded);
+
+ hs_free_all();
+
+ UNMOCK(networkstatus_get_live_consensus);
+}
+
+static void
+test_client_cache_remove(void *arg)
+{
+ int ret;
+ ed25519_keypair_t service_kp;
+ hs_descriptor_t *desc1 = NULL;
+
+ (void) arg;
+
+ hs_init();
+
+ MOCK(networkstatus_get_live_consensus,
+ mock_networkstatus_get_live_consensus);
+
+ /* Set consensus time. Lookup will not return the entry if it has expired
+ * and it is checked against the consensus valid_after time. */
+ parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
+ &mock_ns.valid_after);
+ parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
+ &mock_ns.fresh_until);
+ parse_rfc1123_time("Sat, 26 Oct 1985 16:00:00 UTC",
+ &mock_ns.valid_until);
+
+ /* Generate service keypair */
+ tt_int_op(0, OP_EQ, ed25519_keypair_generate(&service_kp, 0));
+
+ /* Build a descriptor and cache it. */
+ {
+ char *encoded;
+ desc1 = hs_helper_build_hs_desc_with_ip(&service_kp);
+ tt_assert(desc1);
+ ret = hs_desc_encode_descriptor(desc1, &service_kp, NULL, &encoded);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_assert(encoded);
+
+ /* Store it */
+ ret = hs_cache_store_as_client(encoded, &service_kp.pubkey);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
+ tor_free(encoded);
+ tt_assert(hs_cache_lookup_as_client(&service_kp.pubkey));
+ }
+
+ /* Remove the cached entry. */
+ hs_cache_remove_as_client(&service_kp.pubkey);
+ tt_assert(!hs_cache_lookup_as_client(&service_kp.pubkey));
+
+ done:
+ hs_descriptor_free(desc1);
+ hs_free_all();
+
+ UNMOCK(networkstatus_get_live_consensus);
+}
+
struct testcase_t hs_cache[] = {
/* Encoding tests. */
{ "directory", test_directory, TT_FORK,
@@ -579,6 +710,10 @@ struct testcase_t hs_cache[] = {
NULL, NULL },
{ "client_cache", test_client_cache, TT_FORK,
NULL, NULL },
+ { "client_cache_decrypt", test_client_cache_decrypt, TT_FORK,
+ NULL, NULL },
+ { "client_cache_remove", test_client_cache_remove, TT_FORK,
+ NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_hs_cell.c b/src/test/test_hs_cell.c
index 403509fbc8..5406339276 100644
--- a/src/test/test_hs_cell.c
+++ b/src/test/test_hs_cell.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_hs_client.c b/src/test/test_hs_client.c
index b777dafdfb..945f631459 100644
--- a/src/test/test_hs_client.c
+++ b/src/test/test_hs_client.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -10,7 +10,7 @@
#define CRYPTO_PRIVATE
#define MAINLOOP_PRIVATE
#define HS_CLIENT_PRIVATE
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define CIRCUITBUILD_PRIVATE
#define CIRCUITLIST_PRIVATE
#define CONNECTION_PRIVATE
@@ -25,6 +25,7 @@
#include "app/config/config.h"
#include "lib/crypt_ops/crypto_cipher.h"
#include "lib/crypt_ops/crypto_dh.h"
+#include "lib/crypt_ops/crypto_rand.h"
#include "core/or/channeltls.h"
#include "feature/dircommon/directory.h"
#include "core/mainloop/mainloop.h"
@@ -79,6 +80,23 @@ mock_networkstatus_get_live_consensus(time_t now)
}
static int
+mock_write_str_to_file(const char *path, const char *str, int bin)
+{
+ (void) bin;
+ (void) path;
+ (void) str;
+ return 0;
+}
+
+static or_options_t mocked_options;
+
+static const or_options_t *
+mock_get_options(void)
+{
+ return &mocked_options;
+}
+
+static int
helper_config_client(const char *conf, int validate_only)
{
int ret = 0;
@@ -92,6 +110,24 @@ helper_config_client(const char *conf, int validate_only)
return ret;
}
+static void
+helper_add_random_client_auth(const ed25519_public_key_t *service_pk)
+{
+ char *conf = NULL;
+#define conf_fmt "ClientOnionAuthDir %s\n"
+ tor_asprintf(&conf, conf_fmt, get_fname("auth_keys"));
+#undef conf_fmt
+ helper_config_client(conf, 0);
+ tor_free(conf);
+
+ digest256map_t *client_auths = get_hs_client_auths_map();
+ hs_client_service_authorization_t *auth =
+ tor_malloc_zero(sizeof(hs_client_service_authorization_t));
+ curve25519_secret_key_generate(&auth->enc_seckey, 0);
+ hs_build_address(service_pk, HS_VERSION_THREE, auth->onion_address);
+ digest256map_set(client_auths, service_pk->pubkey, auth);
+}
+
/* Test helper function: Setup a circuit and a stream with the same hidden
* service destination, and put them in <b>circ_out</b> and
* <b>conn_out</b>. Make the stream wait for circuits to be established to the
@@ -287,7 +323,7 @@ test_e2e_rend_circuit_setup(void *arg)
mock_connection_ap_handshake_send_begin);
/* Setup */
- retval = helper_get_circ_and_stream_for_test( &or_circ, &conn, 0);
+ retval = helper_get_circ_and_stream_for_test(&or_circ, &conn, 0);
tt_int_op(retval, OP_EQ, 0);
tt_assert(or_circ);
tt_assert(conn);
@@ -303,9 +339,8 @@ test_e2e_rend_circuit_setup(void *arg)
/**********************************************/
/* Setup the circuit */
- retval = hs_circuit_setup_e2e_rend_circ(or_circ,
- ntor_key_seed, sizeof(ntor_key_seed),
- 0);
+ retval = hs_circuit_setup_e2e_rend_circ(or_circ, ntor_key_seed,
+ sizeof(ntor_key_seed), 0);
tt_int_op(retval, OP_EQ, 0);
/**********************************************/
@@ -315,11 +350,9 @@ test_e2e_rend_circuit_setup(void *arg)
tt_int_op(retval, OP_EQ, 1);
/* Check that the crypt path has prop224 algorithm parameters */
- tt_int_op(
- crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.f_digest),
+ tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.f_digest),
OP_EQ, DIGEST_SHA3_256);
- tt_int_op(
- crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.b_digest),
+ tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.b_digest),
OP_EQ, DIGEST_SHA3_256);
tt_assert(or_circ->cpath->pvt_crypto.f_crypto);
tt_assert(or_circ->cpath->pvt_crypto.b_crypto);
@@ -393,7 +426,8 @@ test_client_pick_intro(void *arg)
tt_assert(encoded);
/* store it */
- hs_cache_store_as_client(encoded, &service_kp.pubkey);
+ ret = hs_cache_store_as_client(encoded, &service_kp.pubkey);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
/* fetch it to make sure it works */
const hs_descriptor_t *fetched_desc =
@@ -550,6 +584,17 @@ mock_connection_mark_unattached_ap_(entry_connection_t *conn, int endreason,
}
static void
+mock_connection_mark_unattached_ap_no_close(entry_connection_t *conn,
+ int endreason, int line,
+ const char *file)
+{
+ (void) conn;
+ (void) endreason;
+ (void) line;
+ (void) file;
+}
+
+static void
test_descriptor_fetch(void *arg)
{
int ret;
@@ -687,6 +732,10 @@ test_parse_auth_file_content(void *arg)
/* Bigger key than it should be */
tt_assert(!parse_auth_file_content("xx:descriptor:x25519:"
"vjqea4jbhwwc4hto7ekyvqfbeodghbaq6nxi45hz4wr3qvhqv3yqa"));
+ /* All-zeroes key */
+ tt_assert(!parse_auth_file_content("xx:descriptor:x25519:"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
+
done:
tor_free(auth);
}
@@ -824,6 +873,7 @@ test_desc_has_arrived_cleanup(void *arg)
ed25519_keypair_t signing_kp;
entry_connection_t *socks1 = NULL, *socks2 = NULL;
hs_ident_dir_conn_t hs_dir_ident;
+ dir_connection_t *dir_conn = NULL;
(void) arg;
@@ -852,7 +902,7 @@ test_desc_has_arrived_cleanup(void *arg)
/* Store in the client cache. */
ret = hs_cache_store_as_client(desc_str, &signing_kp.pubkey);
- tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
cached_desc = hs_cache_lookup_as_client(&signing_kp.pubkey);
tt_assert(cached_desc);
hs_helper_desc_equal(desc, cached_desc);
@@ -880,9 +930,11 @@ test_desc_has_arrived_cleanup(void *arg)
* SOCKS connection to be ended with a resolved failed. */
hs_ident_dir_conn_init(&signing_kp.pubkey,
&desc->plaintext_data.blinded_pubkey, &hs_dir_ident);
- hs_client_desc_has_arrived(&hs_dir_ident);
+ dir_conn = dir_connection_new(AF_INET);
+ dir_conn->hs_ident = hs_ident_dir_conn_dup(&hs_dir_ident);
+ hs_client_dir_fetch_done(dir_conn, "A reason", desc_str, 200);
+ connection_free_minimal(TO_CONN(dir_conn));
tt_int_op(socks1->edge_.end_reason, OP_EQ, END_STREAM_REASON_RESOLVEFAILED);
- /* XXX: MUST work with OP_EQ. */
tt_int_op(socks2->edge_.end_reason, OP_EQ, END_STREAM_REASON_RESOLVEFAILED);
/* Now let say tor cleans up the intro state cache which resets all intro
@@ -891,7 +943,6 @@ test_desc_has_arrived_cleanup(void *arg)
/* Retrying all SOCKS which should basically do nothing since we don't have
* any pending SOCKS connection in AP_CONN_STATE_RENDDESC_WAIT state. */
- /* XXX: BUG() is triggered here, shouldn't if socks2 wasn't alive. */
retry_all_socks_conn_waiting_for_desc();
done:
@@ -918,6 +969,7 @@ test_close_intro_circuits_new_desc(void *arg)
(void) arg;
hs_init();
+ rend_cache_init();
/* This is needed because of the client cache expiration timestamp is based
* on having a consensus. See cached_client_descriptor_has_expired(). */
@@ -942,6 +994,51 @@ test_close_intro_circuits_new_desc(void *arg)
circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCING;
ocirc = TO_ORIGIN_CIRCUIT(circ);
+ /* Build a descriptor _without_ client authorization and thus not
+ * decryptable. Make sure the close circuit code path is not triggered. */
+ {
+ char *desc_encoded = NULL;
+ uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN];
+ curve25519_keypair_t client_kp;
+ hs_descriptor_t *desc = NULL;
+
+ tt_int_op(0, OP_EQ, curve25519_keypair_generate(&client_kp, 0));
+ crypto_rand((char *) descriptor_cookie, sizeof(descriptor_cookie));
+
+ desc = hs_helper_build_hs_desc_with_client_auth(descriptor_cookie,
+ &client_kp.pubkey,
+ &service_kp);
+ tt_assert(desc);
+ ret = hs_desc_encode_descriptor(desc, &service_kp, descriptor_cookie,
+ &desc_encoded);
+ tt_int_op(ret, OP_EQ, 0);
+ /* Associate descriptor intro key with the dummy circuit. */
+ const hs_desc_intro_point_t *ip =
+ smartlist_get(desc->encrypted_data.intro_points, 0);
+ tt_assert(ip);
+ ocirc->hs_ident = hs_ident_circuit_new(&service_kp.pubkey);
+ ed25519_pubkey_copy(&ocirc->hs_ident->intro_auth_pk,
+ &ip->auth_key_cert->signed_key);
+ hs_descriptor_free(desc);
+ tt_assert(desc_encoded);
+ /* Put it in the cache. Should not be decrypted since the client
+ * authorization creds were not added to the global map. */
+ ret = hs_cache_store_as_client(desc_encoded, &service_kp.pubkey);
+ tor_free(desc_encoded);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_NEED_CLIENT_AUTH);
+
+ /* Clean cache with a future timestamp. It will trigger the clean up and
+ * attempt to close the circuit but only if the descriptor is decryptable.
+ * Cache object should be removed and circuit untouched. */
+ hs_cache_clean_as_client(mock_ns.valid_after + (60 * 60 * 24));
+ tt_assert(!hs_cache_lookup_as_client(&service_kp.pubkey));
+
+ /* Make sure the circuit still there. */
+ tt_assert(circuit_get_next_intro_circ(NULL, true));
+ /* Get rid of the ident, it will be replaced in the next tests. */
+ hs_ident_circuit_free(ocirc->hs_ident);
+ }
+
/* Build the first descriptor and cache it. */
{
char *encoded;
@@ -953,7 +1050,7 @@ test_close_intro_circuits_new_desc(void *arg)
/* Store it */
ret = hs_cache_store_as_client(encoded, &service_kp.pubkey);
- tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
tor_free(encoded);
tt_assert(hs_cache_lookup_as_client(&service_kp.pubkey));
}
@@ -988,8 +1085,8 @@ test_close_intro_circuits_new_desc(void *arg)
tt_int_op(ret, OP_EQ, 0);
tt_assert(encoded);
- hs_cache_store_as_client(encoded, &service_kp.pubkey);
- tt_int_op(ret, OP_EQ, 0);
+ ret = hs_cache_store_as_client(encoded, &service_kp.pubkey);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
tor_free(encoded);
tt_assert(hs_cache_lookup_as_client(&service_kp.pubkey));
}
@@ -1091,6 +1188,294 @@ test_close_intro_circuits_cache_clean(void *arg)
UNMOCK(networkstatus_get_live_consensus);
}
+static void
+test_socks_hs_errors(void *arg)
+{
+ int ret;
+ char *desc_encoded = NULL;
+ ed25519_keypair_t service_kp;
+ ed25519_keypair_t signing_kp;
+ entry_connection_t *socks_conn = NULL;
+ dir_connection_t *dir_conn = NULL;
+ hs_descriptor_t *desc = NULL;
+ uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN];
+
+ (void) arg;
+
+ MOCK(networkstatus_get_live_consensus,
+ mock_networkstatus_get_live_consensus);
+ MOCK(connection_mark_unattached_ap_,
+ mock_connection_mark_unattached_ap_no_close);
+ MOCK(read_file_to_str, mock_read_file_to_str);
+ MOCK(tor_listdir, mock_tor_listdir);
+ MOCK(check_private_dir, mock_check_private_dir);
+
+ /* Set consensus time */
+ parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
+ &mock_ns.valid_after);
+ parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
+ &mock_ns.fresh_until);
+ parse_rfc1123_time("Sat, 26 Oct 1985 16:00:00 UTC",
+ &mock_ns.valid_until);
+
+ hs_init();
+
+ ret = ed25519_keypair_generate(&service_kp, 0);
+ tt_int_op(ret, OP_EQ, 0);
+ ret = ed25519_keypair_generate(&signing_kp, 0);
+ tt_int_op(ret, OP_EQ, 0);
+
+ socks_conn = helper_build_socks_connection(&service_kp.pubkey,
+ AP_CONN_STATE_RENDDESC_WAIT);
+ tt_assert(socks_conn);
+
+ /* Create directory connection. */
+ dir_conn = dir_connection_new(AF_INET);
+ dir_conn->hs_ident = tor_malloc_zero(sizeof(hs_ident_dir_conn_t));
+ TO_CONN(dir_conn)->purpose = DIR_PURPOSE_FETCH_HSDESC;
+ ed25519_pubkey_copy(&dir_conn->hs_ident->identity_pk, &service_kp.pubkey);
+
+ /* Encode descriptor so we can decode it. */
+ desc = hs_helper_build_hs_desc_with_ip(&service_kp);
+ tt_assert(desc);
+
+ crypto_rand((char *) descriptor_cookie, sizeof(descriptor_cookie));
+ ret = hs_desc_encode_descriptor(desc, &service_kp, descriptor_cookie,
+ &desc_encoded);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_assert(desc_encoded);
+
+ /* Try decoding. Point this to an existing descriptor. The following should
+ * fail thus the desc_out should be set to NULL. */
+ hs_descriptor_t *desc_out = desc;
+ ret = hs_client_decode_descriptor(desc_encoded, &service_kp.pubkey,
+ &desc_out);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_NEED_CLIENT_AUTH);
+ tt_assert(desc_out == NULL);
+
+ /* The caching will fail to decrypt because the descriptor_cookie used above
+ * is not known to the HS subsystem. This will lead to a missing client
+ * auth. */
+ hs_client_dir_fetch_done(dir_conn, "Reason", desc_encoded, 200);
+
+ tt_int_op(socks_conn->socks_request->socks_extended_error_code, OP_EQ,
+ SOCKS5_HS_MISSING_CLIENT_AUTH);
+
+ /* Add in the global client auth list bad creds for this service. */
+ helper_add_random_client_auth(&service_kp.pubkey);
+
+ ret = hs_client_decode_descriptor(desc_encoded, &service_kp.pubkey,
+ &desc_out);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_BAD_CLIENT_AUTH);
+ tt_assert(desc_out == NULL);
+
+ /* Simmulate a fetch done again. This should replace the cached descriptor
+ * and signal a bad client authorization. */
+ hs_client_dir_fetch_done(dir_conn, "Reason", desc_encoded, 200);
+ tt_int_op(socks_conn->socks_request->socks_extended_error_code, OP_EQ,
+ SOCKS5_HS_BAD_CLIENT_AUTH);
+
+ done:
+ connection_free_minimal(ENTRY_TO_CONN(socks_conn));
+ connection_free_minimal(TO_CONN(dir_conn));
+ hs_descriptor_free(desc);
+ tor_free(desc_encoded);
+
+ hs_free_all();
+
+ UNMOCK(networkstatus_get_live_consensus);
+ UNMOCK(connection_mark_unattached_ap_);
+ UNMOCK(read_file_to_str);
+ UNMOCK(tor_listdir);
+ UNMOCK(check_private_dir);
+}
+
+static void
+test_close_intro_circuit_failure(void *arg)
+{
+ char digest[DIGEST_LEN];
+ circuit_t *circ = NULL;
+ ed25519_keypair_t service_kp, intro_kp;
+ origin_circuit_t *ocirc = NULL;
+ tor_addr_t addr;
+ const hs_cache_intro_state_t *entry;
+
+ (void) arg;
+
+ hs_init();
+
+ /* Generate service keypair */
+ tt_int_op(0, OP_EQ, ed25519_keypair_generate(&service_kp, 0));
+ tt_int_op(0, OP_EQ, ed25519_keypair_generate(&intro_kp, 0));
+
+ /* Create and add to the global list a dummy client introduction circuit at
+ * the ACK WAIT state. */
+ circ = dummy_origin_circuit_new(0);
+ tt_assert(circ);
+ circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT;
+ ocirc = TO_ORIGIN_CIRCUIT(circ);
+ ocirc->hs_ident = hs_ident_circuit_new(&service_kp.pubkey);
+ ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
+ /* Code path will log this exit so build it. */
+ ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest,
+ NULL, NULL, NULL, &addr,
+ 4242);
+ ed25519_pubkey_copy(&ocirc->hs_ident->intro_auth_pk, &intro_kp.pubkey);
+
+ /* We'll make for close the circuit for a timeout failure. It should _NOT_
+ * end up in the failure cache just yet. We do that on free() only. */
+ circuit_mark_for_close(circ, END_CIRC_REASON_TIMEOUT);
+ tt_assert(!hs_cache_client_intro_state_find(&service_kp.pubkey,
+ &intro_kp.pubkey));
+ /* Time to free. It should get removed. */
+ circuit_free(circ);
+ entry = hs_cache_client_intro_state_find(&service_kp.pubkey,
+ &intro_kp.pubkey);
+ tt_assert(entry);
+ tt_uint_op(entry->timed_out, OP_EQ, 1);
+ hs_cache_client_intro_state_purge();
+
+ /* Again, create and add to the global list a dummy client introduction
+ * circuit at the INTRODUCING state. */
+ circ = dummy_origin_circuit_new(0);
+ tt_assert(circ);
+ circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCING;
+ ocirc = TO_ORIGIN_CIRCUIT(circ);
+ ocirc->hs_ident = hs_ident_circuit_new(&service_kp.pubkey);
+ ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
+ /* Code path will log this exit so build it. */
+ ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest,
+ NULL, NULL, NULL, &addr,
+ 4242);
+ ed25519_pubkey_copy(&ocirc->hs_ident->intro_auth_pk, &intro_kp.pubkey);
+
+ /* On free, we should get an unreachable failure. */
+ circuit_free(circ);
+ entry = hs_cache_client_intro_state_find(&service_kp.pubkey,
+ &intro_kp.pubkey);
+ tt_assert(entry);
+ tt_uint_op(entry->unreachable_count, OP_EQ, 1);
+ hs_cache_client_intro_state_purge();
+
+ /* Again, create and add to the global list a dummy client introduction
+ * circuit at the INTRODUCING state but we'll close it for timeout. It
+ * should not be noted as a timeout failure. */
+ circ = dummy_origin_circuit_new(0);
+ tt_assert(circ);
+ circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCING;
+ ocirc = TO_ORIGIN_CIRCUIT(circ);
+ ocirc->hs_ident = hs_ident_circuit_new(&service_kp.pubkey);
+ ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
+ /* Code path will log this exit so build it. */
+ ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest,
+ NULL, NULL, NULL, &addr,
+ 4242);
+ ed25519_pubkey_copy(&ocirc->hs_ident->intro_auth_pk, &intro_kp.pubkey);
+
+ circuit_mark_for_close(circ, END_CIRC_REASON_TIMEOUT);
+ circuit_free(circ);
+ tt_assert(!hs_cache_client_intro_state_find(&service_kp.pubkey,
+ &intro_kp.pubkey));
+
+ /* Again, create and add to the global list a dummy client introduction
+ * circuit at the INTRODUCING state but without a chosen_exit. In theory, it
+ * can not happen but we'll make sure it doesn't end up in the failure cache
+ * anyway. */
+ circ = dummy_origin_circuit_new(0);
+ tt_assert(circ);
+ circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCING;
+ ocirc = TO_ORIGIN_CIRCUIT(circ);
+ ocirc->hs_ident = hs_ident_circuit_new(&service_kp.pubkey);
+ ed25519_pubkey_copy(&ocirc->hs_ident->intro_auth_pk, &intro_kp.pubkey);
+
+ circuit_free(circ);
+ tt_assert(!hs_cache_client_intro_state_find(&service_kp.pubkey,
+ &intro_kp.pubkey));
+
+ done:
+ circuit_free(circ);
+ hs_free_all();
+}
+
+static void
+test_purge_ephemeral_client_auth(void *arg)
+{
+ ed25519_keypair_t service_kp;
+ hs_client_service_authorization_t *auth = NULL;
+ hs_client_register_auth_status_t status;
+
+ (void) arg;
+
+ /* We will try to write on disk client credentials. */
+ MOCK(check_private_dir, mock_check_private_dir);
+ MOCK(get_options, mock_get_options);
+ MOCK(write_str_to_file, mock_write_str_to_file);
+
+ /* Boggus directory so when we try to write the permanent client
+ * authorization data to disk, we don't fail. See
+ * store_permanent_client_auth_credentials() for more details. */
+ mocked_options.ClientOnionAuthDir = tor_strdup("auth_dir");
+
+ hs_init();
+
+ /* Generate service keypair */
+ tt_int_op(0, OP_EQ, ed25519_keypair_generate(&service_kp, 0));
+
+ /* Generate a client authorization object. */
+ auth = tor_malloc_zero(sizeof(hs_client_service_authorization_t));
+
+ /* Set it up. No flags meaning it is ephemeral. */
+ curve25519_secret_key_generate(&auth->enc_seckey, 0);
+ hs_build_address(&service_kp.pubkey, HS_VERSION_THREE, auth->onion_address);
+ auth->flags = 0;
+
+ /* Confirm that there is nothing in the client auth map. It is unallocated
+ * until we add the first entry. */
+ tt_assert(!get_hs_client_auths_map());
+
+ /* Add an entry to the client auth list. We loose ownership of the auth
+ * object so nullify it. */
+ status = hs_client_register_auth_credentials(auth);
+ auth = NULL;
+ tt_int_op(status, OP_EQ, REGISTER_SUCCESS);
+
+ /* We should have the entry now. */
+ digest256map_t *client_auths = get_hs_client_auths_map();
+ tt_assert(client_auths);
+ tt_int_op(digest256map_size(client_auths), OP_EQ, 1);
+
+ /* Purge the cache that should remove all ephemeral values. */
+ purge_ephemeral_client_auth();
+ tt_int_op(digest256map_size(client_auths), OP_EQ, 0);
+
+ /* Now add a new authorization object but permanent. */
+ /* Generate a client authorization object. */
+ auth = tor_malloc_zero(sizeof(hs_client_service_authorization_t));
+ curve25519_secret_key_generate(&auth->enc_seckey, 0);
+ hs_build_address(&service_kp.pubkey, HS_VERSION_THREE, auth->onion_address);
+ auth->flags = CLIENT_AUTH_FLAG_IS_PERMANENT;
+
+ /* Add an entry to the client auth list. We loose ownership of the auth
+ * object so nullify it. */
+ status = hs_client_register_auth_credentials(auth);
+ auth = NULL;
+ tt_int_op(status, OP_EQ, REGISTER_SUCCESS);
+ tt_int_op(digest256map_size(client_auths), OP_EQ, 1);
+
+ /* Purge again, the entry should still be there. */
+ purge_ephemeral_client_auth();
+ tt_int_op(digest256map_size(client_auths), OP_EQ, 1);
+
+ done:
+ client_service_authorization_free(auth);
+ hs_free_all();
+ tor_free(mocked_options.ClientOnionAuthDir);
+
+ UNMOCK(check_private_dir);
+ UNMOCK(get_options);
+ UNMOCK(write_str_to_file);
+}
+
struct testcase_t hs_client_tests[] = {
{ "e2e_rend_circuit_setup_legacy", test_e2e_rend_circuit_setup_legacy,
TT_FORK, NULL, NULL },
@@ -1108,10 +1493,19 @@ struct testcase_t hs_client_tests[] = {
TT_FORK, NULL, NULL },
{ "desc_has_arrived_cleanup", test_desc_has_arrived_cleanup,
TT_FORK, NULL, NULL },
+ { "close_intro_circuit_failure", test_close_intro_circuit_failure,
+ TT_FORK, NULL, NULL },
{ "close_intro_circuits_new_desc", test_close_intro_circuits_new_desc,
TT_FORK, NULL, NULL },
{ "close_intro_circuits_cache_clean", test_close_intro_circuits_cache_clean,
TT_FORK, NULL, NULL },
+ /* SOCKS5 Extended Error Code. */
+ { "socks_hs_errors", test_socks_hs_errors, TT_FORK, NULL, NULL },
+
+ /* Client authorization. */
+ { "purge_ephemeral_client_auth", test_purge_ephemeral_client_auth, TT_FORK,
+ NULL, NULL },
+
END_OF_TESTCASES
};
diff --git a/src/test/test_hs_common.c b/src/test/test_hs_common.c
index de3f7e04f7..61306778d4 100644
--- a/src/test/test_hs_common.c
+++ b/src/test/test_hs_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -6,6 +6,7 @@
* \brief Test hidden service common functionalities.
*/
+#define CONNECTION_EDGE_PRIVATE
#define HS_COMMON_PRIVATE
#define HS_CLIENT_PRIVATE
#define HS_SERVICE_PRIVATE
@@ -778,6 +779,7 @@ static void
test_parse_extended_hostname(void *arg)
{
(void) arg;
+ hostname_type_t type;
char address1[] = "fooaddress.onion";
char address2[] = "aaaaaaaaaaaaaaaa.onion";
@@ -788,21 +790,42 @@ test_parse_extended_hostname(void *arg)
char address7[] = ".abcdefghijklmnop.onion";
char address8[] =
"www.25njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid.onion";
+ char address9[] =
+ "www.15njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid.onion";
- tt_assert(BAD_HOSTNAME == parse_extended_hostname(address1));
- tt_assert(ONION_V2_HOSTNAME == parse_extended_hostname(address2));
- tt_str_op(address2,OP_EQ, "aaaaaaaaaaaaaaaa");
- tt_assert(EXIT_HOSTNAME == parse_extended_hostname(address3));
- tt_assert(NORMAL_HOSTNAME == parse_extended_hostname(address4));
- tt_assert(ONION_V2_HOSTNAME == parse_extended_hostname(address5));
- tt_str_op(address5,OP_EQ, "abcdefghijklmnop");
- tt_assert(ONION_V2_HOSTNAME == parse_extended_hostname(address6));
- tt_str_op(address6,OP_EQ, "abcdefghijklmnop");
- tt_assert(BAD_HOSTNAME == parse_extended_hostname(address7));
- tt_assert(ONION_V3_HOSTNAME == parse_extended_hostname(address8));
+ tt_assert(!parse_extended_hostname(address1, &type));
+ tt_int_op(type, OP_EQ, BAD_HOSTNAME);
+
+ tt_assert(parse_extended_hostname(address2, &type));
+ tt_int_op(type, OP_EQ, ONION_V2_HOSTNAME);
+ tt_str_op(address2, OP_EQ, "aaaaaaaaaaaaaaaa");
+
+ tt_assert(parse_extended_hostname(address3, &type));
+ tt_int_op(type, OP_EQ, EXIT_HOSTNAME);
+
+ tt_assert(parse_extended_hostname(address4, &type));
+ tt_int_op(type, OP_EQ, NORMAL_HOSTNAME);
+
+ tt_assert(parse_extended_hostname(address5, &type));
+ tt_int_op(type, OP_EQ, ONION_V2_HOSTNAME);
+ tt_str_op(address5, OP_EQ, "abcdefghijklmnop");
+
+ tt_assert(parse_extended_hostname(address6, &type));
+ tt_int_op(type, OP_EQ, ONION_V2_HOSTNAME);
+ tt_str_op(address6, OP_EQ, "abcdefghijklmnop");
+
+ tt_assert(!parse_extended_hostname(address7, &type));
+ tt_int_op(type, OP_EQ, BAD_HOSTNAME);
+
+ tt_assert(parse_extended_hostname(address8, &type));
+ tt_int_op(type, OP_EQ, ONION_V3_HOSTNAME);
tt_str_op(address8, OP_EQ,
"25njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid");
+ /* Invalid v3 address. */
+ tt_assert(!parse_extended_hostname(address9, &type));
+ tt_int_op(type, OP_EQ, ONION_V3_HOSTNAME);
+
done: ;
}
diff --git a/src/test/test_hs_config.c b/src/test/test_hs_config.c
index 71e1529216..b2537b746b 100644
--- a/src/test/test_hs_config.c
+++ b/src/test/test_hs_config.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_hs_control.c b/src/test/test_hs_control.c
index 7cedc987bb..8ba9f1173c 100644
--- a/src/test/test_hs_control.c
+++ b/src/test/test_hs_control.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -7,14 +7,20 @@
**/
#define CONTROL_EVENTS_PRIVATE
+#define HS_CLIENT_PRIVATE
#include "core/or/or.h"
#include "test/test.h"
+#include "test/test_helpers.h"
+#include "core/mainloop/connection.h"
#include "feature/control/control.h"
#include "feature/control/control_events.h"
+#include "feature/control/control_cmd.h"
#include "feature/control/control_fmt.h"
+#include "feature/control/control_connection_st.h"
#include "app/config/config.h"
#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_client.h"
#include "feature/hs/hs_control.h"
#include "feature/nodelist/nodelist.h"
@@ -22,7 +28,16 @@
#include "feature/nodelist/routerstatus_st.h"
#include "lib/crypt_ops/crypto_format.h"
-#include "test/test_helpers.h"
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#ifdef _WIN32
+/* For mkdir() */
+#include <direct.h>
+#else
+#include <dirent.h>
+#endif /* defined(_WIN32) */
/* mock ID digest and longname for node that's in nodelist */
#define HSDIR_EXIST_ID \
@@ -187,9 +202,511 @@ test_hs_desc_event(void *arg)
tor_free(expected_msg);
}
+/** Test that we can correctly add, remove and view client auth credentials
+ * using the control port. */
+static void
+test_hs_control_good_onion_client_auth_add(void *arg)
+{
+ (void) arg;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ int retval;
+ ed25519_public_key_t service_identity_pk_2fv, service_identity_pk_jt4;
+ control_connection_t conn;
+ char *args = NULL;
+ char *cp1 = NULL;
+ size_t sz;
+
+ hs_init();
+
+ { /* Setup the control conn */
+ memset(&conn, 0, sizeof(control_connection_t));
+ TO_CONN(&conn)->outbuf = buf_new();
+ conn.current_cmd = tor_strdup("ONION_CLIENT_AUTH_ADD");
+ }
+
+ { /* Setup the services */
+ retval = hs_parse_address(
+ "2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd",
+ &service_identity_pk_2fv,
+ NULL, NULL);
+ tt_int_op(retval, OP_EQ, 0);
+
+ retval = hs_parse_address(
+ "jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd",
+ &service_identity_pk_jt4,
+ NULL, NULL);
+ tt_int_op(retval, OP_EQ, 0);
+ }
+
+ digest256map_t *client_auths = get_hs_client_auths_map();
+ tt_assert(!client_auths);
+
+ /* Register first service */
+ args = tor_strdup("2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd "
+ "x25519:iJ1tjKCrMAbiFT2bVrCjhbfMDnE1fpaRbIS5ZHKUvEQ= ");
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Check contents */
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "250 OK\r\n");
+
+ tor_free(cp1);
+ tor_free(args);
+
+ /* Register second service (even with an unrecognized argument) */
+ args = tor_strdup("jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd "
+ "x25519:eIIdIGoSZwI2Q/lSzpf92akGki5I+PZIDz37MA5BhlA= DropSound=No");
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Check contents */
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "250 OK\r\n");
+ tor_free(cp1);
+
+ client_auths = get_hs_client_auths_map();
+ tt_assert(client_auths);
+ tt_uint_op(digest256map_size(client_auths), OP_EQ, 2);
+
+ hs_client_service_authorization_t *client_2fv =
+ digest256map_get(client_auths, service_identity_pk_2fv.pubkey);
+ tt_assert(client_2fv);
+ tt_int_op(client_2fv->flags, OP_EQ, 0);
+
+ hs_client_service_authorization_t *client_jt4 =
+ digest256map_get(client_auths, service_identity_pk_jt4.pubkey);
+ tt_assert(client_jt4);
+ tt_int_op(client_jt4->flags, OP_EQ, 0);
+
+ /* Now let's VIEW the auth credentials */
+ tor_free(conn.current_cmd);
+ conn.current_cmd = tor_strdup("ONION_CLIENT_AUTH_VIEW");
+
+ /* First go with no arguments, so that we view all the credentials */
+ tor_free(args);
+ args = tor_strdup("");
+
+#define VIEW_CORRECT_REPLY_NO_ADDR "250-ONION_CLIENT_AUTH_VIEW\r\n" \
+ "250-CLIENT 2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd " \
+ "x25519:iJ1tjKCrMAbiFT2bVrCjhbfMDnE1fpaRbIS5ZHKUvEQ=\r\n" \
+ "250-CLIENT jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd " \
+ "x25519:eIIdIGoSZwI2Q/lSzpf92akGki5I+PZIDz37MA5BhlA=\r\n" \
+ "250 OK\r\n"
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, VIEW_CORRECT_REPLY_NO_ADDR);
+ tor_free(cp1);
+
+ /* Now specify an HS addr, and see that we only view those creds */
+ tor_free(args);
+ args =
+ tor_strdup("jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd");
+
+#define VIEW_CORRECT_REPLY_JT4 "250-ONION_CLIENT_AUTH_VIEW " \
+ "jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd\r\n" \
+ "250-CLIENT jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd " \
+ "x25519:eIIdIGoSZwI2Q/lSzpf92akGki5I+PZIDz37MA5BhlA=\r\n" \
+ "250 OK\r\n"
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, VIEW_CORRECT_REPLY_JT4);
+ tor_free(cp1);
+
+ /* Now try to REMOVE the auth credentials */
+ tor_free(conn.current_cmd);
+ conn.current_cmd = tor_strdup("ONION_CLIENT_AUTH_REMOVE");
+
+ /* First try with a wrong addr */
+ tor_free(args);
+ args = tor_strdup("thatsok");
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "512 Invalid v3 address \"thatsok\"\r\n");
+ tor_free(cp1);
+
+ client_jt4 = digest256map_get(client_auths, service_identity_pk_jt4.pubkey);
+ tt_assert(client_jt4);
+
+ /* Now actually remove them. */
+ tor_free(args);
+ args =tor_strdup("jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd");
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "250 OK\r\n");
+ tor_free(cp1);
+
+ client_jt4 = digest256map_get(client_auths, service_identity_pk_jt4.pubkey);
+ tt_assert(!client_jt4);
+
+ /* Now try another time (we should get 'already removed' msg) */
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "251 No credentials for "
+ "\"jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd\"\r\n");
+ tor_free(cp1);
+
+ client_jt4 = digest256map_get(client_auths, service_identity_pk_jt4.pubkey);
+ tt_assert(!client_jt4);
+
+ /* Now also remove the other one */
+ tor_free(args);
+ args =tor_strdup("2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd");
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "250 OK\r\n");
+ tor_free(cp1);
+
+ /* Finally, do another VIEW and see that we get nothing. */
+ tor_free(conn.current_cmd);
+ conn.current_cmd = tor_strdup("ONION_CLIENT_AUTH_VIEW");
+ tor_free(args);
+ args = tor_strdup("");
+
+#define VIEW_CORRECT_REPLY_NOTHING "250-ONION_CLIENT_AUTH_VIEW\r\n250 OK\r\n"
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, VIEW_CORRECT_REPLY_NOTHING);
+ tor_free(cp1);
+
+ /* And a final VIEW with a wrong HS addr */
+ tor_free(args);
+ args = tor_strdup("house");
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "512 Invalid v3 addr \"house\"\r\n");
+
+ done:
+ tor_free(args);
+ tor_free(cp1);
+ buf_free(TO_CONN(&conn)->outbuf);
+ tor_free(conn.current_cmd);
+ hs_client_free_all();
+}
+
+/** Test some error cases of ONION_CLIENT_AUTH_ADD */
+static void
+test_hs_control_bad_onion_client_auth_add(void *arg)
+{
+ (void) arg;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ int retval;
+ control_connection_t conn;
+ char *cp1 = NULL;
+ size_t sz;
+ char *args = NULL;
+
+ hs_init();
+
+ { /* Setup the control conn */
+ memset(&conn, 0, sizeof(control_connection_t));
+ TO_CONN(&conn)->outbuf = buf_new();
+ conn.current_cmd = tor_strdup("ONION_CLIENT_AUTH_ADD");
+ }
+
+ digest256map_t *client_auths = get_hs_client_auths_map();
+ tt_assert(!client_auths);
+
+ /* Register first service */
+ args = tor_strdup(
+ "badaddr x25519:iJ1tjKCrMAbiFT2bVrCjhbfMDnE1fpaRbIS5ZHKUvEQ=");
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Check contents */
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "512 Invalid v3 address \"badaddr\"\r\n");
+
+ tor_free(cp1);
+ tor_free(args);
+
+ /* Register second service (even with an unrecognized argument) */
+ args = tor_strdup("jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd "
+ "love:eIIdIGoSZwI2Q/lSzpf92akGki5I+PZIDz37MA5BhlA=");
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Check contents */
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "552 Unrecognized key type \"love\"\r\n");
+
+ tor_free(cp1);
+ tor_free(args);
+
+ /* Register second service (even with an unrecognized argument) */
+ args = tor_strdup("jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd "
+ "x25519:QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEK");
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Check contents */
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "512 Failed to decode x25519 private key\r\n");
+
+ tor_free(cp1);
+ tor_free(args);
+
+ /* Register with an all zero client key */
+ args = tor_strdup("jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd "
+ "x25519:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=");
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Check contents */
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "553 Invalid private key \"AAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAA=\"\r\n");
+
+ client_auths = get_hs_client_auths_map();
+ tt_assert(!client_auths);
+
+ done:
+ tor_free(args);
+ tor_free(cp1);
+ buf_free(TO_CONN(&conn)->outbuf);
+ tor_free(conn.current_cmd);
+ hs_client_free_all();
+}
+
+/** Test that we can correctly add permanent client auth credentials using the
+ * control port. */
+static void
+test_hs_control_store_permanent_creds(void *arg)
+{
+ (void) arg;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ int retval;
+ ed25519_public_key_t service_identity_pk_2fv;
+ control_connection_t conn;
+ char *args = NULL;
+ char *cp1 = NULL;
+ char *creds_file_str = NULL;
+ char *creds_fname = NULL;
+
+ size_t sz;
+
+ hs_init();
+
+ { /* Setup the control conn */
+ memset(&conn, 0, sizeof(control_connection_t));
+ TO_CONN(&conn)->outbuf = buf_new();
+ conn.current_cmd = tor_strdup("ONION_CLIENT_AUTH_ADD");
+ }
+
+ { /* Setup the services */
+ retval = hs_parse_address(
+ "2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd",
+ &service_identity_pk_2fv,
+ NULL, NULL);
+ tt_int_op(retval, OP_EQ, 0);
+ }
+
+ digest256map_t *client_auths = get_hs_client_auths_map();
+ tt_assert(!client_auths);
+
+ /* Try registering first service with no ClientOnionAuthDir set */
+ args = tor_strdup("2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd "
+ "x25519:iJ1tjKCrMAbiFT2bVrCjhbfMDnE1fpaRbIS5ZHKUvEQ= "
+ "Flags=Permanent");
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Check control port response. This one should fail. */
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "553 Unable to store creds for "
+ "\"2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd\"\r\n");
+
+ { /* Setup ClientOnionAuthDir */
+ int ret;
+ char *perm_creds_dir = tor_strdup(get_fname("permanent_credentials"));
+ get_options_mutable()->ClientOnionAuthDir = perm_creds_dir;
+
+ #ifdef _WIN32
+ ret = mkdir(perm_creds_dir);
+ #else
+ ret = mkdir(perm_creds_dir, 0700);
+ #endif
+ tt_int_op(ret, OP_EQ, 0);
+ }
+
+ tor_free(args);
+ tor_free(cp1);
+
+ /* Try the control port command again. This time it should work! */
+ args = tor_strdup("2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd "
+ "x25519:iJ1tjKCrMAbiFT2bVrCjhbfMDnE1fpaRbIS5ZHKUvEQ= "
+ "Flags=Permanent");
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Check control port response */
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "250 OK\r\n");
+
+ /* Check file contents! */
+ creds_fname = tor_strdup(get_fname("permanent_credentials/"
+ "2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd.auth_private"));
+ creds_file_str = read_file_to_str(creds_fname, RFTS_BIN, NULL);
+
+ tt_assert(creds_file_str);
+ tt_str_op(creds_file_str, OP_EQ,
+ "2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd:descriptor:"
+ /* This is the base32 represenation of the base64 iJ1t... key above */
+ "x25519:rcow3dfavmyanyqvhwnvnmfdqw34ydtrgv7jnelmqs4wi4uuxrca");
+
+ tor_free(args);
+ tor_free(cp1);
+
+ /* Overwrite the credentials and check that they got overwrited. */
+ args = tor_strdup("2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd "
+ "x25519:UDRvZLvcJo0QRLvDfkpgbtsqbkhIUQZyeo2FNBrgS18= "
+ "Flags=Permanent");
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Check control port response: we replaced! */
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "251 Client for onion existed and replaced\r\n");
+
+ tor_free(creds_file_str);
+
+ /* Check creds file contents again. See that the key got updated */
+ creds_file_str = read_file_to_str(creds_fname, RFTS_BIN, NULL);
+ tt_assert(creds_file_str);
+ tt_str_op(creds_file_str, OP_EQ,
+ "2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd:descriptor:"
+ /* This is the base32 represenation of the base64 UDRv... key above */
+ "x25519:ka2g6zf33qti2ecexpbx4stan3nsu3sijbiqm4t2rwctigxajnpq");
+
+ /* Now for our next act!!! Actually get the HS client subsystem to parse the
+ * whole directory and make sure that it extracted the right credential! */
+ hs_config_client_authorization(get_options(), 0);
+
+ client_auths = get_hs_client_auths_map();
+ tt_assert(client_auths);
+ tt_uint_op(digest256map_size(client_auths), OP_EQ, 1);
+
+ hs_client_service_authorization_t *client_2fv =
+ digest256map_get(client_auths, service_identity_pk_2fv.pubkey);
+ tt_assert(client_2fv);
+ tt_int_op(client_2fv->flags, OP_EQ, CLIENT_AUTH_FLAG_IS_PERMANENT);
+ tt_str_op(hex_str((char*)client_2fv->enc_seckey.secret_key, 32), OP_EQ,
+ "50346F64BBDC268D1044BBC37E4A606EDB2A6E48485106727A8D85341AE04B5F");
+
+ /* And now for the final act! Use the REMOVE control port command to remove
+ the credential, and ensure that the file has also been removed! */
+ tor_free(conn.current_cmd);
+ tor_free(cp1);
+ tor_free(args);
+
+ /* Ensure that the creds file exists */
+ tt_int_op(file_status(creds_fname), OP_EQ, FN_FILE);
+
+ /* Do the REMOVE */
+ conn.current_cmd = tor_strdup("ONION_CLIENT_AUTH_REMOVE");
+ args =tor_strdup("2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd");
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "250 OK\r\n");
+
+ /* Ensure that the file has been removed and the map is empty */
+ tt_int_op(file_status(creds_fname), OP_EQ, FN_NOENT);
+ tt_uint_op(digest256map_size(client_auths), OP_EQ, 0);
+
+ done:
+ tor_free(get_options_mutable()->ClientOnionAuthDir);
+ tor_free(args);
+ tor_free(cp1);
+ buf_free(TO_CONN(&conn)->outbuf);
+ tor_free(conn.current_cmd);
+ tor_free(creds_fname);
+ tor_free(creds_file_str);
+ hs_client_free_all();
+}
+
+/** Test that ADD_ONION properly handles an attacker passing it a bad private
+ * key. */
+static void
+test_hs_control_add_onion_with_bad_pubkey(void *arg)
+{
+ (void) arg;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ int retval;
+ control_connection_t conn;
+ char *args = NULL;
+ char *cp1 = NULL;
+ size_t sz;
+
+ hs_init();
+
+ { /* Setup the control conn */
+ memset(&conn, 0, sizeof(control_connection_t));
+ TO_CONN(&conn)->outbuf = buf_new();
+ conn.current_cmd = tor_strdup("ADD_ONION");
+ }
+
+ args = tor_strdup("ED25519-V3:AAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "
+ "Port=9735,127.0.0.1 Flags=DiscardPK");
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Check control port response */
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "551 Failed to generate onion address\r\n");
+
+ done:
+ tor_free(args);
+ tor_free(cp1);
+ buf_free(TO_CONN(&conn)->outbuf);
+ tor_free(conn.current_cmd);
+}
+
struct testcase_t hs_control_tests[] = {
{ "hs_desc_event", test_hs_desc_event, TT_FORK,
NULL, NULL },
+ { "hs_control_good_onion_client_auth_add",
+ test_hs_control_good_onion_client_auth_add, TT_FORK,
+ NULL, NULL },
+ { "hs_control_bad_onion_client_auth_add",
+ test_hs_control_bad_onion_client_auth_add, TT_FORK,
+ NULL, NULL },
+ { "hs_control_store_permanent_creds",
+ test_hs_control_store_permanent_creds, TT_FORK, NULL, NULL },
+ { "hs_control_add_onion_with_bad_pubkey",
+ test_hs_control_add_onion_with_bad_pubkey, TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_hs_descriptor.c b/src/test/test_hs_descriptor.c
index 6fe5573c0f..c5077f7143 100644
--- a/src/test/test_hs_descriptor.c
+++ b/src/test/test_hs_descriptor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,6 +14,7 @@
#include "lib/crypt_ops/crypto_rand.h"
#include "trunnel/ed25519_cert.h"
#include "core/or/or.h"
+#include "app/config/config.h"
#include "feature/hs/hs_descriptor.h"
#include "test/test.h"
#include "feature/nodelist/torcert.h"
@@ -24,12 +25,12 @@
#include "test/rng_test_helpers.h"
#ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
-DISABLE_GCC_WARNING(overlength-strings)
+DISABLE_GCC_WARNING("-Woverlength-strings")
/* We allow huge string constants in the unit tests, but not in the code
* at large. */
#endif
#include "test_hs_descriptor.inc"
-ENABLE_GCC_WARNING(overlength-strings)
+ENABLE_GCC_WARNING("-Woverlength-strings")
/* Test certificate encoding put in a descriptor. */
static void
@@ -37,7 +38,6 @@ test_cert_encoding(void *arg)
{
int ret;
char *encoded = NULL;
- time_t now = time(NULL);
ed25519_keypair_t kp;
ed25519_public_key_t signed_key;
ed25519_secret_key_t secret_key;
@@ -45,6 +45,10 @@ test_cert_encoding(void *arg)
(void) arg;
+ /* Change time to 03-01-2002 23:36 UTC */
+ update_approx_time(1010101010);
+ time_t now = approx_time();
+
ret = ed25519_keypair_generate(&kp, 0);
tt_int_op(ret, == , 0);
ret = ed25519_secret_key_generate(&secret_key, 0);
@@ -88,13 +92,31 @@ test_cert_encoding(void *arg)
/* The cert did have the signing key? */
ret= ed25519_pubkey_eq(&parsed_cert->signing_key, &kp.pubkey);
tt_int_op(ret, OP_EQ, 1);
- tor_cert_free(parsed_cert);
/* Get to the end part of the certificate. */
pos += b64_cert_len;
tt_int_op(strcmpstart(pos, "-----END ED25519 CERT-----"), OP_EQ, 0);
pos += strlen("-----END ED25519 CERT-----");
tt_str_op(pos, OP_EQ, "");
+
+ /* Check that certificate expiry works properly and emits the right log
+ message */
+ const char *msg = "fire";
+ /* Move us forward 4 hours so that the the certificate is definitely
+ expired */
+ update_approx_time(approx_time() + 3600*4);
+ setup_full_capture_of_logs(LOG_PROTOCOL_WARN);
+ ret = cert_is_valid(parsed_cert, CERT_TYPE_SIGNING_AUTH, msg);
+ tt_int_op(ret, OP_EQ, 0);
+ /* Since the current time at the creation of the cert was "03-01-2002
+ * 23:36", and the expiration date of the cert was two hours, the Tor code
+ * will ceiling that and make it 02:00. Make sure that the right log
+ * message is emitted */
+ expect_log_msg_containing("Invalid signature for fire: expired"
+ " (2002-01-04 02:00:00)");
+ teardown_capture_of_logs();
+
+ tor_cert_free(parsed_cert);
}
done:
@@ -235,14 +257,14 @@ test_decode_descriptor(void *arg)
/* Give some bad stuff to the decoding function. */
ret = hs_desc_decode_descriptor("hladfjlkjadf", subcredential,
NULL, &decoded);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
ret = hs_desc_encode_descriptor(desc, &signing_kp, NULL, &encoded);
- tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
tt_assert(encoded);
ret = hs_desc_decode_descriptor(encoded, subcredential, NULL, &decoded);
- tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
tt_assert(decoded);
hs_helper_desc_equal(desc, decoded);
@@ -263,7 +285,7 @@ test_decode_descriptor(void *arg)
tt_assert(encoded);
hs_descriptor_free(decoded);
ret = hs_desc_decode_descriptor(encoded, subcredential, NULL, &decoded);
- tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
tt_assert(decoded);
}
@@ -317,21 +339,21 @@ test_decode_descriptor(void *arg)
hs_descriptor_free(decoded);
ret = hs_desc_decode_descriptor(encoded, subcredential,
NULL, &decoded);
- tt_int_op(ret, OP_LT, 0);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_NEED_CLIENT_AUTH);
tt_assert(!decoded);
/* If we have an invalid client secret key, the decoding must fail. */
hs_descriptor_free(decoded);
ret = hs_desc_decode_descriptor(encoded, subcredential,
&invalid_client_kp.seckey, &decoded);
- tt_int_op(ret, OP_LT, 0);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_BAD_CLIENT_AUTH);
tt_assert(!decoded);
/* If we have the client secret key, the decoding must succeed and the
* decoded descriptor must be correct. */
ret = hs_desc_decode_descriptor(encoded, subcredential,
&client_kp.seckey, &decoded);
- tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
tt_assert(decoded);
hs_helper_desc_equal(desc, decoded);
@@ -567,7 +589,7 @@ test_decode_bad_signature(void *arg)
setup_full_capture_of_logs(LOG_WARN);
ret = hs_desc_decode_plaintext(HS_DESC_BAD_SIG, &desc_plaintext);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
expect_log_msg_containing("Malformed signature line. Rejecting.");
teardown_capture_of_logs();
@@ -607,14 +629,14 @@ test_decode_plaintext(void *arg)
tor_asprintf(&plaintext, template, bad_value, "180", "42", "MESSAGE");
ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
tor_free(plaintext);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
}
/* Missing fields. */
{
const char *plaintext = "hs-descriptor 3\n";
ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
}
/* Max length. */
@@ -627,7 +649,7 @@ test_decode_plaintext(void *arg)
plaintext[big - 1] = '\0';
ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
tor_free(plaintext);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
}
/* Bad lifetime value. */
@@ -636,7 +658,7 @@ test_decode_plaintext(void *arg)
tor_asprintf(&plaintext, template, "3", bad_value, "42", "MESSAGE");
ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
tor_free(plaintext);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
}
/* Huge lifetime value. */
@@ -645,7 +667,7 @@ test_decode_plaintext(void *arg)
tor_asprintf(&plaintext, template, "3", "7181615", "42", "MESSAGE");
ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
tor_free(plaintext);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
}
/* Invalid encrypted section. */
@@ -654,7 +676,7 @@ test_decode_plaintext(void *arg)
tor_asprintf(&plaintext, template, "3", "180", "42", bad_value);
ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
tor_free(plaintext);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
}
/* Invalid revision counter. */
@@ -663,7 +685,7 @@ test_decode_plaintext(void *arg)
tor_asprintf(&plaintext, template, "3", "180", bad_value, "MESSAGE");
ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
tor_free(plaintext);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
}
done:
diff --git a/src/test/test_hs_dos.c b/src/test/test_hs_dos.c
index f68639e24a..642513efce 100644
--- a/src/test/test_hs_dos.c
+++ b/src/test/test_hs_dos.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_hs_intropoint.c b/src/test/test_hs_intropoint.c
index feb934d93c..5337188427 100644
--- a/src/test/test_hs_intropoint.c
+++ b/src/test/test_hs_intropoint.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_hs_ntor.c b/src/test/test_hs_ntor.c
index 1c694e6040..4f98bc85dc 100644
--- a/src/test/test_hs_ntor.c
+++ b/src/test/test_hs_ntor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_hs_ntor.sh b/src/test/test_hs_ntor.sh
index 8a0003d44a..ee7141cc9a 100755
--- a/src/test/test_hs_ntor.sh
+++ b/src/test/test_hs_ntor.sh
@@ -3,7 +3,7 @@
exitcode=0
-# Run the python integration test sand return the exitcode of the python
+# Run the python integration tests and return the exitcode of the python
# script. The python script might ask the testsuite to skip it if not all
# python dependencies are covered.
"${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/hs_ntor_ref.py" || exitcode=$?
diff --git a/src/test/test_hs_ntor_cl.c b/src/test/test_hs_ntor_cl.c
index 6341b96d84..a7cebc6af4 100644
--- a/src/test/test_hs_ntor_cl.c
+++ b/src/test/test_hs_ntor_cl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/** This is a wrapper over the little-t-tor HS ntor functions. The wrapper is
diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c
index 66194cee3d..e33d593d94 100644
--- a/src/test/test_hs_service.c
+++ b/src/test/test_hs_service.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -19,7 +19,7 @@
#define MAINLOOP_PRIVATE
#define NETWORKSTATUS_PRIVATE
#define STATEFILE_PRIVATE
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define HS_CLIENT_PRIVATE
#define CRYPT_PATH_PRIVATE
@@ -183,9 +183,8 @@ test_e2e_rend_circuit_setup(void *arg)
/* Setup the circuit: do the ntor key exchange */
{
uint8_t ntor_key_seed[DIGEST256_LEN] = {2};
- retval = hs_circuit_setup_e2e_rend_circ(or_circ,
- ntor_key_seed, sizeof(ntor_key_seed),
- 1);
+ retval = hs_circuit_setup_e2e_rend_circ(or_circ, ntor_key_seed,
+ sizeof(ntor_key_seed), 1);
tt_int_op(retval, OP_EQ, 0);
}
@@ -194,11 +193,9 @@ test_e2e_rend_circuit_setup(void *arg)
tt_int_op(retval, OP_EQ, 1);
/* Check the digest algo */
- tt_int_op(
- crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.f_digest),
+ tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.f_digest),
OP_EQ, DIGEST_SHA3_256);
- tt_int_op(
- crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.b_digest),
+ tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.b_digest),
OP_EQ, DIGEST_SHA3_256);
tt_assert(or_circ->cpath->pvt_crypto.f_crypto);
tt_assert(or_circ->cpath->pvt_crypto.b_crypto);
@@ -1013,7 +1010,6 @@ test_intro_established(void *arg)
/* Send an empty payload. INTRO_ESTABLISHED cells are basically zeroes. */
ret = hs_service_receive_intro_established(circ, payload, sizeof(payload));
tt_int_op(ret, OP_EQ, 0);
- tt_u64_op(ip->circuit_established, OP_EQ, 1);
tt_int_op(TO_CIRCUIT(circ)->purpose, OP_EQ, CIRCUIT_PURPOSE_S_INTRO);
done:
@@ -1296,18 +1292,11 @@ test_service_event(void *arg)
* descriptor map so we can retry it. */
ip = helper_create_service_ip();
service_intro_point_add(service->desc_current->intro_points.map, ip);
- ip->circuit_established = 1; /* We'll test that, it MUST be 0 after. */
- run_housekeeping_event(now);
- tt_int_op(digest256map_size(service->desc_current->intro_points.map),
- OP_EQ, 1);
- /* No removal if we have an established circuit after retries. */
- ip->circuit_retries = MAX_INTRO_POINT_CIRCUIT_RETRIES + 1;
run_housekeeping_event(now);
tt_int_op(digest256map_size(service->desc_current->intro_points.map),
OP_EQ, 1);
/* Remove the IP object at once for the next test. */
ip->circuit_retries = MAX_INTRO_POINT_CIRCUIT_RETRIES + 1;
- ip->circuit_established = 0;
run_housekeeping_event(now);
tt_int_op(digest256map_size(service->desc_current->intro_points.map),
OP_EQ, 0);
diff --git a/src/test/test_introduce.c b/src/test/test_introduce.c
index 104e973b1f..0ae78496b2 100644
--- a/src/test/test_introduce.c
+++ b/src/test/test_introduce.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_key_expiration.sh b/src/test/test_key_expiration.sh
index 54abb4a2fa..2238f7aa78 100755
--- a/src/test/test_key_expiration.sh
+++ b/src/test/test_key_expiration.sh
@@ -6,6 +6,20 @@
umask 077
set -e
+# emulate realpath(), in case coreutils or equivalent is not installed.
+abspath() {
+ f="$*"
+ if [ -d "$f" ]; then
+ dir="$f"
+ base=""
+ else
+ dir="$(dirname "$f")"
+ base="/$(basename "$f")"
+ fi
+ dir="$(cd "$dir" && pwd)"
+ echo "$dir$base"
+}
+
if [ $# -eq 0 ] || [ ! -f "${1}" ] || [ ! -x "${1}" ]; then
if [ "$TESTING_TOR_BINARY" = "" ] ; then
echo "Usage: ${0} PATH_TO_TOR [case-number]"
@@ -21,11 +35,21 @@ if test "$UNAME_OS" = 'CYGWIN' || \
exit 77
fi
+# find the tor binary
if [ $# -ge 1 ]; then
TOR_BINARY="${1}"
shift
else
- TOR_BINARY="${TESTING_TOR_BINARY}"
+ TOR_BINARY="${TESTING_TOR_BINARY:-./src/app/tor}"
+fi
+
+TOR_BINARY="$(abspath "$TOR_BINARY")"
+
+echo "TOR BINARY IS ${TOR_BINARY}"
+
+if "$TOR_BINARY" --list-modules | grep -q "relay: no"; then
+ echo "This test requires the relay module. Skipping." >&2
+ exit 77
fi
if [ $# -ge 1 ]; then
diff --git a/src/test/test_keygen.sh b/src/test/test_keygen.sh
index cbdfd1909c..6812f8883d 100755
--- a/src/test/test_keygen.sh
+++ b/src/test/test_keygen.sh
@@ -6,6 +6,20 @@
umask 077
set -e
+# emulate realpath(), in case coreutils or equivalent is not installed.
+abspath() {
+ f="$*"
+ if [ -d "$f" ]; then
+ dir="$f"
+ base=""
+ else
+ dir="$(dirname "$f")"
+ base="/$(basename "$f")"
+ fi
+ dir="$(cd "$dir" && pwd)"
+ echo "$dir$base"
+}
+
if [ $# -eq 0 ] || [ ! -f "${1}" ] || [ ! -x "${1}" ]; then
if [ "$TESTING_TOR_BINARY" = "" ] ; then
echo "Usage: ${0} PATH_TO_TOR [case-number]"
@@ -21,14 +35,22 @@ if test "$UNAME_OS" = 'CYGWIN' || \
exit 77
fi
+# find the tor binary
if [ $# -ge 1 ]; then
TOR_BINARY="${1}"
shift
else
- TOR_BINARY="${TESTING_TOR_BINARY}"
+ TOR_BINARY="${TESTING_TOR_BINARY:-./src/app/tor}"
fi
+TOR_BINARY="$(abspath "$TOR_BINARY")"
+
+echo "TOR BINARY IS ${TOR_BINARY}"
+if "$TOR_BINARY" --list-modules | grep -q "relay: no"; then
+ echo "This test requires the relay module. Skipping." >&2
+ exit 77
+fi
if [ $# -ge 1 ]; then
dflt=0
diff --git a/src/test/test_keypin.c b/src/test/test_keypin.c
index e7beef8609..ff6397f8c7 100644
--- a/src/test/test_keypin.c
+++ b/src/test/test_keypin.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_link_handshake.c b/src/test/test_link_handshake.c
index 5e78e1ce4d..96542ce7ac 100644
--- a/src/test/test_link_handshake.c
+++ b/src/test/test_link_handshake.c
@@ -1,11 +1,11 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#define CHANNELTLS_PRIVATE
#define CONNECTION_PRIVATE
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define TORTLS_PRIVATE
#include "core/or/or.h"
@@ -325,7 +325,7 @@ test_link_handshake_certs_ok(void *arg)
crypto_pk_free(key2);
}
-typedef struct certs_data_s {
+typedef struct certs_data_t {
int is_ed;
int is_link_cert;
or_connection_t *c;
@@ -972,7 +972,7 @@ test_link_handshake_send_authchallenge(void *arg)
crypto_pk_free(rsa1);
}
-typedef struct authchallenge_data_s {
+typedef struct authchallenge_data_t {
or_connection_t *c;
channel_tls_t *chan;
var_cell_t *cell;
@@ -1171,7 +1171,7 @@ mock_set_circid_type(channel_t *chan,
(void) consider_identity;
}
-typedef struct authenticate_data_s {
+typedef struct authenticate_data_t {
int is_ed;
or_connection_t *c1, *c2;
channel_tls_t *chan2;
@@ -1492,6 +1492,7 @@ AUTHENTICATE_FAIL(missing_ed_auth,
"authentication certificate";
})
+#ifndef COCCI
#define TEST_RSA(name, flags) \
{ #name , test_link_handshake_ ## name, (flags), \
&passthrough_setup, (void*)"RSA" }
@@ -1527,6 +1528,7 @@ AUTHENTICATE_FAIL(missing_ed_auth,
#define TEST_AUTHENTICATE_ED(name) \
{ "authenticate/" #name "_ed25519" , test_link_handshake_auth_ ## name, \
TT_FORK, &setup_authenticate, (void*)3 }
+#endif /* !defined(COCCI) */
struct testcase_t link_handshake_tests[] = {
TEST_RSA(certs_ok, TT_FORK),
diff --git a/src/test/test_logging.c b/src/test/test_logging.c
index 203ce64e32..e09f7a21cd 100644
--- a/src/test/test_logging.c
+++ b/src/test/test_logging.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONFIG_PRIVATE
diff --git a/src/test/test_mainloop.c b/src/test/test_mainloop.c
index ed6b8a9b66..c4e60d9da5 100644
--- a/src/test/test_mainloop.c
+++ b/src/test/test_mainloop.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,9 +13,13 @@
#include "test/test.h"
#include "test/log_test_helpers.h"
+#include "lib/confmgt/confmgt.h"
+
#include "core/or/or.h"
#include "core/mainloop/connection.h"
#include "core/mainloop/mainloop.h"
+#include "core/mainloop/mainloop_state_st.h"
+#include "core/mainloop/mainloop_sys.h"
#include "core/mainloop/netstatus.h"
#include "feature/hs/hs_service.h"
@@ -24,6 +28,8 @@
#include "app/config/statefile.h"
#include "app/config/or_state_st.h"
+#include "app/main/subsysmgr.h"
+
static const uint64_t BILLION = 1000000000;
static void
@@ -287,7 +293,13 @@ static void
test_mainloop_dormant_load_state(void *arg)
{
(void)arg;
- or_state_t *state = or_state_new();
+ or_state_t *or_state = or_state_new();
+ mainloop_state_t *state;
+ {
+ int idx = subsystems_get_state_idx(&sys_mainloop);
+ tor_assert(idx >= 0);
+ state = config_mgr_get_obj_mutable(get_state_mgr(), or_state, idx);
+ }
const time_t start = 1543956575;
reset_user_activity(0);
@@ -326,14 +338,14 @@ test_mainloop_dormant_load_state(void *arg)
tt_i64_op(get_last_user_activity_time(), OP_EQ, start);
done:
- or_state_free(state);
+ or_state_free(or_state);
}
static void
test_mainloop_dormant_save_state(void *arg)
{
(void)arg;
- or_state_t *state = or_state_new();
+ mainloop_state_t *state = tor_malloc_zero(sizeof(mainloop_state_t));
const time_t start = 1543956575;
// Can we save a non-dormant state correctly?
@@ -352,7 +364,7 @@ test_mainloop_dormant_save_state(void *arg)
tt_int_op(state->MinutesSinceUserActivity, OP_EQ, 0);
done:
- or_state_free(state);
+ tor_free(state);
}
#define MAINLOOP_TEST(name) \
diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c
index 804e6c546a..f89025aa6c 100644
--- a/src/test/test_microdesc.c
+++ b/src/test/test_microdesc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -491,7 +491,7 @@ test_md_generate(void *arg)
}
#ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
-DISABLE_GCC_WARNING(overlength-strings)
+DISABLE_GCC_WARNING("-Woverlength-strings")
/* We allow huge string constants in the unit tests, but not in the code
* at large. */
#endif
@@ -686,7 +686,7 @@ static const char MD_PARSE_TEST_DATA[] =
"id rsa1024 2A8wYpHxnkKJ92orocvIQBzeHlE\n"
;
#ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
-ENABLE_GCC_WARNING(overlength-strings)
+ENABLE_GCC_WARNING("-Woverlength-strings")
#endif
/** More tests for parsing different kinds of microdescriptors, and getting
diff --git a/src/test/test_namemap.c b/src/test/test_namemap.c
index df77d4e2de..e93d3fbc3c 100644
--- a/src/test/test_namemap.c
+++ b/src/test/test_namemap.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "test/test.h"
diff --git a/src/test/test_netinfo.c b/src/test/test_netinfo.c
index 27d276d42f..93892978dc 100644
--- a/src/test/test_netinfo.c
+++ b/src/test/test_netinfo.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_nodelist.c b/src/test/test_nodelist.c
index b8ca56bb81..fbbbf0a99f 100644
--- a/src/test/test_nodelist.c
+++ b/src/test/test_nodelist.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -7,6 +7,7 @@
**/
#define NODELIST_PRIVATE
+#define NETWORKSTATUS_PRIVATE
#include "core/or/or.h"
#include "lib/crypt_ops/crypto_rand.h"
@@ -17,6 +18,8 @@
#include "feature/nodelist/torcert.h"
#include "core/or/extend_info_st.h"
+#include "feature/dirauth/dirvote.h"
+#include "feature/nodelist/fmt_routerstatus.h"
#include "feature/nodelist/microdesc_st.h"
#include "feature/nodelist/networkstatus_st.h"
#include "feature/nodelist/node_st.h"
@@ -1246,6 +1249,167 @@ test_nodelist_router_get_verbose_nickname(void *arg)
return;
}
+static void
+test_nodelist_routerstatus_has_visibly_changed(void *arg)
+{
+ (void)arg;
+ routerstatus_t rs_orig, rs;
+ char *fmt_orig = NULL, *fmt = NULL;
+ memset(&rs_orig, 0, sizeof(rs_orig));
+ strlcpy(rs_orig.nickname, "friendly", sizeof(rs_orig.nickname));
+ memcpy(rs_orig.identity_digest, "abcdefghijklmnopqrst", 20);
+ memcpy(rs_orig.descriptor_digest, "abcdefghijklmnopqrst", 20);
+ rs_orig.addr = 0x7f000001;
+ rs_orig.or_port = 3;
+ rs_orig.published_on = time(NULL);
+ rs_orig.has_bandwidth = 1;
+ rs_orig.bandwidth_kb = 20;
+
+#define COPY() memcpy(&rs, &rs_orig, sizeof(rs))
+#define FORMAT() \
+ STMT_BEGIN \
+ tor_free(fmt_orig); \
+ tor_free(fmt); \
+ fmt_orig = routerstatus_format_entry(&rs_orig, NULL, NULL, \
+ NS_CONTROL_PORT, \
+ NULL); \
+ fmt = routerstatus_format_entry(&rs, NULL, NULL, NS_CONTROL_PORT, \
+ NULL); \
+ tt_assert(fmt_orig); \
+ tt_assert(fmt); \
+ STMT_END
+#define ASSERT_SAME() \
+ STMT_BEGIN \
+ tt_assert(! routerstatus_has_visibly_changed(&rs_orig, &rs)); \
+ FORMAT(); \
+ tt_str_op(fmt_orig, OP_EQ, fmt); \
+ COPY(); \
+ STMT_END
+#define ASSERT_CHANGED() \
+ STMT_BEGIN \
+ tt_assert(routerstatus_has_visibly_changed(&rs_orig, &rs)); \
+ FORMAT(); \
+ tt_str_op(fmt_orig, OP_NE, fmt); \
+ COPY(); \
+ STMT_END
+#define ASSERT_CHANGED_NO_FORMAT() \
+ STMT_BEGIN \
+ tt_assert(routerstatus_has_visibly_changed(&rs_orig, &rs)); \
+ COPY(); \
+ STMT_END
+
+ COPY();
+ ASSERT_SAME();
+
+ rs.addr = 0x7f000002;
+ ASSERT_CHANGED();
+
+ strlcpy(rs.descriptor_digest, "hello world", sizeof(rs.descriptor_digest));
+ ASSERT_CHANGED();
+
+ strlcpy(rs.nickname, "fr1end1y", sizeof(rs.nickname));
+ ASSERT_CHANGED();
+
+ rs.published_on += 3600;
+ ASSERT_CHANGED();
+
+ rs.or_port = 55;
+ ASSERT_CHANGED();
+
+ rs.dir_port = 9999;
+ ASSERT_CHANGED();
+
+ tor_addr_parse(&rs.ipv6_addr, "1234::56");
+ ASSERT_CHANGED();
+
+ tor_addr_parse(&rs_orig.ipv6_addr, "1234::56");
+ rs_orig.ipv6_orport = 99;
+ COPY();
+ rs.ipv6_orport = 22;
+ ASSERT_CHANGED();
+
+ rs.is_authority = 1;
+ ASSERT_CHANGED();
+
+ rs.is_exit = 1;
+ ASSERT_CHANGED();
+
+ rs.is_stable = 1;
+ ASSERT_CHANGED();
+
+ rs.is_fast = 1;
+ ASSERT_CHANGED();
+
+ rs.is_flagged_running = 1;
+ ASSERT_CHANGED();
+
+ // This option is obsolete and not actually formatted.
+ rs.is_named = 1;
+ ASSERT_CHANGED_NO_FORMAT();
+
+ // This option is obsolete and not actually formatted.
+ rs.is_unnamed = 1;
+ ASSERT_CHANGED_NO_FORMAT();
+
+ rs.is_valid = 1;
+ ASSERT_CHANGED();
+
+ rs.is_possible_guard = 1;
+ ASSERT_CHANGED();
+
+ rs.is_bad_exit = 1;
+ ASSERT_CHANGED();
+
+ rs.is_hs_dir = 1;
+ ASSERT_CHANGED();
+
+ rs.is_v2_dir = 1;
+ ASSERT_CHANGED();
+
+ rs.is_staledesc = 1;
+ ASSERT_CHANGED();
+
+ // Setting this to zero crashes us with an assertion failure in
+ // routerstatus_format_entry() if we don't have a descriptor.
+ rs.has_bandwidth = 0;
+ ASSERT_CHANGED_NO_FORMAT();
+
+ // Does not actually matter; not visible to controller.
+ rs.has_exitsummary = 1;
+ ASSERT_SAME();
+
+ // Does not actually matter; not visible to the controller.
+ rs.bw_is_unmeasured = 1;
+ ASSERT_SAME();
+
+ rs.bandwidth_kb = 2000;
+ ASSERT_CHANGED();
+
+ // not visible to the controller.
+ rs.has_guardfraction = 1;
+ rs.guardfraction_percentage = 22;
+ ASSERT_SAME();
+
+ // not visible to the controller.
+ rs_orig.has_guardfraction = 1;
+ rs_orig.guardfraction_percentage = 20;
+ COPY();
+ rs.guardfraction_percentage = 25;
+ ASSERT_SAME();
+
+ // not visible to the controller.
+ rs.exitsummary = (char*)"accept 1-2";
+ ASSERT_SAME();
+
+ done:
+#undef COPY
+#undef ASSERT_SAME
+#undef ASSERT_CHANGED
+ tor_free(fmt_orig);
+ tor_free(fmt);
+ return;
+}
+
#define NODE(name, flags) \
{ #name, test_nodelist_##name, (flags), NULL, NULL }
@@ -1266,5 +1430,6 @@ struct testcase_t nodelist_tests[] = {
NODE(routerstatus_describe, 0),
NODE(extend_info_describe, 0),
NODE(router_get_verbose_nickname, 0),
+ NODE(routerstatus_has_visibly_changed, 0),
END_OF_TESTCASES
};
diff --git a/src/test/test_ntor_cl.c b/src/test/test_ntor_cl.c
index 68b6927f56..a1508d0afc 100644
--- a/src/test/test_ntor_cl.c
+++ b/src/test/test_ntor_cl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_oom.c b/src/test/test_oom.c
index da6b2ee14d..51c237ec2e 100644
--- a/src/test/test_oom.c
+++ b/src/test/test_oom.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/* Unit tests for OOM handling logic */
diff --git a/src/test/test_oos.c b/src/test/test_oos.c
index 815feda7ce..f8c712a6b6 100644
--- a/src/test/test_oos.c
+++ b/src/test/test_oos.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/* Unit tests for OOS handler */
diff --git a/src/test/test_options.c b/src/test/test_options.c
index a2641425fe..9cd1d11d29 100644
--- a/src/test/test_options.c
+++ b/src/test/test_options.c
@@ -1,20 +1,29 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONFIG_PRIVATE
+#define RELAY_CONFIG_PRIVATE
+#define LOG_PRIVATE
+#define ROUTERSET_PRIVATE
#include "core/or/or.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "app/config/config.h"
+#include "feature/dirauth/dirauth_config.h"
+#include "feature/dirauth/dirauth_options_st.h"
+#include "feature/dirauth/dirauth_sys.h"
+#include "feature/relay/relay_config.h"
#include "test/test.h"
#include "lib/geoip/geoip.h"
-#define ROUTERSET_PRIVATE
#include "feature/nodelist/routerset.h"
#include "core/mainloop/mainloop.h"
+#include "app/main/subsysmgr.h"
#include "test/log_test_helpers.h"
#include "test/resolve_test_helpers.h"
+#include "lib/crypt_ops/crypto_options_st.h"
+#include "lib/crypt_ops/crypto_sys.h"
#include "lib/sandbox/sandbox.h"
#include "lib/memarea/memarea.h"
@@ -22,14 +31,13 @@
#include "lib/encoding/confline.h"
#include "core/or/policies.h"
#include "test/test_helpers.h"
+#include "test/opts_test_helpers.h"
#include "lib/net/resolve.h"
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
-#define NS_MODULE test_options
-
typedef struct {
int severity;
log_domain_mask_t domain;
@@ -91,16 +99,57 @@ clear_log_messages(void)
messages = NULL;
}
-#define setup_options(opt,dflt) \
+#define setup_options(opt) \
do { \
opt = options_new(); \
opt->command = CMD_RUN_TOR; \
options_init(opt); \
- \
- dflt = config_dup(get_options_mgr(), opt); \
- clear_log_messages(); \
} while (0)
+#ifdef COCCI
+
+#define ENABLE_AUTHORITY_MIN ""
+#define ENABLE_AUTHORITY_V3_MIN ""
+#define ENABLE_AUTHORITY_BRIDGE_MIN ""
+#define AUTHORITY_OPT_REQ_ ""
+#define ENABLE_AUTHORITY ""
+#define ENABLE_AUTHORITY_V3 ""
+#define ENABLE_AUTHORITY_BRIDGE ""
+
+#else /* !defined(COCCI) */
+
+#define ENABLE_AUTHORITY_MIN \
+ "AuthoritativeDirectory 1\n"
+
+#define ENABLE_AUTHORITY_V3_MIN \
+ ENABLE_AUTHORITY_MIN \
+ "V3AuthoritativeDir 1\n"
+
+#define ENABLE_AUTHORITY_BRIDGE_MIN \
+ ENABLE_AUTHORITY_MIN \
+ "BridgeAuthoritativeDir 1\n"
+
+#define AUTHORITY_OPT_REQ_ \
+ "Address 192.0.2.111\n" \
+ "ContactInfo a@example.org\n" \
+ "DirPort 1025\n" \
+ "ORPort 1026\n"
+
+/* Not actually valid: requires v3 / bridge */
+#define ENABLE_AUTHORITY \
+ ENABLE_AUTHORITY_MIN \
+ AUTHORITY_OPT_REQ_
+
+#define ENABLE_AUTHORITY_V3 \
+ ENABLE_AUTHORITY_V3_MIN \
+ AUTHORITY_OPT_REQ_
+
+#define ENABLE_AUTHORITY_BRIDGE \
+ ENABLE_AUTHORITY_BRIDGE_MIN \
+ AUTHORITY_OPT_REQ_
+
+#endif /* defined(COCCI) */
+
#define VALID_DIR_AUTH "DirAuthority dizum orport=443 v3ident=E8A9C45" \
"EDE6D711294FADF8E7951F4DE6CA56B58 194.109.206.212:80 7EA6 EAD6 FD83" \
" 083C 538F 4403 8BBF A077 587D D755\n"
@@ -180,12 +229,11 @@ test_options_validate_impl(const char *configuration,
int phase)
{
or_options_t *opt=NULL;
- or_options_t *dflt;
config_line_t *cl=NULL;
char *msg=NULL;
int r;
- setup_options(opt, dflt);
+ setup_options(opt);
r = config_get_lines(configuration, &cl, 1);
if (phase == PH_GETLINES) {
@@ -208,7 +256,7 @@ test_options_validate_impl(const char *configuration,
if (r)
goto done;
- r = options_validate(NULL, opt, dflt, 0, &msg);
+ r = options_validate(NULL, opt, &msg);
if (phase == PH_VALIDATE) {
if (test_options_checkmsgs(configuration, expect_errmsg,
expect_log_severity,
@@ -222,7 +270,6 @@ test_options_validate_impl(const char *configuration,
policies_free_all();
config_free_lines(cl);
or_options_free(opt);
- or_options_free(dflt);
tor_free(msg);
clear_log_messages();
}
@@ -260,18 +307,10 @@ test_options_validate(void *arg)
WANT_ERR("BridgeRelay 1\nDirCache 0",
"We're a bridge but DirCache is disabled.", PH_VALIDATE);
- // XXXX We should replace this with a more full error message once #29211
- // XXXX is done. It is truncated for now because at the current stage
- // XXXX of refactoring, we can't give a full error message like before.
- WANT_ERR_LOG("HeartbeatPeriod 21 snarks",
- "malformed or out of bounds", LOG_WARN,
- "Unknown unit 'snarks'.",
- PH_ASSIGN);
- // XXXX As above.
- WANT_ERR_LOG("LogTimeGranularity 21 snarks",
- "malformed or out of bounds", LOG_WARN,
- "Unknown unit 'snarks'.",
- PH_ASSIGN);
+ WANT_ERR("HeartbeatPeriod 21 snarks",
+ "Unknown unit in 21 snarks", PH_ASSIGN);
+ WANT_ERR("LogTimeGranularity 21 snarks",
+ "Unknown unit in 21 snarks", PH_ASSIGN);
OK("HeartbeatPeriod 1 hour", PH_VALIDATE);
OK("LogTimeGranularity 100 milliseconds", PH_VALIDATE);
@@ -294,15 +333,13 @@ test_have_enough_mem_for_dircache(void *arg)
{
(void)arg;
or_options_t *opt=NULL;
- or_options_t *dflt=NULL;
config_line_t *cl=NULL;
char *msg=NULL;
int r;
const char *configuration = "ORPort 8080\nDirCache 1", *expect_errmsg;
- setup_options(opt, dflt);
+ setup_options(opt);
setup_log_callback();
- (void)dflt;
r = config_get_lines(configuration, &cl, 1);
tt_int_op(r, OP_EQ, 0);
@@ -376,7 +413,6 @@ test_have_enough_mem_for_dircache(void *arg)
done:
if (msg)
tor_free(msg);
- or_options_free(dflt);
or_options_free(opt);
config_free_lines(cl);
return;
@@ -390,33 +426,8 @@ fixed_get_uname(void)
return fixed_get_uname_result;
}
-#define TEST_OPTIONS_OLD_VALUES "TestingV3AuthInitialVotingInterval 1800\n" \
- "ClientBootstrapConsensusMaxInProgressTries 3\n" \
- "TestingV3AuthInitialVoteDelay 300\n" \
- "TestingV3AuthInitialDistDelay 300\n" \
- "TestingClientMaxIntervalWithoutRequest 600\n" \
- "TestingDirConnectionMaxStall 600\n" \
-
-#define TEST_OPTIONS_DEFAULT_VALUES TEST_OPTIONS_OLD_VALUES \
- "MaxClientCircuitsPending 1\n" \
- "RendPostPeriod 1000\n" \
- "KeepAlivePeriod 1\n" \
- "ConnLimit 1\n" \
- "V3AuthVotingInterval 300\n" \
- "V3AuthVoteDelay 20\n" \
- "V3AuthDistDelay 20\n" \
- "V3AuthNIntervalsValid 3\n" \
- "ClientUseIPv4 1\n" \
- "VirtualAddrNetworkIPv4 127.192.0.0/10\n" \
- "VirtualAddrNetworkIPv6 [FE80::]/10\n" \
- "UseEntryGuards 1\n" \
- "Schedulers Vanilla\n" \
- "ClientDNSRejectInternalAddresses 1\n"
-
typedef struct {
- or_options_t *old_opt;
or_options_t *opt;
- or_options_t *def_opt;
} options_test_data_t;
static void free_options_test_data(options_test_data_t *td);
@@ -429,15 +440,8 @@ get_options_test_data(const char *conf)
config_line_t *cl=NULL;
options_test_data_t *result = tor_malloc(sizeof(options_test_data_t));
result->opt = options_new();
- result->old_opt = options_new();
- result->def_opt = options_new();
- // XXX: Really, all of these options should be set to defaults
- // with options_init(), but about a dozen tests break when I do that.
- // Being kinda lame and just fixing the immedate breakage for now..
- result->opt->ConnectionPadding = -1; // default must be "auto"
- result->opt->DormantClientTimeout = 1800; // must be over 600.
- result->opt->CircuitPadding = 1; // default must be "1"
+ options_init(result->opt);
rv = config_get_lines(conf, &cl, 1);
tt_int_op(rv, OP_EQ, 0);
@@ -450,13 +454,7 @@ get_options_test_data(const char *conf)
config_free_lines(cl);
result->opt->LogTimeGranularity = 1;
result->opt->TokenBucketRefillInterval = 1;
- rv = config_get_lines(TEST_OPTIONS_OLD_VALUES, &cl, 1);
- tt_int_op(rv, OP_EQ, 0);
- rv = config_assign(get_options_mgr(), result->def_opt, cl, 0, &msg);
- if (msg) {
- /* Display the parse error message by comparing it with an empty string */
- tt_str_op(msg, OP_EQ, "");
- }
+ rv = config_get_lines("", &cl, 1);
tt_int_op(rv, OP_EQ, 0);
done:
@@ -475,9 +473,7 @@ static void
free_options_test_data(options_test_data_t *td)
{
if (!td) return;
- or_options_free(td->old_opt);
or_options_free(td->opt);
- or_options_free(td->def_opt);
tor_free(td);
}
@@ -500,7 +496,7 @@ test_options_validate__uname_for_server(void *ignored)
MOCK(get_uname, fixed_get_uname);
fixed_get_uname_result = "Windows 95";
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ options_validate(NULL, tdata->opt, &msg);
expect_log_msg("Tor is running as a server, but you"
" are running Windows 95; this probably won't work. See https://www"
".torproject.org/docs/faq.html#BestOSForRelay for details.\n");
@@ -508,7 +504,7 @@ test_options_validate__uname_for_server(void *ignored)
fixed_get_uname_result = "Windows 98";
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ options_validate(NULL, tdata->opt, &msg);
expect_log_msg("Tor is running as a server, but you"
" are running Windows 98; this probably won't work. See https://www"
".torproject.org/docs/faq.html#BestOSForRelay for details.\n");
@@ -516,7 +512,7 @@ test_options_validate__uname_for_server(void *ignored)
fixed_get_uname_result = "Windows Me";
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ options_validate(NULL, tdata->opt, &msg);
expect_log_msg("Tor is running as a server, but you"
" are running Windows Me; this probably won't work. See https://www"
".torproject.org/docs/faq.html#BestOSForRelay for details.\n");
@@ -524,8 +520,8 @@ test_options_validate__uname_for_server(void *ignored)
fixed_get_uname_result = "Windows 2000";
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- expect_no_log_entry();
+ options_validate(NULL, tdata->opt, &msg);
+ expect_no_log_msg("Tor is running as a server, but you ");
tor_free(msg);
done:
@@ -548,7 +544,7 @@ test_options_validate__outbound_addresses(void *ignored)
options_test_data_t *tdata = get_options_test_data(
"OutboundBindAddress xxyy!!!sdfaf");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Multiple outbound bind addresses configured: "
"xxyy!!!sdfaf");
@@ -585,7 +581,7 @@ test_options_validate__data_directory(void *ignored)
"ONGLONGlongreallylongLONG"
"LONG"); // 440 characters
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Invalid DataDirectory");
@@ -603,7 +599,7 @@ test_options_validate__nickname(void *ignored)
options_test_data_t *tdata = get_options_test_data(
"Nickname ThisNickNameIsABitTooLong");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Nickname 'ThisNickNameIsABitTooLong', nicknames must be between "
@@ -613,16 +609,14 @@ test_options_validate__nickname(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("Nickname AMoreValidNick");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
tdata = get_options_test_data("DataDirectory /tmp/somewhere");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
done:
free_options_test_data(tdata);
@@ -640,8 +634,8 @@ test_options_validate__contactinfo(void *ignored)
setup_capture_of_logs(LOG_DEBUG);
tdata->opt->ContactInfo = NULL;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
expect_log_msg(
"Your ContactInfo config option is not set. Please strongly "
"consider setting it, so we can contact you if your relay is "
@@ -654,8 +648,8 @@ test_options_validate__contactinfo(void *ignored)
tdata = get_options_test_data("ORPort 127.0.0.1:5555\n"
"ContactInfo hella@example.org");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"Your ContactInfo config option is not set. Please strongly "
"consider setting it, so we can contact you if your relay is "
@@ -682,50 +676,53 @@ test_options_validate__logs(void *ignored)
tdata->opt->Logs = NULL;
tdata->opt->RunAsDaemon = 0;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_str_op(tdata->opt->Logs->key, OP_EQ, "Log");
- tt_str_op(tdata->opt->Logs->value, OP_EQ, "notice stdout");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_assert(!tdata->opt->Logs);
tor_free(msg);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, 0);
free_options_test_data(tdata);
tdata = get_options_test_data("");
tdata->opt->Logs = NULL;
tdata->opt->RunAsDaemon = 0;
quiet_level = 1;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_str_op(tdata->opt->Logs->key, OP_EQ, "Log");
- tt_str_op(tdata->opt->Logs->value, OP_EQ, "warn stdout");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_assert(!tdata->opt->Logs);
tor_free(msg);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, 0);
free_options_test_data(tdata);
tdata = get_options_test_data("");
tdata->opt->Logs = NULL;
tdata->opt->RunAsDaemon = 0;
quiet_level = 2;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_assert(!tdata->opt->Logs);
tor_free(msg);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, 0);
free_options_test_data(tdata);
tdata = get_options_test_data("");
tdata->opt->Logs = NULL;
tdata->opt->RunAsDaemon = 0;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 1, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_assert(!tdata->opt->Logs);
tor_free(msg);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, 0);
free_options_test_data(tdata);
tdata = get_options_test_data("");
tdata->opt->Logs = NULL;
tdata->opt->RunAsDaemon = 1;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_assert(!tdata->opt->Logs);
tor_free(msg);
+#ifdef _WIN32
+ /* Can't RunAsDaemon on Windows. */
tt_int_op(ret, OP_EQ, -1);
+#else
+ tt_int_op(ret, OP_EQ, 0);
+#endif /* defined(_WIN32) */
free_options_test_data(tdata);
tdata = get_options_test_data("");
@@ -733,7 +730,7 @@ test_options_validate__logs(void *ignored)
config_line_t *cl=NULL;
config_get_lines("Log foo", &cl, 1);
tdata->opt->Logs = cl;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op((intptr_t)tdata->opt->Logs, OP_EQ, (intptr_t)cl);
tt_int_op(ret, OP_EQ, -1);
@@ -761,13 +758,14 @@ test_options_validate__authdir(void *ignored)
char *msg;
setup_capture_of_logs(LOG_INFO);
options_test_data_t *tdata = get_options_test_data(
- "AuthoritativeDirectory 1\n"
+ ENABLE_AUTHORITY_V3_MIN
"Address this.should.not!exist!.example.org");
+ const dirauth_options_t *da_opt;
sandbox_disable_getaddrinfo_cache();
MOCK(tor_addr_lookup, mock_tor_addr_lookup__fail_on_bad_addrs);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
UNMOCK(tor_addr_lookup);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Failed to resolve/guess local address. See logs for"
@@ -777,246 +775,217 @@ test_options_validate__authdir(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3_MIN
"Address 100.200.10.1");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Authoritative directory servers must set "
"ContactInfo");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3_MIN
"Address 100.200.10.1\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Authoritative directory servers must set ContactInfo");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
+ tdata = get_options_test_data(ENABLE_AUTHORITY_MIN
"Address 100.200.10.1\n"
"TestingTorNetwork 1\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "AuthoritativeDir is set, but none of (Bridge/V3)"
"AuthoritativeDir is set.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
- "ContactInfo hello@hello.com\n");
+ tdata = get_options_test_data(ENABLE_AUTHORITY);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "AuthoritativeDir is set, but none of (Bridge/V3)"
"AuthoritativeDir is set.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
- "RecommendedVersions 1.2, 3.14\n"
- "ContactInfo hello@hello.com\n");
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ "RecommendedVersions 1.2, 3.14\n");
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_str_op(tdata->opt->RecommendedClientVersions->value, OP_EQ, "1.2, 3.14");
- tt_str_op(tdata->opt->RecommendedServerVersions->value, OP_EQ, "1.2, 3.14");
+ options_validate(NULL, tdata->opt, &msg);
+ da_opt = get_dirauth_options(tdata->opt);
+ tt_str_op(da_opt->RecommendedClientVersions->value, OP_EQ, "1.2, 3.14");
+ tt_str_op(da_opt->RecommendedServerVersions->value, OP_EQ, "1.2, 3.14");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"RecommendedVersions 1.2, 3.14\n"
"RecommendedClientVersions 25\n"
- "RecommendedServerVersions 4.18\n"
- "ContactInfo hello@hello.com\n");
+ "RecommendedServerVersions 4.18\n");
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_str_op(tdata->opt->RecommendedClientVersions->value, OP_EQ, "25");
- tt_str_op(tdata->opt->RecommendedServerVersions->value, OP_EQ, "4.18");
+ options_validate(NULL, tdata->opt, &msg);
+ da_opt = get_dirauth_options(tdata->opt);
+ tt_str_op(da_opt->RecommendedClientVersions->value, OP_EQ, "25");
+ tt_str_op(da_opt->RecommendedServerVersions->value, OP_EQ, "4.18");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
+ tdata = get_options_test_data(ENABLE_AUTHORITY
"VersioningAuthoritativeDirectory 1\n"
"RecommendedVersions 1.2, 3.14\n"
"RecommendedClientVersions 25\n"
- "RecommendedServerVersions 4.18\n"
- "ContactInfo hello@hello.com\n");
+ "RecommendedServerVersions 4.18\n");
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ options_validate(NULL, tdata->opt, &msg);
+ da_opt = get_dirauth_options(tdata->opt);
tt_str_op(msg, OP_EQ, "AuthoritativeDir is set, but none of (Bridge/V3)"
"AuthoritativeDir is set.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"VersioningAuthoritativeDirectory 1\n"
- "RecommendedServerVersions 4.18\n"
- "ContactInfo hello@hello.com\n");
+ "RecommendedServerVersions 4.18\n");
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ options_validate(NULL, tdata->opt, &msg);
+ da_opt = get_dirauth_options(tdata->opt);
tt_str_op(msg, OP_EQ, "Versioning authoritative dir servers must set "
"Recommended*Versions.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"VersioningAuthoritativeDirectory 1\n"
- "RecommendedClientVersions 4.18\n"
- "ContactInfo hello@hello.com\n");
+ "RecommendedClientVersions 4.18\n");
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ options_validate(NULL, tdata->opt, &msg);
+ da_opt = get_dirauth_options(tdata->opt);
tt_str_op(msg, OP_EQ, "Versioning authoritative dir servers must set "
"Recommended*Versions.");
tor_free(msg);
+ da_opt = NULL;
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
- "UseEntryGuards 1\n"
- "ContactInfo hello@hello.com\n");
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ "UseEntryGuards 1\n");
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ options_validate(NULL, tdata->opt, &msg);
expect_log_msg("Authoritative directory servers "
"can't set UseEntryGuards. Disabling.\n");
tt_int_op(tdata->opt->UseEntryGuards, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
- "V3AuthoritativeDir 1\n"
- "ContactInfo hello@hello.com\n");
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ "DownloadExtraInfo 0\n");
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ options_validate(NULL, tdata->opt, &msg);
expect_log_msg("Authoritative directories always try"
" to download extra-info documents. Setting DownloadExtraInfo.\n");
tt_int_op(tdata->opt->DownloadExtraInfo, OP_EQ, 1);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
- "DownloadExtraInfo 1\n"
- "V3AuthoritativeDir 1\n"
- "ContactInfo hello@hello.com\n");
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ "V3BandwidthsFile non-existent-file\n");
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- expect_no_log_msg("Authoritative directories always try"
- " to download extra-info documents. Setting DownloadExtraInfo.\n");
- tt_int_op(tdata->opt->DownloadExtraInfo, OP_EQ, 1);
+ options_validate(NULL, tdata->opt, &msg);
+ expect_log_msg("Can't open bandwidth file at configured location: "
+ "non-existent-file\n");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
- "ContactInfo hello@hello.com\n");
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ "GuardfractionFile non-existent-file\n");
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_str_op(msg, OP_EQ, "AuthoritativeDir is set, but none of (Bridge/V3)"
- "AuthoritativeDir is set.");
+ options_validate(NULL, tdata->opt, &msg);
+ expect_log_msg("Cannot open guardfraction file 'non-existent-file'. "
+ "Failing.\n");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3_MIN
"Address 100.200.10.1\n"
- "BridgeAuthoritativeDir 1\n"
- "ContactInfo hello@hello.com\n"
- "V3BandwidthsFile non-existent-file\n");
+ "ORPort 2000\n"
+ "ContactInfo hello@hello.com\n");
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Running as authoritative directory, but no DirPort set.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
+ tdata = get_options_test_data(ENABLE_AUTHORITY_BRIDGE_MIN
"Address 100.200.10.1\n"
- "BridgeAuthoritativeDir 1\n"
- "ContactInfo hello@hello.com\n"
- "V3BandwidthsFile non-existent-file\n");
+ "ORPort 2000\n"
+ "ContactInfo hello@hello.com\n");
mock_clean_saved_logs();
- options_validate(NULL, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Running as authoritative directory, but no DirPort set.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3_MIN
"Address 100.200.10.1\n"
- "BridgeAuthoritativeDir 1\n"
- "ContactInfo hello@hello.com\n"
- "GuardfractionFile non-existent-file\n");
+ "DirPort 999\n"
+ "ContactInfo hello@hello.com\n");
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
- "Running as authoritative directory, but no DirPort set.");
+ "Running as authoritative directory, but no ORPort set.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
+ tdata = get_options_test_data(ENABLE_AUTHORITY_BRIDGE_MIN
"Address 100.200.10.1\n"
- "BridgeAuthoritativeDir 1\n"
- "ContactInfo hello@hello.com\n"
- "GuardfractionFile non-existent-file\n");
+ "DirPort 999\n"
+ "ContactInfo hello@hello.com\n");
mock_clean_saved_logs();
- options_validate(NULL, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
- "Running as authoritative directory, but no DirPort set.");
+ "Running as authoritative directory, but no ORPort set.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
- "BridgeAuthoritativeDir 1\n"
- "ContactInfo hello@hello.com\n");
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ "ClientOnly 1\n");
+ /* We have to call the dirauth-specific function, and fake port parsing,
+ * to hit this case */
+ tdata->opt->DirPort_set = 1;
+ tdata->opt->ORPort_set = 1;
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate_dirauth_mode(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ,
- "Running as authoritative directory, but no DirPort set.");
+ tt_str_op(msg, OP_EQ, "Running as authoritative directory, "
+ "but ClientOnly also set.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
- "DirPort 999\n"
- "BridgeAuthoritativeDir 1\n"
- "ContactInfo hello@hello.com\n");
+ tdata = get_options_test_data(ENABLE_AUTHORITY_BRIDGE
+ "ClientOnly 1\n");
+ /* We have to call the dirauth-specific function, and fake port parsing,
+ * to hit this case */
+ tdata->opt->DirPort_set = 1;
+ tdata->opt->ORPort_set = 1;
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate_dirauth_mode(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ,
- "Running as authoritative directory, but no ORPort set.");
+ tt_str_op(msg, OP_EQ, "Running as authoritative directory, "
+ "but ClientOnly also set.");
tor_free(msg);
- // TODO: This case can't be reached, since clientonly is used to
- // check when parsing port lines as well.
- /* free_options_test_data(tdata); */
- /* tdata = get_options_test_data("AuthoritativeDirectory 1\n" */
- /* "Address 100.200.10.1\n" */
- /* "DirPort 999\n" */
- /* "ORPort 888\n" */
- /* "ClientOnly 1\n" */
- /* "BridgeAuthoritativeDir 1\n" */
- /* "ContactInfo hello@hello.com\n" ); */
- /* mock_clean_saved_logs(); */
- /* ret = options_validate(tdata->old_opt, tdata->opt, */
- /* tdata->def_opt, 0, &msg); */
- /* tt_int_op(ret, OP_EQ, -1); */
- /* tt_str_op(msg, OP_EQ, "Running as authoritative directory, " */
- /* "but ClientOnly also set."); */
-
done:
teardown_capture_of_logs();
// sandbox_free_getaddrinfo_cache();
@@ -1029,6 +998,7 @@ test_options_validate__relay_with_hidden_services(void *ignored)
{
(void)ignored;
char *msg;
+ int ret;
setup_capture_of_logs(LOG_DEBUG);
options_test_data_t *tdata = get_options_test_data(
"ORPort 127.0.0.1:5555\n"
@@ -1037,7 +1007,8 @@ test_options_validate__relay_with_hidden_services(void *ignored)
"HiddenServicePort 80 127.0.0.1:8080\n"
);
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
expect_log_msg(
"Tor is currently configured as a relay and a hidden service. "
"That's not very secure: you should probably run your hidden servi"
@@ -1050,27 +1021,25 @@ test_options_validate__relay_with_hidden_services(void *ignored)
tor_free(msg);
}
-// TODO: it doesn't seem possible to hit the case of having no port lines at
-// all, since there will be a default created for SocksPort
-/* static void */
-/* test_options_validate__ports(void *ignored) */
-/* { */
-/* (void)ignored; */
-/* int ret; */
-/* char *msg; */
-/* setup_capture_of_logs(LOG_WARN); */
-/* options_test_data_t *tdata = get_options_test_data(""); */
-/* ret = options_validate(tdata->old_opt, tdata->opt, */
-/* tdata->def_opt, 0, &msg); */
-/* expect_log_msg("SocksPort, TransPort, NATDPort, DNSPort, and ORPort " */
-/* "are all undefined, and there aren't any hidden services " */
-/* "configured. " */
-/* " Tor will still run, but probably won't do anything.\n"); */
-/* done: */
-/* teardown_capture_of_logs(); */
-/* free_options_test_data(tdata); */
-/* tor_free(msg); */
-/* } */
+static void
+test_options_validate__listen_ports(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ char *msg;
+ setup_capture_of_logs(LOG_WARN);
+ options_test_data_t *tdata = get_options_test_data("SOCKSPort 0");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
+ expect_log_msg("SocksPort, TransPort, NATDPort, DNSPort, and ORPort "
+ "are all undefined, and there aren't any hidden services "
+ "configured. "
+ " Tor will still run, but probably won't do anything.\n");
+ done:
+ teardown_capture_of_logs();
+ free_options_test_data(tdata);
+ tor_free(msg);
+}
static void
test_options_validate__transproxy(void *ignored)
@@ -1084,31 +1053,31 @@ test_options_validate__transproxy(void *ignored)
// Test default trans proxy
tdata = get_options_test_data("TransProxyType default\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->TransProxyType_parsed, OP_EQ, TPT_DEFAULT);
tor_free(msg);
// Test pf-divert trans proxy
free_options_test_data(tdata);
tdata = get_options_test_data("TransProxyType pf-divert\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
-#if !defined(OpenBSD) && !defined( DARWIN )
+#if !defined(OpenBSD) && !defined(DARWIN)
tt_str_op(msg, OP_EQ,
"pf-divert is a OpenBSD-specific and OS X/Darwin-specific feature.");
#else
tt_int_op(tdata->opt->TransProxyType_parsed, OP_EQ, TPT_PF_DIVERT);
tt_str_op(msg, OP_EQ, "Cannot use TransProxyType without "
"any valid TransPort.");
-#endif /* !defined(OpenBSD) && !defined( DARWIN ) */
+#endif /* !defined(OpenBSD) && !defined(DARWIN) */
tor_free(msg);
// Test tproxy trans proxy
free_options_test_data(tdata);
tdata = get_options_test_data("TransProxyType tproxy\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
#if !defined(__linux__)
@@ -1123,7 +1092,7 @@ test_options_validate__transproxy(void *ignored)
// Test ipfw trans proxy
free_options_test_data(tdata);
tdata = get_options_test_data("TransProxyType ipfw\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
#ifndef KERNEL_MAY_SUPPORT_IPFW
@@ -1139,7 +1108,7 @@ test_options_validate__transproxy(void *ignored)
// Test unknown trans proxy
free_options_test_data(tdata);
tdata = get_options_test_data("TransProxyType non-existent\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Unrecognized value for TransProxyType");
tor_free(msg);
@@ -1151,29 +1120,25 @@ test_options_validate__transproxy(void *ignored)
#if defined(__linux__)
tdata = get_options_test_data("TransProxyType tproxy\n"
"TransPort 127.0.0.1:123\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
#elif defined(KERNEL_MAY_SUPPORT_IPFW)
tdata = get_options_test_data("TransProxyType ipfw\n"
"TransPort 127.0.0.1:123\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
#elif defined(OpenBSD)
tdata = get_options_test_data("TransProxyType pf-divert\n"
"TransPort 127.0.0.1:123\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
#elif defined(__NetBSD__)
tdata = get_options_test_data("TransProxyType default\n"
"TransPort 127.0.0.1:123\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
#endif /* defined(__linux__) || ... */
@@ -1183,7 +1148,7 @@ test_options_validate__transproxy(void *ignored)
#else /* !defined(USE_TRANSPARENT) */
tdata = get_options_test_data("TransPort 127.0.0.1:555\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "TransPort is disabled in this build.");
tor_free(msg);
@@ -1194,13 +1159,14 @@ test_options_validate__transproxy(void *ignored)
tor_free(msg);
}
-NS_DECL(country_t, geoip_get_country, (const char *country));
+static country_t opt_tests_geoip_get_country(const char *country);
+ATTR_UNUSED static int opt_tests_geoip_get_country_called = 0;
static country_t
-NS(geoip_get_country)(const char *countrycode)
+opt_tests_geoip_get_country(const char *countrycode)
{
(void)countrycode;
- CALLED(geoip_get_country)++;
+ opt_tests_geoip_get_country_called++;
return 1;
}
@@ -1210,7 +1176,8 @@ test_options_validate__exclude_nodes(void *ignored)
{
(void)ignored;
- NS_MOCK(geoip_get_country);
+ MOCK(geoip_get_country,
+ opt_tests_geoip_get_country);
int ret;
char *msg;
@@ -1218,8 +1185,8 @@ test_options_validate__exclude_nodes(void *ignored)
options_test_data_t *tdata = get_options_test_data(
"ExcludeExitNodes {us}\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(tdata->opt->ExcludeExitNodesUnion_->list), OP_EQ, 1);
tt_str_op((char *)
(smartlist_get(tdata->opt->ExcludeExitNodesUnion_->list, 0)),
@@ -1228,8 +1195,8 @@ test_options_validate__exclude_nodes(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("ExcludeNodes {cn}\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(tdata->opt->ExcludeExitNodesUnion_->list), OP_EQ, 1);
tt_str_op((char *)
(smartlist_get(tdata->opt->ExcludeExitNodesUnion_->list, 0)),
@@ -1239,8 +1206,8 @@ test_options_validate__exclude_nodes(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("ExcludeNodes {cn}\n"
"ExcludeExitNodes {us} {cn}\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(tdata->opt->ExcludeExitNodesUnion_->list), OP_EQ, 2);
tt_str_op((char *)
(smartlist_get(tdata->opt->ExcludeExitNodesUnion_->list, 0)),
@@ -1254,8 +1221,8 @@ test_options_validate__exclude_nodes(void *ignored)
tdata = get_options_test_data("ExcludeNodes {cn}\n"
"StrictNodes 1\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
expect_log_msg(
"You have asked to exclude certain relays from all positions "
"in your circuits. Expect hidden services and other Tor "
@@ -1265,8 +1232,8 @@ test_options_validate__exclude_nodes(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("ExcludeNodes {cn}\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"You have asked to exclude certain relays from all positions "
"in your circuits. Expect hidden services and other Tor "
@@ -1274,7 +1241,7 @@ test_options_validate__exclude_nodes(void *ignored)
tor_free(msg);
done:
- NS_UNMOCK(geoip_get_country);
+ UNMOCK(geoip_get_country);
teardown_capture_of_logs();
free_options_test_data(tdata);
tor_free(msg);
@@ -1290,8 +1257,8 @@ test_options_validate__node_families(void *ignored)
"NodeFamily flux, flax\n"
"NodeFamily somewhere\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_assert(tdata->opt->NodeFamilySets);
tt_int_op(smartlist_len(tdata->opt->NodeFamilySets), OP_EQ, 2);
tt_str_op((char *)(smartlist_get(
@@ -1308,15 +1275,15 @@ test_options_validate__node_families(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_assert(!tdata->opt->NodeFamilySets);
tor_free(msg);
free_options_test_data(tdata);
tdata = get_options_test_data("NodeFamily !flux\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_assert(tdata->opt->NodeFamilySets);
tt_int_op(smartlist_len(tdata->opt->NodeFamilySets), OP_EQ, 0);
@@ -1336,14 +1303,14 @@ test_options_validate__token_bucket(void *ignored)
options_test_data_t *tdata = get_options_test_data("");
tdata->opt->TokenBucketRefillInterval = 0;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"TokenBucketRefillInterval must be between 1 and 1000 inclusive.");
tor_free(msg);
tdata->opt->TokenBucketRefillInterval = 1001;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"TokenBucketRefillInterval must be between 1 and 1000 inclusive.");
@@ -1364,7 +1331,7 @@ test_options_validate__fetch_dir(void *ignored)
"FetchDirInfoExtraEarly 1\n"
"FetchDirInfoEarly 0\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "FetchDirInfoExtraEarly requires that you"
" also set FetchDirInfoEarly");
@@ -1374,10 +1341,8 @@ test_options_validate__fetch_dir(void *ignored)
tdata = get_options_test_data("FetchDirInfoExtraEarly 1\n"
"FetchDirInfoEarly 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_NE, "FetchDirInfoExtraEarly requires that you"
- " also set FetchDirInfoEarly");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
done:
@@ -1394,7 +1359,7 @@ test_options_validate__conn_limit(void *ignored)
options_test_data_t *tdata = get_options_test_data(
"ConnLimit 0\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0");
tor_free(msg);
@@ -1402,10 +1367,8 @@ test_options_validate__conn_limit(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("ConnLimit 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ, "MaxClientCircuitsPending must be between 1 and 1024, "
- "but was set to 0");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
done:
@@ -1428,11 +1391,10 @@ test_options_validate__paths_needed(void *ignored)
setup_capture_of_logs(LOG_WARN);
options_test_data_t *tdata = get_options_test_data(
- "PathsNeededToBuildCircuits 0.1\n"
- "ConnLimit 1\n");
+ "PathsNeededToBuildCircuits 0.1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_assert(tdata->opt->PathsNeededToBuildCircuits > 0.24 &&
tdata->opt->PathsNeededToBuildCircuits < 0.26);
expect_log_msg("PathsNeededToBuildCircuits is too low. "
@@ -1441,11 +1403,10 @@ test_options_validate__paths_needed(void *ignored)
free_options_test_data(tdata);
mock_clean_saved_logs();
- tdata = get_options_test_data("PathsNeededToBuildCircuits 0.99\n"
- "ConnLimit 1\n");
+ tdata = get_options_test_data("PathsNeededToBuildCircuits 0.99\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_assert(tdata->opt->PathsNeededToBuildCircuits > 0.94 &&
tdata->opt->PathsNeededToBuildCircuits < 0.96);
expect_log_msg("PathsNeededToBuildCircuits is "
@@ -1454,14 +1415,13 @@ test_options_validate__paths_needed(void *ignored)
free_options_test_data(tdata);
mock_clean_saved_logs();
- tdata = get_options_test_data("PathsNeededToBuildCircuits 0.91\n"
- "ConnLimit 1\n");
+ tdata = get_options_test_data("PathsNeededToBuildCircuits 0.91\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_assert(tdata->opt->PathsNeededToBuildCircuits > 0.90 &&
tdata->opt->PathsNeededToBuildCircuits < 0.92);
- expect_no_log_entry();
+ expect_no_log_msg_containing("PathsNeededToBuildCircuits");
tor_free(msg);
done:
@@ -1481,32 +1441,28 @@ test_options_validate__max_client_circuits(void *ignored)
int ret;
char *msg;
options_test_data_t *tdata = get_options_test_data(
- "MaxClientCircuitsPending 0\n"
- "ConnLimit 1\n");
+ "MaxClientCircuitsPending 0\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "MaxClientCircuitsPending must be between 1 and 1024,"
" but was set to 0");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("MaxClientCircuitsPending 1025\n"
- "ConnLimit 1\n");
+ tdata = get_options_test_data("MaxClientCircuitsPending 1025\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "MaxClientCircuitsPending must be between 1 and 1024,"
" but was set to 1025");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ tdata = get_options_test_data("MaxClientCircuitsPending 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ, "KeepalivePeriod option must be positive.");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
done:
@@ -1520,23 +1476,18 @@ test_options_validate__ports(void *ignored)
(void)ignored;
int ret;
char *msg;
- options_test_data_t *tdata = get_options_test_data(
- "FirewallPorts 65537\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ options_test_data_t *tdata = get_options_test_data("FirewallPorts 65537\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Port '65537' out of range in FirewallPorts");
tor_free(msg);
free_options_test_data(tdata);
tdata = get_options_test_data("FirewallPorts 1\n"
- "LongLivedPorts 124444\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "LongLivedPorts 124444\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Port '124444' out of range in LongLivedPorts");
tor_free(msg);
@@ -1544,11 +1495,9 @@ test_options_validate__ports(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("FirewallPorts 1\n"
"LongLivedPorts 2\n"
- "RejectPlaintextPorts 112233\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "RejectPlaintextPorts 112233\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Port '112233' out of range in RejectPlaintextPorts");
tor_free(msg);
@@ -1557,11 +1506,9 @@ test_options_validate__ports(void *ignored)
tdata = get_options_test_data("FirewallPorts 1\n"
"LongLivedPorts 2\n"
"RejectPlaintextPorts 3\n"
- "WarnPlaintextPorts 65536\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "WarnPlaintextPorts 65536\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Port '65536' out of range in WarnPlaintextPorts");
tor_free(msg);
@@ -1570,13 +1517,10 @@ test_options_validate__ports(void *ignored)
tdata = get_options_test_data("FirewallPorts 1\n"
"LongLivedPorts 2\n"
"RejectPlaintextPorts 3\n"
- "WarnPlaintextPorts 4\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "WarnPlaintextPorts 4\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ, "KeepalivePeriod option must be positive.");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
done:
@@ -1591,13 +1535,10 @@ test_options_validate__reachable_addresses(void *ignored)
int ret;
char *msg;
setup_capture_of_logs(LOG_NOTICE);
- options_test_data_t *tdata = get_options_test_data(
- "FascistFirewall 1\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ options_test_data_t *tdata = get_options_test_data("FascistFirewall 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
expect_log_msg("Converting FascistFirewall config "
"option to new format: \"ReachableDirAddresses *:80\"\n");
tt_str_op(tdata->opt->ReachableDirAddresses->value, OP_EQ, "*:80");
@@ -1610,13 +1551,17 @@ test_options_validate__reachable_addresses(void *ignored)
mock_clean_saved_logs();
tdata = get_options_test_data("FascistFirewall 1\n"
"ReachableDirAddresses *:81\n"
- "ReachableORAddresses *:444\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
- tdata->opt->FirewallPorts = smartlist_new();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ "ReachableORAddresses *:444\n");
+ tt_assert(tdata->opt->FirewallPorts);
+ SMARTLIST_FOREACH(tdata->opt->FirewallPorts, char *, cp, tor_free(cp));
+ smartlist_clear(tdata->opt->FirewallPorts);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
+#if 0
+ /* This does not actually produce any logs, and did not produce any relevant
+ * logs before. */
expect_log_entry();
+#endif
tt_str_op(tdata->opt->ReachableDirAddresses->value, OP_EQ, "*:81");
tt_str_op(tdata->opt->ReachableORAddresses->value, OP_EQ, "*:444");
tor_free(msg);
@@ -1624,12 +1569,10 @@ test_options_validate__reachable_addresses(void *ignored)
free_options_test_data(tdata);
mock_clean_saved_logs();
tdata = get_options_test_data("FascistFirewall 1\n"
- "FirewallPort 123\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "FirewallPort 123\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
expect_log_msg("Converting FascistFirewall and "
"FirewallPorts config options to new format: "
"\"ReachableAddresses *:123\"\n");
@@ -1641,25 +1584,25 @@ test_options_validate__reachable_addresses(void *ignored)
tdata = get_options_test_data("FascistFirewall 1\n"
"ReachableAddresses *:82\n"
"ReachableAddresses *:83\n"
- "ReachableAddresses reject *:*\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "ReachableAddresses reject *:*\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
+#if 0
+ /* This does not actually produce any logs, and did not produce any relevant
+ * logs before. */
expect_log_entry();
+#endif
tt_str_op(tdata->opt->ReachableAddresses->value, OP_EQ, "*:82");
tor_free(msg);
free_options_test_data(tdata);
mock_clean_saved_logs();
tdata = get_options_test_data("FascistFirewall 1\n"
- "ReachableAddresses *:82\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "ReachableAddresses *:82\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_ptr_op(tdata->opt->ReachableAddresses->next, OP_EQ, NULL);
tor_free(msg);
@@ -1669,44 +1612,36 @@ test_options_validate__reachable_addresses(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("ReachableAddresses *:82\n"
- "ORPort 127.0.0.1:5555\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "ORPort 127.0.0.1:5555\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, SERVERS_REACHABLE_MSG);
tor_free(msg);
free_options_test_data(tdata);
tdata = get_options_test_data("ReachableORAddresses *:82\n"
- "ORPort 127.0.0.1:5555\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "ORPort 127.0.0.1:5555\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, SERVERS_REACHABLE_MSG);
tor_free(msg);
free_options_test_data(tdata);
tdata = get_options_test_data("ReachableDirAddresses *:82\n"
- "ORPort 127.0.0.1:5555\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "ORPort 127.0.0.1:5555\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, SERVERS_REACHABLE_MSG);
tor_free(msg);
free_options_test_data(tdata);
tdata = get_options_test_data("ClientUseIPv4 0\n"
- "ORPort 127.0.0.1:5555\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "ORPort 127.0.0.1:5555\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, SERVERS_REACHABLE_MSG);
tor_free(msg);
@@ -1714,74 +1649,68 @@ test_options_validate__reachable_addresses(void *ignored)
/* Test IPv4-only clients setting IPv6 preferences */
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ClientUseIPv4 1\n"
+ tdata = get_options_test_data("ClientUseIPv4 1\n"
"ClientUseIPv6 0\n"
"UseBridges 0\n"
"ClientPreferIPv6ORPort 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ClientUseIPv4 1\n"
+ tdata = get_options_test_data("ClientUseIPv4 1\n"
"ClientUseIPv6 0\n"
"UseBridges 0\n"
"ClientPreferIPv6DirPort 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
/* Now test an IPv4/IPv6 client setting IPv6 preferences */
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ClientUseIPv4 1\n"
+ tdata = get_options_test_data("ClientUseIPv4 1\n"
"ClientUseIPv6 1\n"
"ClientPreferIPv6ORPort 1\n"
"ClientPreferIPv6DirPort 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL);
/* Now test an IPv6 client setting IPv6 preferences */
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ClientUseIPv6 1\n"
+ tdata = get_options_test_data("ClientUseIPv6 1\n"
"ClientPreferIPv6ORPort 1\n"
"ClientPreferIPv6DirPort 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL);
/* And an implicit (IPv4 disabled) IPv6 client setting IPv6 preferences */
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ClientUseIPv4 0\n"
+ tdata = get_options_test_data("ClientUseIPv4 0\n"
"ClientPreferIPv6ORPort 1\n"
"ClientPreferIPv6DirPort 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL);
/* And an implicit (bridge) client setting IPv6 preferences */
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "UseBridges 1\n"
+ tdata = get_options_test_data("UseBridges 1\n"
"Bridge 127.0.0.1:12345\n"
"ClientPreferIPv6ORPort 1\n"
"ClientPreferIPv6DirPort 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL);
@@ -1800,76 +1729,68 @@ test_options_validate__use_bridges(void *ignored)
options_test_data_t *tdata = get_options_test_data(
"UseBridges 1\n"
"ClientUseIPv4 1\n"
- "ORPort 127.0.0.1:5555\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "ORPort 127.0.0.1:5555\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Servers must be able to freely connect to the rest of"
" the Internet, so they must not set UseBridges.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("UseBridges 1\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ tdata = get_options_test_data("UseBridges 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_NE, "Servers must be able to freely connect to the rest of"
" the Internet, so they must not set UseBridges.");
tor_free(msg);
- NS_MOCK(geoip_get_country);
+ MOCK(geoip_get_country,
+ opt_tests_geoip_get_country);
free_options_test_data(tdata);
tdata = get_options_test_data("UseBridges 1\n"
- "EntryNodes {cn}\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "EntryNodes {cn}\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "You cannot set both UseBridges and EntryNodes.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "UseBridges 1\n");
+ tdata = get_options_test_data("UseBridges 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"If you set UseBridges, you must specify at least one bridge.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "UseBridges 1\n"
+ tdata = get_options_test_data("UseBridges 1\n"
"Bridge 10.0.0.1\n"
"UseEntryGuards 0\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Setting UseBridges requires also setting UseEntryGuards.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "UseBridges 1\n"
+ tdata = get_options_test_data("UseBridges 1\n"
"Bridge 10.0.0.1\n"
"Bridge !!!\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Bridge line did not parse. See logs for details.");
tor_free(msg);
done:
- NS_UNMOCK(geoip_get_country);
+ UNMOCK(geoip_get_country);
policies_free_all();
free_options_test_data(tdata);
tor_free(msg);
@@ -1881,14 +1802,13 @@ test_options_validate__entry_nodes(void *ignored)
(void)ignored;
int ret;
char *msg;
- NS_MOCK(geoip_get_country);
+ MOCK(geoip_get_country,
+ opt_tests_geoip_get_country);
options_test_data_t *tdata = get_options_test_data(
"EntryNodes {cn}\n"
- "UseEntryGuards 0\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "UseEntryGuards 0\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"If EntryNodes is set, UseEntryGuards must be enabled.");
@@ -1896,17 +1816,14 @@ test_options_validate__entry_nodes(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("EntryNodes {cn}\n"
- "UseEntryGuards 1\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "UseEntryGuards 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ, "KeepalivePeriod option must be positive.");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
done:
- NS_UNMOCK(geoip_get_country);
+ UNMOCK(geoip_get_country);
free_options_test_data(tdata);
tor_free(msg);
}
@@ -1917,51 +1834,41 @@ test_options_validate__safe_logging(void *ignored)
(void)ignored;
int ret;
char *msg;
- options_test_data_t *tdata = get_options_test_data(
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ options_test_data_t *tdata = get_options_test_data("SafeLogging 0\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->SafeLogging_, OP_EQ, SAFELOG_SCRUB_NONE);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("SafeLogging 0\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ tdata = get_options_test_data("SafeLogging 0\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->SafeLogging_, OP_EQ, SAFELOG_SCRUB_NONE);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("SafeLogging Relay\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ tdata = get_options_test_data("SafeLogging Relay\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->SafeLogging_, OP_EQ, SAFELOG_SCRUB_RELAY);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("SafeLogging 1\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ tdata = get_options_test_data("SafeLogging 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->SafeLogging_, OP_EQ, SAFELOG_SCRUB_ALL);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("SafeLogging stuffy\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ tdata = get_options_test_data("SafeLogging stuffy\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Unrecognized value '\"stuffy\"' in SafeLogging");
tor_free(msg);
@@ -1980,27 +1887,24 @@ test_options_validate__publish_server_descriptor(void *ignored)
char *msg;
setup_capture_of_logs(LOG_WARN);
options_test_data_t *tdata = get_options_test_data(
- "PublishServerDescriptor bridge\n" TEST_OPTIONS_DEFAULT_VALUES
- );
+ "PublishServerDescriptor bridge\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_assert(!msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("PublishServerDescriptor humma\n"
- TEST_OPTIONS_DEFAULT_VALUES);
+ tdata = get_options_test_data("PublishServerDescriptor humma\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Unrecognized value in PublishServerDescriptor");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("PublishServerDescriptor bridge, v3\n"
- TEST_OPTIONS_DEFAULT_VALUES);
+ tdata = get_options_test_data("PublishServerDescriptor bridge, v3\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Bridges are not supposed to publish router "
"descriptors to the directory authorities. Please correct your "
@@ -2009,10 +1913,9 @@ test_options_validate__publish_server_descriptor(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("BridgeRelay 1\n"
- "PublishServerDescriptor v3\n"
- TEST_OPTIONS_DEFAULT_VALUES);
+ "PublishServerDescriptor v3\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Bridges are not supposed to publish router "
"descriptors to the directory authorities. Please correct your "
@@ -2020,9 +1923,9 @@ test_options_validate__publish_server_descriptor(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("BridgeRelay 1\n" TEST_OPTIONS_DEFAULT_VALUES);
+ tdata = get_options_test_data("BridgeRelay 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_NE, "Bridges are not supposed to publish router "
"descriptors to the directory authorities. Please correct your "
@@ -2031,10 +1934,10 @@ test_options_validate__publish_server_descriptor(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("BridgeRelay 1\n"
- "DirPort 999\n" TEST_OPTIONS_DEFAULT_VALUES);
+ "DirPort 999\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
expect_log_msg("Can't set a DirPort on a bridge "
"relay; disabling DirPort\n");
@@ -2059,21 +1962,19 @@ test_options_validate__testing(void *ignored)
#define ENSURE_DEFAULT(varname, varval) \
STMT_BEGIN \
free_options_test_data(tdata); \
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES \
- #varname " " #varval "\n"); \
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\
+ tdata = get_options_test_data(#varname " " #varval "\n"); \
+ ret = options_validate(NULL, tdata->opt, &msg); \
tt_str_op(msg, OP_EQ, \
#varname " may only be changed in testing Tor networks!"); \
tt_int_op(ret, OP_EQ, -1); \
tor_free(msg); \
\
free_options_test_data(tdata); \
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES \
- #varname " " #varval "\n" \
+ tdata = get_options_test_data(#varname " " #varval "\n" \
VALID_DIR_AUTH \
"TestingTorNetwork 1\n"); \
\
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\
+ ret = options_validate(NULL, tdata->opt, &msg); \
if (msg) { \
tt_str_op(msg, OP_NE, \
#varname " may only be changed in testing Tor networks!"); \
@@ -2081,11 +1982,10 @@ test_options_validate__testing(void *ignored)
} \
\
free_options_test_data(tdata); \
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES \
- #varname " " #varval "\n" \
+ tdata = get_options_test_data(#varname " " #varval "\n" \
"___UsingTestNetworkDefaults 1\n"); \
\
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\
+ ret = options_validate(NULL, tdata->opt, &msg);\
if (msg) { \
tt_str_op(msg, OP_NE, \
#varname " may only be changed in testing Tor networks!"); \
@@ -2098,7 +1998,6 @@ test_options_validate__testing(void *ignored)
ENSURE_DEFAULT(TestingV3AuthInitialDistDelay, 3000);
ENSURE_DEFAULT(TestingV3AuthVotingStartOffset, 3000);
ENSURE_DEFAULT(TestingAuthDirTimeToLearnReachability, 3000);
- ENSURE_DEFAULT(TestingEstimatedDescriptorPropagationTime, 3000);
ENSURE_DEFAULT(TestingServerDownloadInitialDelay, 3000);
ENSURE_DEFAULT(TestingClientDownloadInitialDelay, 3000);
ENSURE_DEFAULT(TestingServerConsensusDownloadInitialDelay, 3000);
@@ -2128,21 +2027,12 @@ test_options_validate__hidserv(void *ignored)
char *msg;
setup_capture_of_logs(LOG_WARN);
- options_test_data_t *tdata = get_options_test_data(
- TEST_OPTIONS_DEFAULT_VALUES);
- tdata->opt->MinUptimeHidServDirectoryV2 = -1;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, 0);
- expect_log_msg("MinUptimeHidServDirectoryV2 "
- "option must be at least 0 seconds. Changing to 0.\n");
- tt_int_op(tdata->opt->MinUptimeHidServDirectoryV2, OP_EQ, 0);
- tor_free(msg);
+ options_test_data_t *tdata = NULL;
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "RendPostPeriod 1\n" );
+ tdata = get_options_test_data("RendPostPeriod 1\n" );
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg("RendPostPeriod option is too short;"
" raising to 600 seconds.\n");
@@ -2150,10 +2040,9 @@ test_options_validate__hidserv(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "RendPostPeriod 302401\n" );
+ tdata = get_options_test_data("RendPostPeriod 302401\n" );
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg("RendPostPeriod is too large; "
"clipping to 302400s.\n");
@@ -2175,45 +2064,40 @@ test_options_validate__path_bias(void *ignored)
char *msg;
options_test_data_t *tdata = get_options_test_data(
- TEST_OPTIONS_DEFAULT_VALUES
"PathBiasNoticeRate 1.1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"PathBiasNoticeRate is too high. It must be between 0 and 1.0");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "PathBiasWarnRate 1.1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("PathBiasWarnRate 1.1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"PathBiasWarnRate is too high. It must be between 0 and 1.0");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "PathBiasExtremeRate 1.1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("PathBiasExtremeRate 1.1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"PathBiasExtremeRate is too high. It must be between 0 and 1.0");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "PathBiasNoticeUseRate 1.1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("PathBiasNoticeUseRate 1.1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"PathBiasNoticeUseRate is too high. It must be between 0 and 1.0");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "PathBiasExtremeUseRate 1.1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("PathBiasExtremeUseRate 1.1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"PathBiasExtremeUseRate is too high. It must be between 0 and 1.0");
@@ -2232,130 +2116,141 @@ test_options_validate__bandwidth(void *ignored)
char *msg;
options_test_data_t *tdata = NULL;
-#define ENSURE_BANDWIDTH_PARAM(p) \
- STMT_BEGIN \
+#define ENSURE_BANDWIDTH_PARAM(p, EXTRA_OPT_STR) \
+ STMT_BEGIN \
free_options_test_data(tdata); \
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES #p " 3Gb\n"); \
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\
+ tdata = get_options_test_data(EXTRA_OPT_STR \
+ #p " 3Gb\n"); \
+ ret = options_validate(NULL, tdata->opt, &msg); \
tt_int_op(ret, OP_EQ, -1); \
tt_mem_op(msg, OP_EQ, #p " (3221225471) must be at most 2147483647", 40); \
tor_free(msg); \
STMT_END
- ENSURE_BANDWIDTH_PARAM(BandwidthRate);
- ENSURE_BANDWIDTH_PARAM(BandwidthBurst);
- ENSURE_BANDWIDTH_PARAM(MaxAdvertisedBandwidth);
- ENSURE_BANDWIDTH_PARAM(RelayBandwidthRate);
- ENSURE_BANDWIDTH_PARAM(RelayBandwidthBurst);
- ENSURE_BANDWIDTH_PARAM(PerConnBWRate);
- ENSURE_BANDWIDTH_PARAM(PerConnBWBurst);
- ENSURE_BANDWIDTH_PARAM(AuthDirFastGuarantee);
- ENSURE_BANDWIDTH_PARAM(AuthDirGuardBWGuarantee);
+ ENSURE_BANDWIDTH_PARAM(BandwidthRate, "");
+ ENSURE_BANDWIDTH_PARAM(BandwidthBurst, "");
+
+ ENSURE_BANDWIDTH_PARAM(BandwidthRate, ENABLE_AUTHORITY_V3);
+ ENSURE_BANDWIDTH_PARAM(BandwidthBurst, ENABLE_AUTHORITY_V3);
+
+ ENSURE_BANDWIDTH_PARAM(BandwidthRate, ENABLE_AUTHORITY_BRIDGE);
+ ENSURE_BANDWIDTH_PARAM(BandwidthBurst, ENABLE_AUTHORITY_BRIDGE);
+
+ ENSURE_BANDWIDTH_PARAM(MaxAdvertisedBandwidth, "");
+ ENSURE_BANDWIDTH_PARAM(RelayBandwidthRate, "");
+ ENSURE_BANDWIDTH_PARAM(RelayBandwidthBurst, "");
+ ENSURE_BANDWIDTH_PARAM(PerConnBWRate, "");
+ ENSURE_BANDWIDTH_PARAM(PerConnBWBurst, "");
+
+ ENSURE_BANDWIDTH_PARAM(MaxAdvertisedBandwidth, ENABLE_AUTHORITY_V3);
+ ENSURE_BANDWIDTH_PARAM(RelayBandwidthRate, ENABLE_AUTHORITY_V3);
+ ENSURE_BANDWIDTH_PARAM(RelayBandwidthBurst, ENABLE_AUTHORITY_V3);
+ ENSURE_BANDWIDTH_PARAM(PerConnBWRate, ENABLE_AUTHORITY_V3);
+ ENSURE_BANDWIDTH_PARAM(PerConnBWBurst, ENABLE_AUTHORITY_V3);
+
+ ENSURE_BANDWIDTH_PARAM(MaxAdvertisedBandwidth, ENABLE_AUTHORITY_BRIDGE);
+ ENSURE_BANDWIDTH_PARAM(RelayBandwidthRate, ENABLE_AUTHORITY_BRIDGE);
+ ENSURE_BANDWIDTH_PARAM(RelayBandwidthBurst, ENABLE_AUTHORITY_BRIDGE);
+ ENSURE_BANDWIDTH_PARAM(PerConnBWRate, ENABLE_AUTHORITY_BRIDGE);
+ ENSURE_BANDWIDTH_PARAM(PerConnBWBurst, ENABLE_AUTHORITY_BRIDGE);
+
+ ENSURE_BANDWIDTH_PARAM(AuthDirFastGuarantee, ENABLE_AUTHORITY_V3);
+ ENSURE_BANDWIDTH_PARAM(AuthDirGuardBWGuarantee, ENABLE_AUTHORITY_V3);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "RelayBandwidthRate 1000\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("RelayBandwidthRate 1000\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_u64_op(tdata->opt->RelayBandwidthBurst, OP_EQ, 1000);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "RelayBandwidthBurst 1001\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("RelayBandwidthBurst 1001\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_u64_op(tdata->opt->RelayBandwidthRate, OP_EQ, 1001);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "RelayBandwidthRate 1001\n"
+ tdata = get_options_test_data("RelayBandwidthRate 1001\n"
"RelayBandwidthBurst 1000\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "RelayBandwidthBurst must be at least equal to "
"RelayBandwidthRate.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "BandwidthRate 1001\n"
+ tdata = get_options_test_data("BandwidthRate 1001\n"
"BandwidthBurst 1000\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"BandwidthBurst must be at least equal to BandwidthRate.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "RelayBandwidthRate 1001\n"
+ tdata = get_options_test_data("RelayBandwidthRate 1001\n"
"BandwidthRate 1000\n"
"BandwidthBurst 1000\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_u64_op(tdata->opt->BandwidthRate, OP_EQ, 1001);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "RelayBandwidthRate 1001\n"
+ tdata = get_options_test_data("RelayBandwidthRate 1001\n"
"BandwidthRate 1000\n"
"RelayBandwidthBurst 1001\n"
"BandwidthBurst 1000\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_u64_op(tdata->opt->BandwidthBurst, OP_EQ, 1001);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ORPort 127.0.0.1:5555\n"
+ tdata = get_options_test_data("ORPort 127.0.0.1:5555\n"
"BandwidthRate 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "BandwidthRate is set to 1 bytes/second. For servers,"
" it must be at least 76800.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ORPort 127.0.0.1:5555\n"
+ tdata = get_options_test_data("ORPort 127.0.0.1:5555\n"
"BandwidthRate 76800\n"
"MaxAdvertisedBandwidth 30000\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "MaxAdvertisedBandwidth is set to 30000 bytes/second."
" For servers, it must be at least 38400.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ORPort 127.0.0.1:5555\n"
+ tdata = get_options_test_data("ORPort 127.0.0.1:5555\n"
"BandwidthRate 76800\n"
"RelayBandwidthRate 1\n"
"MaxAdvertisedBandwidth 38400\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "RelayBandwidthRate is set to 1 bytes/second. For "
"servers, it must be at least 76800.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ORPort 127.0.0.1:5555\n"
+ tdata = get_options_test_data("ORPort 127.0.0.1:5555\n"
"BandwidthRate 76800\n"
"BandwidthBurst 76800\n"
"RelayBandwidthRate 76800\n"
"MaxAdvertisedBandwidth 38400\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
@@ -2374,9 +2269,8 @@ test_options_validate__circuits(void *ignored)
setup_capture_of_logs(LOG_WARN);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "MaxCircuitDirtiness 2592001\n");
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("MaxCircuitDirtiness 2592001\n");
+ options_validate(NULL, tdata->opt, &msg);
expect_log_msg("MaxCircuitDirtiness option is too "
"high; setting to 30 days.\n");
tt_int_op(tdata->opt->MaxCircuitDirtiness, OP_EQ, 2592000);
@@ -2384,9 +2278,8 @@ test_options_validate__circuits(void *ignored)
free_options_test_data(tdata);
mock_clean_saved_logs();
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "CircuitStreamTimeout 1\n");
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("CircuitStreamTimeout 1\n");
+ options_validate(NULL, tdata->opt, &msg);
expect_log_msg("CircuitStreamTimeout option is too"
" short; raising to 10 seconds.\n");
tt_int_op(tdata->opt->CircuitStreamTimeout, OP_EQ, 10);
@@ -2394,9 +2287,8 @@ test_options_validate__circuits(void *ignored)
free_options_test_data(tdata);
mock_clean_saved_logs();
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "CircuitStreamTimeout 111\n");
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("CircuitStreamTimeout 111\n");
+ options_validate(NULL, tdata->opt, &msg);
expect_no_log_msg("CircuitStreamTimeout option is too"
" short; raising to 10 seconds.\n");
tt_int_op(tdata->opt->CircuitStreamTimeout, OP_EQ, 111);
@@ -2404,9 +2296,8 @@ test_options_validate__circuits(void *ignored)
free_options_test_data(tdata);
mock_clean_saved_logs();
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HeartbeatPeriod 1\n");
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HeartbeatPeriod 1\n");
+ options_validate(NULL, tdata->opt, &msg);
expect_log_msg("HeartbeatPeriod option is too short;"
" raising to 1800 seconds.\n");
tt_int_op(tdata->opt->HeartbeatPeriod, OP_EQ, 1800);
@@ -2414,9 +2305,8 @@ test_options_validate__circuits(void *ignored)
free_options_test_data(tdata);
mock_clean_saved_logs();
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HeartbeatPeriod 1982\n");
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HeartbeatPeriod 1982\n");
+ options_validate(NULL, tdata->opt, &msg);
expect_no_log_msg("HeartbeatPeriod option is too short;"
" raising to 1800 seconds.\n");
tt_int_op(tdata->opt->HeartbeatPeriod, OP_EQ, 1982);
@@ -2424,10 +2314,10 @@ test_options_validate__circuits(void *ignored)
free_options_test_data(tdata);
mock_clean_saved_logs();
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data("LearnCircuitBuildTimeout 0\n"
"CircuitBuildTimeout 1\n"
);
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ options_validate(NULL, tdata->opt, &msg);
expect_log_msg("CircuitBuildTimeout is shorter (1"
" seconds) than the recommended minimum (10 seconds), and "
"LearnCircuitBuildTimeout is disabled. If tor isn't working, "
@@ -2436,10 +2326,9 @@ test_options_validate__circuits(void *ignored)
free_options_test_data(tdata);
mock_clean_saved_logs();
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "CircuitBuildTimeout 11\n"
+ tdata = get_options_test_data("CircuitBuildTimeout 11\n"
);
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ options_validate(NULL, tdata->opt, &msg);
expect_no_log_msg("CircuitBuildTimeout is shorter (1 "
"seconds) than the recommended minimum (10 seconds), and "
"LearnCircuitBuildTimeout is disabled. If tor isn't working, "
@@ -2463,12 +2352,12 @@ test_options_validate__rend(void *ignored)
setup_capture_of_logs(LOG_WARN);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(
"UseEntryGuards 0\n"
"HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n"
"HiddenServicePort 80 127.0.0.1:8080\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg("UseEntryGuards is disabled, but you"
" have configured one or more hidden services on this Tor "
@@ -2479,13 +2368,12 @@ test_options_validate__rend(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data(
- TEST_OPTIONS_DEFAULT_VALUES
"UseEntryGuards 1\n"
"HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n"
"HiddenServicePort 80 127.0.0.1:8080\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg("UseEntryGuards is disabled, but you"
" have configured one or more hidden services on this Tor "
@@ -2494,20 +2382,16 @@ test_options_validate__rend(void *ignored)
"attack06 for details.\n");
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HiddenServicePort 80 127.0.0.1:8080\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HiddenServicePort 80 127.0.0.1:8080\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Failed to configure rendezvous options. See logs for details.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HidServAuth failed\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HidServAuth failed\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Failed to configure client authorization for hidden "
"services. See logs for details.");
@@ -2531,11 +2415,10 @@ test_options_validate__single_onion(void *ignored)
/* Test that HiddenServiceSingleHopMode must come with
* HiddenServiceNonAnonymousMode */
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "SOCKSPort 0\n"
+ tdata = get_options_test_data("SOCKSPort 0\n"
"HiddenServiceSingleHopMode 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "HiddenServiceSingleHopMode does not provide any "
"server anonymity. It must be used with "
@@ -2543,12 +2426,11 @@ test_options_validate__single_onion(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "SOCKSPort 0\n"
+ tdata = get_options_test_data("SOCKSPort 0\n"
"HiddenServiceSingleHopMode 1\n"
"HiddenServiceNonAnonymousMode 0\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "HiddenServiceSingleHopMode does not provide any "
"server anonymity. It must be used with "
@@ -2556,23 +2438,21 @@ test_options_validate__single_onion(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "SOCKSPort 0\n"
+ tdata = get_options_test_data("SOCKSPort 0\n"
"HiddenServiceSingleHopMode 1\n"
"HiddenServiceNonAnonymousMode 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL);
free_options_test_data(tdata);
/* Test that SOCKSPort if HiddenServiceSingleHopMode is 1 */
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "SOCKSPort 5000\n"
+ tdata = get_options_test_data("SOCKSPort 5000\n"
"HiddenServiceSingleHopMode 1\n"
"HiddenServiceNonAnonymousMode 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "HiddenServiceNonAnonymousMode is incompatible with "
"using Tor as an anonymous client. Please set "
@@ -2581,32 +2461,30 @@ test_options_validate__single_onion(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "SOCKSPort 0\n"
+ tdata = get_options_test_data("SOCKSPort 0\n"
"HiddenServiceSingleHopMode 1\n"
"HiddenServiceNonAnonymousMode 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "SOCKSPort 5000\n"
+ tdata = get_options_test_data("SOCKSPort 5000\n"
"HiddenServiceSingleHopMode 0\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL);
free_options_test_data(tdata);
/* Test that a hidden service can't be run in non anonymous mode. */
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(
"HiddenServiceNonAnonymousMode 1\n"
"HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n"
"HiddenServicePort 80 127.0.0.1:8080\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "HiddenServiceNonAnonymousMode does not provide any "
"server anonymity. It must be used with "
@@ -2614,10 +2492,10 @@ test_options_validate__single_onion(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(
"HiddenServiceNonAnonymousMode 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "HiddenServiceNonAnonymousMode does not provide any "
"server anonymity. It must be used with "
@@ -2625,23 +2503,23 @@ test_options_validate__single_onion(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(
"HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n"
"HiddenServicePort 80 127.0.0.1:8080\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(
"HiddenServiceNonAnonymousMode 1\n"
"HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n"
"HiddenServicePort 80 127.0.0.1:8080\n"
"HiddenServiceSingleHopMode 1\n"
"SOCKSPort 0\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL);
@@ -2662,53 +2540,56 @@ test_options_validate__accounting(void *ignored)
setup_capture_of_logs(LOG_WARN);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "AccountingRule something_bad\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("AccountingRule something_bad\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "AccountingRule must be 'sum', 'max', 'in', or 'out'");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "AccountingRule sum\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("AccountingRule sum\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->AccountingRule, OP_EQ, ACCT_SUM);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "AccountingRule max\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("AccountingRule max\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->AccountingRule, OP_EQ, ACCT_MAX);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "AccountingStart fail\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("AccountingRule in\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(tdata->opt->AccountingRule, OP_EQ, ACCT_IN);
+ tor_free(msg);
+
+ free_options_test_data(tdata);
+ tdata = get_options_test_data("AccountingRule out\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(tdata->opt->AccountingRule, OP_EQ, ACCT_OUT);
+ tor_free(msg);
+
+ free_options_test_data(tdata);
+ tdata = get_options_test_data("AccountingStart fail\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Failed to parse accounting options. See logs for details.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "AccountingMax 10\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("AccountingMax 10\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
tdata = get_options_test_data(
- TEST_OPTIONS_DEFAULT_VALUES
"ORPort 127.0.0.1:5555\n"
"BandwidthRate 76800\n"
"BandwidthBurst 76800\n"
@@ -2718,7 +2599,7 @@ test_options_validate__accounting(void *ignored)
"AccountingMax 10\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg("Using accounting with a hidden "
"service and an ORPort is risky: your hidden service(s) and "
@@ -2729,13 +2610,12 @@ test_options_validate__accounting(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data(
- TEST_OPTIONS_DEFAULT_VALUES
"HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n"
"HiddenServicePort 80 127.0.0.1:8080\n"
"AccountingMax 10\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg("Using accounting with a hidden "
"service and an ORPort is risky: your hidden service(s) and "
@@ -2746,7 +2626,6 @@ test_options_validate__accounting(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data(
- TEST_OPTIONS_DEFAULT_VALUES
"HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n"
"HiddenServicePort 80 127.0.0.1:8080\n"
"HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service2/\n"
@@ -2754,7 +2633,7 @@ test_options_validate__accounting(void *ignored)
"AccountingMax 10\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg("Using accounting with multiple "
"hidden services is risky: they will all turn off at the same"
@@ -2781,36 +2660,29 @@ test_options_validate__proxy(void *ignored)
MOCK(tor_addr_lookup, mock_tor_addr_lookup__fail_on_bad_addrs);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpProxy 127.0.42.1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HttpProxy 127.0.42.1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->HTTPProxyPort, OP_EQ, 80);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpProxy 127.0.42.1:444\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HttpProxy 127.0.42.1:444\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->HTTPProxyPort, OP_EQ, 444);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpProxy not_so_valid!\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HttpProxy not_so_valid!\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "HTTPProxy failed to parse or resolve. Please fix.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpProxyAuthenticator "
+ tdata = get_options_test_data("HttpProxyAuthenticator "
"onetwothreonetwothreonetwothreonetwothreonetw"
"othreonetwothreonetwothreonetwothreonetwothre"
"onetwothreonetwothreonetwothreonetwothreonetw"
@@ -2823,52 +2695,41 @@ test_options_validate__proxy(void *ignored)
"othreonetwothreonetwothreonetwothreonetwothre"
"onetwothreonetwothreonetwothreonetwothreonetw"
"othreonetwothreeonetwothreeonetwothree"
-
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "HTTPProxyAuthenticator is too long (>= 512 chars).");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpProxyAuthenticator validauth\n"
-
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HttpProxyAuthenticator validauth\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpsProxy 127.0.42.1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HttpsProxy 127.0.42.1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->HTTPSProxyPort, OP_EQ, 443);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpsProxy 127.0.42.1:444\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HttpsProxy 127.0.42.1:444\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->HTTPSProxyPort, OP_EQ, 444);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpsProxy not_so_valid!\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HttpsProxy not_so_valid!\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "HTTPSProxy failed to parse or resolve. Please fix.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpsProxyAuthenticator "
+ tdata = get_options_test_data("HttpsProxyAuthenticator "
"onetwothreonetwothreonetwothreonetwothreonetw"
"othreonetwothreonetwothreonetwothreonetwothre"
"onetwothreonetwothreonetwothreonetwothreonetw"
@@ -2883,103 +2744,86 @@ test_options_validate__proxy(void *ignored)
"othreonetwothreeonetwothreeonetwothree"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "HTTPSProxyAuthenticator is too long (>= 512 chars).");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpsProxyAuthenticator validauth\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HttpsProxyAuthenticator validauth\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks4Proxy 127.0.42.1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("Socks4Proxy 127.0.42.1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->Socks4ProxyPort, OP_EQ, 1080);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks4Proxy 127.0.42.1:444\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("Socks4Proxy 127.0.42.1:444\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->Socks4ProxyPort, OP_EQ, 444);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks4Proxy not_so_valid!\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("Socks4Proxy not_so_valid!\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Socks4Proxy failed to parse or resolve. Please fix.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks5Proxy 127.0.42.1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("Socks5Proxy 127.0.42.1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->Socks5ProxyPort, OP_EQ, 1080);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks5Proxy 127.0.42.1:444\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("Socks5Proxy 127.0.42.1:444\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->Socks5ProxyPort, OP_EQ, 444);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks5Proxy not_so_valid!\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("Socks5Proxy not_so_valid!\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Socks5Proxy failed to parse or resolve. Please fix.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks4Proxy 215.1.1.1\n"
+ tdata = get_options_test_data("Socks4Proxy 215.1.1.1\n"
"Socks5Proxy 215.1.1.2\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "You have configured more than one proxy type. "
- "(Socks4Proxy|Socks5Proxy|HTTPSProxy)");
+ "(Socks4Proxy|Socks5Proxy|HTTPSProxy|TCPProxy)");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpProxy 215.1.1.1\n"
- );
+ tdata = get_options_test_data("HttpProxy 215.1.1.1\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
- expect_log_msg("HTTPProxy configured, but no SOCKS "
- "proxy or HTTPS proxy configured. Watch out: this configuration "
- "will proxy unencrypted directory connections only.\n");
+ expect_log_msg("HTTPProxy configured, but no SOCKS proxy, "
+ "HTTPS proxy, or any other TCP proxy configured. Watch out: "
+ "this configuration will proxy unencrypted directory "
+ "connections only.\n");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpProxy 215.1.1.1\n"
+ tdata = get_options_test_data("HttpProxy 215.1.1.1\n"
"Socks4Proxy 215.1.1.1\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg("HTTPProxy configured, but no SOCKS "
"proxy or HTTPS proxy configured. Watch out: this configuration "
@@ -2987,12 +2831,11 @@ test_options_validate__proxy(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpProxy 215.1.1.1\n"
+ tdata = get_options_test_data("HttpProxy 215.1.1.1\n"
"Socks5Proxy 215.1.1.1\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg("HTTPProxy configured, but no SOCKS "
"proxy or HTTPS proxy configured. Watch out: this configuration "
@@ -3000,12 +2843,11 @@ test_options_validate__proxy(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpProxy 215.1.1.1\n"
+ tdata = get_options_test_data("HttpProxy 215.1.1.1\n"
"HttpsProxy 215.1.1.1\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"HTTPProxy configured, but no SOCKS proxy or HTTPS proxy "
@@ -3014,81 +2856,69 @@ test_options_validate__proxy(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- );
+ tdata = get_options_test_data("");
tdata->opt->Socks5ProxyUsername = tor_strdup("");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Socks5ProxyUsername must be between 1 and 255 characters.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- );
+ tdata = get_options_test_data("");
tdata->opt->Socks5ProxyUsername =
tor_strdup("ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789AB"
"CDEABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCD"
"EABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEA"
"BCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEABC"
"DE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Socks5ProxyUsername must be between 1 and 255 characters.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks5ProxyUsername hello_world\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("Socks5ProxyUsername hello_world\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Socks5ProxyPassword must be included with "
"Socks5ProxyUsername.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks5ProxyUsername hello_world\n"
- );
+ tdata = get_options_test_data("Socks5ProxyUsername hello_world\n");
tdata->opt->Socks5ProxyPassword = tor_strdup("");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Socks5ProxyPassword must be between 1 and 255 characters.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks5ProxyUsername hello_world\n"
- );
+ tdata = get_options_test_data("Socks5ProxyUsername hello_world\n");
tdata->opt->Socks5ProxyPassword =
tor_strdup("ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789AB"
"CDEABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCD"
"EABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEA"
"BCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEABC"
"DE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Socks5ProxyPassword must be between 1 and 255 characters.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks5ProxyUsername hello_world\n"
- "Socks5ProxyPassword world_hello\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("Socks5ProxyUsername hello_world\n"
+ "Socks5ProxyPassword world_hello\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks5ProxyPassword hello_world\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("Socks5ProxyPassword hello_world\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Socks5ProxyPassword must be included with "
"Socks5ProxyUsername.");
@@ -3113,69 +2943,62 @@ test_options_validate__control(void *ignored)
setup_capture_of_logs(LOG_WARN);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HashedControlPassword something_incorrect\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data(
+ "HashedControlPassword something_incorrect\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Bad HashedControlPassword: wrong length or bad encoding");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HashedControlPassword 16:872860B76453A77D60CA"
+ tdata = get_options_test_data("HashedControlPassword 16:872860B76453A77D60CA"
"2BB8C1A7042072093276A3D701AD684053EC4C\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
tdata = get_options_test_data(
- TEST_OPTIONS_DEFAULT_VALUES
"__HashedControlSessionPassword something_incorrect\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Bad HashedControlSessionPassword: wrong length or "
"bad encoding");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "__HashedControlSessionPassword 16:872860B7645"
+ tdata = get_options_test_data("__HashedControlSessionPassword 16:872860B7645"
"3A77D60CA2BB8C1A7042072093276A3D701AD684053EC"
"4C\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
tdata = get_options_test_data(
- TEST_OPTIONS_DEFAULT_VALUES
"__OwningControllerProcess something_incorrect\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Bad OwningControllerProcess: invalid PID");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "__OwningControllerProcess 123\n"
+ tdata = get_options_test_data("__OwningControllerProcess 123\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ControlPort 127.0.0.1:1234\n"
+ tdata = get_options_test_data("ControlPort 127.0.0.1:1234\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg(
"ControlPort is open, but no authentication method has been "
@@ -3185,13 +3008,12 @@ test_options_validate__control(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ControlPort 127.0.0.1:1234\n"
+ tdata = get_options_test_data("ControlPort 127.0.0.1:1234\n"
"HashedControlPassword 16:872860B76453A77D60CA"
"2BB8C1A7042072093276A3D701AD684053EC4C\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"ControlPort is open, but no authentication method has been "
@@ -3201,14 +3023,13 @@ test_options_validate__control(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ControlPort 127.0.0.1:1234\n"
+ tdata = get_options_test_data("ControlPort 127.0.0.1:1234\n"
"__HashedControlSessionPassword 16:872860B7645"
"3A77D60CA2BB8C1A7042072093276A3D701AD684053EC"
"4C\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"ControlPort is open, but no authentication method has been "
@@ -3218,12 +3039,11 @@ test_options_validate__control(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ControlPort 127.0.0.1:1234\n"
+ tdata = get_options_test_data("ControlPort 127.0.0.1:1234\n"
"CookieAuthentication 1\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"ControlPort is open, but no authentication method has been "
@@ -3234,11 +3054,9 @@ test_options_validate__control(void *ignored)
#ifdef HAVE_SYS_UN_H
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ControlSocket unix:/tmp WorldWritable\n"
- );
+ tdata = get_options_test_data("ControlSocket unix:/tmp WorldWritable\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg(
"ControlSocket is world writable, but no authentication method has"
@@ -3248,13 +3066,12 @@ test_options_validate__control(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ControlSocket unix:/tmp WorldWritable\n"
+ tdata = get_options_test_data("ControlSocket unix:/tmp WorldWritable\n"
"HashedControlPassword 16:872860B76453A77D60CA"
"2BB8C1A7042072093276A3D701AD684053EC4C\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"ControlSocket is world writable, but no authentication method has"
@@ -3264,14 +3081,13 @@ test_options_validate__control(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ControlSocket unix:/tmp WorldWritable\n"
+ tdata = get_options_test_data("ControlSocket unix:/tmp WorldWritable\n"
"__HashedControlSessionPassword 16:872860B7645"
"3A77D60CA2BB8C1A7042072093276A3D701AD684053EC"
"4C\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"ControlSocket is world writable, but no authentication method has"
@@ -3281,12 +3097,11 @@ test_options_validate__control(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ControlSocket unix:/tmp WorldWritable\n"
+ tdata = get_options_test_data("ControlSocket unix:/tmp WorldWritable\n"
"CookieAuthentication 1\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"ControlSocket is world writable, but no authentication method has"
@@ -3297,11 +3112,10 @@ test_options_validate__control(void *ignored)
#endif /* defined(HAVE_SYS_UN_H) */
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "CookieAuthFileGroupReadable 1\n"
+ tdata = get_options_test_data("CookieAuthFileGroupReadable 1\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg(
"CookieAuthFileGroupReadable is set, but will have no effect: you "
@@ -3310,12 +3124,11 @@ test_options_validate__control(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "CookieAuthFileGroupReadable 1\n"
+ tdata = get_options_test_data("CookieAuthFileGroupReadable 1\n"
"CookieAuthFile /tmp/somewhere\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"CookieAuthFileGroupReadable is set, but will have no effect: you "
@@ -3340,8 +3153,7 @@ test_options_validate__families(void *ignored)
setup_capture_of_logs(LOG_WARN);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "MyFamily home\n"
+ tdata = get_options_test_data("MyFamily home\n"
"BridgeRelay 1\n"
"ORPort 127.0.0.1:5555\n"
"BandwidthRate 51300\n"
@@ -3350,7 +3162,7 @@ test_options_validate__families(void *ignored)
"DirCache 1\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg(
"Listing a family for a bridge relay is not supported: it can "
@@ -3360,11 +3172,9 @@ test_options_validate__families(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "MyFamily home\n"
- );
+ tdata = get_options_test_data("MyFamily home\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"Listing a family for a bridge relay is not supported: it can "
@@ -3374,22 +3184,18 @@ test_options_validate__families(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "MyFamily !\n"
- );
+ tdata = get_options_test_data("MyFamily !\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Invalid nickname '!' in MyFamily line");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "NodeFamily foo\n"
- "NodeFamily !\n"
- );
+ tdata = get_options_test_data("NodeFamily foo\n"
+ "NodeFamily !\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_assert(!msg);
tor_free(msg);
@@ -3410,11 +3216,10 @@ test_options_validate__addr_policies(void *ignored)
options_test_data_t *tdata = NULL;
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ExitPolicy !!!\n"
+ tdata = get_options_test_data("ExitPolicy !!!\n"
"ExitRelay 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Error in ExitPolicy entry.");
tor_free(msg);
@@ -3435,12 +3240,11 @@ test_options_validate__dir_auth(void *ignored)
setup_capture_of_logs(LOG_WARN);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- VALID_DIR_AUTH
+ tdata = get_options_test_data(VALID_DIR_AUTH
VALID_ALT_DIR_AUTH
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Directory authority/fallback line did not parse. See logs for "
@@ -3450,10 +3254,8 @@ test_options_validate__dir_auth(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingTorNetwork 1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("TestingTorNetwork 1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"TestingTorNetwork may only be configured in combination with a "
@@ -3462,20 +3264,18 @@ test_options_validate__dir_auth(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- VALID_DIR_AUTH
+ tdata = get_options_test_data(VALID_DIR_AUTH
"TestingTorNetwork 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingTorNetwork 1\n"
+ tdata = get_options_test_data("TestingTorNetwork 1\n"
VALID_ALT_DIR_AUTH
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"TestingTorNetwork may only be configured in combination with a "
@@ -3484,11 +3284,10 @@ test_options_validate__dir_auth(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingTorNetwork 1\n"
+ tdata = get_options_test_data("TestingTorNetwork 1\n"
VALID_ALT_BRIDGE_AUTH
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "TestingTorNetwork may only be configured in "
"combination with a non-default set of DirAuthority or both of "
@@ -3496,12 +3295,11 @@ test_options_validate__dir_auth(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- VALID_ALT_DIR_AUTH
+ tdata = get_options_test_data(VALID_ALT_DIR_AUTH
VALID_ALT_BRIDGE_AUTH
"TestingTorNetwork 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
@@ -3522,11 +3320,10 @@ test_options_validate__transport(void *ignored)
setup_capture_of_logs(LOG_NOTICE);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ClientTransportPlugin !!\n"
+ tdata = get_options_test_data("ClientTransportPlugin !!\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Invalid client transport line. See logs for details.");
@@ -3535,20 +3332,17 @@ test_options_validate__transport(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ClientTransportPlugin foo exec bar\n"
+ tdata = get_options_test_data("ClientTransportPlugin foo exec bar\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ServerTransportPlugin !!\n"
- );
+ tdata = get_options_test_data("ServerTransportPlugin !!\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Invalid server transport line. See logs for details.");
@@ -3557,11 +3351,9 @@ test_options_validate__transport(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ServerTransportPlugin foo exec bar\n"
- );
+ tdata = get_options_test_data("ServerTransportPlugin foo exec bar\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg(
"Tor is not configured as a relay but you specified a "
@@ -3570,15 +3362,14 @@ test_options_validate__transport(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ServerTransportPlugin foo exec bar\n"
+ tdata = get_options_test_data("ServerTransportPlugin foo exec bar\n"
"ORPort 127.0.0.1:5555\n"
"BandwidthRate 76900\n"
"BandwidthBurst 76900\n"
"MaxAdvertisedBandwidth 38500\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"Tor is not configured as a relay but you specified a "
@@ -3587,22 +3378,19 @@ test_options_validate__transport(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ServerTransportListenAddr foo 127.0.0.42:55\n"
- "ServerTransportListenAddr !\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("ServerTransportListenAddr foo 127.0.0.42:55\n"
+ "ServerTransportListenAddr !\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"ServerTransportListenAddr did not parse. See logs for details.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ServerTransportListenAddr foo 127.0.0.42:55\n"
+ tdata = get_options_test_data("ServerTransportListenAddr foo 127.0.0.42:55\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg(
"You need at least a single managed-proxy to specify a transport "
@@ -3611,8 +3399,7 @@ test_options_validate__transport(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ServerTransportListenAddr foo 127.0.0.42:55\n"
+ tdata = get_options_test_data("ServerTransportListenAddr foo 127.0.0.42:55\n"
"ServerTransportPlugin foo exec bar\n"
"ORPort 127.0.0.1:5555\n"
"BandwidthRate 76900\n"
@@ -3620,7 +3407,7 @@ test_options_validate__transport(void *ignored)
"MaxAdvertisedBandwidth 38500\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"You need at least a single managed-proxy to specify a transport "
@@ -3645,50 +3432,46 @@ test_options_validate__constrained_sockets(void *ignored)
setup_capture_of_logs(LOG_WARN);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ConstrainedSockets 1\n"
+ tdata = get_options_test_data("ConstrainedSockets 1\n"
"ConstrainedSockSize 0\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "ConstrainedSockSize is invalid. Must be a value "
"between 2048 and 262144 in 1024 byte increments.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ConstrainedSockets 1\n"
+ tdata = get_options_test_data("ConstrainedSockets 1\n"
"ConstrainedSockSize 263168\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "ConstrainedSockSize is invalid. Must be a value "
"between 2048 and 262144 in 1024 byte increments.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ConstrainedSockets 1\n"
+ tdata = get_options_test_data("ConstrainedSockets 1\n"
"ConstrainedSockSize 2047\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "ConstrainedSockSize is invalid. Must be a value "
"between 2048 and 262144 in 1024 byte increments.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ConstrainedSockets 1\n"
+ tdata = get_options_test_data("ConstrainedSockets 1\n"
"ConstrainedSockSize 2048\n"
"DirPort 999\n"
"DirCache 1\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg("You have requested constrained "
"socket buffers while also serving directory entries via DirPort."
@@ -3697,12 +3480,11 @@ test_options_validate__constrained_sockets(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ConstrainedSockets 1\n"
+ tdata = get_options_test_data("ConstrainedSockets 1\n"
"ConstrainedSockSize 2048\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"You have requested constrained socket buffers while also serving"
@@ -3728,12 +3510,12 @@ test_options_validate__v3_auth(void *ignored)
setup_capture_of_logs(LOG_WARN);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"V3AuthVoteDelay 1000\n"
"V3AuthDistDelay 1000\n"
"V3AuthVotingInterval 1000\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"V3AuthVoteDelay plus V3AuthDistDelay must be less than half "
@@ -3741,20 +3523,18 @@ test_options_validate__v3_auth(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "V3AuthVoteDelay 1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ "V3AuthVoteDelay 1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "V3AuthVoteDelay is way too low.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"V3AuthVoteDelay 1\n"
- "TestingTorNetwork 1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ "TestingTorNetwork 1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "V3AuthVoteDelay is way too low.");
tor_free(msg);
@@ -3764,87 +3544,127 @@ test_options_validate__v3_auth(void *ignored)
// since they are the same
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "V3AuthDistDelay 1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ "V3AuthDistDelay 1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "V3AuthDistDelay is way too low.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"V3AuthDistDelay 1\n"
"TestingTorNetwork 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "V3AuthDistDelay is way too low.");
tor_free(msg);
- // TODO: we can't reach the case of v3authdistdelay lower than
+ // We can't reach the case of v3authdistdelay lower than
// MIN_DIST_SECONDS but not lower than MIN_DIST_SECONDS_TESTING,
// since they are the same
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"V3AuthNIntervalsValid 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "V3AuthNIntervalsValid must be at least 2.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"V3AuthVoteDelay 49\n"
"V3AuthDistDelay 49\n"
"V3AuthVotingInterval 200\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "V3AuthVotingInterval is insanely low.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ VALID_DIR_AUTH
+ "TestingTorNetwork 1\n"
+ "V3AuthVoteDelay 49\n"
+ "V3AuthDistDelay 49\n"
+ "V3AuthVotingInterval 200\n"
+ );
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_ptr_op(msg, OP_EQ, NULL);
+ tor_free(msg);
+
+ free_options_test_data(tdata);
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ VALID_DIR_AUTH
+ "TestingTorNetwork 1\n"
+ "V3AuthVoteDelay 2\n"
+ "V3AuthDistDelay 2\n"
+ "V3AuthVotingInterval 9\n"
+ );
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, -1);
+ tt_str_op(msg, OP_EQ,
+ "V3AuthVoteDelay plus V3AuthDistDelay must be less than half "
+ "V3AuthVotingInterval");
+ tor_free(msg);
+
+ free_options_test_data(tdata);
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ VALID_DIR_AUTH
+ "TestingTorNetwork 1\n"
+ "V3AuthVoteDelay 2\n"
+ "V3AuthDistDelay 2\n"
+ "V3AuthVotingInterval 10\n"
+ );
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_ptr_op(msg, OP_EQ, NULL);
+ tor_free(msg);
+
+ free_options_test_data(tdata);
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"V3AuthVoteDelay 49\n"
"V3AuthDistDelay 49\n"
"V3AuthVotingInterval 200000\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "V3AuthVotingInterval is insanely high.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"V3AuthVoteDelay 49\n"
"V3AuthDistDelay 49\n"
"V3AuthVotingInterval 1441\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg("V3AuthVotingInterval does not divide"
" evenly into 24 hours.\n");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"V3AuthVoteDelay 49\n"
"V3AuthDistDelay 49\n"
"V3AuthVotingInterval 1440\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg("V3AuthVotingInterval does not divide"
" evenly into 24 hours.\n");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"V3AuthVoteDelay 49\n"
"V3AuthDistDelay 49\n"
"V3AuthVotingInterval 299\n"
@@ -3852,84 +3672,125 @@ test_options_validate__v3_auth(void *ignored)
"TestingTorNetwork 1\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg("V3AuthVotingInterval is very low. "
"This may lead to failure to synchronise for a consensus.\n");
tor_free(msg);
- // TODO: It is impossible to reach the case of testingtor network, with
- // v3authvotinginterval too low
- /* free_options_test_data(tdata); */
- /* tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES */
- /* "V3AuthVoteDelay 1\n" */
- /* "V3AuthDistDelay 1\n" */
- /* "V3AuthVotingInterval 9\n" */
- /* VALID_DIR_AUTH */
- /* "TestingTorNetwork 1\n" */
- /* ); */
- /* ret = options_validate(tdata->old_opt, tdata->opt, */
- /* tdata->def_opt, 0, &msg); */
- /* tt_int_op(ret, OP_EQ, -1); */
- /* tt_str_op(msg, OP_EQ, "V3AuthVotingInterval is insanely low."); */
+ free_options_test_data(tdata);
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ "V3AuthVoteDelay 1\n"
+ "V3AuthDistDelay 1\n"
+ "V3AuthVotingInterval 9\n"
+ VALID_DIR_AUTH
+ "TestingTorNetwork 1\n"
+ );
+ /* We have to call the dirauth-specific function to reach this case */
+ ret = options_validate_dirauth_schedule(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, -1);
+ tt_str_op(msg, OP_EQ, "V3AuthVoteDelay is way too low.");
+ tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"TestingV3AuthInitialVoteDelay 1\n"
VALID_DIR_AUTH
"TestingTorNetwork 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "TestingV3AuthInitialVoteDelay is way too low.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"TestingV3AuthInitialDistDelay 1\n"
VALID_DIR_AUTH
"TestingTorNetwork 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "TestingV3AuthInitialDistDelay is way too low.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
VALID_DIR_AUTH
"TestingTorNetwork 1\n"
);
tdata->opt->TestingV3AuthVotingStartOffset = 100000;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "TestingV3AuthVotingStartOffset is higher than the "
"voting interval.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
VALID_DIR_AUTH
"TestingTorNetwork 1\n"
);
tdata->opt->TestingV3AuthVotingStartOffset = -1;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"TestingV3AuthVotingStartOffset must be non-negative.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
VALID_DIR_AUTH
"TestingTorNetwork 1\n"
"TestingV3AuthInitialVotingInterval 4\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "TestingV3AuthInitialVotingInterval is insanely low.");
tor_free(msg);
+ free_options_test_data(tdata);
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ VALID_DIR_AUTH
+ "TestingTorNetwork 1\n"
+ "TestingV3AuthInitialVoteDelay 2\n"
+ "TestingV3AuthInitialDistDelay 2\n"
+ "TestingV3AuthInitialVotingInterval 5\n"
+ );
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_ptr_op(msg, OP_EQ, NULL);
+ tor_free(msg);
+
+ free_options_test_data(tdata);
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ VALID_DIR_AUTH
+ "TestingTorNetwork 1\n"
+ "TestingV3AuthInitialVotingInterval 7\n"
+ );
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, -1);
+ tt_str_op(msg, OP_EQ,
+ "TestingV3AuthInitialVotingInterval does not divide evenly into "
+ "30 minutes.");
+ tor_free(msg);
+
+ free_options_test_data(tdata);
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ VALID_DIR_AUTH
+ "TestingTorNetwork 1\n"
+ "TestingV3AuthInitialVoteDelay 3\n"
+ "TestingV3AuthInitialDistDelay 3\n"
+ "TestingV3AuthInitialVotingInterval 5\n"
+ );
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, -1);
+ tt_str_op(msg, OP_EQ,
+ "TestingV3AuthInitialVoteDelay plus "
+ "TestingV3AuthInitialDistDelay must be less than "
+ "TestingV3AuthInitialVotingInterval");
+ tor_free(msg);
+
done:
policies_free_all();
teardown_capture_of_logs();
@@ -3946,19 +3807,16 @@ test_options_validate__virtual_addr(void *ignored)
options_test_data_t *tdata = NULL;
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "VirtualAddrNetworkIPv4 !!"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("VirtualAddrNetworkIPv4 !!");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Error parsing VirtualAddressNetwork !!");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "VirtualAddrNetworkIPv6 !!"
+ tdata = get_options_test_data("VirtualAddrNetworkIPv6 !!"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Error parsing VirtualAddressNetworkIPv6 !!");
tor_free(msg);
@@ -3979,135 +3837,133 @@ test_options_validate__testing_options(void *ignored)
options_test_data_t *tdata = NULL;
setup_capture_of_logs(LOG_WARN);
-#define TEST_TESTING_OPTION(name, low_val, high_val, err_low) \
+#define TEST_TESTING_OPTION(name, accessor, \
+ low_val, high_val, err_low, EXTRA_OPT_STR) \
STMT_BEGIN \
free_options_test_data(tdata); \
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES \
+ tdata = get_options_test_data(EXTRA_OPT_STR \
VALID_DIR_AUTH \
"TestingTorNetwork 1\n" \
); \
- tdata->opt-> name = low_val; \
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\
+ accessor(tdata->opt)->name = low_val; \
+ ret = options_validate(NULL, tdata->opt, &msg); \
tt_int_op(ret, OP_EQ, -1); \
tt_str_op(msg, OP_EQ, #name " " err_low); \
tor_free(msg); \
\
free_options_test_data(tdata); \
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES \
+ tdata = get_options_test_data(EXTRA_OPT_STR \
VALID_DIR_AUTH \
"TestingTorNetwork 1\n" \
); \
- tdata->opt-> name = high_val; \
+ accessor(tdata->opt)->name = high_val; \
mock_clean_saved_logs(); \
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\
+ ret = options_validate(NULL, tdata->opt, &msg); \
tt_int_op(ret, OP_EQ, 0); \
+ tt_ptr_op(msg, OP_EQ, NULL); \
expect_log_msg( #name " is insanely high.\n"); \
tor_free(msg); \
STMT_END
- TEST_TESTING_OPTION(TestingAuthDirTimeToLearnReachability, -1, 8000,
- "must be non-negative.");
- TEST_TESTING_OPTION(TestingEstimatedDescriptorPropagationTime, -1, 3601,
- "must be non-negative.");
- TEST_TESTING_OPTION(TestingClientMaxIntervalWithoutRequest, -1, 3601,
- "is way too low.");
- TEST_TESTING_OPTION(TestingDirConnectionMaxStall, 1, 3601,
- "is way too low.");
+ TEST_TESTING_OPTION(TestingClientMaxIntervalWithoutRequest, , -1, 3601,
+ "is way too low.", "");
+ TEST_TESTING_OPTION(TestingDirConnectionMaxStall, , 1, 3601,
+ "is way too low.", "");
+
+ TEST_TESTING_OPTION(TestingClientMaxIntervalWithoutRequest, , -1, 3601,
+ "is way too low.", ENABLE_AUTHORITY_V3);
+ TEST_TESTING_OPTION(TestingDirConnectionMaxStall, , 1, 3601,
+ "is way too low.", ENABLE_AUTHORITY_V3);
+
+ TEST_TESTING_OPTION(TestingClientMaxIntervalWithoutRequest, , -1, 3601,
+ "is way too low.", ENABLE_AUTHORITY_BRIDGE);
+ TEST_TESTING_OPTION(TestingDirConnectionMaxStall, , 1, 3601,
+ "is way too low.", ENABLE_AUTHORITY_BRIDGE);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingEnableConnBwEvent 1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("TestingEnableConnBwEvent 1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "TestingEnableConnBwEvent may only be changed in "
"testing Tor networks!");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingEnableConnBwEvent 1\n"
+ tdata = get_options_test_data("TestingEnableConnBwEvent 1\n"
VALID_DIR_AUTH
"TestingTorNetwork 1\n"
"___UsingTestNetworkDefaults 0\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_assert(!msg);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingEnableConnBwEvent 1\n"
+ tdata = get_options_test_data("TestingEnableConnBwEvent 1\n"
VALID_DIR_AUTH
"TestingTorNetwork 0\n"
"___UsingTestNetworkDefaults 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_assert(!msg);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingEnableCellStatsEvent 1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("TestingEnableCellStatsEvent 1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "TestingEnableCellStatsEvent may only be changed in "
"testing Tor networks!");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingEnableCellStatsEvent 1\n"
+ tdata = get_options_test_data("TestingEnableCellStatsEvent 1\n"
VALID_DIR_AUTH
"TestingTorNetwork 1\n"
"___UsingTestNetworkDefaults 0\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_assert(!msg);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingEnableCellStatsEvent 1\n"
+ tdata = get_options_test_data("TestingEnableCellStatsEvent 1\n"
VALID_DIR_AUTH
"TestingTorNetwork 0\n"
"___UsingTestNetworkDefaults 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_assert(!msg);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingEnableTbEmptyEvent 1\n"
+ tdata = get_options_test_data("TestingEnableTbEmptyEvent 1\n"
VALID_DIR_AUTH
"TestingTorNetwork 1\n"
"___UsingTestNetworkDefaults 0\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_assert(!msg);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingEnableTbEmptyEvent 1\n"
+ tdata = get_options_test_data("TestingEnableTbEmptyEvent 1\n"
VALID_DIR_AUTH
"TestingTorNetwork 0\n"
"___UsingTestNetworkDefaults 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_assert(!msg);
tor_free(msg);
@@ -4128,40 +3984,32 @@ test_options_validate__accel(void *ignored)
options_test_data_t *tdata = NULL;
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "AccelName foo\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("AccelName foo\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
- tt_int_op(tdata->opt->HardwareAccel, OP_EQ, 1);
+ tt_int_op(get_crypto_options(tdata->opt)->HardwareAccel, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "AccelName foo\n"
- );
- tdata->opt->HardwareAccel = 2;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("AccelName foo\n");
+ get_crypto_options(tdata->opt)->HardwareAccel = 2;
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
- tt_int_op(tdata->opt->HardwareAccel, OP_EQ, 2);
+ tt_int_op(get_crypto_options(tdata->opt)->HardwareAccel, OP_EQ, 2);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "AccelDir 1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("AccelDir 1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Can't use hardware crypto accelerator dir without engine name.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "AccelDir 1\n"
- "AccelName something\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("AccelDir 1\n"
+ "AccelName something\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
@@ -4171,8 +4019,280 @@ test_options_validate__accel(void *ignored)
tor_free(msg);
}
+static int mocked_granularity;
+
+static void
+mock_set_log_time_granularity(int g)
+{
+ mocked_granularity = g;
+}
+
+static void
+test_options_init_logs_granularity(void *arg)
+{
+ options_test_data_t *tdata = get_options_test_data("");
+ int rv;
+ (void) arg;
+
+ MOCK(set_log_time_granularity, mock_set_log_time_granularity);
+
+ /* Reasonable value. */
+ tdata->opt->LogTimeGranularity = 100;
+ mocked_granularity = -1;
+ rv = options_init_logs(NULL, tdata->opt, 0);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_int_op(mocked_granularity, OP_EQ, 100);
+
+ /* Doesn't divide 1000. */
+ tdata->opt->LogTimeGranularity = 249;
+ mocked_granularity = -1;
+ rv = options_init_logs(NULL, tdata->opt, 0);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_int_op(mocked_granularity, OP_EQ, 250);
+
+ /* Doesn't divide 1000. */
+ tdata->opt->LogTimeGranularity = 3;
+ mocked_granularity = -1;
+ rv = options_init_logs(NULL, tdata->opt, 0);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_int_op(mocked_granularity, OP_EQ, 4);
+
+ /* Not a multiple of 1000. */
+ tdata->opt->LogTimeGranularity = 1500;
+ mocked_granularity = -1;
+ rv = options_init_logs(NULL, tdata->opt, 0);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_int_op(mocked_granularity, OP_EQ, 2000);
+
+ /* Reasonable value. */
+ tdata->opt->LogTimeGranularity = 3000;
+ mocked_granularity = -1;
+ rv = options_init_logs(NULL, tdata->opt, 0);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_int_op(mocked_granularity, OP_EQ, 3000);
+
+ /* Negative. (Shouldn't be allowed by rest of config parsing.) */
+ tdata->opt->LogTimeGranularity = -1;
+ mocked_granularity = -1;
+ rv = options_init_logs(NULL, tdata->opt, 0);
+ tt_int_op(rv, OP_EQ, -1);
+
+ /* Very big */
+ tdata->opt->LogTimeGranularity = 3600 * 1000;
+ mocked_granularity = -1;
+ rv = options_init_logs(NULL, tdata->opt, 0);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_int_op(mocked_granularity, OP_EQ, 3600 * 1000);
+
+ done:
+ free_options_test_data(tdata);
+ UNMOCK(set_log_time_granularity);
+}
+
+typedef struct {
+ char *name;
+ log_severity_list_t sev;
+ int fd;
+ bool stream;
+} added_log_t;
+
+static smartlist_t *added_logs = NULL;
+
+static void
+mock_add_stream_log_impl(const log_severity_list_t *sev, const char *name,
+ int fd)
+{
+ added_log_t *a = tor_malloc_zero(sizeof(added_log_t));
+ a->name = tor_strdup(name);
+ memcpy(&a->sev, sev, sizeof(log_severity_list_t));
+ a->fd = fd;
+ a->stream = true;
+ smartlist_add(added_logs, a);
+}
+
+static int
+mock_add_file_log(const log_severity_list_t *sev, const char *name, int fd)
+{
+ added_log_t *a = tor_malloc_zero(sizeof(added_log_t));
+ a->name = tor_strdup(name);
+ memcpy(&a->sev, sev, sizeof(log_severity_list_t));
+ a->fd = fd;
+ smartlist_add(added_logs, a);
+ return 0;
+}
+
+static void
+clear_added_logs(void)
+{
+ SMARTLIST_FOREACH(added_logs, added_log_t *, a,
+ { tor_free(a->name); tor_free(a); });
+ smartlist_clear(added_logs);
+}
+
+static void
+test_options_init_logs_quiet(void *arg)
+{
+ (void)arg;
+ char *cfg = NULL;
+ options_test_data_t *tdata = get_options_test_data("");
+ char *fn1 = tor_strdup(get_fname_rnd("log"));
+ const added_log_t *a;
+ int rv;
+ tdata->opt->RunAsDaemon = 0;
+
+ added_logs = smartlist_new();
+ MOCK(add_stream_log_impl, mock_add_stream_log_impl);
+ MOCK(add_file_log, mock_add_file_log);
+
+ tt_ptr_op(tdata->opt->Logs, OP_EQ, NULL);
+
+ /* First, try with no configured logs, and make sure that our configured
+ logs match the quiet level. */
+ quiet_level = QUIET_SILENT;
+ rv = options_init_logs(NULL, tdata->opt, 0);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_int_op(smartlist_len(added_logs), OP_EQ, 0);
+
+ quiet_level = QUIET_HUSH;
+ rv = options_init_logs(NULL, tdata->opt, 0);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_int_op(smartlist_len(added_logs), OP_EQ, 1);
+ a = smartlist_get(added_logs, 0);
+ tt_assert(a);
+ tt_assert(a->stream);
+ tt_int_op(a->fd, OP_EQ, fileno(stdout));
+ tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_INFO)], OP_EQ, 0);
+ tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_NOTICE)], OP_EQ, 0);
+ tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_WARN)], OP_EQ, LD_ALL_DOMAINS);
+ clear_added_logs();
+
+ quiet_level = QUIET_NONE;
+ rv = options_init_logs(NULL, tdata->opt, 0);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_int_op(smartlist_len(added_logs), OP_EQ, 1);
+ a = smartlist_get(added_logs, 0);
+ tt_assert(a);
+ tt_assert(a->stream);
+ tt_int_op(a->fd, OP_EQ, fileno(stdout));
+ tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_INFO)], OP_EQ, 0);
+ tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_NOTICE)], OP_EQ,
+ LD_ALL_DOMAINS);
+ tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_WARN)], OP_EQ, LD_ALL_DOMAINS);
+ clear_added_logs();
+
+ /* Make sure that adding a configured log makes the default logs go away. */
+ tor_asprintf(&cfg, "Log info file %s\n", fn1);
+ free_options_test_data(tdata);
+ tdata = get_options_test_data(cfg);
+ rv = options_init_logs(NULL, tdata->opt, 0);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_int_op(smartlist_len(added_logs), OP_EQ, 1);
+ a = smartlist_get(added_logs, 0);
+ tt_assert(a);
+ tt_assert(! a->stream);
+ tt_int_op(a->fd, OP_NE, fileno(stdout));
+ tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_INFO)], OP_EQ, LD_ALL_DOMAINS);
+ tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_NOTICE)], OP_EQ,
+ LD_ALL_DOMAINS);
+ tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_WARN)], OP_EQ, LD_ALL_DOMAINS);
+
+ done:
+ free_options_test_data(tdata);
+ tor_free(fn1);
+ tor_free(cfg);
+ clear_added_logs();
+ smartlist_free(added_logs);
+ UNMOCK(add_stream_log_impl);
+ UNMOCK(add_file_log);
+}
+
+static int mock_options_act_status = 0;
+static int
+mock_options_act(const or_options_t *old_options)
+{
+ (void)old_options;
+ return mock_options_act_status;
+}
+static int
+mock_options_act_reversible(const or_options_t *old_options, char **msg_out)
+{
+ (void)old_options;
+ (void)msg_out;
+ return 0;
+}
+
+static void
+test_options_trial_assign(void *arg)
+{
+ (void)arg;
+ setopt_err_t v;
+ config_line_t *lines = NULL;
+ char *msg = NULL;
+ int r;
+
+ // replace options_act*() so that we don't actually launch tor here.
+ MOCK(options_act, mock_options_act);
+ MOCK(options_act_reversible, mock_options_act_reversible);
+
+ // Try assigning nothing; that should work.
+ v = options_trial_assign(lines, 0, &msg);
+ if (msg)
+ puts(msg);
+ tt_ptr_op(msg, OP_EQ, NULL);
+ tt_int_op(v, OP_EQ, SETOPT_OK);
+
+ // Assigning a nickname is okay
+ r = config_get_lines("Nickname Hemiramphinae", &lines, 0);
+ tt_int_op(r, OP_EQ, 0);
+ v = options_trial_assign(lines, 0, &msg);
+ tt_ptr_op(msg, OP_EQ, NULL);
+ tt_int_op(v, OP_EQ, SETOPT_OK);
+ tt_str_op(get_options()->Nickname, OP_EQ, "Hemiramphinae");
+ config_free_lines(lines);
+
+ // We can't change the User; that's a transition error.
+ r = config_get_lines("User Heraclitus", &lines, 0);
+ tt_int_op(r, OP_EQ, 0);
+ v = options_trial_assign(lines, 0, &msg);
+ tt_int_op(v, OP_EQ, SETOPT_ERR_TRANSITION);
+ tt_str_op(msg, OP_EQ, "While Tor is running, changing User is not allowed");
+ tor_free(msg);
+ config_free_lines(lines);
+
+ // We can't set the ORPort to nonsense: that's a validation error.
+ r = config_get_lines("ORPort fractabling planished", &lines, 0);
+ tt_int_op(r, OP_EQ, 0);
+ v = options_trial_assign(lines, 0, &msg);
+ tt_int_op(v, OP_EQ, SETOPT_ERR_PARSE); // (same error code for now)
+ tt_str_op(msg, OP_EQ, "Invalid ORPort configuration");
+ tor_free(msg);
+ config_free_lines(lines);
+
+ // We can't set UseBridges to a non-boolean: that's a parse error.
+ r = config_get_lines("UseBridges ambidextrous", &lines, 0);
+ tt_int_op(r, OP_EQ, 0);
+ v = options_trial_assign(lines, 0, &msg);
+ tt_int_op(v, OP_EQ, SETOPT_ERR_PARSE);
+ tt_str_op(msg, OP_EQ,
+ "Could not parse UseBridges: Unrecognized value ambidextrous. "
+ "Allowed values are 0 and 1.");
+ tor_free(msg);
+ config_free_lines(lines);
+
+ // this didn't change.
+ tt_str_op(get_options()->Nickname, OP_EQ, "Hemiramphinae");
+
+ done:
+ config_free_lines(lines);
+ tor_free(msg);
+ UNMOCK(options_act);
+ UNMOCK(options_act_reversible);
+}
+
+#ifndef COCCI
#define LOCAL_VALIDATE_TEST(name) \
{ "validate__" #name, test_options_validate__ ## name, TT_FORK, NULL, NULL }
+#endif
struct testcase_t options_tests[] = {
{ "validate", test_options_validate, TT_FORK, NULL, NULL },
@@ -4185,6 +4305,7 @@ struct testcase_t options_tests[] = {
LOCAL_VALIDATE_TEST(logs),
LOCAL_VALIDATE_TEST(authdir),
LOCAL_VALIDATE_TEST(relay_with_hidden_services),
+ LOCAL_VALIDATE_TEST(listen_ports),
LOCAL_VALIDATE_TEST(transproxy),
LOCAL_VALIDATE_TEST(exclude_nodes),
LOCAL_VALIDATE_TEST(node_families),
@@ -4218,5 +4339,10 @@ struct testcase_t options_tests[] = {
LOCAL_VALIDATE_TEST(virtual_addr),
LOCAL_VALIDATE_TEST(testing_options),
LOCAL_VALIDATE_TEST(accel),
+ { "init_logs/granularity", test_options_init_logs_granularity, TT_FORK,
+ NULL, NULL },
+ { "init_logs/quiet", test_options_init_logs_quiet, TT_FORK,
+ NULL, NULL },
+ { "trial_assign", test_options_trial_assign, TT_FORK, NULL, NULL },
END_OF_TESTCASES /* */
};
diff --git a/src/test/test_options_act.c b/src/test/test_options_act.c
new file mode 100644
index 0000000000..942584bffd
--- /dev/null
+++ b/src/test/test_options_act.c
@@ -0,0 +1,272 @@
+/* Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define CONFIG_PRIVATE
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "lib/encoding/confline.h"
+
+#include "test/test.h"
+#include "test/log_test_helpers.h"
+#include "test/test_helpers.h"
+
+#ifndef _WIN32
+#include <sys/stat.h>
+
+/**
+ * Check whether fname is readable. On success set
+ * *<b>is_group_readable_out</b> to as appropriate and return 0. On failure
+ * return -1.
+ */
+static int
+get_file_mode(const char *fname, unsigned *permissions_out)
+{
+ struct stat st;
+ int r = stat(fname, &st);
+ if (r < 0)
+ return -1;
+ *permissions_out = (unsigned) st.st_mode;
+ return 0;
+}
+#define assert_mode(fn,mask,expected) STMT_BEGIN \
+ unsigned mode_; \
+ int tmp_ = get_file_mode((fn), &mode_); \
+ if (tmp_ < 0) { \
+ TT_DIE(("Couldn't stat %s: %s", (fn), strerror(errno))); \
+ } \
+ if ((mode_ & (mask)) != (expected)) { \
+ TT_DIE(("Bad mode %o on %s", mode_, (fn))); \
+ } \
+ STMT_END
+#else /* defined(_WIN32) */
+/* "group-readable" isn't meaningful on windows */
+#define assert_mode(fn,mask,expected) STMT_NIL
+#endif /* !defined(_WIN32) */
+
+static or_options_t *mock_opts;
+static const or_options_t *
+mock_get_options(void)
+{
+ return mock_opts;
+}
+
+static void
+test_options_act_create_dirs(void *arg)
+{
+ (void)arg;
+ MOCK(get_options, mock_get_options);
+ char *msg = NULL;
+ or_options_t *opts = mock_opts = options_new();
+
+ /* We're testing options_create_directories(), which assumes that
+ validate_data_directories() has already been called, and all of
+ KeyDirectory, DataDirectory, and CacheDirectory are set. */
+
+ /* Success case 1: all directories are the default */
+ char *fn;
+ fn = tor_strdup(get_fname_rnd("ddir"));
+ opts->DataDirectory = tor_strdup(fn);
+ opts->CacheDirectory = tor_strdup(fn);
+ tor_asprintf(&opts->KeyDirectory, "%s/keys", fn);
+ opts->DataDirectoryGroupReadable = 1;
+ opts->CacheDirectoryGroupReadable = -1; /* default. */
+ int r = options_create_directories(&msg);
+ tt_int_op(r, OP_EQ, 0);
+ tt_ptr_op(msg, OP_EQ, NULL);
+ tt_int_op(FN_DIR, OP_EQ, file_status(opts->DataDirectory));
+ tt_int_op(FN_DIR, OP_EQ, file_status(opts->CacheDirectory));
+ tt_int_op(FN_DIR, OP_EQ, file_status(opts->KeyDirectory));
+ assert_mode(opts->DataDirectory, 0777, 0750);
+ assert_mode(opts->KeyDirectory, 0777, 0700);
+ tor_free(fn);
+ tor_free(opts->KeyDirectory);
+ or_options_free(opts);
+
+ /* Success case 2: all directories are different. */
+ opts = mock_opts = options_new();
+ opts->DataDirectory = tor_strdup(get_fname_rnd("ddir"));
+ opts->CacheDirectory = tor_strdup(get_fname_rnd("cdir"));
+ opts->KeyDirectory = tor_strdup(get_fname_rnd("kdir"));
+ opts->CacheDirectoryGroupReadable = 1; // cache directory group readable
+ r = options_create_directories(&msg);
+ tt_int_op(r, OP_EQ, 0);
+ tt_ptr_op(msg, OP_EQ, NULL);
+ tt_int_op(FN_DIR, OP_EQ, file_status(opts->DataDirectory));
+ tt_int_op(FN_DIR, OP_EQ, file_status(opts->CacheDirectory));
+ tt_int_op(FN_DIR, OP_EQ, file_status(opts->KeyDirectory));
+ assert_mode(opts->DataDirectory, 0777, 0700);
+ assert_mode(opts->KeyDirectory, 0777, 0700);
+ assert_mode(opts->CacheDirectory, 0777, 0750);
+ tor_free(fn);
+ or_options_free(opts);
+
+ /* Success case 3: all directories are the same. */
+ opts = mock_opts = options_new();
+ fn = tor_strdup(get_fname_rnd("ddir"));
+ opts->DataDirectory = tor_strdup(fn);
+ opts->CacheDirectory = tor_strdup(fn);
+ opts->KeyDirectory = tor_strdup(fn);
+ opts->DataDirectoryGroupReadable = 1;
+ opts->CacheDirectoryGroupReadable = -1; /* default. */
+ opts->KeyDirectoryGroupReadable = -1; /* default */
+ r = options_create_directories(&msg);
+ tt_int_op(r, OP_EQ, 0);
+ tt_ptr_op(msg, OP_EQ, NULL);
+ tt_int_op(FN_DIR, OP_EQ, file_status(opts->DataDirectory));
+ tt_int_op(FN_DIR, OP_EQ, file_status(opts->CacheDirectory));
+ tt_int_op(FN_DIR, OP_EQ, file_status(opts->KeyDirectory));
+ assert_mode(opts->DataDirectory, 0777, 0750);
+ assert_mode(opts->KeyDirectory, 0777, 0750);
+ assert_mode(opts->CacheDirectory, 0777, 0750);
+ tor_free(fn);
+ or_options_free(opts);
+
+ /* Failure case 1: Can't make datadir. */
+ opts = mock_opts = options_new();
+ opts->DataDirectory = tor_strdup(get_fname_rnd("ddir"));
+ opts->CacheDirectory = tor_strdup(get_fname_rnd("cdir"));
+ opts->KeyDirectory = tor_strdup(get_fname_rnd("kdir"));
+ write_str_to_file(opts->DataDirectory, "foo", 0);
+ r = options_create_directories(&msg);
+ tt_int_op(r, OP_LT, 0);
+ tt_assert(!strcmpstart(msg, "Couldn't create private data directory"));
+ or_options_free(opts);
+ tor_free(msg);
+
+ /* Failure case 2: Can't make keydir. */
+ opts = mock_opts = options_new();
+ opts->DataDirectory = tor_strdup(get_fname_rnd("ddir"));
+ opts->CacheDirectory = tor_strdup(get_fname_rnd("cdir"));
+ opts->KeyDirectory = tor_strdup(get_fname_rnd("kdir"));
+ write_str_to_file(opts->KeyDirectory, "foo", 0);
+ r = options_create_directories(&msg);
+ tt_int_op(r, OP_LT, 0);
+ tt_assert(!strcmpstart(msg, "Couldn't create private data directory"));
+ or_options_free(opts);
+ tor_free(msg);
+
+ /* Failure case 3: Can't make cachedir. */
+ opts = mock_opts = options_new();
+ opts->DataDirectory = tor_strdup(get_fname_rnd("ddir"));
+ opts->CacheDirectory = tor_strdup(get_fname_rnd("cdir"));
+ opts->KeyDirectory = tor_strdup(get_fname_rnd("kdir"));
+ write_str_to_file(opts->CacheDirectory, "foo", 0);
+ r = options_create_directories(&msg);
+ tt_int_op(r, OP_LT, 0);
+ tt_assert(!strcmpstart(msg, "Couldn't create private data directory"));
+ tor_free(fn);
+ or_options_free(opts);
+ tor_free(msg);
+
+ done:
+ UNMOCK(get_options);
+ or_options_free(opts);
+ mock_opts = NULL;
+ tor_free(fn);
+ tor_free(msg);
+}
+
+static void
+test_options_act_log_transition(void *arg)
+{
+ (void)arg;
+ or_options_t *opts = mock_opts = options_new();
+ or_options_t *old_opts = NULL;
+ opts->LogTimeGranularity = 1000;
+ opts->SafeLogging_ = SAFELOG_SCRUB_ALL;
+ struct log_transaction_t *lt = NULL;
+ char *msg = NULL;
+ MOCK(get_options, mock_get_options);
+
+ tt_ptr_op(opts->Logs, OP_EQ, NULL);
+ config_line_append(&opts->Logs, "Log", "notice stdout");
+ lt = options_start_log_transaction(NULL, &msg);
+ tt_assert(lt);
+ tt_assert(!msg);
+
+ // commit, see that there is a change.
+ options_commit_log_transaction(lt);
+ lt=NULL;
+ tt_int_op(get_min_log_level(), OP_EQ, LOG_NOTICE);
+
+ // Now drop to debug.
+ old_opts = opts;
+ opts = mock_opts = options_new();
+ opts->LogTimeGranularity = 1000;
+ opts->SafeLogging_ = SAFELOG_SCRUB_ALL;
+ config_line_append(&opts->Logs, "Log", "debug stdout");
+ lt = options_start_log_transaction(old_opts, &msg);
+ tt_assert(lt);
+ tt_assert(!msg);
+
+ setup_full_capture_of_logs(LOG_NOTICE);
+ options_commit_log_transaction(lt);
+ lt=NULL;
+ expect_single_log_msg_containing("may contain sensitive information");
+ tt_int_op(get_min_log_level(), OP_EQ, LOG_DEBUG);
+
+ // Turn off SafeLogging
+ or_options_free(old_opts);
+ mock_clean_saved_logs();
+ old_opts = opts;
+ opts = mock_opts = options_new();
+ opts->SafeLogging_ = SAFELOG_SCRUB_NONE;
+ opts->LogTimeGranularity = 1000;
+ config_line_append(&opts->Logs, "Log", "debug stdout");
+ lt = options_start_log_transaction(old_opts, &msg);
+ tt_assert(lt);
+ tt_assert(!msg);
+ options_commit_log_transaction(lt);
+ lt=NULL;
+ expect_single_log_msg_containing("may contain sensitive information");
+ tt_int_op(get_min_log_level(), OP_EQ, LOG_DEBUG);
+
+ // Try rolling back.
+ or_options_free(old_opts);
+ mock_clean_saved_logs();
+ old_opts = opts;
+ opts = mock_opts = options_new();
+ opts->SafeLogging_ = SAFELOG_SCRUB_NONE;
+ opts->LogTimeGranularity = 1000;
+ config_line_append(&opts->Logs, "Log", "notice stdout");
+ lt = options_start_log_transaction(old_opts, &msg);
+ tt_assert(lt);
+ tt_assert(!msg);
+ options_rollback_log_transaction(lt);
+ expect_no_log_entry();
+ lt = NULL;
+ tt_int_op(get_min_log_level(), OP_EQ, LOG_DEBUG);
+
+ // Now try some bad options.
+ or_options_free(opts);
+ mock_clean_saved_logs();
+ opts = mock_opts = options_new();
+ opts->LogTimeGranularity = 1000;
+ config_line_append(&opts->Logs, "Log", "warn blaznert");
+ lt = options_start_log_transaction(old_opts, &msg);
+ tt_assert(!lt);
+ tt_str_op(msg, OP_EQ, "Failed to init Log options. See logs for details.");
+ expect_single_log_msg_containing("Couldn't parse");
+ tt_int_op(get_min_log_level(), OP_EQ, LOG_DEBUG);
+
+ done:
+ UNMOCK(get_options);
+ or_options_free(opts);
+ or_options_free(old_opts);
+ tor_free(msg);
+ if (lt)
+ options_rollback_log_transaction(lt);
+ teardown_capture_of_logs();
+}
+
+#ifndef COCCI
+#define T(name) { #name, test_options_act_##name, TT_FORK, NULL, NULL }
+#endif
+
+struct testcase_t options_act_tests[] = {
+ T(create_dirs),
+ T(log_transition),
+ END_OF_TESTCASES
+};
diff --git a/src/test/test_parsecommon.c b/src/test/test_parsecommon.c
index 0c8f467a45..9c22266da1 100644
--- a/src/test/test_parsecommon.c
+++ b/src/test/test_parsecommon.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
diff --git a/src/test/test_parseconf.sh b/src/test/test_parseconf.sh
index eeb80cdfa7..4fe27d9f5d 100755
--- a/src/test/test_parseconf.sh
+++ b/src/test/test_parseconf.sh
@@ -8,15 +8,22 @@
# Valid configurations are tested with --dump-config, which parses and
# validates the configuration before writing it out. We then make sure that
# the result is what we expect, before parsing and dumping it again to make
-# sure that there is no change.
+# sure that there is no change. Optionally, we can also test the log messages
+# with --verify-config.
#
# Invalid configurations are tested with --verify-config, which parses
# and validates the configuration. We capture its output and make sure that
# it contains the error message we expect.
+#
+# When tor is compiled with different libraries or modules, some
+# configurations may have different results. We can specify these result
+# variants using additional result files.
# This script looks for its test cases as individual directories in
# src/test/conf_examples/. Each test may have these files:
#
+# Configuration Files
+#
# torrc -- Usually needed. This file is passed to Tor on the command line
# with the "-f" flag. (If you omit it, you'll test Tor's behavior when
# it receives a nonexistent configuration file.)
@@ -28,22 +35,79 @@
# cmdline -- Optional. If present, it contains command-line arguments that
# will be passed to Tor.
#
+# (included torrc files or directories) -- Optional. Additional files can be
+# included in configuration, using the "%include" directive. Files or
+# directories can be included in any of the config files listed above.
+# Include paths should be specified relative to the test case directory.
+#
+# Result Files
+#
# expected -- If this file is present, then it should be the expected result
# of "--dump-config short" for this test case. Exactly one of
# "expected" or "error" must be present, or the test will fail.
#
+# expected_log -- Optional. If this file is present, then it contains a regex
+# that must be matched by some line in the output of "--verify-config",
+# which must succeed. Only used if "expected" is also present.
+#
# error -- If this file is present, then it contains a regex that must be
# matched by some line in the output of "--verify-config", which must
# fail. Exactly one of "expected" or "error" must be present, or the
# test will fail.
+#
+# {expected,expected_log,error}_${TOR_LIBS_ENABLED}* -- If this file is
+# present, then the outcome is different when some optional libraries are
+# enabled. If there is no result file matching the exact list of enabled
+# libraries, the script searches for result files with one or more of
+# those libraries disabled. The search terminates at the standard result
+# file. If expected* is present, the script also searches for
+# expected_log*.
+#
+# For example:
+# A test that succeeds, regardless of any enabled libraries:
+# - expected
+# A test that has a different result if the nss library is enabled
+# (but the same result if any other library is enabled). We also check
+# the log output in this test:
+# - expected
+# - expected_log
+# - expected_nss
+# - expected_log_nss
+# A test that fails if the lzma and zstd modules are *not* enabled:
+# - error
+# - expected_lzma_zstd
+#
+# {expected,expected_log,error}*_no_${TOR_MODULES_DISABLED} -- If this file is
+# present, then the outcome is different when some modules are disabled.
+# If there is no result file matching the exact list of disabled modules,
+# the standard result file is used. If expected* is present, the script
+# also searches for expected_log*.
+#
+# For example:
+# A test that succeeds, regardless of any disabled modules:
+# - expected
+# A test that has a different result if the relay module is disabled
+# (but the same result if just the dirauth module is disabled):
+# - expected
+# - expected_no_relay_dirauth
+# A test that fails if the dirauth module is disabled:
+# - expected
+# - error_no_dirauth
+# - error_no_relay_dirauth
+# (Disabling the relay module also disables dirauth module. But we don't
+# want to encode that knowledge in this test script, so we supply a
+# separate result file for every combination of disabled modules that
+# has a different result.)
umask 077
set -e
+MYNAME="$0"
+
# emulate realpath(), in case coreutils or equivalent is not installed.
abspath() {
f="$*"
- if [ -d "$f" ]; then
+ if test -d "$f"; then
dir="$f"
base=""
else
@@ -55,8 +119,8 @@ abspath() {
}
# find the tor binary
-if [ $# -ge 1 ]; then
- TOR_BINARY="${1}"
+if test $# -ge 1; then
+ TOR_BINARY="$1"
shift
else
TOR_BINARY="${TESTING_TOR_BINARY:-./src/app/tor}"
@@ -64,6 +128,8 @@ fi
TOR_BINARY="$(abspath "$TOR_BINARY")"
+echo "Using Tor binary '$TOR_BINARY'."
+
# make a safe space for temporary files
DATA_DIR=$(mktemp -d -t tor_parseconf_tests.XXXXXX)
trap 'rm -rf "$DATA_DIR"' 0
@@ -90,7 +156,31 @@ else
EXITCODE=1
fi
-die() { echo "$1" >&2 ; exit "$EXITCODE"; }
+FINAL_EXIT=0
+NEXT_TEST=
+
+# Log a failure message to stderr, using $@ as a printf string and arguments
+# Set NEXT_TEST to "yes" and FINAL_EXIT to $EXITCODE.
+fail_printf()
+{
+ printf "FAIL: " >&2
+ # The first argument is a printf string, so this warning is spurious
+ # shellcheck disable=SC2059
+ printf "$@" >&2
+ NEXT_TEST="yes"
+ FINAL_EXIT=$EXITCODE
+}
+
+# Log a failure message to stderr, using $@ as a printf string and arguments
+# Exit with status $EXITCODE.
+die_printf()
+{
+ printf "FAIL: CRITICAL error in '%s':" "$MYNAME" >&2
+ # The first argument is a printf string, so this warning is spurious
+ # shellcheck disable=SC2059
+ printf "$@" >&2
+ exit $EXITCODE
+}
if test "$WINDOWS" = 1; then
FILTER="dos2unix"
@@ -98,20 +188,353 @@ else
FILTER="cat"
fi
-touch "${DATA_DIR}/EMPTY" || die "Couldn't create empty file."
+EMPTY="${DATA_DIR}/EMPTY"
+touch "$EMPTY" || die_printf "Couldn't create empty file '%s'.\\n" \
+ "$EMPTY"
+NON_EMPTY="${DATA_DIR}/NON_EMPTY"
+echo "This pattern should not match any log messages" \
+ > "$NON_EMPTY" || die_printf "Couldn't create non-empty file '%s'.\\n" \
+ "$NON_EMPTY"
+
+STANDARD_LIBS="libevent\\|openssl\\|zlib"
+# Lib names are restricted to [a-z0-9]* at the moment
+# We don't actually want to support foreign accents here
+# shellcheck disable=SC2018,SC2019
+TOR_LIBS_ENABLED="$("$TOR_BINARY" --verify-config \
+ -f "$EMPTY" --defaults-torrc "$EMPTY" \
+ | sed -n 's/.* Tor .* running on .* with\(.*\)\./\1/p' \
+ | tr 'A-Z' 'a-z' | tr ',' '\n' \
+ | grep -v "$STANDARD_LIBS" | grep -v "n/a" \
+ | sed 's/\( and\)* \(lib\)*\([a-z0-9]*\) .*/\3/' \
+ | sort | tr '\n' '_')"
+# Remove the last underscore, if there is one
+TOR_LIBS_ENABLED=${TOR_LIBS_ENABLED%_}
+
+# If we ever have more than 3 optional libraries, we'll need more code here
+TOR_LIBS_ENABLED_COUNT="$(echo "$TOR_LIBS_ENABLED_SEARCH" \
+ | tr ' ' '\n' | wc -l)"
+if test "$TOR_LIBS_ENABLED_COUNT" -gt 3; then
+ die_printf "Can not handle more than 3 optional libraries.\\n"
+fi
+# Brute-force the combinations of libraries
+TOR_LIBS_ENABLED_SEARCH_3="$(echo "$TOR_LIBS_ENABLED" \
+ | sed -n \
+ 's/^\([^_]*\)_\([^_]*\)_\([^_]*\)$/_\1_\2 _\1_\3 _\2_\3 _\1 _\2 _\3/p')"
+TOR_LIBS_ENABLED_SEARCH_2="$(echo "$TOR_LIBS_ENABLED" \
+ | sed -n 's/^\([^_]*\)_\([^_]*\)$/_\1 _\2/p')"
+TOR_LIBS_ENABLED_SEARCH="_$TOR_LIBS_ENABLED \
+ $TOR_LIBS_ENABLED_SEARCH_3 \
+ $TOR_LIBS_ENABLED_SEARCH_2"
+TOR_LIBS_ENABLED_SEARCH="$(echo "$TOR_LIBS_ENABLED_SEARCH" | tr ' ' '\n' \
+ | grep -v '^_*$' | tr '\n' ' ')"
+
+TOR_MODULES_DISABLED="$("$TOR_BINARY" --list-modules | grep ': no' \
+ | cut -d ':' -f1 | sort | tr '\n' '_')"
+# Remove the last underscore, if there is one
+TOR_MODULES_DISABLED=${TOR_MODULES_DISABLED%_}
+
+echo "Tor is configured with:"
+echo "Optional Libraries: ${TOR_LIBS_ENABLED:-(None)}"
+if test "$TOR_LIBS_ENABLED"; then
+ echo "Optional Library Search List: $TOR_LIBS_ENABLED_SEARCH"
+fi
+echo "Disabled Modules: ${TOR_MODULES_DISABLED:-(None)}"
+
+# Yes, unix uses "0" for a successful command
+TRUE=0
+FALSE=1
+
+# Run tor --verify-config on the torrc $1, and defaults torrc $2, which may
+# be $EMPTY. Pass tor the extra command line arguments $3, which will be
+# passed unquoted.
+# Send tor's standard output to stderr.
+log_verify_config()
+{
+ # show the command we're about to execute
+ # log_verify_config() is only called when we've failed
+ printf "Tor --verify-config said:\\n" >&2
+ printf "$ %s %s %s %s %s %s %s\\n" \
+ "$TOR_BINARY" --verify-config \
+ -f "$1" \
+ --defaults-torrc "$2" \
+ "$3" \
+ >&2
+ # We need cmdline unquoted
+ # shellcheck disable=SC2086
+ "$TOR_BINARY" --verify-config \
+ -f "$1" \
+ --defaults-torrc "$2" \
+ $3 \
+ >&2 \
+ || true
+}
+
+# Run "tor --dump-config short" on the torrc $1, and defaults torrc $2, which
+# may be $EMPTY. Pass tor the extra command line arguments $3, which will be
+# passed unquoted. Send tor's standard output to $4.
+#
+# Set $FULL_TOR_CMD to the tor command line that was executed.
+#
+# If tor fails, fail_printf() using the file name $5, and context $6,
+# which may be an empty string. Then run log_verify_config().
+dump_config()
+{
+ if test "$6"; then
+ CONTEXT=" $6"
+ else
+ CONTEXT=""
+ fi
+
+ # keep the command we're about to execute, and show if it we fail
+ FULL_TOR_CMD=$(printf "$ %s %s %s %s %s %s %s %s" \
+ "$TOR_BINARY" --dump-config short \
+ -f "$1" \
+ --defaults-torrc "$2" \
+ "$3"
+ )
+ # We need cmdline unquoted
+ # shellcheck disable=SC2086
+ if ! "$TOR_BINARY" --dump-config short \
+ -f "$1" \
+ --defaults-torrc "$2" \
+ $3 \
+ > "$4"; then
+ fail_printf "'%s': Tor --dump-config reported an error%s:\\n%s\\n" \
+ "$5" \
+ "$CONTEXT" \
+ "$FULL_TOR_CMD"
+ log_verify_config "$1" \
+ "$2" \
+ "$3"
+ fi
+}
+
+# Run "$FILTER" on the input $1.
+# Send the standard output to $2.
+# If tor fails, log a failure message using the file name $3, and context $4,
+# which may be an empty string.
+filter()
+{
+ if test "$4"; then
+ CONTEXT=" $4"
+ else
+ CONTEXT=""
+ fi
+
+ "$FILTER" "$1" \
+ > "$2" \
+ || fail_printf "'%s': Filter '%s' reported an error%s.\\n" \
+ "$3" \
+ "$FILTER" \
+ "$CONTEXT"
+}
+
+# Compare the expected file $1, and output file $2.
+#
+# If they are different, fail. Log the differences between the files.
+# Run log_verify_config() with torrc $3, defaults torrc $4, and command
+# line $5, to log Tor's error messages.
+#
+# If the file contents are identical, returns true. Otherwise, return false.
+#
+# Log failure messages using fail_printf(), with the expected file name,
+# context $6, which may be an empty string, and the tor command line $7.
+check_diff()
+{
+ if test "$6"; then
+ CONTEXT=" $6"
+ else
+ CONTEXT=""
+ fi
+
+ if cmp "$1" "$2" > /dev/null; then
+ return "$TRUE"
+ else
+ fail_printf "'%s': Tor --dump-config said%s:\\n%s\\n" \
+ "$1" \
+ "$CONTEXT" \
+ "$7"
+ diff -u "$1" "$2" >&2 \
+ || true
+ log_verify_config "$3" \
+ "$4" \
+ "$5"
+ return "$FALSE"
+ fi
+}
+
+# Run "tor --dump-config short" on the torrc $1, and defaults torrc $2, which
+# may be $EMPTY. Pass tor the extra command line arguments $3, which will be
+# passed unquoted. Send tor's standard output to $4, after running $FILTER
+# on it.
+#
+# If tor fails, run log_verify_config().
+#
+# Compare the expected file $5, and output file. If they are different, fail.
+# If this is the first step that failed in this test, run log_verify_config().
+#
+# If the file contents are identical, returns true. Otherwise, return false,
+# and log the differences between the files.
+#
+# Log failure messages using fail_printf(), with the expected file name, and
+# context $6, which may be an empty string.
+check_dump_config()
+{
+ OUTPUT="$4"
+ OUTPUT_RAW="${OUTPUT}_raw"
+
+ FULL_TOR_CMD=
+ dump_config "$1" \
+ "$2" \
+ "$3" \
+ "$OUTPUT_RAW" \
+ "$5" \
+ "$6"
+
+ filter "$OUTPUT_RAW" \
+ "$OUTPUT" \
+ "$5" \
+ "$6"
+
+ if check_diff "$5" \
+ "$OUTPUT" \
+ "$1" \
+ "$2" \
+ "$3" \
+ "$6" \
+ "$FULL_TOR_CMD"; then
+ return "$TRUE"
+ else
+ return "$FALSE"
+ fi
+}
+
+# Check if $1 is an empty file.
+# If it is, fail_printf() using $2 as the type of file.
+# Returns true if the file is empty, false otherwise.
+check_empty_pattern()
+{
+ if ! test -s "$1"; then
+ fail_printf "%s file '%s' is empty, and will match any output.\\n" \
+ "$2" \
+ "$1"
+ return "$TRUE"
+ else
+ return "$FALSE"
+ fi
+}
+
+# Run tor --verify-config on the torrc $1, and defaults torrc $2, which may
+# be $EMPTY. Pass tor the extra command line arguments $3, which will be
+# passed unquoted. Send tor's standard output to $4.
+#
+# Set $FULL_TOR_CMD to the tor command line that was executed.
+#
+# If tor's exit status does not match the boolean $5, fail_printf()
+# using the file name $6, and context $7, which is required.
+verify_config()
+{
+ RESULT=$TRUE
+
+ # keep the command we're about to execute, and show if it we fail
+ FULL_TOR_CMD=$(printf "$ %s %s %s %s %s %s %s" \
+ "$TOR_BINARY" --verify-config \
+ -f "$1" \
+ --defaults-torrc "$2" \
+ "$3"
+ )
+ # We need cmdline unquoted
+ # shellcheck disable=SC2086
+ "$TOR_BINARY" --verify-config \
+ -f "$1" \
+ --defaults-torrc "$2" \
+ $3 \
+ > "$4" || RESULT=$FALSE
+
+ # Convert the actual and expected results to boolean, and compare
+ if test $((! (! RESULT))) -ne $((! (! $5))); then
+ fail_printf "'%s': Tor --verify-config did not %s:\\n%s\\n" \
+ "$6" \
+ "$7" \
+ "$FULL_TOR_CMD"
+ cat "$4" >&2
+ fi
+}
+
+# Check for the patterns in the match file $1, in the output file $2.
+# Uses grep with the entire contents of the match file as the pattern.
+# (Not "grep -f".)
+#
+# If the pattern does not match any lines in the output file, fail.
+# Log the pattern, and the entire contents of the output file.
+#
+# Log failure messages using fail_printf(), with the match file name,
+# context $3, and tor command line $4, which are required.
+check_pattern()
+{
+ expect_log="$(cat "$1")"
+ if ! grep "$expect_log" "$2" > /dev/null; then
+ fail_printf "Expected %s '%s':\\n%s\\n" \
+ "$3" \
+ "$1" \
+ "$expect_log"
+ printf "Tor --verify-config said:\\n%s\\n" \
+ "$4" >&2
+ cat "$2" >&2
+ fi
+}
+
+# Run tor --verify-config on the torrc $1, and defaults torrc $2, which may
+# be $EMPTY. Pass tor the extra command line arguments $3, which will be
+# passed unquoted. Send tor's standard output to $4.
+#
+# If tor's exit status does not match the boolean $5, fail.
+#
+# Check for the patterns in the match file $6, in the output file.
+# Uses grep with the entire contents of the match file as the pattern.
+# (Not "grep -f".) The match file must not be empty.
+#
+# If the pattern does not match any lines in the output file, fail.
+# Log the pattern, and the entire contents of the output file.
+#
+# Log failure messages using fail_printf(), with the match file name,
+# and context $7, which is required.
+check_verify_config()
+{
+ if check_empty_pattern "$6" "$7"; then
+ return
+ fi
+
+ FULL_TOR_CMD=
+ verify_config "$1" \
+ "$2" \
+ "$3" \
+ "$4" \
+ "$5" \
+ "$6" \
+ "$7"
+
+ check_pattern "$6" \
+ "$4" \
+ "$7" \
+ "$FULL_TOR_CMD"
+}
for dir in "${EXAMPLEDIR}"/*; do
- if ! test -d "${dir}"; then
+ NEXT_TEST=
+
+ if ! test -d "$dir"; then
# Only count directories.
continue
fi
testname="$(basename "${dir}")"
# We use printf since "echo -n" is not standard
- printf "%s: " "$testname"
+ printf "%s: " \
+ "$testname"
PREV_DIR="$(pwd)"
- cd "${dir}"
+ cd "$dir"
if test -f "./torrc.defaults"; then
DEFAULTS="./torrc.defaults"
@@ -125,80 +548,108 @@ for dir in "${EXAMPLEDIR}"/*; do
CMDLINE=""
fi
- if test -f "./expected"; then
- if test -f "./error"; then
- echo "FAIL: Found both ${dir}/expected and ${dir}/error."
- echo "(Only one of these files should exist.)"
- exit $EXITCODE
- fi
+ EXPECTED=
+ EXPECTED_LOG=
+ ERROR=
+ # Search for a custom result file for any combination of enabled optional
+ # libraries
+ # The libs in the list are [A-Za-z0-9_]* and space-separated.
+ # shellcheck disable=SC2086
+ for lib_suffix in $TOR_LIBS_ENABLED_SEARCH ""; do
+ # Search for a custom result file for any disabled modules
+ for mod_suffix in "_no_${TOR_MODULES_DISABLED}" ""; do
+ suffix="${lib_suffix}${mod_suffix}"
- # This case should succeed: run dump-config and see if it does.
+ if test -f "./expected${suffix}"; then
- "${TOR_BINARY}" -f "./torrc" \
- --defaults-torrc "${DEFAULTS}" \
- --dump-config short \
- ${CMDLINE} \
- | "${FILTER}" > "${DATA_DIR}/output.${testname}" \
- || die "Failure: Tor exited."
+ # Check for broken configs
+ if test -f "./error${suffix}"; then
+ fail_printf "Found both '%s' and '%s'.%s\\n" \
+ "${dir}/expected${suffix}" \
+ "${dir}/error${suffix}" \
+ "(Only one of these files should exist.)"
+ break
+ fi
- if cmp "./expected" "${DATA_DIR}/output.${testname}">/dev/null ; then
- # Check round-trip.
- "${TOR_BINARY}" -f "${DATA_DIR}/output.${testname}" \
- --defaults-torrc "${DATA_DIR}/empty" \
- --dump-config short \
- | "${FILTER}" \
- > "${DATA_DIR}/output_2.${testname}" \
- || die "Failure: Tor exited on round-trip."
-
- if ! cmp "${DATA_DIR}/output.${testname}" \
- "${DATA_DIR}/output_2.${testname}"; then
- echo "Failure: did not match on round-trip."
- exit $EXITCODE
- fi
+ EXPECTED="./expected${suffix}"
+ if test -f "./expected_log${suffix}"; then
+ EXPECTED_LOG="./expected_log${suffix}"
+ fi
+ break
- echo "OK"
- else
- echo "FAIL"
- if test "$(wc -c < "${DATA_DIR}/output.${testname}")" = 0; then
- # There was no output -- probably we failed.
- "${TOR_BINARY}" -f "./torrc" \
- --defaults-torrc "${DEFAULTS}" \
- --verify-config \
- ${CMDLINE} || true
+ elif test -f "./error${suffix}"; then
+ ERROR="./error${suffix}"
+ break
fi
- diff -u "./expected" "${DATA_DIR}/output.${testname}" || /bin/true
- exit $EXITCODE
+ done
+
+ # Exit as soon as the inner loop finds a file, or fails
+ if test -f "$EXPECTED" || test -f "$ERROR" || test "$NEXT_TEST"; then
+ break
fi
+ done
- elif test -f "./error"; then
- # This case should fail: run verify-config and see if it does.
+ if test "$NEXT_TEST"; then
+ # The test failed inside the file search loop: go to the next test
+ continue
+ elif test -f "$EXPECTED"; then
+ # This case should succeed: run dump-config and see if it does.
+
+ if check_dump_config "./torrc" \
+ "$DEFAULTS" \
+ "$CMDLINE" \
+ "${DATA_DIR}/output.${testname}" \
+ "$EXPECTED" \
+ ""; then
+ # Check round-trip.
+ check_dump_config "${DATA_DIR}/output.${testname}" \
+ "$EMPTY" \
+ "" \
+ "${DATA_DIR}/output_2.${testname}" \
+ "$EXPECTED" \
+ "on round-trip" || true
+ fi
- "${TOR_BINARY}" --verify-config \
- -f ./torrc \
- --defaults-torrc "${DEFAULTS}" \
- ${CMDLINE} \
- > "${DATA_DIR}/output.${testname}" \
- && die "Failure: Tor did not report an error."
+ if test -f "$EXPECTED_LOG"; then
+ # This case should succeed: run verify-config and see if it does.
- expect_err="$(cat ./error)"
- if grep "${expect_err}" "${DATA_DIR}/output.${testname}" >/dev/null; then
- echo "OK"
+ check_verify_config "./torrc" \
+ "$DEFAULTS" \
+ "$CMDLINE" \
+ "${DATA_DIR}/output_log.${testname}" \
+ "$TRUE" \
+ "$EXPECTED_LOG" \
+ "log success"
else
- echo "FAIL"
- echo "Expected error: ${expect_err}"
- echo "Tor said:"
- cat "${DATA_DIR}/output.${testname}"
- exit $EXITCODE
+ printf "\\nNOTICE: Missing '%s_log' file:\\n" \
+ "$EXPECTED" >&2
+ log_verify_config "./torrc" \
+ "$DEFAULTS" \
+ "$CMDLINE"
fi
+ elif test -f "$ERROR"; then
+ # This case should fail: run verify-config and see if it does.
+
+ check_verify_config "./torrc" \
+ "$DEFAULTS" \
+ "$CMDLINE" \
+ "${DATA_DIR}/output.${testname}" \
+ "$FALSE" \
+ "$ERROR" \
+ "log error"
else
# This case is not actually configured with a success or a failure.
# call that an error.
+ fail_printf "Did not find ${dir}/*expected or ${dir}/*error.\\n"
+ fi
- echo "FAIL: Did not find ${dir}/expected or ${dir}/error."
- exit $EXITCODE
+ if test -z "$NEXT_TEST"; then
+ echo "OK"
fi
- cd "${PREV_DIR}"
+ cd "$PREV_DIR"
done
+
+exit "$FINAL_EXIT"
diff --git a/src/test/test_pem.c b/src/test/test_pem.c
index 9eb99181e2..9772be124b 100644
--- a/src/test/test_pem.c
+++ b/src/test/test_pem.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_periodic_event.c b/src/test/test_periodic_event.c
index 267156a908..b7f1785805 100644
--- a/src/test/test_periodic_event.c
+++ b/src/test/test_periodic_event.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_policy.c b/src/test/test_policy.c
index e58bb3d174..762241249c 100644
--- a/src/test/test_policy.c
+++ b/src/test/test_policy.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONFIG_PRIVATE
diff --git a/src/test/test_prob_distr.c b/src/test/test_prob_distr.c
index 0ecbf65f41..c3d1c80d70 100644
--- a/src/test/test_prob_distr.c
+++ b/src/test/test_prob_distr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -946,7 +946,7 @@ psi_test(const size_t C[PSI_DF], const double logP[PSI_DF], size_t N)
static bool
test_stochastic_geometric_impl(double p)
{
- const struct geometric geometric = {
+ const struct geometric_t geometric = {
.base = GEOMETRIC(geometric),
.p = p,
};
@@ -1012,7 +1012,8 @@ test_stochastic_geometric_impl(double p)
* +inf, and x_i = i*(hi - lo)/(n - 2).
*/
static void
-bin_cdfs(const struct dist *dist, double lo, double hi, double *logP, size_t n)
+bin_cdfs(const struct dist_t *dist, double lo, double hi, double *logP,
+ size_t n)
{
#define CDF(x) dist_cdf(dist, x)
#define SF(x) dist_sf(dist, x)
@@ -1059,7 +1060,8 @@ bin_cdfs(const struct dist *dist, double lo, double hi, double *logP, size_t n)
* +inf, and x_i = i*(hi - lo)/(n - 2).
*/
static void
-bin_samples(const struct dist *dist, double lo, double hi, size_t *C, size_t n)
+bin_samples(const struct dist_t *dist, double lo, double hi, size_t *C,
+ size_t n)
{
const double w = (hi - lo)/(n - 2);
size_t i;
@@ -1088,7 +1090,7 @@ bin_samples(const struct dist *dist, double lo, double hi, size_t *C, size_t n)
* 0.01^2 = 0.0001.
*/
static bool
-test_psi_dist_sample(const struct dist *dist)
+test_psi_dist_sample(const struct dist_t *dist)
{
double logP[PSI_DF] = {0};
unsigned ntry = NTRIALS, npass = 0;
@@ -1134,32 +1136,32 @@ test_stochastic_uniform(void *arg)
{
(void) arg;
- const struct uniform uniform01 = {
+ const struct uniform_t uniform01 = {
.base = UNIFORM(uniform01),
.a = 0,
.b = 1,
};
- const struct uniform uniform_pos = {
+ const struct uniform_t uniform_pos = {
.base = UNIFORM(uniform_pos),
.a = 1.23,
.b = 4.56,
};
- const struct uniform uniform_neg = {
+ const struct uniform_t uniform_neg = {
.base = UNIFORM(uniform_neg),
.a = -10,
.b = -1,
};
- const struct uniform uniform_cross = {
+ const struct uniform_t uniform_cross = {
.base = UNIFORM(uniform_cross),
.a = -1.23,
.b = 4.56,
};
- const struct uniform uniform_subnormal = {
+ const struct uniform_t uniform_subnormal = {
.base = UNIFORM(uniform_subnormal),
.a = 4e-324,
.b = 4e-310,
};
- const struct uniform uniform_subnormal_cross = {
+ const struct uniform_t uniform_subnormal_cross = {
.base = UNIFORM(uniform_subnormal_cross),
.a = -4e-324,
.b = 4e-310,
@@ -1189,7 +1191,7 @@ test_stochastic_uniform(void *arg)
static bool
test_stochastic_logistic_impl(double mu, double sigma)
{
- const struct logistic dist = {
+ const struct logistic_t dist = {
.base = LOGISTIC(dist),
.mu = mu,
.sigma = sigma,
@@ -1202,7 +1204,7 @@ test_stochastic_logistic_impl(double mu, double sigma)
static bool
test_stochastic_log_logistic_impl(double alpha, double beta)
{
- const struct log_logistic dist = {
+ const struct log_logistic_t dist = {
.base = LOG_LOGISTIC(dist),
.alpha = alpha,
.beta = beta,
@@ -1215,7 +1217,7 @@ test_stochastic_log_logistic_impl(double alpha, double beta)
static bool
test_stochastic_weibull_impl(double lambda, double k)
{
- const struct weibull dist = {
+ const struct weibull_t dist = {
.base = WEIBULL(dist),
.lambda = lambda,
.k = k,
@@ -1235,7 +1237,7 @@ test_stochastic_weibull_impl(double lambda, double k)
static bool
test_stochastic_genpareto_impl(double mu, double sigma, double xi)
{
- const struct genpareto dist = {
+ const struct genpareto_t dist = {
.base = GENPARETO(dist),
.mu = mu,
.sigma = sigma,
diff --git a/src/test/test_process.c b/src/test/test_process.c
index 7836312761..c1da6db278 100644
--- a/src/test/test_process.c
+++ b/src/test/test_process.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_process_descs.c b/src/test/test_process_descs.c
index 7dc9abde31..14865cff13 100644
--- a/src/test/test_process_descs.c
+++ b/src/test/test_process_descs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2019, The Tor Project, Inc. */
+/* Copyright (c) 2019-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -20,13 +20,10 @@ test_process_descs_versions(void *arg)
{ "Tor 0.1.2.3-alpha", true },
// a non-tor program: don't reject.
{ "Wombat 0.1.2.3-alpha", false },
- // a slightly old version: reject
- { "Tor 0.2.9.4-alpha", true },
- // a slightly old version: just new enough to support.
- { "Tor 0.2.9.5-alpha", false },
- // a newer 0.2.9 version: supported.
- { "Tor 0.2.9.100", false },
// some unsupported versions: reject.
+ { "Tor 0.2.9.4-alpha", true },
+ { "Tor 0.2.9.5-alpha", true },
+ { "Tor 0.2.9.100", true },
{ "Tor 0.3.0.0-alpha-dev", true },
{ "Tor 0.3.0.2-alpha", true },
{ "Tor 0.3.0.5", true },
@@ -37,11 +34,17 @@ test_process_descs_versions(void *arg)
{ "Tor 0.3.4.100", true },
{ "Tor 0.3.5.1-alpha", true },
{ "Tor 0.3.5.6-rc", true},
+ { "Tor 0.4.0.1-alpha", true },
+ { "Tor 0.4.0.5", true },
+ { "Tor 0.4.1.1-alpha", true },
+ { "Tor 0.4.1.4-rc", true },
// new enough to be supported
{ "Tor 0.3.5.7", false },
{ "Tor 0.3.5.8", false },
- { "Tor 0.4.0.1-alpha", false },
{ "Tor 0.4.1.5", false },
+ { "Tor 0.4.2.1-alpha", false },
+ { "Tor 0.4.2.4-rc", false },
+ { "Tor 0.4.3.0-alpha-dev", false },
// Very far in the future
{ "Tor 100.100.1.5", false },
};
diff --git a/src/test/test_process_slow.c b/src/test/test_process_slow.c
index f311e8b293..f74d4adc9a 100644
--- a/src/test/test_process_slow.c
+++ b/src/test/test_process_slow.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_procmon.c b/src/test/test_procmon.c
index e23578f4fd..1752008f63 100644
--- a/src/test/test_procmon.c
+++ b/src/test/test_procmon.c
@@ -1,7 +1,6 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#define PROCMON_PRIVATE
#include "orconfig.h"
#include "core/or/or.h"
#include "test/test.h"
@@ -10,8 +9,6 @@
#include "test/log_test_helpers.h"
-#define NS_MODULE procmon
-
struct event_base;
static void
diff --git a/src/test/test_proto_haproxy.c b/src/test/test_proto_haproxy.c
new file mode 100644
index 0000000000..040354ec1f
--- /dev/null
+++ b/src/test/test_proto_haproxy.c
@@ -0,0 +1,66 @@
+/* Copyright (c) 2019-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file test_proto_haproxy.c
+ * \brief Tests for our HAProxy protocol parser code
+ */
+
+#define PROTO_HAPROXY_PRIVATE
+
+#include "test/test.h"
+#include "core/proto/proto_haproxy.h"
+#include "test/log_test_helpers.h"
+
+static void
+test_format_proxy_header_line(void *arg)
+{
+ tor_addr_t addr;
+ tor_addr_port_t *addr_port = NULL;
+ char *output = NULL;
+
+ (void) arg;
+
+ /* IPv4 address. */
+ tor_addr_parse(&addr, "192.168.1.2");
+ addr_port = tor_addr_port_new(&addr, 8000);
+ output = haproxy_format_proxy_header_line(addr_port);
+
+ tt_str_op(output, OP_EQ, "PROXY TCP4 0.0.0.0 192.168.1.2 0 8000\r\n");
+
+ tor_free(addr_port);
+ tor_free(output);
+
+ /* IPv6 address. */
+ tor_addr_parse(&addr, "123:45:6789::5005:11");
+ addr_port = tor_addr_port_new(&addr, 8000);
+ output = haproxy_format_proxy_header_line(addr_port);
+
+ tt_str_op(output, OP_EQ, "PROXY TCP6 :: 123:45:6789::5005:11 0 8000\r\n");
+
+ tor_free(addr_port);
+ tor_free(output);
+
+ /* UNIX socket address. */
+ memset(&addr, 0, sizeof(addr));
+ addr.family = AF_UNIX;
+ addr_port = tor_addr_port_new(&addr, 8000);
+ output = haproxy_format_proxy_header_line(addr_port);
+
+ /* If it's not an IPv4 or IPv6 address, haproxy_format_proxy_header_line
+ * must return NULL. */
+ tt_ptr_op(output, OP_EQ, NULL);
+
+ tor_free(addr_port);
+ tor_free(output);
+
+ done:
+ tor_free(addr_port);
+ tor_free(output);
+}
+
+struct testcase_t proto_haproxy_tests[] = {
+ { "format_proxy_header_line", test_format_proxy_header_line, 0, NULL, NULL },
+
+ END_OF_TESTCASES
+};
diff --git a/src/test/test_proto_http.c b/src/test/test_proto_http.c
index f9339e8dd3..481d78b2c1 100644
--- a/src/test/test_proto_http.c
+++ b/src/test/test_proto_http.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_proto_misc.c b/src/test/test_proto_misc.c
index 18669a7772..64bf5c4993 100644
--- a/src/test/test_proto_misc.c
+++ b/src/test/test_proto_misc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_protover.c b/src/test/test_protover.c
index 0254501165..f1d1ef0d4a 100644
--- a/src/test/test_protover.c
+++ b/src/test/test_protover.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define PROTOVER_PRIVATE
diff --git a/src/test/test_pt.c b/src/test/test_pt.c
index 8f3ce03c42..26eaf7b7e7 100644
--- a/src/test/test_pt.c
+++ b/src/test/test_pt.c
@@ -1,17 +1,16 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#define PT_PRIVATE
-#define UTIL_PRIVATE
#define STATEFILE_PRIVATE
#define CONTROL_EVENTS_PRIVATE
#define PROCESS_PRIVATE
#include "core/or/or.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "feature/control/control.h"
#include "feature/control/control_events.h"
#include "feature/client/transports.h"
diff --git a/src/test/test_ptr_slow.c b/src/test/test_ptr_slow.c
index 76bdbf1891..25b893c4c0 100644
--- a/src/test/test_ptr_slow.c
+++ b/src/test/test_ptr_slow.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_pubsub_build.c b/src/test/test_pubsub_build.c
index 021323fbf1..5f9005926c 100644
--- a/src/test/test_pubsub_build.c
+++ b/src/test/test_pubsub_build.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define DISPATCH_PRIVATE
diff --git a/src/test/test_pubsub_msg.c b/src/test/test_pubsub_msg.c
index 73c7c9f540..3054db885d 100644
--- a/src/test/test_pubsub_msg.c
+++ b/src/test/test_pubsub_msg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define DISPATCH_PRIVATE
diff --git a/src/test/test_rebind.py b/src/test/test_rebind.py
index c9b9200b2d..3fc3deb68e 100644
--- a/src/test/test_rebind.py
+++ b/src/test/test_rebind.py
@@ -1,4 +1,7 @@
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
from __future__ import print_function
+from __future__ import unicode_literals
import errno
import logging
diff --git a/src/test/test_rebind.sh b/src/test/test_rebind.sh
index d6d9d86668..879008c1c1 100755
--- a/src/test/test_rebind.sh
+++ b/src/test/test_rebind.sh
@@ -1,7 +1,23 @@
#!/bin/sh
+umask 077
+set -e
set -x
+# emulate realpath(), in case coreutils or equivalent is not installed.
+abspath() {
+ f="$*"
+ if [ -d "$f" ]; then
+ dir="$f"
+ base=""
+ else
+ dir="$(dirname "$f")"
+ base="/$(basename "$f")"
+ fi
+ dir="$(cd "$dir" && pwd)"
+ echo "$dir$base"
+}
+
UNAME_OS=$(uname -s | cut -d_ -f1)
if test "$UNAME_OS" = 'CYGWIN' || \
test "$UNAME_OS" = 'MSYS' || \
@@ -12,6 +28,23 @@ if test "$UNAME_OS" = 'CYGWIN' || \
fi
fi
+# find the tor binary
+if [ $# -ge 1 ]; then
+ TOR_BINARY="${1}"
+ shift
+else
+ TOR_BINARY="${TESTING_TOR_BINARY:-./src/app/tor}"
+fi
+
+TOR_BINARY="$(abspath "$TOR_BINARY")"
+
+echo "TOR BINARY IS ${TOR_BINARY}"
+
+if "${TOR_BINARY}" --list-modules | grep -q "relay: no"; then
+ echo "This test requires the relay module. Skipping." >&2
+ exit 77
+fi
+
tmpdir=
clean () {
if [ -n "$tmpdir" ] && [ -d "$tmpdir" ]; then
@@ -30,6 +63,6 @@ elif [ ! -d "$tmpdir" ]; then
exit 3
fi
-"${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/test_rebind.py" "${TESTING_TOR_BINARY}" "$tmpdir"
+"${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/test_rebind.py" "${TOR_BINARY}" "$tmpdir"
exit $?
diff --git a/src/test/test_relay.c b/src/test/test_relay.c
index 0b7a7be332..066aeaa7b3 100644
--- a/src/test/test_relay.c
+++ b/src/test/test_relay.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CIRCUITBUILD_PRIVATE
@@ -10,7 +10,6 @@
#include "core/or/channeltls.h"
#include "feature/stats/rephist.h"
#include "core/or/relay.h"
-#include "feature/stats/rephist.h"
#include "lib/container/order.h"
/* For init/free stuff */
#include "core/or/scheduler.h"
@@ -21,42 +20,10 @@
/* Test suite stuff */
#include "test/test.h"
#include "test/fakechans.h"
-
-static or_circuit_t * new_fake_orcirc(channel_t *nchan, channel_t *pchan);
+#include "test/fakecircs.h"
static void test_relay_append_cell_to_circuit_queue(void *arg);
-static or_circuit_t *
-new_fake_orcirc(channel_t *nchan, channel_t *pchan)
-{
- or_circuit_t *orcirc = NULL;
- circuit_t *circ = NULL;
-
- orcirc = tor_malloc_zero(sizeof(*orcirc));
- circ = &(orcirc->base_);
- circ->magic = OR_CIRCUIT_MAGIC;
-
- circuit_set_n_circid_chan(circ, get_unique_circ_id_by_chan(nchan), nchan);
- cell_queue_init(&(circ->n_chan_cells));
-
- circ->n_hop = NULL;
- circ->streams_blocked_on_n_chan = 0;
- circ->streams_blocked_on_p_chan = 0;
- circ->n_delete_pending = 0;
- circ->p_delete_pending = 0;
- circ->received_destroy = 0;
- circ->state = CIRCUIT_STATE_OPEN;
- circ->purpose = CIRCUIT_PURPOSE_OR;
- circ->package_window = CIRCWINDOW_START_MAX;
- circ->deliver_window = CIRCWINDOW_START_MAX;
- circ->n_chan_create_cell = NULL;
-
- circuit_set_p_circid_chan(orcirc, get_unique_circ_id_by_chan(pchan), pchan);
- cell_queue_init(&(orcirc->p_chan_cells));
-
- return orcirc;
-}
-
static void
assert_circuit_ok_mock(const circuit_t *c)
{
@@ -145,7 +112,7 @@ test_relay_close_circuit(void *arg)
cell_queue_clear(&orcirc->base_.n_chan_cells);
cell_queue_clear(&orcirc->p_chan_cells);
}
- tor_free(orcirc);
+ free_fake_orcirc(orcirc);
free_fake_channel(nchan);
free_fake_channel(pchan);
UNMOCK(assert_circuit_ok);
@@ -218,7 +185,7 @@ test_relay_append_cell_to_circuit_queue(void *arg)
cell_queue_clear(&orcirc->base_.n_chan_cells);
cell_queue_clear(&orcirc->p_chan_cells);
}
- tor_free(orcirc);
+ free_fake_orcirc(orcirc);
free_fake_channel(nchan);
free_fake_channel(pchan);
diff --git a/src/test/test_relaycell.c b/src/test/test_relaycell.c
index c65279fb25..da9e791fb6 100644
--- a/src/test/test_relaycell.c
+++ b/src/test/test_relaycell.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/* Unit tests for handling different kinds of relay cell */
@@ -30,7 +30,6 @@
#include "core/or/half_edge_st.h"
#include "feature/client/circpathbias.h"
-#include "core/or/connection_edge.h"
static int srm_ncalls;
static entry_connection_t *srm_conn;
diff --git a/src/test/test_relaycrypt.c b/src/test/test_relaycrypt.c
index 4bbf07c3ec..737c243e2d 100644
--- a/src/test/test_relaycrypt.c
+++ b/src/test/test_relaycrypt.c
@@ -1,6 +1,6 @@
/* Copyright 2001-2004 Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CRYPT_PATH_PRIVATE
diff --git a/src/test/test_rendcache.c b/src/test/test_rendcache.c
index 4f544cf21c..e396f9fd50 100644
--- a/src/test/test_rendcache.c
+++ b/src/test/test_rendcache.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -21,8 +21,6 @@
#include "test/rend_test_helpers.h"
#include "test/log_test_helpers.h"
-#define NS_MODULE rend_cache
-
static const int RECENT_TIME = -10;
static const int TIME_IN_THE_PAST = -(REND_CACHE_MAX_AGE + \
REND_CACHE_MAX_SKEW + 60);
@@ -369,13 +367,12 @@ test_rend_cache_store_v2_desc_as_client_with_different_time(void *data)
rend_data_free(mock_rend_query);
}
-#define NS_SUBMODULE lookup_v2_desc_as_dir
-NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void));
+static const routerinfo_t *rcache_lookup_v2_as_dir_get_my_routerinfo(void);
static routerinfo_t *mock_routerinfo;
static const routerinfo_t *
-NS(router_get_my_routerinfo)(void)
+rcache_lookup_v2_as_dir_get_my_routerinfo(void)
{
if (!mock_routerinfo) {
mock_routerinfo = tor_malloc(sizeof(routerinfo_t));
@@ -395,7 +392,8 @@ test_rend_cache_lookup_v2_desc_as_dir(void *data)
(void)data;
- NS_MOCK(router_get_my_routerinfo);
+ MOCK(router_get_my_routerinfo,
+ rcache_lookup_v2_as_dir_get_my_routerinfo);
rend_cache_init();
@@ -418,20 +416,17 @@ test_rend_cache_lookup_v2_desc_as_dir(void *data)
tt_assert(ret_desc);
done:
- NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(router_get_my_routerinfo);
tor_free(mock_routerinfo);
rend_cache_free_all();
rend_encoded_v2_service_descriptor_free(desc_holder);
tor_free(service_id);
}
-#undef NS_SUBMODULE
-
-#define NS_SUBMODULE store_v2_desc_as_dir
-NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void));
+static const routerinfo_t *rcache_store_v2_as_dir_get_my_routerinfo(void);
static const routerinfo_t *
-NS(router_get_my_routerinfo)(void)
+rcache_store_v2_as_dir_get_my_routerinfo(void)
{
return mock_routerinfo;
}
@@ -444,7 +439,8 @@ test_rend_cache_store_v2_desc_as_dir(void *data)
rend_encoded_v2_service_descriptor_t *desc_holder = NULL;
char *service_id = NULL;
- NS_MOCK(router_get_my_routerinfo);
+ MOCK(router_get_my_routerinfo,
+ rcache_store_v2_as_dir_get_my_routerinfo);
rend_cache_init();
@@ -485,7 +481,7 @@ test_rend_cache_store_v2_desc_as_dir(void *data)
tt_int_op(ret, OP_EQ, 0);
done:
- NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(router_get_my_routerinfo);
rend_encoded_v2_service_descriptor_free(desc_holder);
tor_free(service_id);
rend_cache_free_all();
@@ -505,7 +501,8 @@ test_rend_cache_store_v2_desc_as_dir_with_different_time(void *data)
rend_encoded_v2_service_descriptor_t *desc_holder_newer;
rend_encoded_v2_service_descriptor_t *desc_holder_older;
- NS_MOCK(router_get_my_routerinfo);
+ MOCK(router_get_my_routerinfo,
+ rcache_store_v2_as_dir_get_my_routerinfo);
rend_cache_init();
@@ -543,7 +540,7 @@ test_rend_cache_store_v2_desc_as_dir_with_different_time(void *data)
tt_int_op(ret, OP_EQ, 0);
done:
- NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(router_get_my_routerinfo);
rend_cache_free_all();
rend_service_descriptor_free(generated);
tor_free(service_id);
@@ -568,7 +565,8 @@ test_rend_cache_store_v2_desc_as_dir_with_different_content(void *data)
rend_encoded_v2_service_descriptor_t *desc_holder_one = NULL;
rend_encoded_v2_service_descriptor_t *desc_holder_two = NULL;
- NS_MOCK(router_get_my_routerinfo);
+ MOCK(router_get_my_routerinfo,
+ rcache_store_v2_as_dir_get_my_routerinfo);
rend_cache_init();
@@ -602,7 +600,7 @@ test_rend_cache_store_v2_desc_as_dir_with_different_content(void *data)
tt_int_op(ret, OP_EQ, 0);
done:
- NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(router_get_my_routerinfo);
rend_cache_free_all();
rend_service_descriptor_free(generated);
tor_free(service_id);
@@ -613,8 +611,6 @@ test_rend_cache_store_v2_desc_as_dir_with_different_content(void *data)
rend_encoded_v2_service_descriptor_free(desc_holder_two);
}
-#undef NS_SUBMODULE
-
static void
test_rend_cache_init(void *data)
{
@@ -1074,8 +1070,6 @@ test_rend_cache_intro_failure_note(void *data)
rend_cache_free_all();
}
-#define NS_SUBMODULE clean_v2_descs_as_dir
-
static void
test_rend_cache_clean_v2_descs_as_dir(void *data)
{
@@ -1116,8 +1110,6 @@ test_rend_cache_clean_v2_descs_as_dir(void *data)
rend_cache_free_all();
}
-#undef NS_SUBMODULE
-
static void
test_rend_cache_entry_allocation(void *data)
{
@@ -1250,4 +1242,3 @@ struct testcase_t rend_cache_tests[] = {
test_rend_cache_validate_intro_point_failure, 0, NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_replay.c b/src/test/test_replay.c
index 28a508bf4d..1487b0a29d 100644
--- a/src/test/test_replay.c
+++ b/src/test/test_replay.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define REPLAYCACHE_PRIVATE
diff --git a/src/test/test_rng.c b/src/test/test_rng.c
index dcf08fff1d..ebaffb74f5 100644
--- a/src/test/test_rng.c
+++ b/src/test/test_rng.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/*
diff --git a/src/test/test_router.c b/src/test/test_router.c
index 5477ab51e9..cf0c2b3dd1 100644
--- a/src/test/test_router.c
+++ b/src/test/test_router.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* Copyright (c) 2017, isis agora lovecruft */
/* See LICENSE for licensing information */
@@ -8,11 +8,13 @@
**/
#define CONFIG_PRIVATE
+#define CONNECTION_PRIVATE
#define ROUTER_PRIVATE
#include "core/or/or.h"
#include "app/config/config.h"
#include "core/mainloop/mainloop.h"
+#include "core/mainloop/connection.h"
#include "feature/hibernate/hibernate.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/networkstatus_st.h"
@@ -27,16 +29,19 @@
#include "lib/crypt_ops/crypto_ed25519.h"
#include "lib/encoding/confline.h"
+#include "core/or/listener_connection_st.h"
+
/* Test suite stuff */
#include "test/test.h"
#include "test/log_test_helpers.h"
-NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void));
+static const routerinfo_t * rtr_tests_router_get_my_routerinfo(void);
+ATTR_UNUSED static int rtr_tests_router_get_my_routerinfo_called = 0;
static routerinfo_t* mock_routerinfo;
static const routerinfo_t*
-NS(router_get_my_routerinfo)(void)
+rtr_tests_router_get_my_routerinfo(void)
{
crypto_pk_t* ident_key;
crypto_pk_t* tap_key;
@@ -86,19 +91,20 @@ test_router_dump_router_to_string_no_bridge_distribution_method(void *arg)
char* found = NULL;
(void)arg;
- NS_MOCK(router_get_my_routerinfo);
+ MOCK(router_get_my_routerinfo,
+ rtr_tests_router_get_my_routerinfo);
options->ORPort_set = 1;
options->BridgeRelay = 1;
/* Generate keys which router_dump_router_to_string() expects to exist. */
- tt_int_op(0, ==, curve25519_keypair_generate(&ntor_keypair, 0));
- tt_int_op(0, ==, ed25519_keypair_generate(&signing_keypair, 0));
+ tt_int_op(0, OP_EQ, curve25519_keypair_generate(&ntor_keypair, 0));
+ tt_int_op(0, OP_EQ, ed25519_keypair_generate(&signing_keypair, 0));
/* Set up part of our routerinfo_t so that we don't trigger any other
* assertions in router_dump_router_to_string(). */
router = (routerinfo_t*)router_get_my_routerinfo();
- tt_ptr_op(router, !=, NULL);
+ tt_ptr_op(router, OP_NE, NULL);
/* The real router_get_my_routerinfo() looks up onion_curve25519_pkey using
* get_current_curve25519_keypair(), but we don't initialise static data in
@@ -115,12 +121,12 @@ test_router_dump_router_to_string_no_bridge_distribution_method(void *arg)
&ntor_keypair,
&signing_keypair);
crypto_pk_free(onion_pkey);
- tt_ptr_op(desc, !=, NULL);
+ tt_ptr_op(desc, OP_NE, NULL);
found = strstr(desc, needle);
- tt_ptr_op(found, !=, NULL);
+ tt_ptr_op(found, OP_NE, NULL);
done:
- NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(router_get_my_routerinfo);
tor_free(desc);
}
@@ -484,6 +490,117 @@ test_router_get_my_family(void *arg)
#undef CLEAR
}
+static smartlist_t *fake_connection_array = NULL;
+static smartlist_t *
+mock_get_connection_array(void)
+{
+ return fake_connection_array;
+}
+
+static void
+test_router_get_advertised_or_port(void *arg)
+{
+ (void)arg;
+ int r, w=0, n=0;
+ char *msg=NULL;
+ or_options_t *opts = options_new();
+ listener_connection_t *listener = NULL;
+ tor_addr_port_t ipv6;
+
+ // Test one failing case of router_get_advertised_ipv6_or_ap().
+ router_get_advertised_ipv6_or_ap(opts, &ipv6);
+ tt_str_op(fmt_addrport(&ipv6.addr, ipv6.port), OP_EQ, "[::]:0");
+
+ // And one failing case of router_get_advertised_or_port().
+ tt_int_op(0, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET));
+ tt_int_op(0, OP_EQ, router_get_advertised_or_port(opts));
+
+ // Set up a couple of configured ports.
+ config_line_append(&opts->ORPort_lines, "ORPort", "[1234::5678]:auto");
+ config_line_append(&opts->ORPort_lines, "ORPort", "5.6.7.8:9999");
+ r = parse_ports(opts, 0, &msg, &n, &w);
+ tt_assert(r == 0);
+
+ // There are no listeners, so the "auto" case will turn up no results.
+ tt_int_op(0, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET6));
+ router_get_advertised_ipv6_or_ap(opts, &ipv6);
+ tt_str_op(fmt_addrport(&ipv6.addr, ipv6.port), OP_EQ, "[::]:0");
+
+ // This will return the matching value from the configured port.
+ tt_int_op(9999, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET));
+ tt_int_op(9999, OP_EQ, router_get_advertised_or_port(opts));
+
+ // Now set up a dummy listener.
+ MOCK(get_connection_array, mock_get_connection_array);
+ fake_connection_array = smartlist_new();
+ listener = listener_connection_new(CONN_TYPE_OR_LISTENER, AF_INET6);
+ TO_CONN(listener)->port = 54321;
+ smartlist_add(fake_connection_array, TO_CONN(listener));
+
+ // We should get a port this time.
+ tt_int_op(54321, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET6));
+
+ // Test one succeeding case of router_get_advertised_ipv6_or_ap().
+ router_get_advertised_ipv6_or_ap(opts, &ipv6);
+ tt_str_op(fmt_addrport(&ipv6.addr, ipv6.port), OP_EQ,
+ "[1234::5678]:54321");
+
+ // This will return the matching value from the configured port.
+ tt_int_op(9999, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET));
+ tt_int_op(9999, OP_EQ, router_get_advertised_or_port(opts));
+
+ done:
+ or_options_free(opts);
+ config_free_all();
+ smartlist_free(fake_connection_array);
+ connection_free_minimal(TO_CONN(listener));
+ UNMOCK(get_connection_array);
+}
+
+static void
+test_router_get_advertised_or_port_localhost(void *arg)
+{
+ (void)arg;
+ int r, w=0, n=0;
+ char *msg=NULL;
+ or_options_t *opts = options_new();
+ tor_addr_port_t ipv6;
+
+ // Set up a couple of configured ports on localhost.
+ config_line_append(&opts->ORPort_lines, "ORPort", "[::1]:9999");
+ config_line_append(&opts->ORPort_lines, "ORPort", "127.0.0.1:8888");
+ r = parse_ports(opts, 0, &msg, &n, &w);
+ tt_assert(r == 0);
+
+ // We should refuse to advertise them, since we have default dirauths.
+ router_get_advertised_ipv6_or_ap(opts, &ipv6);
+ tt_str_op(fmt_addrport(&ipv6.addr, ipv6.port), OP_EQ, "[::]:0");
+ // But the lower-level function should still report the correct value
+ tt_int_op(9999, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET6));
+
+ // The IPv4 checks are done in resolve_my_address(), which doesn't use
+ // ORPorts so we can't test them here. (See #33681.) Both these lower-level
+ // functions should still report the correct value.
+ tt_int_op(8888, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET));
+ tt_int_op(8888, OP_EQ, router_get_advertised_or_port(opts));
+
+ // Now try with a fake authority set up.
+ config_line_append(&opts->DirAuthorities, "DirAuthority",
+ "127.0.0.1:1066 "
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
+
+ tt_int_op(9999, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET6));
+ router_get_advertised_ipv6_or_ap(opts, &ipv6);
+ tt_str_op(fmt_addrport(&ipv6.addr, ipv6.port), OP_EQ, "[::1]:9999");
+
+ tt_int_op(8888, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET));
+ tt_int_op(8888, OP_EQ, router_get_advertised_or_port(opts));
+
+ done:
+ or_options_free(opts);
+ config_free_all();
+}
+
#define ROUTER_TEST(name, flags) \
{ #name, test_router_ ## name, flags, NULL, NULL }
@@ -492,5 +609,7 @@ struct testcase_t router_tests[] = {
ROUTER_TEST(dump_router_to_string_no_bridge_distribution_method, TT_FORK),
ROUTER_TEST(mark_if_too_old, TT_FORK),
ROUTER_TEST(get_my_family, TT_FORK),
+ ROUTER_TEST(get_advertised_or_port, TT_FORK),
+ ROUTER_TEST(get_advertised_or_port_localhost, TT_FORK),
END_OF_TESTCASES
};
diff --git a/src/test/test_routerkeys.c b/src/test/test_routerkeys.c
index 0c6b533698..fc437dccc0 100644
--- a/src/test/test_routerkeys.c
+++ b/src/test/test_routerkeys.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_routerlist.c b/src/test/test_routerlist.c
index 6d596e87ea..f2a83c18a3 100644
--- a/src/test/test_routerlist.c
+++ b/src/test/test_routerlist.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_routerset.c b/src/test/test_routerset.c
index cc73e6c20a..892ac6e210 100644
--- a/src/test/test_routerset.c
+++ b/src/test/test_routerset.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ROUTERSET_PRIVATE
@@ -18,17 +18,13 @@
#include "test/test.h"
-#define NS_MODULE routerset
-
-#define NS_SUBMODULE routerset_new
-
/*
* Functional (blackbox) test to determine that each member of the routerset
* is non-NULL
*/
static void
-NS(test_main)(void *arg)
+test_rset_new(void *arg)
{
routerset_t *rs;
(void)arg;
@@ -46,15 +42,12 @@ NS(test_main)(void *arg)
routerset_free(rs);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE routerset_get_countryname
-
/*
* Functional test to strip the braces from a "{xx}" country code string.
*/
static void
-NS(test_main)(void *arg)
+test_rset_get_countryname(void *arg)
{
const char *input;
char *name;
@@ -91,257 +84,272 @@ NS(test_main)(void *arg)
tor_free(name);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_refresh_counties, geoip_not_loaded)
-
/*
* Structural (whitebox) test for routerset_refresh_counties, when the GeoIP DB
* is not loaded.
*/
-NS_DECL(int, geoip_is_loaded, (sa_family_t family));
-NS_DECL(int, geoip_get_n_countries, (void));
+static int rset_refresh_geoip_not_loaded_geoip_is_loaded(sa_family_t family);
+static int rset_refresh_geoip_not_loaded_geoip_is_loaded_called = 0;
+static int rset_refresh_geoip_not_loaded_geoip_get_n_countries(void);
+static int rset_refresh_geoip_not_loaded_geoip_get_n_countries_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_refresh_geoip_not_loaded(void *arg)
{
routerset_t *set = routerset_new();
(void)arg;
- NS_MOCK(geoip_is_loaded);
- NS_MOCK(geoip_get_n_countries);
+ MOCK(geoip_is_loaded,
+ rset_refresh_geoip_not_loaded_geoip_is_loaded);
+ MOCK(geoip_get_n_countries,
+ rset_refresh_geoip_not_loaded_geoip_get_n_countries);
routerset_refresh_countries(set);
tt_ptr_op(set->countries, OP_EQ, NULL);
tt_int_op(set->n_countries, OP_EQ, 0);
- tt_int_op(CALLED(geoip_is_loaded), OP_EQ, 1);
- tt_int_op(CALLED(geoip_get_n_countries), OP_EQ, 0);
+ tt_int_op(rset_refresh_geoip_not_loaded_geoip_is_loaded_called, OP_EQ, 1);
+ tt_int_op(rset_refresh_geoip_not_loaded_geoip_get_n_countries_called,
+ OP_EQ, 0);
done:
- NS_UNMOCK(geoip_is_loaded);
- NS_UNMOCK(geoip_get_n_countries);
+ UNMOCK(geoip_is_loaded);
+ UNMOCK(geoip_get_n_countries);
routerset_free(set);
}
static int
-NS(geoip_is_loaded)(sa_family_t family)
+rset_refresh_geoip_not_loaded_geoip_is_loaded(sa_family_t family)
{
(void)family;
- CALLED(geoip_is_loaded)++;
+ rset_refresh_geoip_not_loaded_geoip_is_loaded_called++;
return 0;
}
static int
-NS(geoip_get_n_countries)(void)
+rset_refresh_geoip_not_loaded_geoip_get_n_countries(void)
{
- CALLED(geoip_get_n_countries)++;
+ rset_refresh_geoip_not_loaded_geoip_get_n_countries_called++;
return 0;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_refresh_counties, no_countries)
-
/*
* Structural test for routerset_refresh_counties, when there are no countries.
*/
-NS_DECL(int, geoip_is_loaded, (sa_family_t family));
-NS_DECL(int, geoip_get_n_countries, (void));
-NS_DECL(country_t, geoip_get_country, (const char *country));
+static int rset_refresh_no_countries_geoip_is_loaded(sa_family_t family);
+static int rset_refresh_no_countries_geoip_is_loaded_called = 0;
+static int rset_refresh_no_countries_geoip_get_n_countries(void);
+static int rset_refresh_no_countries_geoip_get_n_countries_called = 0;
+static country_t rset_refresh_no_countries_geoip_get_country(
+ const char *country);
+static int rset_refresh_no_countries_geoip_get_country_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_refresh_no_countries(void *arg)
{
routerset_t *set = routerset_new();
(void)arg;
- NS_MOCK(geoip_is_loaded);
- NS_MOCK(geoip_get_n_countries);
- NS_MOCK(geoip_get_country);
+ MOCK(geoip_is_loaded,
+ rset_refresh_no_countries_geoip_is_loaded);
+ MOCK(geoip_get_n_countries,
+ rset_refresh_no_countries_geoip_get_n_countries);
+ MOCK(geoip_get_country,
+ rset_refresh_no_countries_geoip_get_country);
routerset_refresh_countries(set);
tt_ptr_op(set->countries, OP_NE, NULL);
tt_int_op(set->n_countries, OP_EQ, 1);
tt_int_op((unsigned int)(*set->countries), OP_EQ, 0);
- tt_int_op(CALLED(geoip_is_loaded), OP_EQ, 1);
- tt_int_op(CALLED(geoip_get_n_countries), OP_EQ, 1);
- tt_int_op(CALLED(geoip_get_country), OP_EQ, 0);
+ tt_int_op(rset_refresh_no_countries_geoip_is_loaded_called, OP_EQ, 1);
+ tt_int_op(rset_refresh_no_countries_geoip_get_n_countries_called, OP_EQ, 1);
+ tt_int_op(rset_refresh_no_countries_geoip_get_country_called, OP_EQ, 0);
done:
- NS_UNMOCK(geoip_is_loaded);
- NS_UNMOCK(geoip_get_n_countries);
- NS_UNMOCK(geoip_get_country);
+ UNMOCK(geoip_is_loaded);
+ UNMOCK(geoip_get_n_countries);
+ UNMOCK(geoip_get_country);
routerset_free(set);
}
static int
-NS(geoip_is_loaded)(sa_family_t family)
+rset_refresh_no_countries_geoip_is_loaded(sa_family_t family)
{
(void)family;
- CALLED(geoip_is_loaded)++;
+ rset_refresh_no_countries_geoip_is_loaded_called++;
return 1;
}
static int
-NS(geoip_get_n_countries)(void)
+rset_refresh_no_countries_geoip_get_n_countries(void)
{
- CALLED(geoip_get_n_countries)++;
+ rset_refresh_no_countries_geoip_get_n_countries_called++;
return 1;
}
static country_t
-NS(geoip_get_country)(const char *countrycode)
+rset_refresh_no_countries_geoip_get_country(const char *countrycode)
{
(void)countrycode;
- CALLED(geoip_get_country)++;
+ rset_refresh_no_countries_geoip_get_country_called++;
return 1;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_refresh_counties, one_valid_country)
-
/*
* Structural test for routerset_refresh_counties, with one valid country.
*/
-NS_DECL(int, geoip_is_loaded, (sa_family_t family));
-NS_DECL(int, geoip_get_n_countries, (void));
-NS_DECL(country_t, geoip_get_country, (const char *country));
+static int rset_refresh_one_valid_country_geoip_is_loaded(sa_family_t family);
+static int rset_refresh_one_valid_country_geoip_is_loaded_called = 0;
+static int rset_refresh_one_valid_country_geoip_get_n_countries(void);
+static int rset_refresh_one_valid_country_geoip_get_n_countries_called = 0;
+static country_t rset_refresh_one_valid_country_geoip_get_country(
+ const char *country);
+static int rset_refresh_one_valid_country_geoip_get_country_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_refresh_one_valid_country(void *arg)
{
routerset_t *set = routerset_new();
(void)arg;
- NS_MOCK(geoip_is_loaded);
- NS_MOCK(geoip_get_n_countries);
- NS_MOCK(geoip_get_country);
+ MOCK(geoip_is_loaded,
+ rset_refresh_one_valid_country_geoip_is_loaded);
+ MOCK(geoip_get_n_countries,
+ rset_refresh_one_valid_country_geoip_get_n_countries);
+ MOCK(geoip_get_country,
+ rset_refresh_one_valid_country_geoip_get_country);
smartlist_add(set->country_names, tor_strndup("foo", 3));
routerset_refresh_countries(set);
tt_ptr_op(set->countries, OP_NE, NULL);
tt_int_op(set->n_countries, OP_EQ, 2);
- tt_int_op(CALLED(geoip_is_loaded), OP_EQ, 1);
- tt_int_op(CALLED(geoip_get_n_countries), OP_EQ, 1);
- tt_int_op(CALLED(geoip_get_country), OP_EQ, 1);
+ tt_int_op(rset_refresh_one_valid_country_geoip_is_loaded_called, OP_EQ, 1);
+ tt_int_op(rset_refresh_one_valid_country_geoip_get_n_countries_called,
+ OP_EQ, 1);
+ tt_int_op(rset_refresh_one_valid_country_geoip_get_country_called, OP_EQ, 1);
tt_int_op((unsigned int)(*set->countries), OP_NE, 0);
done:
- NS_UNMOCK(geoip_is_loaded);
- NS_UNMOCK(geoip_get_n_countries);
- NS_UNMOCK(geoip_get_country);
+ UNMOCK(geoip_is_loaded);
+ UNMOCK(geoip_get_n_countries);
+ UNMOCK(geoip_get_country);
routerset_free(set);
}
static int
-NS(geoip_is_loaded)(sa_family_t family)
+rset_refresh_one_valid_country_geoip_is_loaded(sa_family_t family)
{
(void)family;
- CALLED(geoip_is_loaded)++;
+ rset_refresh_one_valid_country_geoip_is_loaded_called++;
return 1;
}
static int
-NS(geoip_get_n_countries)(void)
+rset_refresh_one_valid_country_geoip_get_n_countries(void)
{
- CALLED(geoip_get_n_countries)++;
+ rset_refresh_one_valid_country_geoip_get_n_countries_called++;
return 2;
}
static country_t
-NS(geoip_get_country)(const char *countrycode)
+rset_refresh_one_valid_country_geoip_get_country(const char *countrycode)
{
(void)countrycode;
- CALLED(geoip_get_country)++;
+ rset_refresh_one_valid_country_geoip_get_country_called++;
return 1;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_refresh_counties, one_invalid_country)
-
/*
* Structural test for routerset_refresh_counties, with one invalid
* country code..
*/
-NS_DECL(int, geoip_is_loaded, (sa_family_t family));
-NS_DECL(int, geoip_get_n_countries, (void));
-NS_DECL(country_t, geoip_get_country, (const char *country));
+static int rset_refresh_one_invalid_country_geoip_is_loaded(
+ sa_family_t family);
+static int rset_refresh_one_invalid_country_geoip_is_loaded_called = 0;
+static int rset_refresh_one_invalid_country_geoip_get_n_countries(void);
+static int rset_refresh_one_invalid_country_geoip_get_n_countries_called = 0;
+static country_t rset_refresh_one_invalid_country_geoip_get_country(
+ const char *country);
+static int rset_refresh_one_invalid_country_geoip_get_country_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_refresh_one_invalid_country(void *arg)
{
routerset_t *set = routerset_new();
(void)arg;
- NS_MOCK(geoip_is_loaded);
- NS_MOCK(geoip_get_n_countries);
- NS_MOCK(geoip_get_country);
+ MOCK(geoip_is_loaded,
+ rset_refresh_one_invalid_country_geoip_is_loaded);
+ MOCK(geoip_get_n_countries,
+ rset_refresh_one_invalid_country_geoip_get_n_countries);
+ MOCK(geoip_get_country,
+ rset_refresh_one_invalid_country_geoip_get_country);
smartlist_add(set->country_names, tor_strndup("foo", 3));
routerset_refresh_countries(set);
tt_ptr_op(set->countries, OP_NE, NULL);
tt_int_op(set->n_countries, OP_EQ, 2);
- tt_int_op(CALLED(geoip_is_loaded), OP_EQ, 1);
- tt_int_op(CALLED(geoip_get_n_countries), OP_EQ, 1);
- tt_int_op(CALLED(geoip_get_country), OP_EQ, 1);
+ tt_int_op(rset_refresh_one_invalid_country_geoip_is_loaded_called, OP_EQ, 1);
+ tt_int_op(rset_refresh_one_invalid_country_geoip_get_n_countries_called,
+ OP_EQ, 1);
+ tt_int_op(rset_refresh_one_invalid_country_geoip_get_country_called,
+ OP_EQ, 1);
tt_int_op((unsigned int)(*set->countries), OP_EQ, 0);
done:
- NS_UNMOCK(geoip_is_loaded);
- NS_UNMOCK(geoip_get_n_countries);
- NS_UNMOCK(geoip_get_country);
+ UNMOCK(geoip_is_loaded);
+ UNMOCK(geoip_get_n_countries);
+ UNMOCK(geoip_get_country);
routerset_free(set);
}
static int
-NS(geoip_is_loaded)(sa_family_t family)
+rset_refresh_one_invalid_country_geoip_is_loaded(sa_family_t family)
{
(void)family;
- CALLED(geoip_is_loaded)++;
+ rset_refresh_one_invalid_country_geoip_is_loaded_called++;
return 1;
}
static int
-NS(geoip_get_n_countries)(void)
+rset_refresh_one_invalid_country_geoip_get_n_countries(void)
{
- CALLED(geoip_get_n_countries)++;
+ rset_refresh_one_invalid_country_geoip_get_n_countries_called++;
return 2;
}
static country_t
-NS(geoip_get_country)(const char *countrycode)
+rset_refresh_one_invalid_country_geoip_get_country(const char *countrycode)
{
(void)countrycode;
- CALLED(geoip_get_country)++;
+ rset_refresh_one_invalid_country_geoip_get_country_called++;
return -1;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_parse, malformed)
-
/*
* Functional test, with a malformed string to parse.
*/
static void
-NS(test_main)(void *arg)
+test_rset_parse_malformed(void *arg)
{
routerset_t *set = routerset_new();
const char *s = "_";
@@ -356,16 +364,13 @@ NS(test_main)(void *arg)
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_parse, valid_hexdigest)
-
/*
* Functional test for routerset_parse, that routerset_parse returns 0
* on a valid hexdigest entry.
*/
static void
-NS(test_main)(void *arg)
+test_rset_parse_valid_hexdigest(void *arg)
{
routerset_t *set;
const char *s;
@@ -382,15 +387,12 @@ NS(test_main)(void *arg)
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_parse, valid_nickname)
-
/*
* Functional test for routerset_parse, when given a valid nickname as input.
*/
static void
-NS(test_main)(void *arg)
+test_rset_parse_valid_nickname(void *arg)
{
routerset_t *set;
const char *s;
@@ -407,15 +409,12 @@ NS(test_main)(void *arg)
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_parse, get_countryname)
-
/*
* Functional test for routerset_parse, when given a valid countryname.
*/
static void
-NS(test_main)(void *arg)
+test_rset_parse_get_countryname(void *arg)
{
routerset_t *set;
const char *s;
@@ -432,158 +431,158 @@ NS(test_main)(void *arg)
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_parse, policy_wildcard)
-
/*
* Structural test for routerset_parse, when given a valid wildcard policy.
*/
-NS_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string,
- (const char *s, int assume_action, int *malformed_list));
+static addr_policy_t * rset_parse_policy_wildcard_parse_item_from_string(
+ const char *s, int assume_action, int *malformed_list);
+static int rset_parse_policy_wildcard_parse_item_from_string_called = 0;
-static addr_policy_t *NS(mock_addr_policy);
+static addr_policy_t *rset_parse_policy_wildcard_mock_addr_policy;
static void
-NS(test_main)(void *arg)
+test_rset_parse_policy_wildcard(void *arg)
{
routerset_t *set;
const char *s;
int r;
(void)arg;
- NS_MOCK(router_parse_addr_policy_item_from_string);
- NS(mock_addr_policy) = tor_malloc_zero(sizeof(addr_policy_t));
+ MOCK(router_parse_addr_policy_item_from_string,
+ rset_parse_policy_wildcard_parse_item_from_string);
+ rset_parse_policy_wildcard_mock_addr_policy =
+ tor_malloc_zero(sizeof(addr_policy_t));
set = routerset_new();
s = "*";
r = routerset_parse(set, s, "");
tt_int_op(r, OP_EQ, 0);
tt_int_op(smartlist_len(set->policies), OP_NE, 0);
- tt_int_op(CALLED(router_parse_addr_policy_item_from_string), OP_EQ, 1);
+ tt_int_op(rset_parse_policy_wildcard_parse_item_from_string_called,
+ OP_EQ, 1);
done:
routerset_free(set);
}
addr_policy_t *
-NS(router_parse_addr_policy_item_from_string)(const char *s,
+rset_parse_policy_wildcard_parse_item_from_string(const char *s,
int assume_action,
int *malformed_list)
{
(void)s;
(void)assume_action;
(void)malformed_list;
- CALLED(router_parse_addr_policy_item_from_string)++;
+ rset_parse_policy_wildcard_parse_item_from_string_called++;
- return NS(mock_addr_policy);
+ return rset_parse_policy_wildcard_mock_addr_policy;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_parse, policy_ipv4)
-
/*
* Structural test for routerset_parse, when given a valid IPv4 address
* literal policy.
*/
-NS_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string,
- (const char *s, int assume_action, int *bogus));
+static addr_policy_t * rset_parse_policy_ipv4_parse_item_from_string(
+ const char *s, int assume_action, int *bogus);
+static int rset_parse_policy_ipv4_parse_item_from_string_called = 0;
-static addr_policy_t *NS(mock_addr_policy);
+static addr_policy_t *rset_parse_policy_ipv4_mock_addr_policy;
static void
-NS(test_main)(void *arg)
+test_rset_parse_policy_ipv4(void *arg)
{
routerset_t *set;
const char *s;
int r;
(void)arg;
- NS_MOCK(router_parse_addr_policy_item_from_string);
- NS(mock_addr_policy) = tor_malloc_zero(sizeof(addr_policy_t));
+ MOCK(router_parse_addr_policy_item_from_string,
+ rset_parse_policy_ipv4_parse_item_from_string);
+ rset_parse_policy_ipv4_mock_addr_policy =
+ tor_malloc_zero(sizeof(addr_policy_t));
set = routerset_new();
s = "127.0.0.1";
r = routerset_parse(set, s, "");
tt_int_op(r, OP_EQ, 0);
tt_int_op(smartlist_len(set->policies), OP_NE, 0);
- tt_int_op(CALLED(router_parse_addr_policy_item_from_string), OP_EQ, 1);
+ tt_int_op(rset_parse_policy_ipv4_parse_item_from_string_called, OP_EQ, 1);
done:
routerset_free(set);
}
addr_policy_t *
-NS(router_parse_addr_policy_item_from_string)(const char *s, int assume_action,
- int *bogus)
+rset_parse_policy_ipv4_parse_item_from_string(
+ const char *s, int assume_action,
+ int *bogus)
{
(void)s;
(void)assume_action;
- CALLED(router_parse_addr_policy_item_from_string)++;
+ rset_parse_policy_ipv4_parse_item_from_string_called++;
*bogus = 0;
- return NS(mock_addr_policy);
+ return rset_parse_policy_ipv4_mock_addr_policy;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_parse, policy_ipv6)
-
/*
* Structural test for routerset_parse, when given a valid IPv6 address
* literal policy.
*/
-NS_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string,
- (const char *s, int assume_action, int *bad));
+static addr_policy_t * rset_parse_policy_ipv6_parse_item_from_string(
+ const char *s, int assume_action, int *bad);
+static int rset_parse_policy_ipv6_parse_item_from_string_called = 0;
-static addr_policy_t *NS(mock_addr_policy);
+static addr_policy_t *rset_parse_policy_ipv6_mock_addr_policy;
static void
-NS(test_main)(void *arg)
+test_rset_parse_policy_ipv6(void *arg)
{
routerset_t *set;
const char *s;
int r;
(void)arg;
- NS_MOCK(router_parse_addr_policy_item_from_string);
- NS(mock_addr_policy) = tor_malloc_zero(sizeof(addr_policy_t));
+ MOCK(router_parse_addr_policy_item_from_string,
+ rset_parse_policy_ipv6_parse_item_from_string);
+ rset_parse_policy_ipv6_mock_addr_policy =
+ tor_malloc_zero(sizeof(addr_policy_t));
set = routerset_new();
s = "::1";
r = routerset_parse(set, s, "");
tt_int_op(r, OP_EQ, 0);
tt_int_op(smartlist_len(set->policies), OP_NE, 0);
- tt_int_op(CALLED(router_parse_addr_policy_item_from_string), OP_EQ, 1);
+ tt_int_op(rset_parse_policy_ipv6_parse_item_from_string_called, OP_EQ, 1);
done:
routerset_free(set);
}
addr_policy_t *
-NS(router_parse_addr_policy_item_from_string)(const char *s,
+rset_parse_policy_ipv6_parse_item_from_string(const char *s,
int assume_action, int *bad)
{
(void)s;
(void)assume_action;
- CALLED(router_parse_addr_policy_item_from_string)++;
+ rset_parse_policy_ipv6_parse_item_from_string_called++;
*bad = 0;
- return NS(mock_addr_policy);
+ return rset_parse_policy_ipv6_mock_addr_policy;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_union, source_bad)
-
/*
* Structural test for routerset_union, when given a bad source argument.
*/
-NS_DECL(smartlist_t *, smartlist_new, (void));
+static smartlist_t * rset_union_source_bad_smartlist_new(void);
+static int rset_union_source_bad_smartlist_new_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_union_source_bad(void *arg)
{
routerset_t *set, *bad_set;
(void)arg;
@@ -593,16 +592,17 @@ NS(test_main)(void *arg)
smartlist_free(bad_set->list);
bad_set->list = NULL;
- NS_MOCK(smartlist_new);
+ MOCK(smartlist_new,
+ rset_union_source_bad_smartlist_new);
routerset_union(set, NULL);
- tt_int_op(CALLED(smartlist_new), OP_EQ, 0);
+ tt_int_op(rset_union_source_bad_smartlist_new_called, OP_EQ, 0);
routerset_union(set, bad_set);
- tt_int_op(CALLED(smartlist_new), OP_EQ, 0);
+ tt_int_op(rset_union_source_bad_smartlist_new_called, OP_EQ, 0);
done:
- NS_UNMOCK(smartlist_new);
+ UNMOCK(smartlist_new);
routerset_free(set);
/* Just recreate list, so we can simply use routerset_free. */
@@ -611,22 +611,19 @@ NS(test_main)(void *arg)
}
static smartlist_t *
-NS(smartlist_new)(void)
+rset_union_source_bad_smartlist_new(void)
{
- CALLED(smartlist_new)++;
+ rset_union_source_bad_smartlist_new_called++;
return NULL;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_union, one)
-
/*
* Functional test for routerset_union.
*/
static void
-NS(test_main)(void *arg)
+test_rset_union_one(void *arg)
{
routerset_t *src = routerset_new();
routerset_t *tgt;
@@ -643,15 +640,12 @@ NS(test_main)(void *arg)
routerset_free(tgt);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE routerset_is_list
-
/*
* Functional tests for routerset_is_list.
*/
static void
-NS(test_main)(void *arg)
+test_rset_is_list(void *arg)
{
routerset_t *set;
addr_policy_t *policy;
@@ -696,15 +690,12 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE routerset_needs_geoip
-
/*
* Functional tests for routerset_needs_geoip.
*/
static void
-NS(test_main)(void *arg)
+test_rset_needs_geoip(void *arg)
{
routerset_t *set;
int needs_geoip;
@@ -731,15 +722,12 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE routerset_is_empty
-
/*
* Functional tests for routerset_is_empty.
*/
static void
-NS(test_main)(void *arg)
+test_rset_is_empty(void *arg)
{
routerset_t *set = NULL;
int is_empty;
@@ -765,16 +753,13 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, null_set_or_null_set_list)
-
/*
* Functional test for routerset_contains, when given a NULL set or the
* set has a NULL list.
*/
static void
-NS(test_main)(void *arg)
+test_rset_contains_null_set_or_list(void *arg)
{
routerset_t *set = NULL;
int contains;
@@ -794,16 +779,13 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, set_and_null_nickname)
-
/*
* Functional test for routerset_contains, when given a valid routerset but a
* NULL nickname.
*/
static void
-NS(test_main)(void *arg)
+test_rset_contains_null_nickname(void *arg)
{
routerset_t *set = routerset_new();
char *nickname = NULL;
@@ -819,16 +801,13 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, set_and_nickname)
-
/*
* Functional test for routerset_contains, when given a valid routerset
* and the nickname is in the routerset.
*/
static void
-NS(test_main)(void *arg)
+test_rset_contains_nickname(void *arg)
{
routerset_t *set = routerset_new();
const char *nickname;
@@ -845,16 +824,13 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, set_and_no_nickname)
-
/*
* Functional test for routerset_contains, when given a valid routerset
* and the nickname is not in the routerset.
*/
static void
-NS(test_main)(void *arg)
+test_rset_contains_no_nickname(void *arg)
{
routerset_t *set = routerset_new();
int contains;
@@ -869,16 +845,13 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, set_and_digest)
-
/*
* Functional test for routerset_contains, when given a valid routerset
* and the digest is contained in the routerset.
*/
static void
-NS(test_main)(void *arg)
+test_rset_contains_digest(void *arg)
{
routerset_t *set = routerset_new();
int contains;
@@ -894,16 +867,13 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, set_and_no_digest)
-
/*
* Functional test for routerset_contains, when given a valid routerset
* and the digest is not contained in the routerset.
*/
static void
-NS(test_main)(void *arg)
+test_rset_contains_no_digest(void *arg)
{
routerset_t *set = routerset_new();
int contains;
@@ -920,16 +890,13 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, set_and_null_digest)
-
/*
* Functional test for routerset_contains, when given a valid routerset
* and the digest is NULL.
*/
static void
-NS(test_main)(void *arg)
+test_rset_contains_null_digest(void *arg)
{
routerset_t *set = routerset_new();
int contains;
@@ -945,34 +912,34 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, set_and_addr)
-
/*
* Structural test for routerset_contains, when given a valid routerset
* and the address is rejected by policy.
*/
-NS_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy,
- (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy));
+static addr_policy_result_t rset_contains_addr_cmp_addr_to_policy(
+ const tor_addr_t *addr, uint16_t port,
+ const smartlist_t *policy);
+static int rset_contains_addr_cmp_addr_to_policy_called = 0;
static tor_addr_t MOCK_TOR_ADDR;
#define MOCK_TOR_ADDR_PTR (&MOCK_TOR_ADDR)
static void
-NS(test_main)(void *arg)
+test_rset_contains_addr(void *arg)
{
routerset_t *set = routerset_new();
tor_addr_t *addr = MOCK_TOR_ADDR_PTR;
int contains;
(void)arg;
- NS_MOCK(compare_tor_addr_to_addr_policy);
+ MOCK(compare_tor_addr_to_addr_policy,
+ rset_contains_addr_cmp_addr_to_policy);
contains = routerset_contains(set, addr, 0, NULL, NULL, 0);
routerset_free(set);
- tt_int_op(CALLED(compare_tor_addr_to_addr_policy), OP_EQ, 1);
+ tt_int_op(rset_contains_addr_cmp_addr_to_policy_called, OP_EQ, 1);
tt_int_op(contains, OP_EQ, 3);
done:
@@ -980,12 +947,12 @@ NS(test_main)(void *arg)
}
addr_policy_result_t
-NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port,
+rset_contains_addr_cmp_addr_to_policy(const tor_addr_t *addr, uint16_t port,
const smartlist_t *policy)
{
(void)port;
(void)policy;
- CALLED(compare_tor_addr_to_addr_policy)++;
+ rset_contains_addr_cmp_addr_to_policy_called++;
tt_ptr_op(addr, OP_EQ, MOCK_TOR_ADDR_PTR);
return ADDR_POLICY_REJECTED;
@@ -993,31 +960,31 @@ NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port,
return 0;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, set_and_no_addr)
-
/*
* Structural test for routerset_contains, when given a valid routerset
* and the address is not rejected by policy.
*/
-NS_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy,
- (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy));
+static addr_policy_result_t rset_contains_no_addr_cmp_addr_to_policy(
+ const tor_addr_t *addr, uint16_t port,
+ const smartlist_t *policy);
+static int rset_contains_no_addr_cmp_addr_to_policy_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_contains_no_addr(void *arg)
{
routerset_t *set = routerset_new();
tor_addr_t *addr = MOCK_TOR_ADDR_PTR;
int contains;
(void)arg;
- NS_MOCK(compare_tor_addr_to_addr_policy);
+ MOCK(compare_tor_addr_to_addr_policy,
+ rset_contains_no_addr_cmp_addr_to_policy);
contains = routerset_contains(set, addr, 0, NULL, NULL, 0);
routerset_free(set);
- tt_int_op(CALLED(compare_tor_addr_to_addr_policy), OP_EQ, 1);
+ tt_int_op(rset_contains_no_addr_cmp_addr_to_policy_called, OP_EQ, 1);
tt_int_op(contains, OP_EQ, 0);
done:
@@ -1025,12 +992,12 @@ NS(test_main)(void *arg)
}
addr_policy_result_t
-NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port,
+rset_contains_no_addr_cmp_addr_to_policy(const tor_addr_t *addr, uint16_t port,
const smartlist_t *policy)
{
(void)port;
(void)policy;
- CALLED(compare_tor_addr_to_addr_policy)++;
+ rset_contains_no_addr_cmp_addr_to_policy_called++;
tt_ptr_op(addr, OP_EQ, MOCK_TOR_ADDR_PTR);
return ADDR_POLICY_ACCEPTED;
@@ -1039,25 +1006,25 @@ NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port,
return 0;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, set_and_null_addr)
-
/*
* Structural test for routerset_contains, when given a valid routerset
* and the address is NULL.
*/
-NS_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy,
- (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy));
+static addr_policy_result_t rset_contains_null_addr_cmp_addr_to_policy(
+ const tor_addr_t *addr, uint16_t port,
+ const smartlist_t *policy);
+static int rset_contains_null_addr_cmp_addr_to_policy_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_contains_null_addr(void *arg)
{
routerset_t *set = routerset_new();
int contains;
(void)arg;
- NS_MOCK(compare_tor_addr_to_addr_policy);
+ MOCK(compare_tor_addr_to_addr_policy,
+ rset_contains_null_addr_cmp_addr_to_policy);
contains = routerset_contains(set, NULL, 0, NULL, NULL, 0);
routerset_free(set);
@@ -1069,12 +1036,13 @@ NS(test_main)(void *arg)
}
addr_policy_result_t
-NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port,
+rset_contains_null_addr_cmp_addr_to_policy(
+ const tor_addr_t *addr, uint16_t port,
const smartlist_t *policy)
{
(void)port;
(void)policy;
- CALLED(compare_tor_addr_to_addr_policy)++;
+ rset_contains_null_addr_cmp_addr_to_policy_called++;
tt_ptr_op(addr, OP_EQ, MOCK_TOR_ADDR_PTR);
return ADDR_POLICY_ACCEPTED;
@@ -1083,27 +1051,30 @@ NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port,
return 0;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, countries_no_geoip)
-
/*
* Structural test for routerset_contains, when there is no matching country
* for the address.
*/
-NS_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy,
- (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy));
-NS_DECL(int, geoip_get_country_by_addr, (const tor_addr_t *addr));
+static addr_policy_result_t rset_countries_no_geoip_cmp_addr_to_policy(
+ const tor_addr_t *addr, uint16_t port,
+ const smartlist_t *policy);
+static int rset_countries_no_geoip_cmp_addr_to_policy_called = 0;
+static int rset_countries_no_geoip_geoip_get_country_by_addr(
+ const tor_addr_t *addr);
+static int rset_countries_no_geoip_geoip_get_country_by_addr_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_countries_no_geoip(void *arg)
{
routerset_t *set = routerset_new();
int contains = 1;
(void)arg;
- NS_MOCK(compare_tor_addr_to_addr_policy);
- NS_MOCK(geoip_get_country_by_addr);
+ MOCK(compare_tor_addr_to_addr_policy,
+ rset_countries_no_geoip_cmp_addr_to_policy);
+ MOCK(geoip_get_country_by_addr,
+ rset_countries_no_geoip_geoip_get_country_by_addr);
set->countries = bitarray_init_zero(1);
bitarray_set(set->countries, 1);
@@ -1111,20 +1082,23 @@ NS(test_main)(void *arg)
routerset_free(set);
tt_int_op(contains, OP_EQ, 0);
- tt_int_op(CALLED(compare_tor_addr_to_addr_policy), OP_EQ, 1);
- tt_int_op(CALLED(geoip_get_country_by_addr), OP_EQ, 1);
+ tt_int_op(rset_countries_no_geoip_cmp_addr_to_policy_called,
+ OP_EQ, 1);
+ tt_int_op(rset_countries_no_geoip_geoip_get_country_by_addr_called,
+ OP_EQ, 1);
done:
;
}
addr_policy_result_t
-NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port,
+rset_countries_no_geoip_cmp_addr_to_policy(
+ const tor_addr_t *addr, uint16_t port,
const smartlist_t *policy)
{
(void)port;
(void)policy;
- CALLED(compare_tor_addr_to_addr_policy)++;
+ rset_countries_no_geoip_cmp_addr_to_policy_called++;
tt_ptr_op(addr, OP_EQ, MOCK_TOR_ADDR_PTR);
done:
@@ -1132,36 +1106,39 @@ NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port,
}
int
-NS(geoip_get_country_by_addr)(const tor_addr_t *addr)
+rset_countries_no_geoip_geoip_get_country_by_addr(const tor_addr_t *addr)
{
- CALLED(geoip_get_country_by_addr)++;
+ rset_countries_no_geoip_geoip_get_country_by_addr_called++;
tt_ptr_op(addr, OP_EQ, MOCK_TOR_ADDR_PTR);
done:
return -1;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, countries_geoip)
-
/*
* Structural test for routerset_contains, when there a matching country
* for the address.
*/
-NS_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy,
- (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy));
-NS_DECL(int, geoip_get_country_by_addr, (const tor_addr_t *addr));
+static addr_policy_result_t rset_countries_geoip_cmp_addr_to_policy(
+ const tor_addr_t *addr, uint16_t port,
+ const smartlist_t *policy);
+static int rset_countries_geoip_cmp_addr_to_policy_called = 0;
+static int rset_countries_geoip_geoip_get_country_by_addr(
+ const tor_addr_t *addr);
+static int rset_countries_geoip_geoip_get_country_by_addr_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_countries_geoip(void *arg)
{
routerset_t *set = routerset_new();
int contains = 1;
(void)arg;
- NS_MOCK(compare_tor_addr_to_addr_policy);
- NS_MOCK(geoip_get_country_by_addr);
+ MOCK(compare_tor_addr_to_addr_policy,
+ rset_countries_geoip_cmp_addr_to_policy);
+ MOCK(geoip_get_country_by_addr,
+ rset_countries_geoip_geoip_get_country_by_addr);
set->n_countries = 2;
set->countries = bitarray_init_zero(1);
@@ -1170,20 +1147,24 @@ NS(test_main)(void *arg)
routerset_free(set);
tt_int_op(contains, OP_EQ, 2);
- tt_int_op(CALLED(compare_tor_addr_to_addr_policy), OP_EQ, 1);
- tt_int_op(CALLED(geoip_get_country_by_addr), OP_EQ, 1);
+ tt_int_op(
+ rset_countries_geoip_cmp_addr_to_policy_called,
+ OP_EQ, 1);
+ tt_int_op(rset_countries_geoip_geoip_get_country_by_addr_called,
+ OP_EQ, 1);
done:
;
}
addr_policy_result_t
-NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port,
+rset_countries_geoip_cmp_addr_to_policy(
+ const tor_addr_t *addr, uint16_t port,
const smartlist_t *policy)
{
(void)port;
(void)policy;
- CALLED(compare_tor_addr_to_addr_policy)++;
+ rset_countries_geoip_cmp_addr_to_policy_called++;
tt_ptr_op(addr, OP_EQ, MOCK_TOR_ADDR_PTR);
done:
@@ -1191,25 +1172,22 @@ NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port,
}
int
-NS(geoip_get_country_by_addr)(const tor_addr_t *addr)
+rset_countries_geoip_geoip_get_country_by_addr(const tor_addr_t *addr)
{
- CALLED(geoip_get_country_by_addr)++;
+ rset_countries_geoip_geoip_get_country_by_addr_called++;
tt_ptr_op(addr, OP_EQ, MOCK_TOR_ADDR_PTR);
done:
return 1;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_add_unknown_ccs, only_flag_and_no_ccs)
-
/*
* Functional test for routerset_add_unknown_ccs, where only_if_some_cc_set
* is set and there are no country names.
*/
static void
-NS(test_main)(void *arg)
+test_rset_add_unknown_ccs_only_flag(void *arg)
{
routerset_t *set = routerset_new();
routerset_t **setp = &set;
@@ -1224,26 +1202,26 @@ NS(test_main)(void *arg)
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_add_unknown_ccs, creates_set)
-
/*
* Functional test for routerset_add_unknown_ccs, where the set argument
* is created if passed in as NULL.
*/
/* The mock is only used to stop the test from asserting erroneously. */
-NS_DECL(country_t, geoip_get_country, (const char *country));
+static country_t rset_add_unknown_ccs_creates_set_geoip_get_country(
+ const char *country);
+static int rset_add_unknown_ccs_creates_set_geoip_get_country_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_add_unknown_ccs_creates_set(void *arg)
{
routerset_t *set = NULL;
routerset_t **setp = &set;
int r;
(void)arg;
- NS_MOCK(geoip_get_country);
+ MOCK(geoip_get_country,
+ rset_add_unknown_ccs_creates_set_geoip_get_country);
r = routerset_add_unknown_ccs(setp, 0);
@@ -1256,35 +1234,38 @@ NS(test_main)(void *arg)
}
country_t
-NS(geoip_get_country)(const char *country)
+rset_add_unknown_ccs_creates_set_geoip_get_country(const char *country)
{
(void)country;
- CALLED(geoip_get_country)++;
+ rset_add_unknown_ccs_creates_set_geoip_get_country_called++;
return -1;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_add_unknown_ccs, add_unknown)
-
/*
* Structural test for routerset_add_unknown_ccs, that the "{??}"
* country code is added to the list.
*/
-NS_DECL(country_t, geoip_get_country, (const char *country));
-NS_DECL(int, geoip_is_loaded, (sa_family_t family));
+static country_t rset_add_unknown_ccs_add_unknown_geoip_get_country(
+ const char *country);
+static int rset_add_unknown_ccs_add_unknown_geoip_get_country_called = 0;
+static int rset_add_unknown_ccs_add_unknown_geoip_is_loaded(
+ sa_family_t family);
+static int rset_add_unknown_ccs_add_unknown_geoip_is_loaded_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_add_unknown_ccs_add_unknown(void *arg)
{
routerset_t *set = routerset_new();
routerset_t **setp = &set;
int r;
(void)arg;
- NS_MOCK(geoip_get_country);
- NS_MOCK(geoip_is_loaded);
+ MOCK(geoip_get_country,
+ rset_add_unknown_ccs_add_unknown_geoip_get_country);
+ MOCK(geoip_is_loaded,
+ rset_add_unknown_ccs_add_unknown_geoip_is_loaded);
r = routerset_add_unknown_ccs(setp, 0);
@@ -1298,11 +1279,11 @@ NS(test_main)(void *arg)
}
country_t
-NS(geoip_get_country)(const char *country)
+rset_add_unknown_ccs_add_unknown_geoip_get_country(const char *country)
{
int arg_is_qq, arg_is_a1;
- CALLED(geoip_get_country)++;
+ rset_add_unknown_ccs_add_unknown_geoip_get_country_called++;
arg_is_qq = !strcmp(country, "??");
arg_is_a1 = !strcmp(country, "A1");
@@ -1317,9 +1298,9 @@ NS(geoip_get_country)(const char *country)
}
int
-NS(geoip_is_loaded)(sa_family_t family)
+rset_add_unknown_ccs_add_unknown_geoip_is_loaded(sa_family_t family)
{
- CALLED(geoip_is_loaded)++;
+ rset_add_unknown_ccs_add_unknown_geoip_is_loaded_called++;
tt_int_op(family, OP_EQ, AF_INET);
@@ -1327,27 +1308,29 @@ NS(geoip_is_loaded)(sa_family_t family)
return 0;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_add_unknown_ccs, add_a1)
-
/*
* Structural test for routerset_add_unknown_ccs, that the "{a1}"
* country code is added to the list.
*/
-NS_DECL(country_t, geoip_get_country, (const char *country));
-NS_DECL(int, geoip_is_loaded, (sa_family_t family));
+static country_t rset_add_unknown_ccs_add_a1_geoip_get_country(
+ const char *country);
+static int rset_add_unknown_ccs_add_a1_geoip_get_country_called = 0;
+static int rset_add_unknown_ccs_add_a1_geoip_is_loaded(sa_family_t family);
+static int rset_add_unknown_ccs_add_a1_geoip_is_loaded_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_add_unknown_ccs_add_a1(void *arg)
{
routerset_t *set = routerset_new();
routerset_t **setp = &set;
int r;
(void)arg;
- NS_MOCK(geoip_get_country);
- NS_MOCK(geoip_is_loaded);
+ MOCK(geoip_get_country,
+ rset_add_unknown_ccs_add_a1_geoip_get_country);
+ MOCK(geoip_is_loaded,
+ rset_add_unknown_ccs_add_a1_geoip_is_loaded);
r = routerset_add_unknown_ccs(setp, 0);
@@ -1361,11 +1344,11 @@ NS(test_main)(void *arg)
}
country_t
-NS(geoip_get_country)(const char *country)
+rset_add_unknown_ccs_add_a1_geoip_get_country(const char *country)
{
int arg_is_qq, arg_is_a1;
- CALLED(geoip_get_country)++;
+ rset_add_unknown_ccs_add_a1_geoip_get_country_called++;
arg_is_qq = !strcmp(country, "??");
arg_is_a1 = !strcmp(country, "A1");
@@ -1380,9 +1363,9 @@ NS(geoip_get_country)(const char *country)
}
int
-NS(geoip_is_loaded)(sa_family_t family)
+rset_add_unknown_ccs_add_a1_geoip_is_loaded(sa_family_t family)
{
- CALLED(geoip_is_loaded)++;
+ rset_add_unknown_ccs_add_a1_geoip_is_loaded_called++;
tt_int_op(family, OP_EQ, AF_INET);
@@ -1390,15 +1373,12 @@ NS(geoip_is_loaded)(sa_family_t family)
return 0;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE routerset_contains_extendinfo
-
/*
* Functional test for routerset_contains_extendinfo.
*/
static void
-NS(test_main)(void *arg)
+test_rset_contains_extendinfo(void *arg)
{
routerset_t *set = routerset_new();
extend_info_t ei;
@@ -1418,15 +1398,12 @@ NS(test_main)(void *arg)
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE routerset_contains_router
-
/*
* Functional test for routerset_contains_router.
*/
static void
-NS(test_main)(void *arg)
+test_rset_contains_router(void *arg)
{
routerset_t *set = routerset_new();
routerinfo_t ri;
@@ -1446,9 +1423,6 @@ NS(test_main)(void *arg)
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE routerset_contains_routerstatus
-
/*
* Functional test for routerset_contains_routerstatus.
*/
@@ -1458,7 +1432,7 @@ NS(test_main)(void *arg)
// a bit more or test a bit more.
static void
-NS(test_main)(void *arg)
+test_rset_contains_routerstatus(void *arg)
{
routerset_t *set = routerset_new();
routerstatus_t rs;
@@ -1479,46 +1453,41 @@ NS(test_main)(void *arg)
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains_node, none)
-
/*
* Functional test for routerset_contains_node, when the node has no
* routerset or routerinfo.
*/
-static node_t NS(mock_node);
+static node_t rset_contains_none_mock_node;
static void
-NS(test_main)(void *arg)
+test_rset_contains_none(void *arg)
{
routerset_t *set = routerset_new();
int r;
(void)arg;
- memset(&NS(mock_node), 0, sizeof(NS(mock_node)));
- NS(mock_node).ri = NULL;
- NS(mock_node).rs = NULL;
+ memset(&rset_contains_none_mock_node, 0,
+ sizeof(rset_contains_none_mock_node));
+ rset_contains_none_mock_node.ri = NULL;
+ rset_contains_none_mock_node.rs = NULL;
- r = routerset_contains_node(set, &NS(mock_node));
+ r = routerset_contains_node(set, &rset_contains_none_mock_node);
tt_int_op(r, OP_EQ, 0);
done:
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains_node, routerstatus)
-
/*
* Functional test for routerset_contains_node, when the node has a
* routerset and no routerinfo.
*/
-static node_t NS(mock_node);
+static node_t rset_contains_rs_mock_node;
static void
-NS(test_main)(void *arg)
+test_rset_contains_rs(void *arg)
{
routerset_t *set = routerset_new();
int r;
@@ -1530,27 +1499,24 @@ NS(test_main)(void *arg)
strncpy(rs.nickname, nickname, sizeof(rs.nickname) - 1);
rs.nickname[sizeof(rs.nickname) - 1] = '\0';
- memset(&NS(mock_node), 0, sizeof(NS(mock_node)));
- NS(mock_node).ri = NULL;
- NS(mock_node).rs = &rs;
+ memset(&rset_contains_rs_mock_node, 0, sizeof(rset_contains_rs_mock_node));
+ rset_contains_rs_mock_node.ri = NULL;
+ rset_contains_rs_mock_node.rs = &rs;
- r = routerset_contains_node(set, &NS(mock_node));
+ r = routerset_contains_node(set, &rset_contains_rs_mock_node);
tt_int_op(r, OP_EQ, 4);
done:
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains_node, routerinfo)
-
/*
* Functional test for routerset_contains_node, when the node has no
* routerset and a routerinfo.
*/
static void
-NS(test_main)(void *arg)
+test_rset_contains_routerinfo(void *arg)
{
routerset_t *set = routerset_new();
int r;
@@ -1573,16 +1539,13 @@ NS(test_main)(void *arg)
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, no_routerset)
-
/*
* Functional test for routerset_get_all_nodes, when routerset is NULL or
* the routerset list is NULL.
*/
static void
-NS(test_main)(void *arg)
+test_rset_get_all_no_routerset(void *arg)
{
smartlist_t *out = smartlist_new();
routerset_t *set = NULL;
@@ -1606,30 +1569,29 @@ NS(test_main)(void *arg)
smartlist_free(out);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, list_with_no_nodes)
-
/*
* Structural test for routerset_get_all_nodes, when the routerset list
* is empty.
*/
-NS_DECL(const node_t *, node_get_by_nickname,
- (const char *nickname, unsigned flags));
-static const char *NS(mock_nickname);
+static const node_t * rset_get_all_l_no_nodes_node_get_by_nickname(
+ const char *nickname, unsigned flags);
+static int rset_get_all_l_no_nodes_node_get_by_nickname_called = 0;
+static const char *rset_get_all_l_no_nodes_mock_nickname;
static void
-NS(test_main)(void *arg)
+test_rset_get_all_l_no_nodes(void *arg)
{
smartlist_t *out = smartlist_new();
routerset_t *set = routerset_new();
int out_len;
(void)arg;
- NS_MOCK(node_get_by_nickname);
+ MOCK(node_get_by_nickname,
+ rset_get_all_l_no_nodes_node_get_by_nickname);
- NS(mock_nickname) = "foo";
- smartlist_add_strdup(set->list, NS(mock_nickname));
+ rset_get_all_l_no_nodes_mock_nickname = "foo";
+ smartlist_add_strdup(set->list, rset_get_all_l_no_nodes_mock_nickname);
routerset_get_all_nodes(out, set, NULL, 0);
out_len = smartlist_len(out);
@@ -1638,49 +1600,49 @@ NS(test_main)(void *arg)
routerset_free(set);
tt_int_op(out_len, OP_EQ, 0);
- tt_int_op(CALLED(node_get_by_nickname), OP_EQ, 1);
+ tt_int_op(rset_get_all_l_no_nodes_node_get_by_nickname_called, OP_EQ, 1);
done:
;
}
const node_t *
-NS(node_get_by_nickname)(const char *nickname, unsigned flags)
+rset_get_all_l_no_nodes_node_get_by_nickname(const char *nickname,
+ unsigned flags)
{
- CALLED(node_get_by_nickname)++;
- tt_str_op(nickname, OP_EQ, NS(mock_nickname));
+ rset_get_all_l_no_nodes_node_get_by_nickname_called++;
+ tt_str_op(nickname, OP_EQ, rset_get_all_l_no_nodes_mock_nickname);
tt_uint_op(flags, OP_EQ, 0);
done:
return NULL;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, list_flag_not_running)
-
/*
* Structural test for routerset_get_all_nodes, with the running_only flag
* is set but the nodes are not running.
*/
-NS_DECL(const node_t *, node_get_by_nickname,
- (const char *nickname, unsigned flags));
-static const char *NS(mock_nickname);
-static node_t NS(mock_node);
+static const node_t * rset_get_all_l_not_running_node_get_by_nickname(
+ const char *nickname, unsigned flags);
+static int rset_get_all_l_not_running_node_get_by_nickname_called = 0;
+static const char *rset_get_all_l_not_running_mock_nickname;
+static node_t rset_get_all_l_not_running_mock_node;
static void
-NS(test_main)(void *arg)
+test_rset_get_all_l_not_running(void *arg)
{
smartlist_t *out = smartlist_new();
routerset_t *set = routerset_new();
int out_len;
(void)arg;
- NS_MOCK(node_get_by_nickname);
+ MOCK(node_get_by_nickname,
+ rset_get_all_l_not_running_node_get_by_nickname);
- NS(mock_node).is_running = 0;
- NS(mock_nickname) = "foo";
- smartlist_add_strdup(set->list, NS(mock_nickname));
+ rset_get_all_l_not_running_mock_node.is_running = 0;
+ rset_get_all_l_not_running_mock_nickname = "foo";
+ smartlist_add_strdup(set->list, rset_get_all_l_not_running_mock_nickname);
routerset_get_all_nodes(out, set, NULL, 1);
out_len = smartlist_len(out);
@@ -1689,37 +1651,36 @@ NS(test_main)(void *arg)
routerset_free(set);
tt_int_op(out_len, OP_EQ, 0);
- tt_int_op(CALLED(node_get_by_nickname), OP_EQ, 1);
+ tt_int_op(rset_get_all_l_not_running_node_get_by_nickname_called, OP_EQ, 1);
done:
;
}
const node_t *
-NS(node_get_by_nickname)(const char *nickname, unsigned flags)
+rset_get_all_l_not_running_node_get_by_nickname(const char *nickname,
+ unsigned flags)
{
- CALLED(node_get_by_nickname)++;
- tt_str_op(nickname, OP_EQ, NS(mock_nickname));
+ rset_get_all_l_not_running_node_get_by_nickname_called++;
+ tt_str_op(nickname, OP_EQ, rset_get_all_l_not_running_mock_nickname);
tt_int_op(flags, OP_EQ, 0);
done:
- return &NS(mock_node);
+ return &rset_get_all_l_not_running_mock_node;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, list)
-
/*
* Structural test for routerset_get_all_nodes.
*/
-NS_DECL(const node_t *, node_get_by_nickname,
- (const char *nickname, unsigned flags));
-static char *NS(mock_nickname);
-static node_t NS(mock_node);
+static const node_t * rset_get_all_list_node_get_by_nickname(
+ const char *nickname, unsigned flags);
+static int rset_get_all_list_node_get_by_nickname_called = 0;
+static char *rset_get_all_list_mock_nickname;
+static node_t rset_get_all_list_mock_node;
static void
-NS(test_main)(void *arg)
+test_rset_get_all_list(void *arg)
{
smartlist_t *out = smartlist_new();
routerset_t *set = routerset_new();
@@ -1727,10 +1688,11 @@ NS(test_main)(void *arg)
node_t *ent;
(void)arg;
- NS_MOCK(node_get_by_nickname);
+ MOCK(node_get_by_nickname,
+ rset_get_all_list_node_get_by_nickname);
- NS(mock_nickname) = tor_strdup("foo");
- smartlist_add(set->list, NS(mock_nickname));
+ rset_get_all_list_mock_nickname = tor_strdup("foo");
+ smartlist_add(set->list, rset_get_all_list_mock_nickname);
routerset_get_all_nodes(out, set, NULL, 0);
out_len = smartlist_len(out);
@@ -1740,127 +1702,122 @@ NS(test_main)(void *arg)
routerset_free(set);
tt_int_op(out_len, OP_EQ, 1);
- tt_ptr_op(ent, OP_EQ, &NS(mock_node));
- tt_int_op(CALLED(node_get_by_nickname), OP_EQ, 1);
+ tt_ptr_op(ent, OP_EQ, &rset_get_all_list_mock_node);
+ tt_int_op(rset_get_all_list_node_get_by_nickname_called, OP_EQ, 1);
done:
;
}
const node_t *
-NS(node_get_by_nickname)(const char *nickname, unsigned flags)
+rset_get_all_list_node_get_by_nickname(const char *nickname, unsigned flags)
{
- CALLED(node_get_by_nickname)++;
- tt_str_op(nickname, OP_EQ, NS(mock_nickname));
+ rset_get_all_list_node_get_by_nickname_called++;
+ tt_str_op(nickname, OP_EQ, rset_get_all_list_mock_nickname);
tt_int_op(flags, OP_EQ, 0);
done:
- return &NS(mock_node);
+ return &rset_get_all_list_mock_node;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, nodelist_with_no_nodes)
-
/*
* Structural test for routerset_get_all_nodes, when the nodelist has no nodes.
*/
-NS_DECL(const smartlist_t *, nodelist_get_list, (void));
-
-static smartlist_t *NS(mock_smartlist);
+static const smartlist_t * rset_get_all_n_no_nodes_nodelist_get_list(void);
+static int rset_get_all_n_no_nodes_nodelist_get_list_called = 0;
+static smartlist_t *rset_get_all_n_no_nodes_mock_smartlist;
static void
-NS(test_main)(void *arg)
+test_rset_get_all_n_no_nodes(void *arg)
{
routerset_t *set = routerset_new();
smartlist_t *out = smartlist_new();
int r;
(void)arg;
- NS_MOCK(nodelist_get_list);
+ MOCK(nodelist_get_list,
+ rset_get_all_n_no_nodes_nodelist_get_list);
smartlist_add_strdup(set->country_names, "{xx}");
- NS(mock_smartlist) = smartlist_new();
+ rset_get_all_n_no_nodes_mock_smartlist = smartlist_new();
routerset_get_all_nodes(out, set, NULL, 1);
r = smartlist_len(out);
routerset_free(set);
smartlist_free(out);
- smartlist_free(NS(mock_smartlist));
+ smartlist_free(rset_get_all_n_no_nodes_mock_smartlist);
tt_int_op(r, OP_EQ, 0);
- tt_int_op(CALLED(nodelist_get_list), OP_EQ, 1);
+ tt_int_op(rset_get_all_n_no_nodes_nodelist_get_list_called, OP_EQ, 1);
done:
;
}
const smartlist_t *
-NS(nodelist_get_list)(void)
+rset_get_all_n_no_nodes_nodelist_get_list(void)
{
- CALLED(nodelist_get_list)++;
+ rset_get_all_n_no_nodes_nodelist_get_list_called++;
- return NS(mock_smartlist);
+ return rset_get_all_n_no_nodes_mock_smartlist;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, nodelist_flag_not_running)
-
/*
* Structural test for routerset_get_all_nodes, with a non-list routerset
* the running_only flag is set, but the nodes are not running.
*/
-NS_DECL(const smartlist_t *, nodelist_get_list, (void));
+static const smartlist_t * rset_get_all_n_not_running_nodelist_get_list(void);
+static int rset_get_all_n_not_running_nodelist_get_list_called = 0;
-static smartlist_t *NS(mock_smartlist);
-static node_t NS(mock_node);
+static smartlist_t *rset_get_all_n_not_running_mock_smartlist;
+static node_t rset_get_all_n_not_running_mock_node;
static void
-NS(test_main)(void *arg)
+test_rset_get_all_n_not_running(void *arg)
{
routerset_t *set = routerset_new();
smartlist_t *out = smartlist_new();
int r;
(void)arg;
- NS_MOCK(nodelist_get_list);
+ MOCK(nodelist_get_list,
+ rset_get_all_n_not_running_nodelist_get_list);
smartlist_add_strdup(set->country_names, "{xx}");
- NS(mock_smartlist) = smartlist_new();
- NS(mock_node).is_running = 0;
- smartlist_add(NS(mock_smartlist), (void *)&NS(mock_node));
+ rset_get_all_n_not_running_mock_smartlist = smartlist_new();
+ rset_get_all_n_not_running_mock_node.is_running = 0;
+ smartlist_add(rset_get_all_n_not_running_mock_smartlist,
+ (void *)&rset_get_all_n_not_running_mock_node);
routerset_get_all_nodes(out, set, NULL, 1);
r = smartlist_len(out);
routerset_free(set);
smartlist_free(out);
- smartlist_free(NS(mock_smartlist));
+ smartlist_free(rset_get_all_n_not_running_mock_smartlist);
tt_int_op(r, OP_EQ, 0);
- tt_int_op(CALLED(nodelist_get_list), OP_EQ, 1);
+ tt_int_op(rset_get_all_n_not_running_nodelist_get_list_called, OP_EQ, 1);
done:
;
}
const smartlist_t *
-NS(nodelist_get_list)(void)
+rset_get_all_n_not_running_nodelist_get_list(void)
{
- CALLED(nodelist_get_list)++;
+ rset_get_all_n_not_running_nodelist_get_list_called++;
- return NS(mock_smartlist);
+ return rset_get_all_n_not_running_mock_smartlist;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE routerset_subtract_nodes
-
/*
* Functional test for routerset_subtract_nodes.
*/
static void
-NS(test_main)(void *arg)
+test_rset_subtract_nodes(void *arg)
{
routerset_t *set = routerset_new();
smartlist_t *list = smartlist_new();
@@ -1885,15 +1842,12 @@ NS(test_main)(void *arg)
smartlist_free(list);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_subtract_nodes, null_routerset)
-
/*
* Functional test for routerset_subtract_nodes, with a NULL routerset.
*/
static void
-NS(test_main)(void *arg)
+test_rset_subtract_nodes_null_routerset(void *arg)
{
routerset_t *set = NULL;
smartlist_t *list = smartlist_new();
@@ -1915,15 +1869,12 @@ NS(test_main)(void *arg)
smartlist_free(list);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE routerset_to_string
-
/*
* Functional test for routerset_to_string.
*/
static void
-NS(test_main)(void *arg)
+test_rset_to_string(void *arg)
{
routerset_t *set = NULL;
char *s = NULL;
@@ -1960,15 +1911,12 @@ NS(test_main)(void *arg)
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_equal, empty_empty)
-
/*
* Functional test for routerset_equal, with both routersets empty.
*/
static void
-NS(test_main)(void *arg)
+test_rset_equal_empty_empty(void *arg)
{
routerset_t *a = routerset_new(), *b = routerset_new();
int r;
@@ -1984,15 +1932,12 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_equal, empty_not_empty)
-
/*
* Functional test for routerset_equal, with one routersets empty.
*/
static void
-NS(test_main)(void *arg)
+test_rset_equal_empty_not_empty(void *arg)
{
routerset_t *a = routerset_new(), *b = routerset_new();
int r;
@@ -2008,16 +1953,13 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_equal, differing_lengths)
-
/*
* Functional test for routerset_equal, with the routersets having
* differing lengths.
*/
static void
-NS(test_main)(void *arg)
+test_rset_equal_differing_lengths(void *arg)
{
routerset_t *a = routerset_new(), *b = routerset_new();
int r;
@@ -2035,16 +1977,13 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_equal, unequal)
-
/*
* Functional test for routerset_equal, with the routersets being
* different.
*/
static void
-NS(test_main)(void *arg)
+test_rset_equal_unequal(void *arg)
{
routerset_t *a = routerset_new(), *b = routerset_new();
int r;
@@ -2061,16 +2000,13 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_equal, equal)
-
/*
* Functional test for routerset_equal, with the routersets being
* equal.
*/
static void
-NS(test_main)(void *arg)
+test_rset_equal_equal(void *arg)
{
routerset_t *a = routerset_new(), *b = routerset_new();
int r;
@@ -2087,147 +2023,176 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_free, null_routerset)
-
/*
* Structural test for routerset_free, where the routerset is NULL.
*/
-NS_DECL(void, smartlist_free_, (smartlist_t *sl));
+static void rset_free_null_routerset_smartlist_free_(smartlist_t *sl);
+static int rset_free_null_routerset_smartlist_free__called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_free_null_routerset(void *arg)
{
(void)arg;
- NS_MOCK(smartlist_free_);
+ MOCK(smartlist_free_,
+ rset_free_null_routerset_smartlist_free_);
routerset_free_(NULL);
- tt_int_op(CALLED(smartlist_free_), OP_EQ, 0);
+ tt_int_op(rset_free_null_routerset_smartlist_free__called, OP_EQ, 0);
done:
;
}
void
-NS(smartlist_free_)(smartlist_t *s)
+rset_free_null_routerset_smartlist_free_(smartlist_t *s)
{
(void)s;
- CALLED(smartlist_free_)++;
+ rset_free_null_routerset_smartlist_free__called++;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE routerset_free
-
/*
* Structural test for routerset_free.
*/
-NS_DECL(void, smartlist_free_, (smartlist_t *sl));
-NS_DECL(void, strmap_free_,(strmap_t *map, void (*free_val)(void*)));
-NS_DECL(void, digestmap_free_, (digestmap_t *map, void (*free_val)(void*)));
+static void rset_free_smartlist_free_(smartlist_t *sl);
+static int rset_free_smartlist_free__called = 0;
+static void rset_free_strmap_free_(strmap_t *map, void (*free_val)(void*));
+static int rset_free_strmap_free__called = 0;
+static void rset_free_digestmap_free_(digestmap_t *map,
+ void (*free_val)(void*));
+static int rset_free_digestmap_free__called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_free(void *arg)
{
routerset_t *routerset = routerset_new();
(void)arg;
- NS_MOCK(smartlist_free_);
- NS_MOCK(strmap_free_);
- NS_MOCK(digestmap_free_);
+ MOCK(smartlist_free_,
+ rset_free_smartlist_free_);
+ MOCK(strmap_free_,
+ rset_free_strmap_free_);
+ MOCK(digestmap_free_,
+ rset_free_digestmap_free_);
routerset_free(routerset);
- tt_int_op(CALLED(smartlist_free_), OP_NE, 0);
- tt_int_op(CALLED(strmap_free_), OP_NE, 0);
- tt_int_op(CALLED(digestmap_free_), OP_NE, 0);
+ tt_int_op(rset_free_smartlist_free__called, OP_NE, 0);
+ tt_int_op(rset_free_strmap_free__called, OP_NE, 0);
+ tt_int_op(rset_free_digestmap_free__called, OP_NE, 0);
done:
;
}
void
-NS(smartlist_free_)(smartlist_t *s)
+rset_free_smartlist_free_(smartlist_t *s)
{
- CALLED(smartlist_free_)++;
+ rset_free_smartlist_free__called++;
smartlist_free___real(s);
}
void
-NS(strmap_free_)(strmap_t *map, void (*free_val)(void*))
+rset_free_strmap_free_(strmap_t *map, void (*free_val)(void*))
{
- CALLED(strmap_free_)++;
+ rset_free_strmap_free__called++;
strmap_free___real(map, free_val);
}
void
-NS(digestmap_free_)(digestmap_t *map, void (*free_val)(void*))
+rset_free_digestmap_free_(digestmap_t *map, void (*free_val)(void*))
{
- CALLED(digestmap_free_)++;
+ rset_free_digestmap_free__called++;
digestmap_free___real(map, free_val);
}
-#undef NS_SUBMODULE
-
struct testcase_t routerset_tests[] = {
- TEST_CASE(routerset_new),
- TEST_CASE(routerset_get_countryname),
- TEST_CASE(routerset_is_list),
- TEST_CASE(routerset_needs_geoip),
- TEST_CASE(routerset_is_empty),
- TEST_CASE_ASPECT(routerset_contains, null_set_or_null_set_list),
- TEST_CASE_ASPECT(routerset_contains, set_and_nickname),
- TEST_CASE_ASPECT(routerset_contains, set_and_null_nickname),
- TEST_CASE_ASPECT(routerset_contains, set_and_no_nickname),
- TEST_CASE_ASPECT(routerset_contains, set_and_digest),
- TEST_CASE_ASPECT(routerset_contains, set_and_no_digest),
- TEST_CASE_ASPECT(routerset_contains, set_and_null_digest),
- TEST_CASE_ASPECT(routerset_contains, set_and_addr),
- TEST_CASE_ASPECT(routerset_contains, set_and_no_addr),
- TEST_CASE_ASPECT(routerset_contains, set_and_null_addr),
- TEST_CASE_ASPECT(routerset_contains, countries_no_geoip),
- TEST_CASE_ASPECT(routerset_contains, countries_geoip),
- TEST_CASE_ASPECT(routerset_add_unknown_ccs, only_flag_and_no_ccs),
- TEST_CASE_ASPECT(routerset_add_unknown_ccs, creates_set),
- TEST_CASE_ASPECT(routerset_add_unknown_ccs, add_unknown),
- TEST_CASE_ASPECT(routerset_add_unknown_ccs, add_a1),
- TEST_CASE(routerset_contains_extendinfo),
- TEST_CASE(routerset_contains_router),
- TEST_CASE(routerset_contains_routerstatus),
- TEST_CASE_ASPECT(routerset_contains_node, none),
- TEST_CASE_ASPECT(routerset_contains_node, routerinfo),
- TEST_CASE_ASPECT(routerset_contains_node, routerstatus),
- TEST_CASE_ASPECT(routerset_get_all_nodes, no_routerset),
- TEST_CASE_ASPECT(routerset_get_all_nodes, list_with_no_nodes),
- TEST_CASE_ASPECT(routerset_get_all_nodes, list_flag_not_running),
- TEST_CASE_ASPECT(routerset_get_all_nodes, list),
- TEST_CASE_ASPECT(routerset_get_all_nodes, nodelist_with_no_nodes),
- TEST_CASE_ASPECT(routerset_get_all_nodes, nodelist_flag_not_running),
- TEST_CASE_ASPECT(routerset_refresh_counties, geoip_not_loaded),
- TEST_CASE_ASPECT(routerset_refresh_counties, no_countries),
- TEST_CASE_ASPECT(routerset_refresh_counties, one_valid_country),
- TEST_CASE_ASPECT(routerset_refresh_counties, one_invalid_country),
- TEST_CASE_ASPECT(routerset_union, source_bad),
- TEST_CASE_ASPECT(routerset_union, one),
- TEST_CASE_ASPECT(routerset_parse, malformed),
- TEST_CASE_ASPECT(routerset_parse, valid_hexdigest),
- TEST_CASE_ASPECT(routerset_parse, valid_nickname),
- TEST_CASE_ASPECT(routerset_parse, get_countryname),
- TEST_CASE_ASPECT(routerset_parse, policy_wildcard),
- TEST_CASE_ASPECT(routerset_parse, policy_ipv4),
- TEST_CASE_ASPECT(routerset_parse, policy_ipv6),
- TEST_CASE(routerset_subtract_nodes),
- TEST_CASE_ASPECT(routerset_subtract_nodes, null_routerset),
- TEST_CASE(routerset_to_string),
- TEST_CASE_ASPECT(routerset_equal, empty_empty),
- TEST_CASE_ASPECT(routerset_equal, empty_not_empty),
- TEST_CASE_ASPECT(routerset_equal, differing_lengths),
- TEST_CASE_ASPECT(routerset_equal, unequal),
- TEST_CASE_ASPECT(routerset_equal, equal),
- TEST_CASE_ASPECT(routerset_free, null_routerset),
- TEST_CASE(routerset_free),
+ { "new", test_rset_new, TT_FORK, NULL, NULL },
+ { "get_countryname", test_rset_get_countryname, TT_FORK, NULL, NULL },
+ { "is_list", test_rset_is_list, TT_FORK, NULL, NULL },
+ { "needs_geoip", test_rset_needs_geoip, TT_FORK, NULL, NULL },
+ { "is_empty", test_rset_is_empty, TT_FORK, NULL, NULL },
+ { "contains_null_set_or_list", test_rset_contains_null_set_or_list,
+ TT_FORK, NULL, NULL },
+ { "contains_nickname", test_rset_contains_nickname, TT_FORK, NULL, NULL },
+ { "contains_null_nickname", test_rset_contains_null_nickname,
+ TT_FORK, NULL, NULL },
+ { "contains_no_nickname", test_rset_contains_no_nickname,
+ TT_FORK, NULL, NULL },
+ { "contains_digest", test_rset_contains_digest, TT_FORK, NULL, NULL },
+ { "contains_no_digest", test_rset_contains_no_digest, TT_FORK, NULL, NULL },
+ { "contains_null_digest", test_rset_contains_null_digest,
+ TT_FORK, NULL, NULL },
+ { "contains_addr", test_rset_contains_addr, TT_FORK, NULL, NULL },
+ { "contains_no_addr", test_rset_contains_no_addr, TT_FORK, NULL, NULL },
+ { "contains_null_addr", test_rset_contains_null_addr, TT_FORK, NULL, NULL },
+ { "contains_countries_no_geoip", test_rset_countries_no_geoip,
+ TT_FORK, NULL, NULL },
+ { "contains_countries_geoip", test_rset_countries_geoip,
+ TT_FORK, NULL, NULL },
+ { "add_unknown_ccs_only_flag", test_rset_add_unknown_ccs_only_flag,
+ TT_FORK, NULL, NULL },
+ { "add_unknown_ccs_creates_set", test_rset_add_unknown_ccs_creates_set,
+ TT_FORK, NULL, NULL },
+ { "add_unknown_ccs_add_unknown", test_rset_add_unknown_ccs_add_unknown,
+ TT_FORK, NULL, NULL },
+ { "add_unknown_ccs_add_a1", test_rset_add_unknown_ccs_add_a1,
+ TT_FORK, NULL, NULL },
+ { "contains_extendinfo", test_rset_contains_extendinfo,
+ TT_FORK, NULL, NULL },
+ { "contains_router", test_rset_contains_router, TT_FORK, NULL, NULL },
+ { "contains_routerstatus", test_rset_contains_routerstatus,
+ TT_FORK, NULL, NULL },
+ { "contains_none", test_rset_contains_none, TT_FORK, NULL, NULL },
+ { "contains_routerinfo", test_rset_contains_routerinfo,
+ TT_FORK, NULL, NULL },
+ { "contains_rs", test_rset_contains_rs, TT_FORK, NULL, NULL },
+ { "get_all_no_routerset", test_rset_get_all_no_routerset,
+ TT_FORK, NULL, NULL },
+ { "get_all_l_no_nodes", test_rset_get_all_l_no_nodes, TT_FORK, NULL, NULL },
+ { "get_all_l_not_running", test_rset_get_all_l_not_running,
+ TT_FORK, NULL, NULL },
+ { "get_all_list", test_rset_get_all_list, TT_FORK, NULL, NULL },
+ { "get_all_n_no_nodes", test_rset_get_all_n_no_nodes, TT_FORK, NULL, NULL },
+ { "get_all_n_not_running", test_rset_get_all_n_not_running,
+ TT_FORK, NULL, NULL },
+ { "refresh_geoip_not_loaded", test_rset_refresh_geoip_not_loaded,
+ TT_FORK, NULL, NULL },
+ { "refresh_no_countries", test_rset_refresh_no_countries,
+ TT_FORK, NULL, NULL },
+ { "refresh_one_valid_country", test_rset_refresh_one_valid_country,
+ TT_FORK, NULL, NULL },
+ { "refresh_one_invalid_country", test_rset_refresh_one_invalid_country,
+ TT_FORK, NULL, NULL },
+ { "union_source_bad", test_rset_union_source_bad, TT_FORK, NULL, NULL },
+ { "union_one", test_rset_union_one, TT_FORK, NULL, NULL },
+ { "parse_malformed", test_rset_parse_malformed, TT_FORK, NULL, NULL },
+ { "parse_valid_hexdigest", test_rset_parse_valid_hexdigest,
+ TT_FORK, NULL, NULL },
+ { "parse_valid_nickname", test_rset_parse_valid_nickname,
+ TT_FORK, NULL, NULL },
+ { "parse_get_countryname", test_rset_parse_get_countryname,
+ TT_FORK, NULL, NULL },
+ { "parse_policy_wildcard", test_rset_parse_policy_wildcard,
+ TT_FORK, NULL, NULL },
+ { "parse_policy_ipv4", test_rset_parse_policy_ipv4, TT_FORK, NULL, NULL },
+ { "parse_policy_ipv6", test_rset_parse_policy_ipv6, TT_FORK, NULL, NULL },
+ { "subtract_nodes", test_rset_subtract_nodes, TT_FORK, NULL, NULL },
+ { "subtract_nodes_null_routerset", test_rset_subtract_nodes_null_routerset,
+ TT_FORK, NULL, NULL },
+ { "to_string", test_rset_to_string, TT_FORK, NULL, NULL },
+ { "equal_empty_empty", test_rset_equal_empty_empty, TT_FORK, NULL, NULL },
+ { "equal_empty_not_empty", test_rset_equal_empty_not_empty,
+ TT_FORK, NULL, NULL },
+ { "equal_differing_lengths", test_rset_equal_differing_lengths,
+ TT_FORK, NULL, NULL },
+ { "equal_unequal", test_rset_equal_unequal, TT_FORK, NULL, NULL },
+ { "equal_equal", test_rset_equal_equal, TT_FORK, NULL, NULL },
+ { "free_null_routerset", test_rset_free_null_routerset,
+ TT_FORK, NULL, NULL },
+ { "free", test_rset_free, TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_scheduler.c b/src/test/test_scheduler.c
index bf9c6a49cd..9ec15948e8 100644
--- a/src/test/test_scheduler.c
+++ b/src/test/test_scheduler.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -6,8 +6,8 @@
#include <math.h>
#define SCHEDULER_KIST_PRIVATE
-#define TOR_CHANNEL_INTERNAL_
-#define CHANNEL_PRIVATE_
+#define CHANNEL_OBJECT_PRIVATE
+#define CHANNEL_FILE_PRIVATE
#include "core/or/or.h"
#include "app/config/config.h"
#include "lib/evloop/compat_libevent.h"
@@ -15,7 +15,7 @@
#include "core/or/channeltls.h"
#include "core/mainloop/connection.h"
#include "feature/nodelist/networkstatus.h"
-#define SCHEDULER_PRIVATE_
+#define SCHEDULER_PRIVATE
#include "core/or/scheduler.h"
/* Test suite stuff */
@@ -848,8 +848,8 @@ test_scheduler_initfree(void *arg)
{
(void)arg;
- tt_ptr_op(channels_pending, ==, NULL);
- tt_ptr_op(run_sched_ev, ==, NULL);
+ tt_ptr_op(channels_pending, OP_EQ, NULL);
+ tt_ptr_op(run_sched_ev, OP_EQ, NULL);
MOCK(get_options, mock_get_options);
set_scheduler_options(SCHEDULER_KIST);
@@ -858,17 +858,17 @@ test_scheduler_initfree(void *arg)
scheduler_init();
- tt_ptr_op(channels_pending, !=, NULL);
- tt_ptr_op(run_sched_ev, !=, NULL);
+ tt_ptr_op(channels_pending, OP_NE, NULL);
+ tt_ptr_op(run_sched_ev, OP_NE, NULL);
/* We have specified nothing in the torrc and there's no consensus so the
* KIST scheduler is what should be in use */
- tt_ptr_op(the_scheduler, ==, get_kist_scheduler());
- tt_int_op(sched_run_interval, ==, 10);
+ tt_ptr_op(the_scheduler, OP_EQ, get_kist_scheduler());
+ tt_int_op(sched_run_interval, OP_EQ, 10);
scheduler_free_all();
- tt_ptr_op(channels_pending, ==, NULL);
- tt_ptr_op(run_sched_ev, ==, NULL);
+ tt_ptr_op(channels_pending, OP_EQ, NULL);
+ tt_ptr_op(run_sched_ev, OP_EQ, NULL);
done:
UNMOCK(get_options);
@@ -890,11 +890,11 @@ test_scheduler_can_use_kist(void *arg)
res_should = scheduler_can_use_kist();
res_freq = kist_scheduler_run_interval();
#ifdef HAVE_KIST_SUPPORT
- tt_int_op(res_should, ==, 1);
+ tt_int_op(res_should, OP_EQ, 1);
#else /* HAVE_KIST_SUPPORT */
- tt_int_op(res_should, ==, 0);
+ tt_int_op(res_should, OP_EQ, 0);
#endif /* HAVE_KIST_SUPPORT */
- tt_int_op(res_freq, ==, 1234);
+ tt_int_op(res_freq, OP_EQ, 1234);
/* Test defer to consensus, but no consensus available */
clear_options();
@@ -902,11 +902,11 @@ test_scheduler_can_use_kist(void *arg)
res_should = scheduler_can_use_kist();
res_freq = kist_scheduler_run_interval();
#ifdef HAVE_KIST_SUPPORT
- tt_int_op(res_should, ==, 1);
+ tt_int_op(res_should, OP_EQ, 1);
#else /* HAVE_KIST_SUPPORT */
- tt_int_op(res_should, ==, 0);
+ tt_int_op(res_should, OP_EQ, 0);
#endif /* HAVE_KIST_SUPPORT */
- tt_int_op(res_freq, ==, 10);
+ tt_int_op(res_freq, OP_EQ, 10);
/* Test defer to consensus, and kist consensus available */
MOCK(networkstatus_get_param, mock_kist_networkstatus_get_param);
@@ -915,11 +915,11 @@ test_scheduler_can_use_kist(void *arg)
res_should = scheduler_can_use_kist();
res_freq = kist_scheduler_run_interval();
#ifdef HAVE_KIST_SUPPORT
- tt_int_op(res_should, ==, 1);
+ tt_int_op(res_should, OP_EQ, 1);
#else /* HAVE_KIST_SUPPORT */
- tt_int_op(res_should, ==, 0);
+ tt_int_op(res_should, OP_EQ, 0);
#endif /* HAVE_KIST_SUPPORT */
- tt_int_op(res_freq, ==, 12);
+ tt_int_op(res_freq, OP_EQ, 12);
UNMOCK(networkstatus_get_param);
/* Test defer to consensus, and vanilla consensus available */
@@ -928,8 +928,8 @@ test_scheduler_can_use_kist(void *arg)
mocked_options.KISTSchedRunInterval = 0;
res_should = scheduler_can_use_kist();
res_freq = kist_scheduler_run_interval();
- tt_int_op(res_should, ==, 0);
- tt_int_op(res_freq, ==, 0);
+ tt_int_op(res_should, OP_EQ, 0);
+ tt_int_op(res_freq, OP_EQ, 0);
UNMOCK(networkstatus_get_param);
done:
@@ -956,7 +956,7 @@ test_scheduler_ns_changed(void *arg)
set_scheduler_options(SCHEDULER_KIST);
set_scheduler_options(SCHEDULER_VANILLA);
- tt_ptr_op(the_scheduler, ==, NULL);
+ tt_ptr_op(the_scheduler, OP_EQ, NULL);
/* Change from vanilla to kist via consensus */
the_scheduler = get_vanilla_scheduler();
@@ -964,9 +964,9 @@ test_scheduler_ns_changed(void *arg)
scheduler_notify_networkstatus_changed();
UNMOCK(networkstatus_get_param);
#ifdef HAVE_KIST_SUPPORT
- tt_ptr_op(the_scheduler, ==, get_kist_scheduler());
+ tt_ptr_op(the_scheduler, OP_EQ, get_kist_scheduler());
#else
- tt_ptr_op(the_scheduler, ==, get_vanilla_scheduler());
+ tt_ptr_op(the_scheduler, OP_EQ, get_vanilla_scheduler());
#endif
/* Change from kist to vanilla via consensus */
@@ -974,7 +974,7 @@ test_scheduler_ns_changed(void *arg)
MOCK(networkstatus_get_param, mock_vanilla_networkstatus_get_param);
scheduler_notify_networkstatus_changed();
UNMOCK(networkstatus_get_param);
- tt_ptr_op(the_scheduler, ==, get_vanilla_scheduler());
+ tt_ptr_op(the_scheduler, OP_EQ, get_vanilla_scheduler());
/* Doesn't change when using KIST */
the_scheduler = get_kist_scheduler();
@@ -982,9 +982,9 @@ test_scheduler_ns_changed(void *arg)
scheduler_notify_networkstatus_changed();
UNMOCK(networkstatus_get_param);
#ifdef HAVE_KIST_SUPPORT
- tt_ptr_op(the_scheduler, ==, get_kist_scheduler());
+ tt_ptr_op(the_scheduler, OP_EQ, get_kist_scheduler());
#else
- tt_ptr_op(the_scheduler, ==, get_vanilla_scheduler());
+ tt_ptr_op(the_scheduler, OP_EQ, get_vanilla_scheduler());
#endif
/* Doesn't change when using vanilla */
@@ -992,7 +992,7 @@ test_scheduler_ns_changed(void *arg)
MOCK(networkstatus_get_param, mock_vanilla_networkstatus_get_param);
scheduler_notify_networkstatus_changed();
UNMOCK(networkstatus_get_param);
- tt_ptr_op(the_scheduler, ==, get_vanilla_scheduler());
+ tt_ptr_op(the_scheduler, OP_EQ, get_vanilla_scheduler());
done:
UNMOCK(get_options);
diff --git a/src/test/test_sendme.c b/src/test/test_sendme.c
index eb402232bc..2ff4809124 100644
--- a/src/test/test_sendme.c
+++ b/src/test/test_sendme.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/* Unit tests for handling different kinds of relay cell */
diff --git a/src/test/test_shared_random.c b/src/test/test_shared_random.c
index 9c8703fa6f..f2accb2376 100644
--- a/src/test/test_shared_random.c
+++ b/src/test/test_shared_random.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define SHARED_RANDOM_PRIVATE
diff --git a/src/test/test_slow.c b/src/test/test_slow.c
index d4d5b755a5..49b1066dac 100644
--- a/src/test/test_slow.c
+++ b/src/test/test_slow.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_socks.c b/src/test/test_socks.c
index 6d3ebd2320..4a465c7361 100644
--- a/src/test/test_socks.c
+++ b/src/test/test_socks.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
@@ -399,6 +399,43 @@ test_socks_5_supported_commands(void *ptr)
tt_int_op(0,OP_EQ, buf_datalen(buf));
+ socks_request_clear(socks);
+
+ /* SOCKS 5 Send RESOLVE_PTR [F1] for an IPv6 address */
+ ADD_DATA(buf, "\x05\x01\x00");
+ ADD_DATA(buf, "\x05\xF1\x00\x04"
+ "\x20\x01\x0d\xb8\x85\xa3\x00\x00\x00\x00\x8a\x2e\x03\x70\x73\x34"
+ "\x12\x34");
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks),
+ OP_EQ, 1);
+ tt_int_op(5,OP_EQ, socks->socks_version);
+ tt_int_op(2,OP_EQ, socks->replylen);
+ tt_int_op(5,OP_EQ, socks->reply[0]);
+ tt_int_op(0,OP_EQ, socks->reply[1]);
+ tt_str_op("[2001:db8:85a3::8a2e:370:7334]",OP_EQ, socks->address);
+
+ tt_int_op(0,OP_EQ, buf_datalen(buf));
+
+ socks_request_clear(socks);
+
+ /* SOCKS 5 Send RESOLVE_PTR [F1] for a an IPv6 address written as a
+ * string with brackets */
+ ADD_DATA(buf, "\x05\x01\x00");
+ ADD_DATA(buf, "\x05\xF1\x00\x03\x1e");
+ ADD_DATA(buf, "[2001:db8:85a3::8a2e:370:7334]");
+ ADD_DATA(buf, "\x12\x34");
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks),
+ OP_EQ, 1);
+ tt_int_op(5,OP_EQ, socks->socks_version);
+ tt_int_op(2,OP_EQ, socks->replylen);
+ tt_int_op(5,OP_EQ, socks->reply[0]);
+ tt_int_op(0,OP_EQ, socks->reply[1]);
+ tt_str_op("[2001:db8:85a3::8a2e:370:7334]",OP_EQ, socks->address);
+
+ tt_int_op(0,OP_EQ, buf_datalen(buf));
+
done:
;
}
diff --git a/src/test/test_stats.c b/src/test/test_stats.c
new file mode 100644
index 0000000000..291473ebc9
--- /dev/null
+++ b/src/test/test_stats.c
@@ -0,0 +1,258 @@
+/* Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file test_stats.c
+ * \brief Unit tests for the statistics (reputation history) module.
+ **/
+
+#include "orconfig.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "app/config/or_state_st.h"
+#include "test/rng_test_helpers.h"
+
+#include <stdio.h>
+
+#ifdef _WIN32
+/* For mkdir() */
+#include <direct.h>
+#else
+#include <dirent.h>
+#endif /* defined(_WIN32) */
+
+#include <math.h>
+
+/* These macros pull in declarations for some functions and structures that
+ * are typically file-private. */
+#define CIRCUITSTATS_PRIVATE
+#define CIRCUITLIST_PRIVATE
+#define MAINLOOP_PRIVATE
+#define STATEFILE_PRIVATE
+
+#include "core/or/or.h"
+#include "lib/err/backtrace.h"
+#include "lib/buf/buffers.h"
+#include "core/or/circuitstats.h"
+#include "app/config/config.h"
+#include "test/test.h"
+#include "core/mainloop/mainloop.h"
+#include "lib/memarea/memarea.h"
+#include "feature/stats/rephist.h"
+#include "app/config/statefile.h"
+
+/** Run unit tests for some stats code. */
+static void
+test_stats(void *arg)
+{
+ time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
+ char *s = NULL;
+ int i;
+
+ /* Start with testing exit port statistics; we shouldn't collect exit
+ * stats without initializing them. */
+ (void)arg;
+ rep_hist_note_exit_stream_opened(80);
+ rep_hist_note_exit_bytes(80, 100, 10000);
+ s = rep_hist_format_exit_stats(now + 86400);
+ tt_ptr_op(s, OP_EQ, NULL);
+
+ /* Initialize stats, note some streams and bytes, and generate history
+ * string. */
+ rep_hist_exit_stats_init(now);
+ rep_hist_note_exit_stream_opened(80);
+ rep_hist_note_exit_bytes(80, 100, 10000);
+ rep_hist_note_exit_stream_opened(443);
+ rep_hist_note_exit_bytes(443, 100, 10000);
+ rep_hist_note_exit_bytes(443, 100, 10000);
+ s = rep_hist_format_exit_stats(now + 86400);
+ tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "exit-kibibytes-written 80=1,443=1,other=0\n"
+ "exit-kibibytes-read 80=10,443=20,other=0\n"
+ "exit-streams-opened 80=4,443=4,other=0\n",OP_EQ, s);
+ tor_free(s);
+
+ /* Add a few bytes on 10 more ports and ensure that only the top 10
+ * ports are contained in the history string. */
+ for (i = 50; i < 60; i++) {
+ rep_hist_note_exit_bytes(i, i, i);
+ rep_hist_note_exit_stream_opened(i);
+ }
+ s = rep_hist_format_exit_stats(now + 86400);
+ tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "exit-kibibytes-written 52=1,53=1,54=1,55=1,56=1,57=1,58=1,"
+ "59=1,80=1,443=1,other=1\n"
+ "exit-kibibytes-read 52=1,53=1,54=1,55=1,56=1,57=1,58=1,"
+ "59=1,80=10,443=20,other=1\n"
+ "exit-streams-opened 52=4,53=4,54=4,55=4,56=4,57=4,58=4,"
+ "59=4,80=4,443=4,other=4\n",OP_EQ, s);
+ tor_free(s);
+
+ /* Stop collecting stats, add some bytes, and ensure we don't generate
+ * a history string. */
+ rep_hist_exit_stats_term();
+ rep_hist_note_exit_bytes(80, 100, 10000);
+ s = rep_hist_format_exit_stats(now + 86400);
+ tt_ptr_op(s, OP_EQ, NULL);
+
+ /* Re-start stats, add some bytes, reset stats, and see what history we
+ * get when observing no streams or bytes at all. */
+ rep_hist_exit_stats_init(now);
+ rep_hist_note_exit_stream_opened(80);
+ rep_hist_note_exit_bytes(80, 100, 10000);
+ rep_hist_reset_exit_stats(now);
+ s = rep_hist_format_exit_stats(now + 86400);
+ tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "exit-kibibytes-written other=0\n"
+ "exit-kibibytes-read other=0\n"
+ "exit-streams-opened other=0\n",OP_EQ, s);
+ tor_free(s);
+
+ /* Continue with testing connection statistics; we shouldn't collect
+ * conn stats without initializing them. */
+ rep_hist_note_or_conn_bytes(1, 20, 400, now);
+ s = rep_hist_format_conn_stats(now + 86400);
+ tt_ptr_op(s, OP_EQ, NULL);
+
+ /* Initialize stats, note bytes, and generate history string. */
+ rep_hist_conn_stats_init(now);
+ rep_hist_note_or_conn_bytes(1, 30000, 400000, now);
+ rep_hist_note_or_conn_bytes(1, 30000, 400000, now + 5);
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10);
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
+ s = rep_hist_format_conn_stats(now + 86400);
+ tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,1,0\n",OP_EQ, s);
+ tor_free(s);
+
+ /* Stop collecting stats, add some bytes, and ensure we don't generate
+ * a history string. */
+ rep_hist_conn_stats_term();
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
+ s = rep_hist_format_conn_stats(now + 86400);
+ tt_ptr_op(s, OP_EQ, NULL);
+
+ /* Re-start stats, add some bytes, reset stats, and see what history we
+ * get when observing no bytes at all. */
+ rep_hist_conn_stats_init(now);
+ rep_hist_note_or_conn_bytes(1, 30000, 400000, now);
+ rep_hist_note_or_conn_bytes(1, 30000, 400000, now + 5);
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10);
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
+ rep_hist_reset_conn_stats(now);
+ s = rep_hist_format_conn_stats(now + 86400);
+ tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n",OP_EQ, s);
+ tor_free(s);
+
+ /* Continue with testing buffer statistics; we shouldn't collect buffer
+ * stats without initializing them. */
+ rep_hist_add_buffer_stats(2.0, 2.0, 20);
+ s = rep_hist_format_buffer_stats(now + 86400);
+ tt_ptr_op(s, OP_EQ, NULL);
+
+ /* Initialize stats, add statistics for a single circuit, and generate
+ * the history string. */
+ rep_hist_buffer_stats_init(now);
+ rep_hist_add_buffer_stats(2.0, 2.0, 20);
+ s = rep_hist_format_buffer_stats(now + 86400);
+ tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "cell-processed-cells 20,0,0,0,0,0,0,0,0,0\n"
+ "cell-queued-cells 2.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,"
+ "0.00,0.00\n"
+ "cell-time-in-queue 2,0,0,0,0,0,0,0,0,0\n"
+ "cell-circuits-per-decile 1\n",OP_EQ, s);
+ tor_free(s);
+
+ /* Add nineteen more circuit statistics to the one that's already in the
+ * history to see that the math works correctly. */
+ for (i = 21; i < 30; i++)
+ rep_hist_add_buffer_stats(2.0, 2.0, i);
+ for (i = 20; i < 30; i++)
+ rep_hist_add_buffer_stats(3.5, 3.5, i);
+ s = rep_hist_format_buffer_stats(now + 86400);
+ tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "cell-processed-cells 29,28,27,26,25,24,23,22,21,20\n"
+ "cell-queued-cells 2.75,2.75,2.75,2.75,2.75,2.75,2.75,2.75,"
+ "2.75,2.75\n"
+ "cell-time-in-queue 3,3,3,3,3,3,3,3,3,3\n"
+ "cell-circuits-per-decile 2\n",OP_EQ, s);
+ tor_free(s);
+
+ /* Stop collecting stats, add statistics for one circuit, and ensure we
+ * don't generate a history string. */
+ rep_hist_buffer_stats_term();
+ rep_hist_add_buffer_stats(2.0, 2.0, 20);
+ s = rep_hist_format_buffer_stats(now + 86400);
+ tt_ptr_op(s, OP_EQ, NULL);
+
+ /* Re-start stats, add statistics for one circuit, reset stats, and make
+ * sure that the history has all zeros. */
+ rep_hist_buffer_stats_init(now);
+ rep_hist_add_buffer_stats(2.0, 2.0, 20);
+ rep_hist_reset_buffer_stats(now);
+ s = rep_hist_format_buffer_stats(now + 86400);
+ tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "cell-processed-cells 0,0,0,0,0,0,0,0,0,0\n"
+ "cell-queued-cells 0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,"
+ "0.00,0.00\n"
+ "cell-time-in-queue 0,0,0,0,0,0,0,0,0,0\n"
+ "cell-circuits-per-decile 0\n",OP_EQ, s);
+
+ done:
+ tor_free(s);
+}
+
+/** Run unit tests the mtbf stats code. */
+static void
+test_rephist_mtbf(void *arg)
+{
+ (void)arg;
+
+ time_t now = 1572500000; /* 2010-10-31 05:33:20 UTC */
+ time_t far_future = MAX(now, time(NULL)) + 365*24*60*60;
+ int r;
+
+ /* Make a temporary datadir for these tests */
+ char *ddir_fname = tor_strdup(get_fname_rnd("datadir_mtbf"));
+ tor_free(get_options_mutable()->DataDirectory);
+ get_options_mutable()->DataDirectory = tor_strdup(ddir_fname);
+ check_private_dir(ddir_fname, CPD_CREATE, NULL);
+
+ rep_history_clean(far_future);
+
+ /* No data */
+
+ r = rep_hist_load_mtbf_data(now);
+ tt_int_op(r, OP_EQ, -1);
+ rep_history_clean(far_future);
+
+ /* Blank data */
+
+ r = rep_hist_record_mtbf_data(now, 0);
+ tt_int_op(r, OP_EQ, 0);
+ r = rep_hist_load_mtbf_data(now);
+ tt_int_op(r, OP_EQ, 0);
+ rep_history_clean(far_future);
+
+ r = rep_hist_record_mtbf_data(now, 1);
+ tt_int_op(r, OP_EQ, 0);
+ r = rep_hist_load_mtbf_data(now);
+ tt_int_op(r, OP_EQ, 0);
+ rep_history_clean(far_future);
+
+ done:
+ rep_history_clean(far_future);
+ tor_free(ddir_fname);
+}
+
+#define ENT(name) \
+ { #name, test_ ## name , 0, NULL, NULL }
+#define FORK(name) \
+ { #name, test_ ## name , TT_FORK, NULL, NULL }
+
+struct testcase_t stats_tests[] = {
+ FORK(stats),
+ ENT(rephist_mtbf),
+
+ END_OF_TESTCASES
+};
diff --git a/src/test/test_status.c b/src/test/test_status.c
index 2fb2a7b24f..82afe0fd2a 100644
--- a/src/test/test_status.c
+++ b/src/test/test_status.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define STATUS_PRIVATE
@@ -33,10 +33,6 @@
#include "test/test.h"
-#define NS_MODULE status
-
-#define NS_SUBMODULE count_circuits
-
/*
* Test that count_circuits() is correctly counting the number of
* global circuits.
@@ -44,10 +40,10 @@
static smartlist_t * mock_global_circuitlist = NULL;
-NS_DECL(smartlist_t *, circuit_get_global_list, (void));
+static smartlist_t * status_count_circuits_circuit_get_global_list(void);
static void
-NS(test_main)(void *arg)
+test_status_count_circuits(void *arg)
{
/* Choose origin_circuit_t wlog. */
origin_circuit_t *mock_circuit1, *mock_circuit2;
@@ -61,7 +57,8 @@ NS(test_main)(void *arg)
smartlist_add(mock_global_circuitlist, TO_CIRCUIT(mock_circuit1));
smartlist_add(mock_global_circuitlist, TO_CIRCUIT(mock_circuit2));
- NS_MOCK(circuit_get_global_list);
+ MOCK(circuit_get_global_list,
+ status_count_circuits_circuit_get_global_list);
actual_circuits = count_circuits();
@@ -72,25 +69,22 @@ NS(test_main)(void *arg)
tor_free(mock_circuit2);
smartlist_free(mock_global_circuitlist);
mock_global_circuitlist = NULL;
- NS_UNMOCK(circuit_get_global_list);
+ UNMOCK(circuit_get_global_list);
}
static smartlist_t *
-NS(circuit_get_global_list)(void)
+status_count_circuits_circuit_get_global_list(void)
{
return mock_global_circuitlist;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE secs_to_uptime
-
/*
* Test that secs_to_uptime() is converting the number of seconds that
* Tor is up for into the appropriate string form containing hours and minutes.
*/
static void
-NS(test_main)(void *arg)
+test_status_secs_to_uptime(void *arg)
{
const char *expected;
char *actual;
@@ -161,9 +155,6 @@ NS(test_main)(void *arg)
tor_free(actual);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE bytes_to_usage
-
/*
* Test that bytes_to_usage() is correctly converting the number of bytes that
* Tor has read/written into the appropriate string form containing kilobytes,
@@ -171,7 +162,7 @@ NS(test_main)(void *arg)
*/
static void
-NS(test_main)(void *arg)
+test_status_bytes_to_usage(void *arg)
{
const char *expected;
char *actual;
@@ -242,29 +233,30 @@ NS(test_main)(void *arg)
tor_free(actual);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(log_heartbeat, fails)
-
/*
* Tests that log_heartbeat() fails when in the public server mode,
* not hibernating, and we couldn't get the current routerinfo.
*/
-NS_DECL(double, tls_get_write_overhead_ratio, (void));
-NS_DECL(int, we_are_hibernating, (void));
-NS_DECL(int, public_server_mode, (const or_options_t *options));
-NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void));
+static double status_hb_fails_tls_get_write_overhead_ratio(void);
+static int status_hb_fails_we_are_hibernating(void);
+static int status_hb_fails_public_server_mode(const or_options_t *options);
+static const routerinfo_t * status_hb_fails_router_get_my_routerinfo(void);
static void
-NS(test_main)(void *arg)
+test_status_hb_fails(void *arg)
{
int expected, actual;
(void)arg;
- NS_MOCK(tls_get_write_overhead_ratio);
- NS_MOCK(we_are_hibernating);
- NS_MOCK(public_server_mode);
- NS_MOCK(router_get_my_routerinfo);
+ MOCK(tls_get_write_overhead_ratio,
+ status_hb_fails_tls_get_write_overhead_ratio);
+ MOCK(we_are_hibernating,
+ status_hb_fails_we_are_hibernating);
+ MOCK(public_server_mode,
+ status_hb_fails_public_server_mode);
+ MOCK(router_get_my_routerinfo,
+ status_hb_fails_router_get_my_routerinfo);
expected = -1;
actual = log_heartbeat(0);
@@ -272,26 +264,26 @@ NS(test_main)(void *arg)
tt_int_op(actual, OP_EQ, expected);
done:
- NS_UNMOCK(tls_get_write_overhead_ratio);
- NS_UNMOCK(we_are_hibernating);
- NS_UNMOCK(public_server_mode);
- NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(tls_get_write_overhead_ratio);
+ UNMOCK(we_are_hibernating);
+ UNMOCK(public_server_mode);
+ UNMOCK(router_get_my_routerinfo);
}
static double
-NS(tls_get_write_overhead_ratio)(void)
+status_hb_fails_tls_get_write_overhead_ratio(void)
{
return 2.0;
}
static int
-NS(we_are_hibernating)(void)
+status_hb_fails_we_are_hibernating(void)
{
return 0;
}
static int
-NS(public_server_mode)(const or_options_t *options)
+status_hb_fails_public_server_mode(const or_options_t *options)
{
(void)options;
@@ -299,43 +291,51 @@ NS(public_server_mode)(const or_options_t *options)
}
static const routerinfo_t *
-NS(router_get_my_routerinfo)(void)
+status_hb_fails_router_get_my_routerinfo(void)
{
return NULL;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(log_heartbeat, not_in_consensus)
-
/*
* Tests that log_heartbeat() logs appropriately if we are not in the cached
* consensus.
*/
-NS_DECL(double, tls_get_write_overhead_ratio, (void));
-NS_DECL(int, we_are_hibernating, (void));
-NS_DECL(int, public_server_mode, (const or_options_t *options));
-NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void));
-NS_DECL(const node_t *, node_get_by_id, (const char *identity_digest));
-NS_DECL(void, logv, (int severity, log_domain_mask_t domain,
- const char *funcname, const char *suffix, const char *format, va_list ap));
-NS_DECL(int, server_mode, (const or_options_t *options));
+static double status_hb_not_in_consensus_tls_get_write_overhead_ratio(void);
+static int status_hb_not_in_consensus_we_are_hibernating(void);
+static int status_hb_not_in_consensus_public_server_mode(
+ const or_options_t *options);
+static const routerinfo_t *status_hb_not_in_consensus_get_my_routerinfo(void);
+static const node_t * status_hb_not_in_consensus_node_get_by_id(
+ const char *identity_digest);
+static void status_hb_not_in_consensus_logv(
+ int severity, log_domain_mask_t domain, const char *funcname,
+ const char *suffix, const char *format, va_list ap);
+static int status_hb_not_in_consensus_logv_called = 0;
+static int status_hb_not_in_consensus_server_mode(const or_options_t *options);
static routerinfo_t *mock_routerinfo;
static void
-NS(test_main)(void *arg)
+test_status_hb_not_in_consensus(void *arg)
{
int expected, actual;
(void)arg;
- NS_MOCK(tls_get_write_overhead_ratio);
- NS_MOCK(we_are_hibernating);
- NS_MOCK(public_server_mode);
- NS_MOCK(router_get_my_routerinfo);
- NS_MOCK(node_get_by_id);
- NS_MOCK(logv);
- NS_MOCK(server_mode);
+ MOCK(tls_get_write_overhead_ratio,
+ status_hb_not_in_consensus_tls_get_write_overhead_ratio);
+ MOCK(we_are_hibernating,
+ status_hb_not_in_consensus_we_are_hibernating);
+ MOCK(public_server_mode,
+ status_hb_not_in_consensus_public_server_mode);
+ MOCK(router_get_my_routerinfo,
+ status_hb_not_in_consensus_get_my_routerinfo);
+ MOCK(node_get_by_id,
+ status_hb_not_in_consensus_node_get_by_id);
+ MOCK(logv,
+ status_hb_not_in_consensus_logv);
+ MOCK(server_mode,
+ status_hb_not_in_consensus_server_mode);
log_global_min_severity_ = LOG_DEBUG;
onion_handshakes_requested[ONION_HANDSHAKE_TYPE_TAP] = 1;
@@ -347,33 +347,33 @@ NS(test_main)(void *arg)
actual = log_heartbeat(0);
tt_int_op(actual, OP_EQ, expected);
- tt_int_op(CALLED(logv), OP_EQ, 6);
+ tt_int_op(status_hb_not_in_consensus_logv_called, OP_EQ, 6);
done:
- NS_UNMOCK(tls_get_write_overhead_ratio);
- NS_UNMOCK(we_are_hibernating);
- NS_UNMOCK(public_server_mode);
- NS_UNMOCK(router_get_my_routerinfo);
- NS_UNMOCK(node_get_by_id);
- NS_UNMOCK(logv);
- NS_UNMOCK(server_mode);
+ UNMOCK(tls_get_write_overhead_ratio);
+ UNMOCK(we_are_hibernating);
+ UNMOCK(public_server_mode);
+ UNMOCK(router_get_my_routerinfo);
+ UNMOCK(node_get_by_id);
+ UNMOCK(logv);
+ UNMOCK(server_mode);
tor_free(mock_routerinfo);
}
static double
-NS(tls_get_write_overhead_ratio)(void)
+status_hb_not_in_consensus_tls_get_write_overhead_ratio(void)
{
return 1.0;
}
static int
-NS(we_are_hibernating)(void)
+status_hb_not_in_consensus_we_are_hibernating(void)
{
return 0;
}
static int
-NS(public_server_mode)(const or_options_t *options)
+status_hb_not_in_consensus_public_server_mode(const or_options_t *options)
{
(void)options;
@@ -381,7 +381,7 @@ NS(public_server_mode)(const or_options_t *options)
}
static const routerinfo_t *
-NS(router_get_my_routerinfo)(void)
+status_hb_not_in_consensus_get_my_routerinfo(void)
{
mock_routerinfo = tor_malloc(sizeof(routerinfo_t));
@@ -389,7 +389,7 @@ NS(router_get_my_routerinfo)(void)
}
static const node_t *
-NS(node_get_by_id)(const char *identity_digest)
+status_hb_not_in_consensus_node_get_by_id(const char *identity_digest)
{
(void)identity_digest;
@@ -397,10 +397,10 @@ NS(node_get_by_id)(const char *identity_digest)
}
static void
-NS(logv)(int severity, log_domain_mask_t domain,
+status_hb_not_in_consensus_logv(int severity, log_domain_mask_t domain,
const char *funcname, const char *suffix, const char *format, va_list ap)
{
- switch (CALLED(logv))
+ switch (status_hb_not_in_consensus_logv_called)
{
case 0:
tt_int_op(severity, OP_EQ, LOG_NOTICE);
@@ -449,12 +449,13 @@ NS(logv)(int severity, log_domain_mask_t domain,
case 5:
tt_int_op(severity, OP_EQ, LOG_NOTICE);
tt_u64_op(domain, OP_EQ, LD_HEARTBEAT);
- tt_str_op(format, OP_EQ, "DoS mitigation since startup:%s%s%s%s");
+ tt_str_op(format, OP_EQ, "DoS mitigation since startup:%s%s%s%s%s");
tt_str_op(va_arg(ap, char *), OP_EQ,
" 0 circuits killed with too many cells.");
tt_str_op(va_arg(ap, char *), OP_EQ, " [cc not enabled]");
tt_str_op(va_arg(ap, char *), OP_EQ, " [conn not enabled]");
tt_str_op(va_arg(ap, char *), OP_EQ, "");
+ tt_str_op(va_arg(ap, char *), OP_EQ, " 0 INTRODUCE2 rejected.");
break;
default:
tt_abort_msg("unexpected call to logv()"); // TODO: prettyprint args
@@ -462,51 +463,58 @@ NS(logv)(int severity, log_domain_mask_t domain,
}
done:
- CALLED(logv)++;
+ status_hb_not_in_consensus_logv_called++;
}
static int
-NS(server_mode)(const or_options_t *options)
+status_hb_not_in_consensus_server_mode(const or_options_t *options)
{
(void)options;
return 0;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(log_heartbeat, simple)
-
/*
* Tests that log_heartbeat() correctly logs heartbeat information
* normally.
*/
-NS_DECL(double, tls_get_write_overhead_ratio, (void));
-NS_DECL(int, we_are_hibernating, (void));
-NS_DECL(int, public_server_mode, (const or_options_t *options));
-NS_DECL(long, get_uptime, (void));
-NS_DECL(uint64_t, get_bytes_read, (void));
-NS_DECL(uint64_t, get_bytes_written, (void));
-NS_DECL(void, logv, (int severity, log_domain_mask_t domain,
- const char *funcname, const char *suffix, const char *format, va_list ap));
-NS_DECL(int, server_mode, (const or_options_t *options));
+static double status_hb_simple_tls_get_write_overhead_ratio(void);
+static int status_hb_simple_we_are_hibernating(void);
+static int status_hb_simple_public_server_mode(const or_options_t *options);
+static long status_hb_simple_get_uptime(void);
+static uint64_t status_hb_simple_get_bytes_read(void);
+static uint64_t status_hb_simple_get_bytes_written(void);
+static void status_hb_simple_logv(int severity, log_domain_mask_t domain,
+ const char *funcname, const char *suffix,
+ const char *format, va_list ap);
+ATTR_UNUSED static int status_hb_simple_logv_called = 0;
+static int status_hb_simple_server_mode(const or_options_t *options);
-static int NS(n_msgs) = 0;
+static int status_hb_simple_n_msgs = 0;
static void
-NS(test_main)(void *arg)
+test_status_hb_simple(void *arg)
{
int expected, actual;
(void)arg;
- NS_MOCK(tls_get_write_overhead_ratio);
- NS_MOCK(we_are_hibernating);
- NS_MOCK(public_server_mode);
- NS_MOCK(get_uptime);
- NS_MOCK(get_bytes_read);
- NS_MOCK(get_bytes_written);
- NS_MOCK(logv);
- NS_MOCK(server_mode);
+ MOCK(tls_get_write_overhead_ratio,
+ status_hb_simple_tls_get_write_overhead_ratio);
+ MOCK(we_are_hibernating,
+ status_hb_simple_we_are_hibernating);
+ MOCK(public_server_mode,
+ status_hb_simple_public_server_mode);
+ MOCK(get_uptime,
+ status_hb_simple_get_uptime);
+ MOCK(get_bytes_read,
+ status_hb_simple_get_bytes_read);
+ MOCK(get_bytes_written,
+ status_hb_simple_get_bytes_written);
+ MOCK(logv,
+ status_hb_simple_logv);
+ MOCK(server_mode,
+ status_hb_simple_server_mode);
log_global_min_severity_ = LOG_DEBUG;
@@ -514,33 +522,33 @@ NS(test_main)(void *arg)
actual = log_heartbeat(0);
tt_int_op(actual, OP_EQ, expected);
- tt_int_op(NS(n_msgs), OP_EQ, 1);
+ tt_int_op(status_hb_simple_n_msgs, OP_EQ, 1);
done:
- NS_UNMOCK(tls_get_write_overhead_ratio);
- NS_UNMOCK(we_are_hibernating);
- NS_UNMOCK(public_server_mode);
- NS_UNMOCK(get_uptime);
- NS_UNMOCK(get_bytes_read);
- NS_UNMOCK(get_bytes_written);
- NS_UNMOCK(logv);
- NS_UNMOCK(server_mode);
+ UNMOCK(tls_get_write_overhead_ratio);
+ UNMOCK(we_are_hibernating);
+ UNMOCK(public_server_mode);
+ UNMOCK(get_uptime);
+ UNMOCK(get_bytes_read);
+ UNMOCK(get_bytes_written);
+ UNMOCK(logv);
+ UNMOCK(server_mode);
}
static double
-NS(tls_get_write_overhead_ratio)(void)
+status_hb_simple_tls_get_write_overhead_ratio(void)
{
return 1.0;
}
static int
-NS(we_are_hibernating)(void)
+status_hb_simple_we_are_hibernating(void)
{
return 1;
}
static int
-NS(public_server_mode)(const or_options_t *options)
+status_hb_simple_public_server_mode(const or_options_t *options)
{
(void)options;
@@ -548,30 +556,31 @@ NS(public_server_mode)(const or_options_t *options)
}
static long
-NS(get_uptime)(void)
+status_hb_simple_get_uptime(void)
{
return 0;
}
static uint64_t
-NS(get_bytes_read)(void)
+status_hb_simple_get_bytes_read(void)
{
return 0;
}
static uint64_t
-NS(get_bytes_written)(void)
+status_hb_simple_get_bytes_written(void)
{
return 0;
}
static void
-NS(logv)(int severity, log_domain_mask_t domain, const char *funcname,
+status_hb_simple_logv(int severity, log_domain_mask_t domain,
+ const char *funcname,
const char *suffix, const char *format, va_list ap)
{
if (severity == LOG_INFO)
return;
- ++NS(n_msgs);
+ ++status_hb_simple_n_msgs;
tt_int_op(severity, OP_EQ, LOG_NOTICE);
tt_u64_op(domain, OP_EQ, LD_HEARTBEAT);
@@ -591,54 +600,69 @@ NS(logv)(int severity, log_domain_mask_t domain, const char *funcname,
}
static int
-NS(server_mode)(const or_options_t *options)
+status_hb_simple_server_mode(const or_options_t *options)
{
(void)options;
return 0;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(log_heartbeat, calls_log_accounting)
-
/*
* Tests that log_heartbeat() correctly logs heartbeat information
* and accounting information when configured.
*/
-NS_DECL(double, tls_get_write_overhead_ratio, (void));
-NS_DECL(int, we_are_hibernating, (void));
-NS_DECL(int, public_server_mode, (const or_options_t *options));
-NS_DECL(long, get_uptime, (void));
-NS_DECL(uint64_t, get_bytes_read, (void));
-NS_DECL(uint64_t, get_bytes_written, (void));
-NS_DECL(void, logv, (int severity, log_domain_mask_t domain,
- const char *funcname, const char *suffix, const char *format, va_list ap));
-NS_DECL(int, server_mode, (const or_options_t *options));
-NS_DECL(or_state_t *, get_or_state, (void));
-NS_DECL(int, accounting_is_enabled, (const or_options_t *options));
-NS_DECL(time_t, accounting_get_end_time, (void));
-
-static or_state_t * NS(mock_state) = NULL;
-static or_options_t * NS(mock_options) = NULL;
+static double status_hb_calls_log_accounting_tls_get_write_overhead_ratio(
+ void);
+static int status_hb_calls_log_accounting_we_are_hibernating(void);
+static int status_hb_calls_log_accounting_public_server_mode(
+ const or_options_t *options);
+static long status_hb_calls_log_accounting_get_uptime(void);
+static uint64_t status_hb_calls_log_accounting_get_bytes_read(void);
+static uint64_t status_hb_calls_log_accounting_get_bytes_written(void);
+static void status_hb_calls_log_accounting_logv(
+ int severity, log_domain_mask_t domain,
+ const char *funcname, const char *suffix,
+ const char *format, va_list ap);
+static int status_hb_calls_log_accounting_logv_called = 0;
+static int status_hb_calls_log_accounting_server_mode(
+ const or_options_t *options);
+static or_state_t * status_hb_calls_log_accounting_get_or_state(void);
+static int status_hb_calls_log_accounting_accounting_is_enabled(
+ const or_options_t *options);
+static time_t status_hb_calls_log_accounting_accounting_get_end_time(void);
+
+static or_state_t * status_hb_calls_log_accounting_mock_state = NULL;
+static or_options_t * status_hb_calls_log_accounting_mock_options = NULL;
static void
-NS(test_main)(void *arg)
+test_status_hb_calls_log_accounting(void *arg)
{
int expected, actual;
(void)arg;
- NS_MOCK(tls_get_write_overhead_ratio);
- NS_MOCK(we_are_hibernating);
- NS_MOCK(public_server_mode);
- NS_MOCK(get_uptime);
- NS_MOCK(get_bytes_read);
- NS_MOCK(get_bytes_written);
- NS_MOCK(logv);
- NS_MOCK(server_mode);
- NS_MOCK(get_or_state);
- NS_MOCK(accounting_is_enabled);
- NS_MOCK(accounting_get_end_time);
+ MOCK(tls_get_write_overhead_ratio,
+ status_hb_calls_log_accounting_tls_get_write_overhead_ratio);
+ MOCK(we_are_hibernating,
+ status_hb_calls_log_accounting_we_are_hibernating);
+ MOCK(public_server_mode,
+ status_hb_calls_log_accounting_public_server_mode);
+ MOCK(get_uptime,
+ status_hb_calls_log_accounting_get_uptime);
+ MOCK(get_bytes_read,
+ status_hb_calls_log_accounting_get_bytes_read);
+ MOCK(get_bytes_written,
+ status_hb_calls_log_accounting_get_bytes_written);
+ MOCK(logv,
+ status_hb_calls_log_accounting_logv);
+ MOCK(server_mode,
+ status_hb_calls_log_accounting_server_mode);
+ MOCK(get_or_state,
+ status_hb_calls_log_accounting_get_or_state);
+ MOCK(accounting_is_enabled,
+ status_hb_calls_log_accounting_accounting_is_enabled);
+ MOCK(accounting_get_end_time,
+ status_hb_calls_log_accounting_accounting_get_end_time);
log_global_min_severity_ = LOG_DEBUG;
@@ -646,37 +670,37 @@ NS(test_main)(void *arg)
actual = log_heartbeat(0);
tt_int_op(actual, OP_EQ, expected);
- tt_int_op(CALLED(logv), OP_EQ, 3);
+ tt_int_op(status_hb_calls_log_accounting_logv_called, OP_EQ, 3);
done:
- NS_UNMOCK(tls_get_write_overhead_ratio);
- NS_UNMOCK(we_are_hibernating);
- NS_UNMOCK(public_server_mode);
- NS_UNMOCK(get_uptime);
- NS_UNMOCK(get_bytes_read);
- NS_UNMOCK(get_bytes_written);
- NS_UNMOCK(logv);
- NS_UNMOCK(server_mode);
- NS_UNMOCK(accounting_is_enabled);
- NS_UNMOCK(accounting_get_end_time);
- tor_free_(NS(mock_state));
- tor_free_(NS(mock_options));
+ UNMOCK(tls_get_write_overhead_ratio);
+ UNMOCK(we_are_hibernating);
+ UNMOCK(public_server_mode);
+ UNMOCK(get_uptime);
+ UNMOCK(get_bytes_read);
+ UNMOCK(get_bytes_written);
+ UNMOCK(logv);
+ UNMOCK(server_mode);
+ UNMOCK(accounting_is_enabled);
+ UNMOCK(accounting_get_end_time);
+ tor_free_(status_hb_calls_log_accounting_mock_state);
+ tor_free_(status_hb_calls_log_accounting_mock_options);
}
static double
-NS(tls_get_write_overhead_ratio)(void)
+status_hb_calls_log_accounting_tls_get_write_overhead_ratio(void)
{
return 1.0;
}
static int
-NS(we_are_hibernating)(void)
+status_hb_calls_log_accounting_we_are_hibernating(void)
{
return 0;
}
static int
-NS(public_server_mode)(const or_options_t *options)
+status_hb_calls_log_accounting_public_server_mode(const or_options_t *options)
{
(void)options;
@@ -684,28 +708,28 @@ NS(public_server_mode)(const or_options_t *options)
}
static long
-NS(get_uptime)(void)
+status_hb_calls_log_accounting_get_uptime(void)
{
return 0;
}
static uint64_t
-NS(get_bytes_read)(void)
+status_hb_calls_log_accounting_get_bytes_read(void)
{
return 0;
}
static uint64_t
-NS(get_bytes_written)(void)
+status_hb_calls_log_accounting_get_bytes_written(void)
{
return 0;
}
static void
-NS(logv)(int severity, log_domain_mask_t domain,
+status_hb_calls_log_accounting_logv(int severity, log_domain_mask_t domain,
const char *funcname, const char *suffix, const char *format, va_list ap)
{
- switch (CALLED(logv))
+ switch (status_hb_calls_log_accounting_logv_called)
{
case 0:
tt_int_op(severity, OP_EQ, LOG_NOTICE);
@@ -750,11 +774,11 @@ NS(logv)(int severity, log_domain_mask_t domain,
}
done:
- CALLED(logv)++;
+ status_hb_calls_log_accounting_logv_called++;
}
static int
-NS(server_mode)(const or_options_t *options)
+status_hb_calls_log_accounting_server_mode(const or_options_t *options)
{
(void)options;
@@ -762,7 +786,8 @@ NS(server_mode)(const or_options_t *options)
}
static int
-NS(accounting_is_enabled)(const or_options_t *options)
+status_hb_calls_log_accounting_accounting_is_enabled(
+ const or_options_t *options)
{
(void)options;
@@ -770,55 +795,71 @@ NS(accounting_is_enabled)(const or_options_t *options)
}
static time_t
-NS(accounting_get_end_time)(void)
+status_hb_calls_log_accounting_accounting_get_end_time(void)
{
return 60;
}
static or_state_t *
-NS(get_or_state)(void)
+status_hb_calls_log_accounting_get_or_state(void)
{
- NS(mock_state) = tor_malloc_zero(sizeof(or_state_t));
- NS(mock_state)->AccountingBytesReadInInterval = 0;
- NS(mock_state)->AccountingBytesWrittenInInterval = 0;
-
- return NS(mock_state);
+ status_hb_calls_log_accounting_mock_state =
+ tor_malloc_zero(sizeof(or_state_t));
+ status_hb_calls_log_accounting_mock_state
+ ->AccountingBytesReadInInterval = 0;
+ status_hb_calls_log_accounting_mock_state
+ ->AccountingBytesWrittenInInterval = 0;
+
+ return status_hb_calls_log_accounting_mock_state;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(log_heartbeat, packaged_cell_fullness)
-
/*
* Tests that log_heartbeat() correctly logs packaged cell
* fullness information.
*/
-NS_DECL(double, tls_get_write_overhead_ratio, (void));
-NS_DECL(int, we_are_hibernating, (void));
-NS_DECL(int, public_server_mode, (const or_options_t *options));
-NS_DECL(long, get_uptime, (void));
-NS_DECL(uint64_t, get_bytes_read, (void));
-NS_DECL(uint64_t, get_bytes_written, (void));
-NS_DECL(void, logv, (int severity, log_domain_mask_t domain,
- const char *funcname, const char *suffix, const char *format, va_list ap));
-NS_DECL(int, server_mode, (const or_options_t *options));
-NS_DECL(int, accounting_is_enabled, (const or_options_t *options));
+static double status_hb_packaged_cell_fullness_tls_get_write_overhead_ratio(
+ void);
+static int status_hb_packaged_cell_fullness_we_are_hibernating(void);
+static int status_hb_packaged_cell_fullness_public_server_mode(
+ const or_options_t *options);
+static long status_hb_packaged_cell_fullness_get_uptime(void);
+static uint64_t status_hb_packaged_cell_fullness_get_bytes_read(void);
+static uint64_t status_hb_packaged_cell_fullness_get_bytes_written(void);
+static void status_hb_packaged_cell_fullness_logv(
+ int severity, log_domain_mask_t domain,
+ const char *funcname, const char *suffix,
+ const char *format, va_list ap);
+static int status_hb_packaged_cell_fullness_logv_called = 0;
+static int status_hb_packaged_cell_fullness_server_mode(
+ const or_options_t *options);
+static int status_hb_packaged_cell_fullness_accounting_is_enabled(
+ const or_options_t *options);
static void
-NS(test_main)(void *arg)
+test_status_hb_packaged_cell_fullness(void *arg)
{
int expected, actual;
(void)arg;
- NS_MOCK(tls_get_write_overhead_ratio);
- NS_MOCK(we_are_hibernating);
- NS_MOCK(public_server_mode);
- NS_MOCK(get_uptime);
- NS_MOCK(get_bytes_read);
- NS_MOCK(get_bytes_written);
- NS_MOCK(logv);
- NS_MOCK(server_mode);
- NS_MOCK(accounting_is_enabled);
+ MOCK(tls_get_write_overhead_ratio,
+ status_hb_packaged_cell_fullness_tls_get_write_overhead_ratio);
+ MOCK(we_are_hibernating,
+ status_hb_packaged_cell_fullness_we_are_hibernating);
+ MOCK(public_server_mode,
+ status_hb_packaged_cell_fullness_public_server_mode);
+ MOCK(get_uptime,
+ status_hb_packaged_cell_fullness_get_uptime);
+ MOCK(get_bytes_read,
+ status_hb_packaged_cell_fullness_get_bytes_read);
+ MOCK(get_bytes_written,
+ status_hb_packaged_cell_fullness_get_bytes_written);
+ MOCK(logv,
+ status_hb_packaged_cell_fullness_logv);
+ MOCK(server_mode,
+ status_hb_packaged_cell_fullness_server_mode);
+ MOCK(accounting_is_enabled,
+ status_hb_packaged_cell_fullness_accounting_is_enabled);
log_global_min_severity_ = LOG_DEBUG;
stats_n_data_bytes_packaged = RELAY_PAYLOAD_SIZE;
@@ -827,36 +868,37 @@ NS(test_main)(void *arg)
actual = log_heartbeat(0);
tt_int_op(actual, OP_EQ, expected);
- tt_int_op(CALLED(logv), OP_EQ, 2);
+ tt_int_op(status_hb_packaged_cell_fullness_logv_called, OP_EQ, 2);
done:
stats_n_data_bytes_packaged = 0;
stats_n_data_cells_packaged = 0;
- NS_UNMOCK(tls_get_write_overhead_ratio);
- NS_UNMOCK(we_are_hibernating);
- NS_UNMOCK(public_server_mode);
- NS_UNMOCK(get_uptime);
- NS_UNMOCK(get_bytes_read);
- NS_UNMOCK(get_bytes_written);
- NS_UNMOCK(logv);
- NS_UNMOCK(server_mode);
- NS_UNMOCK(accounting_is_enabled);
+ UNMOCK(tls_get_write_overhead_ratio);
+ UNMOCK(we_are_hibernating);
+ UNMOCK(public_server_mode);
+ UNMOCK(get_uptime);
+ UNMOCK(get_bytes_read);
+ UNMOCK(get_bytes_written);
+ UNMOCK(logv);
+ UNMOCK(server_mode);
+ UNMOCK(accounting_is_enabled);
}
static double
-NS(tls_get_write_overhead_ratio)(void)
+status_hb_packaged_cell_fullness_tls_get_write_overhead_ratio(void)
{
return 1.0;
}
static int
-NS(we_are_hibernating)(void)
+status_hb_packaged_cell_fullness_we_are_hibernating(void)
{
return 0;
}
static int
-NS(public_server_mode)(const or_options_t *options)
+status_hb_packaged_cell_fullness_public_server_mode(
+ const or_options_t *options)
{
(void)options;
@@ -864,28 +906,29 @@ NS(public_server_mode)(const or_options_t *options)
}
static long
-NS(get_uptime)(void)
+status_hb_packaged_cell_fullness_get_uptime(void)
{
return 0;
}
static uint64_t
-NS(get_bytes_read)(void)
+status_hb_packaged_cell_fullness_get_bytes_read(void)
{
return 0;
}
static uint64_t
-NS(get_bytes_written)(void)
+status_hb_packaged_cell_fullness_get_bytes_written(void)
{
return 0;
}
static void
-NS(logv)(int severity, log_domain_mask_t domain, const char *funcname,
+status_hb_packaged_cell_fullness_logv(int severity,
+ log_domain_mask_t domain, const char *funcname,
const char *suffix, const char *format, va_list ap)
{
- switch (CALLED(logv))
+ switch (status_hb_packaged_cell_fullness_logv_called)
{
case 0:
tt_int_op(severity, OP_EQ, LOG_NOTICE);
@@ -918,11 +961,11 @@ NS(logv)(int severity, log_domain_mask_t domain, const char *funcname,
}
done:
- CALLED(logv)++;
+ status_hb_packaged_cell_fullness_logv_called++;
}
static int
-NS(server_mode)(const or_options_t *options)
+status_hb_packaged_cell_fullness_server_mode(const or_options_t *options)
{
(void)options;
@@ -930,47 +973,60 @@ NS(server_mode)(const or_options_t *options)
}
static int
-NS(accounting_is_enabled)(const or_options_t *options)
+status_hb_packaged_cell_fullness_accounting_is_enabled(
+ const or_options_t *options)
{
(void)options;
return 0;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(log_heartbeat, tls_write_overhead)
-
/*
* Tests that log_heartbeat() correctly logs the TLS write overhead information
* when the TLS write overhead ratio exceeds 1.
*/
-NS_DECL(double, tls_get_write_overhead_ratio, (void));
-NS_DECL(int, we_are_hibernating, (void));
-NS_DECL(int, public_server_mode, (const or_options_t *options));
-NS_DECL(long, get_uptime, (void));
-NS_DECL(uint64_t, get_bytes_read, (void));
-NS_DECL(uint64_t, get_bytes_written, (void));
-NS_DECL(void, logv, (int severity, log_domain_mask_t domain,
- const char *funcname, const char *suffix, const char *format, va_list ap));
-NS_DECL(int, server_mode, (const or_options_t *options));
-NS_DECL(int, accounting_is_enabled, (const or_options_t *options));
+static double status_hb_tls_write_overhead_tls_get_write_overhead_ratio(void);
+static int status_hb_tls_write_overhead_we_are_hibernating(void);
+static int status_hb_tls_write_overhead_public_server_mode(
+ const or_options_t *options);
+static long status_hb_tls_write_overhead_get_uptime(void);
+static uint64_t status_hb_tls_write_overhead_get_bytes_read(void);
+static uint64_t status_hb_tls_write_overhead_get_bytes_written(void);
+static void status_hb_tls_write_overhead_logv(
+ int severity, log_domain_mask_t domain,
+ const char *funcname, const char *suffix,
+ const char *format, va_list ap);
+static int status_hb_tls_write_overhead_logv_called = 0;
+static int status_hb_tls_write_overhead_server_mode(
+ const or_options_t *options);
+static int status_hb_tls_write_overhead_accounting_is_enabled(
+ const or_options_t *options);
static void
-NS(test_main)(void *arg)
+test_status_hb_tls_write_overhead(void *arg)
{
int expected, actual;
(void)arg;
- NS_MOCK(tls_get_write_overhead_ratio);
- NS_MOCK(we_are_hibernating);
- NS_MOCK(public_server_mode);
- NS_MOCK(get_uptime);
- NS_MOCK(get_bytes_read);
- NS_MOCK(get_bytes_written);
- NS_MOCK(logv);
- NS_MOCK(server_mode);
- NS_MOCK(accounting_is_enabled);
+ MOCK(tls_get_write_overhead_ratio,
+ status_hb_tls_write_overhead_tls_get_write_overhead_ratio);
+ MOCK(we_are_hibernating,
+ status_hb_tls_write_overhead_we_are_hibernating);
+ MOCK(public_server_mode,
+ status_hb_tls_write_overhead_public_server_mode);
+ MOCK(get_uptime,
+ status_hb_tls_write_overhead_get_uptime);
+ MOCK(get_bytes_read,
+ status_hb_tls_write_overhead_get_bytes_read);
+ MOCK(get_bytes_written,
+ status_hb_tls_write_overhead_get_bytes_written);
+ MOCK(logv,
+ status_hb_tls_write_overhead_logv);
+ MOCK(server_mode,
+ status_hb_tls_write_overhead_server_mode);
+ MOCK(accounting_is_enabled,
+ status_hb_tls_write_overhead_accounting_is_enabled);
stats_n_data_cells_packaged = 0;
log_global_min_severity_ = LOG_DEBUG;
@@ -978,34 +1034,34 @@ NS(test_main)(void *arg)
actual = log_heartbeat(0);
tt_int_op(actual, OP_EQ, expected);
- tt_int_op(CALLED(logv), OP_EQ, 2);
+ tt_int_op(status_hb_tls_write_overhead_logv_called, OP_EQ, 2);
done:
- NS_UNMOCK(tls_get_write_overhead_ratio);
- NS_UNMOCK(we_are_hibernating);
- NS_UNMOCK(public_server_mode);
- NS_UNMOCK(get_uptime);
- NS_UNMOCK(get_bytes_read);
- NS_UNMOCK(get_bytes_written);
- NS_UNMOCK(logv);
- NS_UNMOCK(server_mode);
- NS_UNMOCK(accounting_is_enabled);
+ UNMOCK(tls_get_write_overhead_ratio);
+ UNMOCK(we_are_hibernating);
+ UNMOCK(public_server_mode);
+ UNMOCK(get_uptime);
+ UNMOCK(get_bytes_read);
+ UNMOCK(get_bytes_written);
+ UNMOCK(logv);
+ UNMOCK(server_mode);
+ UNMOCK(accounting_is_enabled);
}
static double
-NS(tls_get_write_overhead_ratio)(void)
+status_hb_tls_write_overhead_tls_get_write_overhead_ratio(void)
{
return 2.0;
}
static int
-NS(we_are_hibernating)(void)
+status_hb_tls_write_overhead_we_are_hibernating(void)
{
return 0;
}
static int
-NS(public_server_mode)(const or_options_t *options)
+status_hb_tls_write_overhead_public_server_mode(const or_options_t *options)
{
(void)options;
@@ -1013,28 +1069,28 @@ NS(public_server_mode)(const or_options_t *options)
}
static long
-NS(get_uptime)(void)
+status_hb_tls_write_overhead_get_uptime(void)
{
return 0;
}
static uint64_t
-NS(get_bytes_read)(void)
+status_hb_tls_write_overhead_get_bytes_read(void)
{
return 0;
}
static uint64_t
-NS(get_bytes_written)(void)
+status_hb_tls_write_overhead_get_bytes_written(void)
{
return 0;
}
static void
-NS(logv)(int severity, log_domain_mask_t domain,
+status_hb_tls_write_overhead_logv(int severity, log_domain_mask_t domain,
const char *funcname, const char *suffix, const char *format, va_list ap)
{
- switch (CALLED(logv))
+ switch (status_hb_tls_write_overhead_logv_called)
{
case 0:
tt_int_op(severity, OP_EQ, LOG_NOTICE);
@@ -1067,11 +1123,11 @@ NS(logv)(int severity, log_domain_mask_t domain,
}
done:
- CALLED(logv)++;
+ status_hb_tls_write_overhead_logv_called++;
}
static int
-NS(server_mode)(const or_options_t *options)
+status_hb_tls_write_overhead_server_mode(const or_options_t *options)
{
(void)options;
@@ -1079,24 +1135,26 @@ NS(server_mode)(const or_options_t *options)
}
static int
-NS(accounting_is_enabled)(const or_options_t *options)
+status_hb_tls_write_overhead_accounting_is_enabled(const or_options_t *options)
{
(void)options;
return 0;
}
-#undef NS_SUBMODULE
-
struct testcase_t status_tests[] = {
- TEST_CASE(count_circuits),
- TEST_CASE(secs_to_uptime),
- TEST_CASE(bytes_to_usage),
- TEST_CASE_ASPECT(log_heartbeat, fails),
- TEST_CASE_ASPECT(log_heartbeat, simple),
- TEST_CASE_ASPECT(log_heartbeat, not_in_consensus),
- TEST_CASE_ASPECT(log_heartbeat, calls_log_accounting),
- TEST_CASE_ASPECT(log_heartbeat, packaged_cell_fullness),
- TEST_CASE_ASPECT(log_heartbeat, tls_write_overhead),
+ { "count_circuits", test_status_count_circuits, TT_FORK, NULL, NULL },
+ { "secs_to_uptime", test_status_secs_to_uptime, TT_FORK, NULL, NULL },
+ { "bytes_to_usage", test_status_bytes_to_usage, TT_FORK, NULL, NULL },
+ { "hb_fails", test_status_hb_fails, TT_FORK, NULL, NULL },
+ { "hb_simple", test_status_hb_simple, TT_FORK, NULL, NULL },
+ { "hb_not_in_consensus", test_status_hb_not_in_consensus,
+ TT_FORK, NULL, NULL },
+ { "hb_calls_log_accounting", test_status_hb_calls_log_accounting,
+ TT_FORK, NULL, NULL },
+ { "hb_packaged_cell_fullness", test_status_hb_packaged_cell_fullness,
+ TT_FORK, NULL, NULL },
+ { "hb_tls_write_overhead", test_status_hb_tls_write_overhead,
+ TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_storagedir.c b/src/test/test_storagedir.c
index 24e45c7428..eb3779cfee 100644
--- a/src/test/test_storagedir.c
+++ b/src/test/test_storagedir.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
diff --git a/src/test/test_switch_id.c b/src/test/test_switch_id.c
index 19483713f7..ca189a9cf5 100644
--- a/src/test/test_switch_id.c
+++ b/src/test/test_switch_id.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2019, The Tor Project, Inc. */
+/* Copyright (c) 2015-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
diff --git a/src/test/test_threads.c b/src/test/test_threads.c
index 4a5ecc6fae..d5a1834aef 100644
--- a/src/test/test_threads.c
+++ b/src/test/test_threads.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -155,7 +155,7 @@ test_threads_basic(void *arg)
tor_mutex_free(thread_test_start2_);
}
-typedef struct cv_testinfo_s {
+typedef struct cv_testinfo_t {
tor_cond_t *cond;
tor_mutex_t *mutex;
int value;
diff --git a/src/test/test_token_bucket.c b/src/test/test_token_bucket.c
index 31670718d9..cf315f2944 100644
--- a/src/test/test_token_bucket.c
+++ b/src/test/test_token_bucket.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_tortls.c b/src/test/test_tortls.c
index d59b8e001d..12ba873650 100644
--- a/src/test/test_tortls.c
+++ b/src/test/test_tortls.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define TORTLS_PRIVATE
@@ -225,7 +225,7 @@ test_tortls_tor_tls_get_error(void *data)
done:
UNMOCK(tor_tls_cert_matches_key);
- NS_UNMOCK(logv);
+ UNMOCK(logv);
crypto_pk_free(key1);
crypto_pk_free(key2);
tor_tls_free(tls);
diff --git a/src/test/test_tortls.h b/src/test/test_tortls.h
index 4567b9f6a0..21c6fa0a8f 100644
--- a/src/test/test_tortls.h
+++ b/src/test/test_tortls.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TEST_TORTLS_H
diff --git a/src/test/test_tortls_openssl.c b/src/test/test_tortls_openssl.c
index 93135d0b19..e20b0d1ede 100644
--- a/src/test/test_tortls_openssl.c
+++ b/src/test/test_tortls_openssl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define TORTLS_PRIVATE
@@ -16,7 +16,7 @@
/* Some versions of OpenSSL declare SSL_get_selected_srtp_profile twice in
* srtp.h. Suppress the GCC warning so we can build with -Wredundant-decl. */
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/opensslv.h>
@@ -29,7 +29,7 @@ DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/evp.h>
#include <openssl/bn.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
#include "core/or/or.h"
#include "lib/log/log.h"
@@ -46,8 +46,6 @@ ENABLE_GCC_WARNING(redundant-decls)
#include "test/log_test_helpers.h"
#include "test/test_tortls.h"
-#define NS_MODULE tortls
-
#ifndef HAVE_SSL_STATE
#define OPENSSL_OPAQUE
#endif
@@ -123,8 +121,6 @@ test_tortls_tor_tls_new(void *data)
tor_tls_free_all();
}
-#define NS_MODULE tortls
-
static void
library_init(void)
{
diff --git a/src/test/test_util.c b/src/test/test_util.c
index aebefe64c5..0d86a5ab5d 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -1,14 +1,11 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
-#define COMPAT_PRIVATE
#define COMPAT_TIME_PRIVATE
-#define UTIL_PRIVATE
#define UTIL_MALLOC_PRIVATE
-#define SOCKET_PRIVATE
#define PROCESS_WIN32_PRIVATE
#include "lib/testsupport/testsupport.h"
#include "core/or/or.h"
@@ -33,6 +30,7 @@
#include "lib/process/env.h"
#include "lib/process/pidfile.h"
#include "lib/intmath/weakrng.h"
+#include "lib/intmath/muldiv.h"
#include "lib/thread/numcpus.h"
#include "lib/math/fp.h"
#include "lib/math/laplace.h"
@@ -74,6 +72,11 @@
#include <ctype.h>
#include <float.h>
+/* These platforms don't have meaningful pwdb or homedirs. */
+#if defined(_WIN32) || defined(__ANDROID__)
+#define DISABLE_PWDB_TESTS
+#endif
+
#define INFINITY_DBL ((double)INFINITY)
#define NAN_DBL ((double)NAN)
@@ -304,6 +307,7 @@ test_util_write_chunks_to_file(void *arg)
tor_free(temp_str);
}
+#ifndef COCCI
#define _TFE(a, b, f) tt_int_op((a).f, OP_EQ, (b).f)
/** test the minimum set of struct tm fields needed for a unique epoch value
* this is also the set we use to test tor_timegm */
@@ -316,6 +320,7 @@ test_util_write_chunks_to_file(void *arg)
_TFE(a, b, tm_min ); \
_TFE(a, b, tm_sec ); \
TT_STMT_END
+#endif /* !defined(COCCI) */
static void
test_util_time(void *arg)
@@ -1845,7 +1850,7 @@ test_util_config_line_crlf(void *arg)
tor_free(k); tor_free(v);
}
-#ifndef _WIN32
+#ifndef DISABLE_PWDB_TESTS
static void
test_util_expand_filename(void *arg)
{
@@ -1942,7 +1947,7 @@ test_util_expand_filename(void *arg)
done:
tor_free(str);
}
-#endif /* !defined(_WIN32) */
+#endif /* !defined(DISABLE_PWDB_TESTS) */
/** Test tor_escape_str_for_pt_args(). */
static void
@@ -4104,10 +4109,43 @@ test_util_string_is_utf8(void *ptr)
tt_int_op(0, OP_EQ, string_is_utf8("\xed\xbf\xbf", 3));
tt_int_op(1, OP_EQ, string_is_utf8("\xee\x80\x80", 3));
- // The maximum legal codepoint, 10FFFF.
+ // The minimum legal codepoint, 0x00.
+ tt_int_op(1, OP_EQ, string_is_utf8("\0", 1));
+
+ // The maximum legal codepoint, 0x10FFFF.
tt_int_op(1, OP_EQ, string_is_utf8("\xf4\x8f\xbf\xbf", 4));
tt_int_op(0, OP_EQ, string_is_utf8("\xf4\x90\x80\x80", 4));
+ /* Test cases that vary between programming languages /
+ * UTF-8 implementations.
+ * Source: POC||GTFO 19, page 43
+ * https://www.alchemistowl.org/pocorgtfo/
+ */
+
+ // Invalid (in most implementations)
+ // surrogate
+ tt_int_op(0, OP_EQ, string_is_utf8("\xed\xa0\x81", 3));
+ // nullsurrog
+ tt_int_op(0, OP_EQ, string_is_utf8("\x30\x00\xed\xa0\x81", 5));
+ // threehigh
+ tt_int_op(0, OP_EQ, string_is_utf8("\xed\xbf\xbf", 3));
+ // fourhigh
+ tt_int_op(0, OP_EQ, string_is_utf8("\xf4\x90\xbf\xbf", 4));
+ // fivebyte
+ tt_int_op(0, OP_EQ, string_is_utf8("\xfb\x80\x80\x80\x80", 5));
+ // sixbyte
+ tt_int_op(0, OP_EQ, string_is_utf8("\xfd\x80\x80\x80\x80", 5));
+ // sixhigh
+ tt_int_op(0, OP_EQ, string_is_utf8("\xfd\xbf\xbf\xbf\xbf", 5));
+
+ // Valid (in most implementations)
+ // fourbyte
+ tt_int_op(1, OP_EQ, string_is_utf8("\xf0\x90\x8d\x88", 4));
+ // fourbyte2
+ tt_int_op(1, OP_EQ, string_is_utf8("\xf0\xbf\xbf\xbf", 4));
+ // nullbyte
+ tt_int_op(1, OP_EQ, string_is_utf8("\x30\x31\x32\x00\x33", 5));
+
done:
;
}
@@ -5653,7 +5691,7 @@ test_util_touch_file(void *arg)
;
}
-#ifndef _WIN32
+#ifndef DISABLE_PWDB_TESTS
static void
test_util_pwdb(void *arg)
{
@@ -5725,7 +5763,7 @@ test_util_pwdb(void *arg)
tor_free(dir);
teardown_capture_of_logs();
}
-#endif /* !defined(_WIN32) */
+#endif /* !defined(DISABLE_PWDB_TESTS) */
static void
test_util_calloc_check(void *arg)
@@ -5973,6 +6011,14 @@ test_util_nowrap_math(void *arg)
tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(2, UINT32_MAX-1));
tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(UINT32_MAX, UINT32_MAX));
+ tt_u64_op(0, OP_EQ, tor_mul_u64_nowrap(0, 0));
+ tt_u64_op(1, OP_EQ, tor_mul_u64_nowrap(1, 1));
+ tt_u64_op(2, OP_EQ, tor_mul_u64_nowrap(2, 1));
+ tt_u64_op(4, OP_EQ, tor_mul_u64_nowrap(2, 2));
+ tt_u64_op(UINT64_MAX, OP_EQ, tor_mul_u64_nowrap(UINT64_MAX, 1));
+ tt_u64_op(UINT64_MAX, OP_EQ, tor_mul_u64_nowrap(2, UINT64_MAX));
+ tt_u64_op(UINT64_MAX, OP_EQ, tor_mul_u64_nowrap(UINT64_MAX, UINT64_MAX));
+
done:
;
}
@@ -6257,6 +6303,7 @@ test_util_map_anon_nofork(void *arg)
#endif /* defined(_WIN32) */
}
+#ifndef COCCI
#define UTIL_LEGACY(name) \
{ #name, test_util_ ## name , 0, NULL, NULL }
@@ -6281,16 +6328,19 @@ test_util_map_anon_nofork(void *arg)
{ "compress_dos/" #name, test_util_decompress_dos, 0, \
&compress_setup, \
(char*)(identifier) }
+#endif /* !defined(COCCI) */
#ifdef _WIN32
-#define UTIL_TEST_NO_WIN(n, f) { #n, NULL, TT_SKIP, NULL, NULL }
#define UTIL_TEST_WIN_ONLY(n, f) UTIL_TEST(n, (f))
-#define UTIL_LEGACY_NO_WIN(n) UTIL_TEST_NO_WIN(n, 0)
#else
-#define UTIL_TEST_NO_WIN(n, f) UTIL_TEST(n, (f))
#define UTIL_TEST_WIN_ONLY(n, f) { #n, NULL, TT_SKIP, NULL, NULL }
-#define UTIL_LEGACY_NO_WIN(n) UTIL_LEGACY(n)
-#endif /* defined(_WIN32) */
+#endif
+
+#ifdef DISABLE_PWDB_TESTS
+#define UTIL_TEST_PWDB(n, f) { #n, NULL, TT_SKIP, NULL, NULL }
+#else
+#define UTIL_TEST_PWDB(n, f) UTIL_TEST(n, (f))
+#endif
struct testcase_t util_tests[] = {
UTIL_LEGACY(time),
@@ -6300,7 +6350,7 @@ struct testcase_t util_tests[] = {
UTIL_LEGACY(config_line_comment_character),
UTIL_LEGACY(config_line_escaped_content),
UTIL_LEGACY(config_line_crlf),
- UTIL_LEGACY_NO_WIN(expand_filename),
+ UTIL_TEST_PWDB(expand_filename, 0),
UTIL_LEGACY(escape_string_socks),
UTIL_LEGACY(string_is_key_value),
UTIL_LEGACY(strmisc),
@@ -6385,7 +6435,7 @@ struct testcase_t util_tests[] = {
UTIL_TEST(writepid, 0),
UTIL_TEST(get_avail_disk_space, 0),
UTIL_TEST(touch_file, 0),
- UTIL_TEST_NO_WIN(pwdb, TT_FORK),
+ UTIL_TEST_PWDB(pwdb, TT_FORK),
UTIL_TEST(calloc_check, 0),
UTIL_TEST(monotonic_time, 0),
UTIL_TEST(monotonic_time_ratchet, TT_FORK),
diff --git a/src/test/test_util_format.c b/src/test/test_util_format.c
index 2859da66b2..726e8e7427 100644
--- a/src/test/test_util_format.c
+++ b/src/test/test_util_format.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -7,11 +7,8 @@
#include "test/test.h"
#include "lib/crypt_ops/crypto_rand.h"
-#define UTIL_FORMAT_PRIVATE
#include "lib/encoding/binascii.h"
-#define NS_MODULE util_format
-
static void
test_util_format_unaligned_accessors(void *ignored)
{
diff --git a/src/test/test_util_process.c b/src/test/test_util_process.c
index 4d04eb6dfc..0e17e009f3 100644
--- a/src/test/test_util_process.c
+++ b/src/test/test_util_process.c
@@ -1,7 +1,6 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#define UTIL_PROCESS_PRIVATE
#include "orconfig.h"
#include "core/or/or.h"
@@ -12,7 +11,6 @@
#include "test/log_test_helpers.h"
#ifndef _WIN32
-#define NS_MODULE util_process
static void
temp_callback(int r, void *s)
diff --git a/src/test/test_voting_flags.c b/src/test/test_voting_flags.c
index c8111ea5df..ae89e43889 100644
--- a/src/test/test_voting_flags.c
+++ b/src/test/test_voting_flags.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -8,6 +8,7 @@
#include "core/or/or.h"
#include "feature/dirauth/voteflags.h"
+#include "feature/dirauth/dirauth_options_st.h"
#include "feature/nodelist/node_st.h"
#include "feature/nodelist/routerstatus_st.h"
#include "feature/nodelist/routerinfo_st.h"
@@ -15,6 +16,7 @@
#include "app/config/config.h"
#include "test/test.h"
+#include "test/opts_test_helpers.h"
typedef struct {
time_t now;
@@ -119,7 +121,7 @@ test_voting_flags_ipv6(void *arg)
if (!check_result(cfg))
goto done;
- get_options_mutable()->AuthDirHasIPv6Connectivity = 1;
+ get_dirauth_options(get_options_mutable())->AuthDirHasIPv6Connectivity = 1;
// no change in expected results, since last_reachable6 won't be set.
if (!check_result(cfg))
goto done;
diff --git a/src/test/test_voting_schedule.c b/src/test/test_voting_schedule.c
index ba4d53a4ae..54d1815a77 100644
--- a/src/test/test_voting_schedule.c
+++ b/src/test/test_voting_schedule.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_workqueue.c b/src/test/test_workqueue.c
index ba478a45a4..3734c08e48 100644
--- a/src/test/test_workqueue.c
+++ b/src/test/test_workqueue.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
@@ -32,7 +32,7 @@ int handled_len;
bitarray_t *handled;
#endif
-typedef struct state_s {
+typedef struct state_t {
int magic;
int n_handled;
crypto_pk_t *rsa;
@@ -40,13 +40,13 @@ typedef struct state_s {
int is_shutdown;
} state_t;
-typedef struct rsa_work_s {
+typedef struct rsa_work_t {
int serial;
uint8_t msg[128];
uint8_t msglen;
} rsa_work_t;
-typedef struct ecdh_work_s {
+typedef struct ecdh_work_t {
int serial;
union {
curve25519_public_key_t pk;
@@ -339,7 +339,7 @@ main(int argc, char **argv)
replyqueue_t *rq;
threadpool_t *tp;
int i;
- tor_libevent_cfg evcfg;
+ tor_libevent_cfg_t evcfg;
uint32_t as_flags = 0;
for (i = 1; i < argc; ++i) {
diff --git a/src/test/test_x509.c b/src/test/test_x509.c
index 792849ae4b..94e7db33de 100644
--- a/src/test/test_x509.c
+++ b/src/test/test_x509.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define TOR_X509_PRIVATE
diff --git a/src/test/test_zero_length_keys.sh b/src/test/test_zero_length_keys.sh
index 84ca513b0a..b944d9bf3f 100755
--- a/src/test/test_zero_length_keys.sh
+++ b/src/test/test_zero_length_keys.sh
@@ -1,10 +1,44 @@
#!/bin/sh
# Check that tor regenerates keys when key files are zero-length
+umask 077
+set -e
+
+# emulate realpath(), in case coreutils or equivalent is not installed.
+abspath() {
+ f="$*"
+ if [ -d "$f" ]; then
+ dir="$f"
+ base=""
+ else
+ dir="$(dirname "$f")"
+ base="/$(basename "$f")"
+ fi
+ dir="$(cd "$dir" && pwd)"
+ echo "$dir$base"
+}
+
+# find the tor binary
+if [ $# -ge 1 ]; then
+ TOR_BINARY="${1}"
+ shift
+else
+ TOR_BINARY="${TESTING_TOR_BINARY:-./src/app/tor}"
+fi
+
+TOR_BINARY="$(abspath "$TOR_BINARY")"
+
+echo "TOR BINARY IS ${TOR_BINARY}"
+
+if "$TOR_BINARY" --list-modules | grep -q "relay: no"; then
+ echo "This test requires the relay module. Skipping." >&2
+ exit 77
+fi
+
exitcode=0
-"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/app/tor" -z || exitcode=1
-"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/app/tor" -d || exitcode=1
-"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/app/tor" -e || exitcode=1
+"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "$TOR_BINARY" -z || exitcode=1
+"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "$TOR_BINARY" -d || exitcode=1
+"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "$TOR_BINARY" -e || exitcode=1
exit ${exitcode}
diff --git a/src/test/testing_common.c b/src/test/testing_common.c
index 06a6f312ad..e9aa4112c0 100644
--- a/src/test/testing_common.c
+++ b/src/test/testing_common.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -89,6 +89,17 @@ setup_directory(void)
(int)getpid(), rnd32);
r = mkdir(temp_dir);
}
+#elif defined(__ANDROID__)
+ /* tor might not like the default perms, so create a subdir */
+ tor_snprintf(temp_dir, sizeof(temp_dir),
+ "/data/local/tmp/tor_%d_%d_%s",
+ (int) getuid(), (int) getpid(), rnd32);
+ r = mkdir(temp_dir, 0700);
+ if (r) {
+ fprintf(stderr, "Can't create directory %s:", temp_dir);
+ perror("");
+ exit(1);
+ }
#else /* !defined(_WIN32) */
tor_snprintf(temp_dir, sizeof(temp_dir), "/tmp/tor_test_%d_%s",
(int) getpid(), rnd32);
@@ -97,7 +108,7 @@ setup_directory(void)
/* undo sticky bit so tests don't get confused. */
r = chown(temp_dir, getuid(), getgid());
}
-#endif /* defined(_WIN32) */
+#endif /* defined(_WIN32) || ... */
if (r) {
fprintf(stderr, "Can't create directory %s:", temp_dir);
perror("");
@@ -266,12 +277,15 @@ main(int c, const char **v)
options = options_new();
- struct tor_libevent_cfg cfg;
+ struct tor_libevent_cfg_t cfg;
memset(&cfg, 0, sizeof(cfg));
tor_libevent_initialize(&cfg);
control_initialize_event_queue();
+ /* Don't add default logs; the tests manage their own. */
+ quiet_level = QUIET_SILENT;
+
for (i_out = i = 1; i < c; ++i) {
if (!strcmp(v[i], "--warn")) {
loglevel = LOG_WARN;
@@ -323,6 +337,7 @@ main(int c, const char **v)
initialize_mainloop_events();
options_init(options);
options->DataDirectory = tor_strdup(temp_dir);
+ options->DataDirectory_option = tor_strdup(temp_dir);
tor_asprintf(&options->KeyDirectory, "%s"PATH_SEPARATOR"keys",
options->DataDirectory);
options->CacheDirectory = tor_strdup(temp_dir);
diff --git a/src/test/testing_rsakeys.c b/src/test/testing_rsakeys.c
index 727449e6eb..e058f72d01 100644
--- a/src/test/testing_rsakeys.c
+++ b/src/test/testing_rsakeys.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "lib/crypt_ops/crypto_rand.h"
diff --git a/src/tools/.may_include b/src/tools/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/tools/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/tools/tools.md b/src/tools/tools.md
new file mode 100644
index 0000000000..1f00381679
--- /dev/null
+++ b/src/tools/tools.md
@@ -0,0 +1,6 @@
+@dir /tools
+@brief tools: other command-line tools for use with Tor.
+
+The "tools" directory has a few other programs that use Tor, but are not part
+of the main Tor binary.
+
diff --git a/src/tools/tor-gencert.c b/src/tools/tor-gencert.c
index ea96f41dbf..e4f6530b46 100644
--- a/src/tools/tor-gencert.c
+++ b/src/tools/tor-gencert.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -21,7 +21,7 @@
/* Some versions of OpenSSL declare X509_STORE_CTX_set_verify_cb twice in
* x509.h and x509_vfy.h. Suppress the GCC warning so we can build with
* -Wredundant-decl. */
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/evp.h>
#include <openssl/pem.h>
@@ -30,7 +30,7 @@ DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/obj_mac.h>
#include <openssl/err.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
#endif /* defined(ENABLE_OPENSSL) */
#include <errno.h>
diff --git a/src/tools/tor-print-ed-signing-cert.c b/src/tools/tor-print-ed-signing-cert.c
index 43a1d7bcbd..7836293df4 100644
--- a/src/tools/tor-print-ed-signing-cert.c
+++ b/src/tools/tor-print-ed-signing-cert.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include <errno.h>
diff --git a/src/tools/tor-resolve.c b/src/tools/tor-resolve.c
index 5d97696c18..d369445dfc 100644
--- a/src/tools/tor-resolve.c
+++ b/src/tools/tor-resolve.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson
- * Copyright (c) 2007-2019, The Tor Project, Inc.
+ * Copyright (c) 2007-2020, The Tor Project, Inc.
*/
/* See LICENSE for licensing information */
@@ -45,8 +45,10 @@
#define RESPONSE_LEN_4 8
#define log_sock_error(act, _s) \
- STMT_BEGIN log_fn(LOG_ERR, LD_NET, "Error while %s: %s", act, \
- tor_socket_strerror(tor_socket_errno(_s))); STMT_END
+ STMT_BEGIN \
+ log_fn(LOG_ERR, LD_NET, "Error while %s: %s", act, \
+ tor_socket_strerror(tor_socket_errno(_s))); \
+ STMT_END
static void usage(void) ATTR_NORETURN;
diff --git a/src/tools/tor_runner.c b/src/tools/tor_runner.c
index 3c6ade91d9..83f1a495cd 100644
--- a/src/tools/tor_runner.c
+++ b/src/tools/tor_runner.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/trunnel/.may_include b/src/trunnel/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/trunnel/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/trunnel/hs/.may_include b/src/trunnel/hs/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/trunnel/hs/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h
index 38464f1c59..ee203da680 100644
--- a/src/win32/orconfig.h
+++ b/src/win32/orconfig.h
@@ -102,7 +102,6 @@
/* Define to 1 if you have the <sys/socket.h> header file. */
#undef HAVE_SYS_SOCKET_H
-
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H
@@ -218,9 +217,7 @@
#define USING_TWOS_COMPLEMENT
/* Version number of package */
-#define VERSION "0.4.2.8-dev"
-
-
+#define VERSION "0.4.3.6-dev"
#define HAVE_STRUCT_SOCKADDR_IN6
#define HAVE_STRUCT_IN6_ADDR